javac-wrapper: fixes after rebase and review
This commit is contained in:
committed by
Alexander Baratynskiy
parent
2dc0c55e76
commit
67fdd9f76e
@@ -150,10 +150,10 @@ class JavacWrapper(
|
||||
it.sourceFile.isNameCompatible("package-info", JavaFileObject.Kind.SOURCE) &&
|
||||
it.packageName != null
|
||||
}.associateBy({ FqName(it.packageName!!.toString()) }) { compilationUnit ->
|
||||
compilationUnit.packageAnnotations/*.map { TreeBasedAnnotation(it, compilationUnit, this) }*/
|
||||
compilationUnit.packageAnnotations
|
||||
}
|
||||
|
||||
val classifierResolver = ClassifierResolver(this)
|
||||
private val classifierResolver = ClassifierResolver(this)
|
||||
private val identifierResolver = IdentifierResolver(this)
|
||||
private val kotlinClassifiersCache by lazy { KotlinClassifiersCache(if (javaFiles.isNotEmpty()) kotlinFiles else emptyList(), this) }
|
||||
private val symbolBasedPackagesCache = hashMapOf<String, SymbolBasedPackage?>()
|
||||
|
||||
+19
-24
@@ -35,7 +35,7 @@ class ClassifierResolver(private val javac: JavacWrapper) {
|
||||
if (tree in beingResolved) return null
|
||||
beingResolved(tree)
|
||||
|
||||
return tryToResolve2(tree, unit, containingElement).apply {
|
||||
return tryToResolve(tree, unit, containingElement).apply {
|
||||
cache[tree] = this
|
||||
removeBeingResolved(tree)
|
||||
}
|
||||
@@ -67,7 +67,7 @@ class ClassifierResolver(private val javac: JavacWrapper) {
|
||||
private fun pathSegments(path: String): List<String> {
|
||||
val pathSegments = arrayListOf<String>()
|
||||
var numberOfBrackets = 0
|
||||
var builder = StringBuilder()
|
||||
val builder = StringBuilder()
|
||||
path.forEach { char ->
|
||||
when (char) {
|
||||
'<' -> numberOfBrackets++
|
||||
@@ -75,7 +75,7 @@ class ClassifierResolver(private val javac: JavacWrapper) {
|
||||
'.' -> {
|
||||
if (numberOfBrackets == 0) {
|
||||
pathSegments.add(builder.toString())
|
||||
builder = StringBuilder()
|
||||
builder.setLength(0)
|
||||
}
|
||||
}
|
||||
'@' -> {}
|
||||
@@ -86,15 +86,18 @@ class ClassifierResolver(private val javac: JavacWrapper) {
|
||||
return pathSegments.apply { add(builder.toString()) }
|
||||
}
|
||||
|
||||
private fun tryToResolve2(tree: Tree, unit: CompilationUnitTree, containingElement: JavaElement): JavaClassifier? {
|
||||
private fun tryToResolve(tree: Tree, unit: CompilationUnitTree, containingElement: JavaElement): JavaClassifier? {
|
||||
val pathSegments = pathSegments(tree.toString())
|
||||
val containingClass = when (containingElement) {
|
||||
is JavaClass -> containingElement
|
||||
is JavaTypeParameterListOwner -> {
|
||||
val identifier = Name.identifier(pathSegments.first())
|
||||
containingElement.typeParameters.find { it.name == identifier }?.let { return it }
|
||||
pathSegments.singleOrNull()?.let { pathSegment ->
|
||||
val identifier = Name.identifier(pathSegment)
|
||||
containingElement.typeParameters.find { it.name == identifier }?.let { return it }
|
||||
}
|
||||
(containingElement as JavaMember).containingClass
|
||||
}
|
||||
is JavaPackage -> return SingleTypeImportScope(javac, unit).findClass(pathSegments.first(), pathSegments)
|
||||
else -> throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
@@ -110,6 +113,10 @@ private abstract class Scope(protected val javac: JavacWrapper,
|
||||
|
||||
abstract val parent: Scope?
|
||||
|
||||
/**
|
||||
* @param name name of a class to find
|
||||
* @param pathSegments name of a class to find that is split into path segments (e.g. Outer<String>.Inner -> {"Outer", "Inner"})
|
||||
*/
|
||||
abstract fun findClass(name: String, pathSegments: List<String>): JavaClassifier?
|
||||
|
||||
}
|
||||
@@ -132,9 +139,9 @@ private class GlobalScope(javac: JavacWrapper,
|
||||
pathSegments.forEachIndexed { index, _ ->
|
||||
if (index != 0) {
|
||||
val packageFqName = pathSegments.take(index).joinToString(separator = ".")
|
||||
helper.findPackage(packageFqName)?.let { pack ->
|
||||
helper.findPackage(packageFqName)?.let { packageName ->
|
||||
val className = pathSegments.drop(index)
|
||||
helper.findJavaOrKotlinClass(ClassId(pack, Name.identifier(className.first())))?.let { javaClass ->
|
||||
helper.findJavaOrKotlinClass(ClassId(packageName, Name.identifier(className.first())))?.let { javaClass ->
|
||||
return helper.getJavaClassFromPathSegments(javaClass, className)
|
||||
}
|
||||
}
|
||||
@@ -169,14 +176,8 @@ private class ImportOnDemandScope(javac: JavacWrapper,
|
||||
}
|
||||
|
||||
private fun asteriskImports() =
|
||||
compilationUnit.imports
|
||||
.mapNotNull {
|
||||
val fqName = it.qualifiedIdentifier.toString()
|
||||
if (fqName.endsWith("*")) {
|
||||
fqName.dropLast(1)
|
||||
}
|
||||
else null
|
||||
}
|
||||
compilationUnit.imports
|
||||
.mapNotNull { it.qualifiedIdentifier.toString().takeIf { it.endsWith("*") }?.dropLast(1) }
|
||||
|
||||
}
|
||||
|
||||
@@ -214,14 +215,8 @@ private class SingleTypeImportScope(javac: JavacWrapper,
|
||||
}
|
||||
|
||||
private fun imports(firstSegment: String) =
|
||||
(compilationUnit as JCTree.JCCompilationUnit).imports
|
||||
.mapNotNull {
|
||||
val fqName = it.qualifiedIdentifier.toString()
|
||||
if (fqName.endsWith(".$firstSegment")) {
|
||||
fqName
|
||||
}
|
||||
else null
|
||||
}
|
||||
compilationUnit.imports
|
||||
.mapNotNull { it.qualifiedIdentifier.toString().takeIf { it.endsWith(".$firstSegment") } }
|
||||
}
|
||||
|
||||
private class CurrentClassAndInnerScope(javac: JavacWrapper,
|
||||
|
||||
@@ -36,14 +36,14 @@ class ConstantEvaluator(private val containingClass: JavaClass,
|
||||
}
|
||||
is JCTree.JCIdent,
|
||||
is JCTree.JCFieldAccess -> javac.resolveField(expr, compilationUnit, containingClass)?.initializerValue
|
||||
is JCTree.JCBinary -> binaryInitializerValue(expr)
|
||||
is JCTree.JCBinary -> evaluateBinaryExpression(expr)
|
||||
is JCTree.JCParens -> getValue(expr.expr)
|
||||
is JCTree.JCUnary -> unaryInitializerValue(expr)
|
||||
is JCTree.JCUnary -> evaluateUnaryExpression(expr)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun unaryInitializerValue(value: JCTree.JCUnary): Any? {
|
||||
private fun evaluateUnaryExpression(value: JCTree.JCUnary): Any? {
|
||||
val argValue = getValue(value.arg)
|
||||
return when (value.tag) {
|
||||
JCTree.Tag.COMPL -> {
|
||||
@@ -60,7 +60,7 @@ class ConstantEvaluator(private val containingClass: JavaClass,
|
||||
}
|
||||
}
|
||||
|
||||
private fun binaryInitializerValue(value: JCTree.JCBinary): Any? {
|
||||
private fun evaluateBinaryExpression(value: JCTree.JCBinary): Any? {
|
||||
val lhsValue = getValue(value.lhs) ?: return null
|
||||
val rhsValue = getValue(value.rhs) ?: return null
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ internal class ResolveHelper(private val javac: JavacWrapper,
|
||||
private val compilationUnit: CompilationUnitTree) {
|
||||
|
||||
fun getJavaClassFromPathSegments(javaClass: JavaClass,
|
||||
pathSegments: List<String>) =
|
||||
pathSegments: List<String>) =
|
||||
if (pathSegments.size == 1) {
|
||||
javaClass
|
||||
}
|
||||
@@ -66,7 +66,8 @@ internal class ResolveHelper(private val javac: JavacWrapper,
|
||||
(it.classifier as? JavaClass)?.let { supertype ->
|
||||
if (supertype !in checkedSupertypes) {
|
||||
findInnerOrNested(supertype, name, checkedSupertypes)
|
||||
} else null
|
||||
}
|
||||
else null
|
||||
}
|
||||
}.singleOrNull()
|
||||
}
|
||||
|
||||
+6
-4
@@ -80,7 +80,7 @@ class SymbolBasedClass(
|
||||
|
||||
val innerClasses: Map<Name, JavaClass>
|
||||
by lazy {
|
||||
element.enclosedElements
|
||||
enclosedElements
|
||||
.filterIsInstance(TypeElement::class.java)
|
||||
.map { SymbolBasedClass(it, javac, classId?.createNestedClassId(Name.identifier(it.simpleName.toString())), file) }
|
||||
.associateBy(JavaClass::name)
|
||||
@@ -106,7 +106,7 @@ class SymbolBasedClass(
|
||||
get() = null
|
||||
|
||||
override val methods: Collection<JavaMethod>
|
||||
get() = element.enclosedElements
|
||||
get() = enclosedElements
|
||||
.filter { it.kind == ElementKind.METHOD && !isEnumValuesOrValueOf(it as ExecutableElement) }
|
||||
.map { SymbolBasedMethod(it as ExecutableElement, this, javac) }
|
||||
|
||||
@@ -119,12 +119,12 @@ class SymbolBasedClass(
|
||||
}
|
||||
|
||||
override val fields: Collection<JavaField>
|
||||
get() = element.enclosedElements
|
||||
get() = enclosedElements
|
||||
.filter { it.kind.isField && Name.isValidIdentifier(it.simpleName.toString()) }
|
||||
.map { SymbolBasedField(it as VariableElement, this, javac) }
|
||||
|
||||
override val constructors: Collection<JavaConstructor>
|
||||
get() = element.enclosedElements
|
||||
get() = enclosedElements
|
||||
.filter { it.kind == ElementKind.CONSTRUCTOR }
|
||||
.map { SymbolBasedConstructor(it as ExecutableElement, this, javac) }
|
||||
|
||||
@@ -139,4 +139,6 @@ class SymbolBasedClass(
|
||||
|
||||
override fun findInnerClass(name: Name) = innerClasses[name]
|
||||
|
||||
private val enclosedElements by lazy { element.enclosedElements }
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@ class SymbolBasedReferenceAnnotationArgument(
|
||||
javac: JavacWrapper
|
||||
) : SymbolBasedAnnotationArgument(name, javac), JavaEnumValueAnnotationArgument {
|
||||
override val entryName: Name?
|
||||
get() = Name.identifier(name)
|
||||
get() = name
|
||||
|
||||
override fun resolve(): SymbolBasedField {
|
||||
val containingClass = (element.enclosingElement as Symbol.ClassSymbol).let {
|
||||
|
||||
+17
-35
@@ -55,6 +55,8 @@ class TreeBasedReferenceAnnotationArgument(name: Name,
|
||||
private val field: JCTree.JCFieldAccess,
|
||||
javac: JavacWrapper,
|
||||
private val onElement: JavaElement) : TreeBasedAnnotationArgument(name, javac), JavaEnumValueAnnotationArgument {
|
||||
override val entryName: Name?
|
||||
get() = name
|
||||
|
||||
override fun resolve(): JavaField? {
|
||||
val javaClass = javac.resolve(field.selected, compilationUnit, onElement) as? JavaClass ?: return null
|
||||
@@ -67,7 +69,7 @@ class TreeBasedReferenceAnnotationArgument(name: Name,
|
||||
|
||||
class TreeBasedArrayAnnotationArgument(val args: List<JavaAnnotationArgument>,
|
||||
name: Name,
|
||||
javac: JavacWrapper): TreeBasedAnnotationArgument(name, javac), JavaArrayAnnotationArgument {
|
||||
javac: JavacWrapper) : TreeBasedAnnotationArgument(name, javac), JavaArrayAnnotationArgument {
|
||||
override fun getElements() = args
|
||||
|
||||
}
|
||||
@@ -76,10 +78,10 @@ class TreeBasedJavaClassObjectAnnotationArgument(private val type: JCTree.JCExpr
|
||||
name: Name,
|
||||
private val compilationUnit: CompilationUnitTree,
|
||||
javac: JavacWrapper,
|
||||
private val onElement: JavaElement): TreeBasedAnnotationArgument(name, javac), JavaClassObjectAnnotationArgument {
|
||||
private val onElement: JavaElement) : TreeBasedAnnotationArgument(name, javac), JavaClassObjectAnnotationArgument {
|
||||
|
||||
override fun getReferencedType(): JavaType =
|
||||
TreeBasedType.create(type, compilationUnit, javac, emptyList(), onElement)
|
||||
TreeBasedType.create(type, compilationUnit, javac, emptyList(), onElement)
|
||||
|
||||
}
|
||||
|
||||
@@ -87,25 +89,19 @@ class TreeBasedAnnotationAsAnnotationArgument(private val annotation: JCTree.JCA
|
||||
name: Name,
|
||||
private val compilationUnit: CompilationUnitTree,
|
||||
javac: JavacWrapper,
|
||||
private val onElement: JavaElement): TreeBasedAnnotationArgument(name, javac), JavaAnnotationAsAnnotationArgument {
|
||||
private val onElement: JavaElement) : TreeBasedAnnotationArgument(name, javac), JavaAnnotationAsAnnotationArgument {
|
||||
override fun getAnnotation(): JavaAnnotation =
|
||||
TreeBasedAnnotation(annotation, compilationUnit, javac, onElement)
|
||||
TreeBasedAnnotation(annotation, compilationUnit, javac, onElement)
|
||||
|
||||
}
|
||||
|
||||
private fun createAnnotationArguments(annotation: TreeBasedAnnotation,
|
||||
javac: JavacWrapper,
|
||||
onElement: JavaElement): Collection<JavaAnnotationArgument> {
|
||||
val arguments = annotation.annotation.arguments
|
||||
val javaClass = annotation.resolve() ?: return emptyList()
|
||||
val methods = javaClass.methods
|
||||
|
||||
if (arguments.size != methods.size) return emptyList()
|
||||
|
||||
return methods.mapIndexedNotNull { index, it ->
|
||||
createAnnotationArgument(arguments[index], it.name, annotation.compilationUnit, javac, annotation, onElement)
|
||||
}
|
||||
}
|
||||
onElement: JavaElement): Collection<JavaAnnotationArgument> =
|
||||
annotation.annotation.arguments.mapNotNull {
|
||||
val name = if (it is JCTree.JCAssign) Name.identifier(it.lhs.toString()) else Name.identifier("value")
|
||||
createAnnotationArgument(it, name, annotation.compilationUnit, javac, annotation, onElement)
|
||||
}
|
||||
|
||||
private fun createAnnotationArgument(argument: JCTree.JCExpression,
|
||||
name: Name,
|
||||
@@ -118,17 +114,18 @@ private fun createAnnotationArgument(argument: JCTree.JCExpression,
|
||||
is JCTree.JCFieldAccess -> {
|
||||
if (argument.name.contentEquals("class")) {
|
||||
TreeBasedJavaClassObjectAnnotationArgument(argument.selected, name, compilationUnit, javac, onElement)
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
TreeBasedReferenceAnnotationArgument(name, compilationUnit, argument, javac, onElement)
|
||||
}
|
||||
}
|
||||
is JCTree.JCAssign -> createAnnotationArgument(argument.rhs, name, compilationUnit, javac, annotation, onElement)
|
||||
is JCTree.JCNewArray -> arrayAnnotationArguments(argument.elems, name, compilationUnit, javac, annotation, onElement)
|
||||
is JCTree.JCNewArray -> TreeBasedArrayAnnotationArgument(argument.elems.mapNotNull { createAnnotationArgument(it, name, compilationUnit, javac, annotation, onElement) }, name, javac)
|
||||
is JCTree.JCAnnotation -> TreeBasedAnnotationAsAnnotationArgument(argument, name, compilationUnit, javac, onElement)
|
||||
is JCTree.JCParens -> createAnnotationArgument(argument.expr, name, compilationUnit, javac, annotation, onElement)
|
||||
is JCTree.JCBinary -> resolveArgumentValue(argument, annotation, name, compilationUnit, javac)
|
||||
is JCTree.JCUnary -> resolveArgumentValue(argument, annotation, name, compilationUnit, javac)
|
||||
else -> null
|
||||
else -> throw UnsupportedOperationException("Unknown annotation argument $argument")
|
||||
}
|
||||
|
||||
private fun resolveArgumentValue(argument: JCTree.JCExpression,
|
||||
@@ -140,19 +137,4 @@ private fun resolveArgumentValue(argument: JCTree.JCExpression,
|
||||
val evaluator = ConstantEvaluator(containingAnnotation, javac, compilationUnit)
|
||||
|
||||
return evaluator.getValue(argument)?.let { TreeBasedLiteralAnnotationArgument(name, it, javac) }
|
||||
}
|
||||
|
||||
private fun arrayAnnotationArguments(values: List<JCTree.JCExpression>,
|
||||
name: Name,
|
||||
compilationUnit: CompilationUnitTree,
|
||||
javac: JavacWrapper,
|
||||
annotation: TreeBasedAnnotation,
|
||||
onElement: JavaElement): JavaArrayAnnotationArgument =
|
||||
values.mapNotNull {
|
||||
if (it is JCTree.JCNewArray) {
|
||||
arrayAnnotationArguments(it.elems, name, compilationUnit, javac, annotation, onElement)
|
||||
}
|
||||
else {
|
||||
createAnnotationArgument(it, name, compilationUnit, javac, annotation, onElement)
|
||||
}
|
||||
}.let { TreeBasedArrayAnnotationArgument(it, name, javac) }
|
||||
}
|
||||
+1
-1
@@ -77,7 +77,7 @@ class TreeBasedClass(
|
||||
by lazy {
|
||||
arrayListOf<JavaClassifierType>().also { list ->
|
||||
if (isEnum) {
|
||||
EnumSupertype(this, javac).let { list.add(it) }
|
||||
list.add(EnumSupertype(this, javac))
|
||||
}
|
||||
else if (isAnnotationType) {
|
||||
javac.JAVA_LANG_ANNOTATION_ANNOTATION?.let { list.add(it) }
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ class TreeBasedMethod(
|
||||
get() = Name.identifier(tree.name.toString())
|
||||
|
||||
override val isAbstract: Boolean
|
||||
get() = (containingClass.isInterface && !tree.modifiers.hasDefaultModifier) || tree.modifiers.isAbstract
|
||||
get() = (containingClass.isInterface && !tree.modifiers.hasDefaultModifier && !isStatic) || tree.modifiers.isAbstract
|
||||
|
||||
override val isStatic: Boolean
|
||||
get() = tree.modifiers.isStatic
|
||||
|
||||
Reference in New Issue
Block a user