Improve constants analysis in KAPT
When analyzing source files in KAPT for incremental annotation processing, avoid creating TreePath instances for initializers that are literals. E.g. if it is just a boolean/int literal, we do not need to visit the tree nor create expensive TreePath instance. For classes that contain only constants (such as R.java for Android projects) this is a significant improvement. Class that contains 16000 constants took more than 10 seconds to analyze, now it is 70ms.
This commit is contained in:
committed by
Yan Zhulanow
parent
84c048ca81
commit
76f62da6ae
+15
-2
@@ -47,7 +47,7 @@ private enum class Visibility {
|
|||||||
ABI, NON_ABI
|
ABI, NON_ABI
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TypeTreeVisitor(val elementUtils: Elements, val trees: Trees, val compilationUnit: CompilationUnitTree, val sourceStructure: SourceFileStructure) :
|
private class TypeTreeVisitor(val elementUtils: Elements, val trees: Trees, val compilationUnit: CompilationUnitTree, val sourceStructure: SourceFileStructure) :
|
||||||
SimpleTreeVisitor<Void, Visibility>() {
|
SimpleTreeVisitor<Void, Visibility>() {
|
||||||
|
|
||||||
val constantTreeVisitor = ConstantTreeVisitor(sourceStructure)
|
val constantTreeVisitor = ConstantTreeVisitor(sourceStructure)
|
||||||
@@ -113,7 +113,9 @@ private class TypeTreeVisitor(val elementUtils: Elements, val trees: Trees, val
|
|||||||
val flags = node.modifiers.getFlags()
|
val flags = node.modifiers.getFlags()
|
||||||
|
|
||||||
node.sym.constValue?.let { _ ->
|
node.sym.constValue?.let { _ ->
|
||||||
constantTreeVisitor.scan(trees.getPath(compilationUnit, node.init), null)
|
if (!constantTreeVisitor.isTrivialLiteralExpression(node.init)) {
|
||||||
|
constantTreeVisitor.scan(trees.getPath(compilationUnit, node.init), null)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (flags.contains(Modifier.PRIVATE)) Visibility.NON_ABI else Visibility.ABI
|
if (flags.contains(Modifier.PRIVATE)) Visibility.NON_ABI else Visibility.ABI
|
||||||
} else {
|
} else {
|
||||||
@@ -196,12 +198,23 @@ private class TypeTreeVisitor(val elementUtils: Elements, val trees: Trees, val
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val literalKinds = setOf(
|
||||||
|
Tree.Kind.BOOLEAN_LITERAL,
|
||||||
|
Tree.Kind.INT_LITERAL,
|
||||||
|
Tree.Kind.LONG_LITERAL,
|
||||||
|
Tree.Kind.DOUBLE_LITERAL,
|
||||||
|
Tree.Kind.FLOAT_LITERAL,
|
||||||
|
Tree.Kind.CHAR_LITERAL,
|
||||||
|
Tree.Kind.STRING_LITERAL
|
||||||
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visits a constant initializer expression, and extracts all references to constants, either through field select (A.MY_FIELD) or
|
* Visits a constant initializer expression, and extracts all references to constants, either through field select (A.MY_FIELD) or
|
||||||
* identifier (MY_FIELD, which happens if A.MY_FIELD is statically imported).
|
* identifier (MY_FIELD, which happens if A.MY_FIELD is statically imported).
|
||||||
*/
|
*/
|
||||||
private class ConstantTreeVisitor(val sourceStructure: SourceFileStructure) : TreePathScanner<Void, Void>() {
|
private class ConstantTreeVisitor(val sourceStructure: SourceFileStructure) : TreePathScanner<Void, Void>() {
|
||||||
|
|
||||||
|
fun isTrivialLiteralExpression(tree: Tree) = tree.kind in literalKinds
|
||||||
|
|
||||||
override fun visitAssignment(node: AssignmentTree, p: Void?): Void? {
|
override fun visitAssignment(node: AssignmentTree, p: Void?): Void? {
|
||||||
// Annotation element values are in "element = expression" form, and we only want to analyze "expression" part. So ignore variable.
|
// Annotation element values are in "element = expression" form, and we only want to analyze "expression" part. So ignore variable.
|
||||||
|
|||||||
Reference in New Issue
Block a user