• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.protolog.tool
18 
19 import com.android.json.stream.JsonWriter
20 import com.github.javaparser.ast.CompilationUnit
21 import com.android.protolog.tool.Constants.VERSION
22 import com.github.javaparser.ast.expr.MethodCallExpr
23 import java.io.StringWriter
24 
25 class ViewerConfigBuilder(
26     private val processor: ProtoLogCallProcessor
27 ) {
28     private fun addLogCall(logCall: LogCall, context: ParsingContext) {
29         val group = logCall.logGroup
30         val messageString = logCall.messageString
31         if (group.enabled) {
32             val key = logCall.key()
33             if (statements.containsKey(key)) {
34                 if (statements[key] != logCall) {
35                     throw HashCollisionException(
36                             "Please modify the log message \"$messageString\" " +
37                                     "or \"${statements[key]}\" - their hashes are equal.", context)
38                 }
39             } else {
40                 groups.add(group)
41                 statements[key] = logCall
42             }
43         }
44     }
45 
46     private val statements: MutableMap<Int, LogCall> = mutableMapOf()
47     private val groups: MutableSet<LogGroup> = mutableSetOf()
48 
49     fun findLogCalls(
50         unit: CompilationUnit,
51         path: String,
52         packagePath: String
53     ): List<Pair<LogCall, ParsingContext>> {
54         val calls = mutableListOf<Pair<LogCall, ParsingContext>>()
55         val visitor = object : ProtoLogCallVisitor {
56             override fun processCall(
57                 call: MethodCallExpr,
58                 messageString: String,
59                 level: LogLevel,
60                 group: LogGroup
61             ) {
62                 val logCall = LogCall(messageString, level, group, packagePath)
63                 val context = ParsingContext(path, call)
64                 calls.add(logCall to context)
65             }
66         }
67         processor.process(unit, visitor, path)
68 
69         return calls
70     }
71 
72     fun addLogCalls(calls: List<Pair<LogCall, ParsingContext>>) {
73         calls.forEach { (logCall, context) ->
74             addLogCall(logCall, context)
75         }
76     }
77 
78     fun build(): String {
79         val stringWriter = StringWriter()
80         val writer = JsonWriter(stringWriter)
81         writer.setIndent("  ")
82         writer.beginObject()
83         writer.name("version")
84         writer.value(VERSION)
85         writer.name("messages")
86         writer.beginObject()
87         statements.toSortedMap().forEach { (key, value) ->
88             writer.name(key.toString())
89             writer.beginObject()
90             writer.name("message")
91             writer.value(value.messageString)
92             writer.name("level")
93             writer.value(value.logLevel.name)
94             writer.name("group")
95             writer.value(value.logGroup.name)
96             writer.name("at")
97             writer.value(value.position)
98             writer.endObject()
99         }
100         writer.endObject()
101         writer.name("groups")
102         writer.beginObject()
103         groups.toSortedSet(Comparator { o1, o2 -> o1.name.compareTo(o2.name) }).forEach { group ->
104             writer.name(group.name)
105             writer.beginObject()
106             writer.name("tag")
107             writer.value(group.tag)
108             writer.endObject()
109         }
110         writer.endObject()
111         writer.endObject()
112         stringWriter.buffer.append('\n')
113         return stringWriter.toString()
114     }
115 
116     data class LogCall(
117         val messageString: String,
118         val logLevel: LogLevel,
119         val logGroup: LogGroup,
120         val position: String
121     ) {
122         fun key() = CodeUtils.hash(position, messageString, logLevel, logGroup)
123     }
124 }
125