blob: 175c71ff810b1ad77376f99c0816370292872592 [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.protolog.tool
import com.android.json.stream.JsonWriter
import com.github.javaparser.ast.CompilationUnit
import com.android.protolog.tool.Constants.VERSION
import com.github.javaparser.ast.expr.MethodCallExpr
import java.io.StringWriter
class ViewerConfigBuilder(
private val processor: ProtoLogCallProcessor
) {
private fun addLogCall(logCall: LogCall, context: ParsingContext) {
val group = logCall.logGroup
val messageString = logCall.messageString
if (group.enabled) {
val key = logCall.key()
if (statements.containsKey(key)) {
if (statements[key] != logCall) {
throw HashCollisionException(
"Please modify the log message \"$messageString\" " +
"or \"${statements[key]}\" - their hashes are equal.", context)
}
} else {
groups.add(group)
statements[key] = logCall
}
}
}
private val statements: MutableMap<Int, LogCall> = mutableMapOf()
private val groups: MutableSet<LogGroup> = mutableSetOf()
fun findLogCalls(
unit: CompilationUnit,
path: String,
packagePath: String
): List<Pair<LogCall, ParsingContext>> {
val calls = mutableListOf<Pair<LogCall, ParsingContext>>()
val visitor = object : ProtoLogCallVisitor {
override fun processCall(
call: MethodCallExpr,
messageString: String,
level: LogLevel,
group: LogGroup
) {
val logCall = LogCall(messageString, level, group, packagePath)
val context = ParsingContext(path, call)
calls.add(logCall to context)
}
}
processor.process(unit, visitor, path)
return calls
}
fun addLogCalls(calls: List<Pair<LogCall, ParsingContext>>) {
calls.forEach { (logCall, context) ->
addLogCall(logCall, context)
}
}
fun build(): String {
val stringWriter = StringWriter()
val writer = JsonWriter(stringWriter)
writer.setIndent(" ")
writer.beginObject()
writer.name("version")
writer.value(VERSION)
writer.name("messages")
writer.beginObject()
statements.toSortedMap().forEach { (key, value) ->
writer.name(key.toString())
writer.beginObject()
writer.name("message")
writer.value(value.messageString)
writer.name("level")
writer.value(value.logLevel.name)
writer.name("group")
writer.value(value.logGroup.name)
writer.name("at")
writer.value(value.position)
writer.endObject()
}
writer.endObject()
writer.name("groups")
writer.beginObject()
groups.toSortedSet(Comparator { o1, o2 -> o1.name.compareTo(o2.name) }).forEach { group ->
writer.name(group.name)
writer.beginObject()
writer.name("tag")
writer.value(group.tag)
writer.endObject()
}
writer.endObject()
writer.endObject()
stringWriter.buffer.append('\n')
return stringWriter.toString()
}
data class LogCall(
val messageString: String,
val logLevel: LogLevel,
val logGroup: LogGroup,
val position: String
) {
fun key() = CodeUtils.hash(position, messageString, logLevel, logGroup)
}
}