Support package level annotations in Java

#KT-10942 In Progress
This commit is contained in:
Denis Zharkov
2017-07-02 15:17:46 +03:00
parent b7ead75947
commit 79e14f88e4
15 changed files with 222 additions and 21 deletions
@@ -43,10 +43,8 @@ import com.sun.tools.javac.util.Options
import org.jetbrains.kotlin.javac.wrappers.symbols.SymbolBasedClass
import org.jetbrains.kotlin.javac.wrappers.symbols.SymbolBasedClassifierType
import org.jetbrains.kotlin.javac.wrappers.symbols.SymbolBasedPackage
import org.jetbrains.kotlin.javac.wrappers.trees.TreeBasedClass
import org.jetbrains.kotlin.javac.wrappers.trees.TreeBasedPackage
import org.jetbrains.kotlin.javac.wrappers.trees.TreePathResolverCache
import org.jetbrains.kotlin.javac.wrappers.trees.computeClassId
import org.jetbrains.kotlin.javac.wrappers.trees.*
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.load.java.structure.JavaClassifier
import org.jetbrains.kotlin.load.java.structure.JavaPackage
@@ -142,6 +140,14 @@ class JavacWrapper(
}
.associateBy(TreeBasedPackage::fqName)
private val packageSourceAnnotations = compilationUnits
.filter {
it.sourceFile.isNameCompatible("package-info", JavaFileObject.Kind.SOURCE) &&
it.packageName != null
}.associateBy({ FqName(it.packageName!!.toString()) }) { compilationUnit ->
compilationUnit.packageAnnotations.map { TreeBasedAnnotation(it, compilationUnit, this) }
}
private val kotlinClassifiersCache = KotlinClassifiersCache(if (javaFiles.isNotEmpty()) kotlinFiles else emptyList(), this)
private val treePathResolverCache = TreePathResolverCache(this)
private val symbolBasedClassesCache = hashMapOf<String, SymbolBasedClass?>()
@@ -212,6 +218,9 @@ class JavacWrapper(
.filterKeys { it.isSubpackageOf(fqName) && it != fqName }
.map { it.value }
fun getPackageAnnotationsFromSources(fqName: FqName): List<JavaAnnotation> =
packageSourceAnnotations[fqName] ?: emptyList()
fun findClassesFromPackage(fqName: FqName): List<JavaClass> =
javaClasses
.filterKeys { it?.parentOrNull() == fqName }
@@ -329,4 +338,4 @@ class JavacWrapper(
return symbol.let { SymbolBasedClass(it, this@JavacWrapper, it.classfile) }
}
}
}
@@ -17,7 +17,10 @@
package org.jetbrains.kotlin.javac.wrappers.symbols
import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
import org.jetbrains.kotlin.load.java.structure.JavaPackage
import org.jetbrains.kotlin.load.java.structure.MapBasedJavaAnnotationOwner
import org.jetbrains.kotlin.load.java.structure.buildLazyValueForMap
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import javax.lang.model.element.PackageElement
@@ -25,7 +28,7 @@ import javax.lang.model.element.PackageElement
class SymbolBasedPackage(
element: PackageElement,
javac: JavacWrapper
) : SymbolBasedElement<PackageElement>(element, javac), JavaPackage {
) : SymbolBasedElement<PackageElement>(element, javac), JavaPackage, MapBasedJavaAnnotationOwner {
override val fqName: FqName
get() = FqName(element.qualifiedName.toString())
@@ -33,9 +36,15 @@ class SymbolBasedPackage(
override val subPackages: Collection<JavaPackage>
get() = javac.findSubPackages(FqName(element.qualifiedName.toString()))
override val annotations: Collection<JavaAnnotation>
get() = element.annotationMirrors.map { SymbolBasedAnnotation(it, javac) }
override val annotationsByFqName: Map<FqName?, JavaAnnotation> by buildLazyValueForMap()
override fun getClasses(nameFilter: (Name) -> Boolean) =
javac.findClassesFromPackage(fqName).filter { nameFilter(it.name) }
override fun toString() = element.qualifiedName.toString()
}
}
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.javac.wrappers.trees
import com.sun.source.tree.CompilationUnitTree
import com.sun.source.util.TreePath
import com.sun.tools.javac.tree.JCTree
import org.jetbrains.kotlin.javac.JavacWrapper
@@ -27,11 +28,17 @@ import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
class TreeBasedAnnotation(
val annotation: JCTree.JCAnnotation,
val treePath: TreePath,
val javac: JavacWrapper
private val annotation: JCTree.JCAnnotation,
private val compilationUnit: CompilationUnitTree,
private val javac: JavacWrapper
) : JavaElement, JavaAnnotation {
constructor(
annotation: JCTree.JCAnnotation,
treePath: TreePath,
javac: JavacWrapper
) : this(annotation, treePath.compilationUnit, javac)
override val arguments: Collection<JavaAnnotationArgument>
get() = annotation.arguments.map { TreeBasedAnnotationArgument(Name.identifier(it.toString())) }
@@ -39,8 +46,8 @@ class TreeBasedAnnotation(
get() = resolve()?.computeClassId()
override fun resolve() =
javac.resolve(TreePath.getPath(treePath.compilationUnit, annotation.annotationType)) as? JavaClass
javac.resolve(TreePath.getPath(compilationUnit, annotation.annotationType)) as? JavaClass
}
class TreeBasedAnnotationArgument(override val name: Name) : JavaAnnotationArgument, JavaElement
class TreeBasedAnnotationArgument(override val name: Name) : JavaAnnotationArgument, JavaElement
@@ -154,4 +154,4 @@ class TreeBasedClass(
override fun findInnerClass(name: Name) = innerClasses[name]
}
}
@@ -18,12 +18,15 @@ package org.jetbrains.kotlin.javac.wrappers.trees
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
import org.jetbrains.kotlin.load.java.structure.JavaPackage
import org.jetbrains.kotlin.load.java.structure.MapBasedJavaAnnotationOwner
import org.jetbrains.kotlin.load.java.structure.buildLazyValueForMap
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import javax.tools.JavaFileObject
class TreeBasedPackage(val name: String, val javac: JavacWrapper, val file: JavaFileObject) : JavaPackage {
class TreeBasedPackage(val name: String, val javac: JavacWrapper, val file: JavaFileObject) : JavaPackage, MapBasedJavaAnnotationOwner {
override val fqName: FqName
get() = FqName(name)
@@ -38,10 +41,15 @@ class TreeBasedPackage(val name: String, val javac: JavacWrapper, val file: Java
override fun getClasses(nameFilter: (Name) -> Boolean) =
javac.findClassesFromPackage(fqName).filter { nameFilter(it.fqName!!.shortName()) }
override val annotations
get() = javac.getPackageAnnotationsFromSources(fqName)
override val annotationsByFqName: Map<FqName?, JavaAnnotation> by buildLazyValueForMap()
override fun equals(other: Any?) = (other as? TreeBasedPackage)?.name == name
override fun hashCode() = name.hashCode()
override fun toString() = name
}
}