javac-wrapper: constant evaluator

This commit is contained in:
baratynskiy
2017-08-03 16:21:49 +03:00
committed by Alexander Baratynskiy
parent 4f180e1292
commit 1b0d7ff5be
40 changed files with 910 additions and 322 deletions
@@ -149,7 +149,7 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
var useJavac: Boolean by FreezableVar(false)
@Argument(value = "-Xcompile-java", description = "Reuse javac analysis and compile Java source files")
public boolean compileJava;
var compileJava by FreezableVar(false)
@Argument(
value = "-Xjavac-arguments",
@@ -253,7 +253,7 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
private fun compileJavaFilesIfNeeded(environment: KotlinCoreEnvironment,
arguments: K2JVMCompilerArguments): Boolean {
if (arguments.useJavac) {
if (arguments.compileJava) {
return JavacWrapper.getInstance(environment.project).use { it.compile() }
}
return true
@@ -279,7 +279,7 @@ class KotlinCoreEnvironment private constructor(
bootClasspath: List<File>? = null,
sourcePath: List<File>? = null
): Boolean {
return JavacWrapperRegistrar.registerJavac(projectEnvironment.project, configuration, javaFiles, kotlinFiles, arguments, bootClasspath, sourcePath, CliLightClassGenerationSupport(project))
return JavacWrapperRegistrar.registerJavac(projectEnvironment.project, configuration, javaFiles, kotlinFiles, arguments, bootClasspath, sourcePath, LightClassGenerationSupport.getInstance(project))
}
private val applicationEnvironment: CoreApplicationEnvironment
@@ -17,8 +17,9 @@
package org.jetbrains.kotlin.cli.jvm.javac
import com.intellij.psi.PsiClass
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.cli.jvm.compiler.CliLightClassGenerationSupport
import org.jetbrains.kotlin.asJava.findFacadeClass
import org.jetbrains.kotlin.javac.JavacWrapperKotlinResolver
import org.jetbrains.kotlin.javac.resolve.MockKotlinField
import org.jetbrains.kotlin.load.java.structure.JavaField
@@ -26,8 +27,9 @@ import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtFile
class JavacWrapperKotlinResolverImpl(private val lightClassGenerationSupport: CliLightClassGenerationSupport) : JavacWrapperKotlinResolver {
class JavacWrapperKotlinResolverImpl(private val lightClassGenerationSupport: LightClassGenerationSupport) : JavacWrapperKotlinResolver {
private val cache = hashMapOf<KtClassOrObject, KtLightClass>()
@@ -44,6 +46,12 @@ class JavacWrapperKotlinResolverImpl(private val lightClassGenerationSupport: Cl
return lightClass.allFields.find { it.name == name}?.let(::MockKotlinField)
}
override fun findField(ktFile: KtFile?, name: String): JavaField? {
val lightClass = ktFile?.findFacadeClass() ?: return null
return lightClass.allFields.find { it.name == name}?.let(::MockKotlinField)
}
private fun KtClassOrObject.getLightClass(): KtLightClass? =
cache[this] ?: lightClassGenerationSupport.getLightClass(this)?.also { cache[this] = it }
@@ -18,9 +18,9 @@ package org.jetbrains.kotlin.cli.jvm.javac
import com.intellij.mock.MockProject
import com.sun.tools.javac.util.Context
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.STRONG_WARNING
import org.jetbrains.kotlin.cli.jvm.compiler.CliLightClassGenerationSupport
import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys
@@ -40,7 +40,7 @@ object JavacWrapperRegistrar {
arguments: Array<String>?,
bootClasspath: List<File>?,
sourcePath: List<File>?,
lightClassGenerationSupport: CliLightClassGenerationSupport
lightClassGenerationSupport: LightClassGenerationSupport
): Boolean {
val messageCollector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
@@ -0,0 +1,24 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* 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 org.jetbrains.kotlin.javac
import org.jetbrains.kotlin.load.java.structure.impl.VirtualFileBoundJavaClass
import org.jetbrains.kotlin.name.ClassId
interface JavaClassWithClassId : VirtualFileBoundJavaClass {
val classId: ClassId?
}
@@ -21,7 +21,6 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.psi.CommonClassNames
import com.intellij.psi.search.EverythingGlobalScope
import com.intellij.psi.search.GlobalSearchScope
import com.sun.source.tree.CompilationUnitTree
@@ -80,21 +79,21 @@ class JavacWrapper(
fun getInstance(project: Project): JavacWrapper = ServiceManager.getService(project, JavacWrapper::class.java)
}
private fun createCommonClassifierType(fqName: String) =
findClassInSymbols(fqName)?.let {
private fun createCommonClassifierType(classId: ClassId) =
findClassInSymbols(classId)?.let {
SymbolBasedClassifierType(it.element.asType(), this)
}
val JAVA_LANG_OBJECT by lazy {
createCommonClassifierType(CommonClassNames.JAVA_LANG_OBJECT)
createCommonClassifierType(classId("java.lang", "Object"))
}
val JAVA_LANG_ENUM by lazy {
findClassInSymbols(CommonClassNames.JAVA_LANG_ENUM)
findClassInSymbols(classId("java.lang", "Enum"))
}
val JAVA_LANG_ANNOTATION_ANNOTATION by lazy {
createCommonClassifierType(CommonClassNames.JAVA_LANG_ANNOTATION_ANNOTATION)
createCommonClassifierType(classId("java.lang.annotation", "Annotation"))
}
init {
@@ -133,31 +132,15 @@ class JavacWrapper(
private val fileObjects = fileManager.getJavaFileObjectsFromFiles(javaFiles).toJavacList()
private val compilationUnits: JavacList<JCTree.JCCompilationUnit> = fileObjects.map(javac::parse).toJavacList()
private val treeBasedJavaClasses = hashMapOf<ClassId, TreeBasedClass>()
private val javaClassDeclarations = compilationUnits.flatMap { unit ->
private val treeBasedJavaClasses = compilationUnits.flatMap { unit ->
unit.typeDecls.map { classDeclaration ->
val packageName = unit.packageName?.toString() ?: ""
val className = (classDeclaration as JCTree.JCClassDecl).simpleName.toString()
val classId = classId(packageName, className)
classId to Pair(classDeclaration, unit)
classId to TreeBasedClass(classDeclaration, trees.getPath(unit, classDeclaration), this, unit.sourceFile, classId)
}
}.toMap()
private fun getTreeBasedClass(classId: ClassId): TreeBasedClass? {
if (treeBasedJavaClasses.containsKey(classId)) {
return treeBasedJavaClasses[classId]
}
val (classDeclaration, unit) = javaClassDeclarations[classId] ?: return null
val treeBasedClass = TreeBasedClass(classDeclaration,
trees.getPath(unit, classDeclaration),
this,
unit.sourceFile)
return treeBasedClass.apply { treeBasedJavaClasses[classId] = this }
}
private val javaPackages = compilationUnits
.mapTo(hashSetOf<TreeBasedPackage>()) { unit ->
unit.packageName?.toString()?.let { packageName ->
@@ -176,8 +159,9 @@ class JavacWrapper(
val classifierResolver = ClassifierResolver(this)
private val identifierResolver = IdentifierResolver(this)
private val kotlinClassifiersCache = KotlinClassifiersCache(if (javaFiles.isNotEmpty()) kotlinFiles else emptyList(), this)
private val kotlinClassifiersCache by lazy { KotlinClassifiersCache(if (javaFiles.isNotEmpty()) kotlinFiles else emptyList(), this) }
private val symbolBasedPackagesCache = hashMapOf<String, SymbolBasedPackage?>()
private val symbolBasedClassesCache = hashMapOf<ClassId, SymbolBasedClass>()
fun compile(outDir: File? = null): Boolean = with(javac) {
if (!compileJava) return true
@@ -211,12 +195,19 @@ class JavacWrapper(
return outerClass
}
getTreeBasedClass(classId)?.let { javaClass ->
treeBasedJavaClasses[classId]?.let { javaClass ->
javaClass.virtualFile?.let { if (it in scope) return javaClass }
}
if (symbolBasedClassesCache.containsKey(classId)) {
val javaClass = symbolBasedClassesCache[classId]
javaClass?.virtualFile?.let { file ->
if (file in scope) return javaClass
}
}
findPackageInSymbols(classId.packageFqName.asString())?.let {
(it.element as Symbol.PackageSymbol).findClass(classId.relativeClassName.asString())?.let { javaClass ->
(it.element as Symbol.PackageSymbol).findClass(classId)?.let { javaClass ->
javaClass.virtualFile?.let { file ->
if (file in scope) return javaClass
}
@@ -249,20 +240,20 @@ class JavacWrapper(
packageSourceAnnotations[fqName] ?: emptyList()
fun findClassesFromPackage(fqName: FqName): List<JavaClass> =
javaClassDeclarations
treeBasedJavaClasses
.filterKeys { it.packageFqName == fqName }
.map { getTreeBasedClass(it.key)!! } +
.map { treeBasedJavaClasses[it.key]!! } +
elements.getPackageElement(fqName.asString())
?.members()
?.elements
?.filterIsInstance(Symbol.ClassSymbol::class.java)
?.map { SymbolBasedClass(it, this, it.classfile) }
?.map { SymbolBasedClass(it, this, null, it.classfile) }
.orEmpty()
fun knownClassNamesInPackage(fqName: FqName): Set<String> =
javaClassDeclarations
treeBasedJavaClasses
.filterKeys { it.packageFqName == fqName }
.mapTo(hashSetOf()) { it.key.shortClassName.asString() } +
.mapTo(hashSetOf()) { it.value.name.asString() } +
elements.getPackageElement(fqName.asString())
?.members_field
?.elements
@@ -309,9 +300,9 @@ class JavacWrapper(
private inline fun <reified T> Iterable<T>.toJavacList() = JavacList.from(this)
private fun findClassInSymbols(fqName: String): SymbolBasedClass? =
elements.getTypeElement(fqName)?.let { symbol ->
SymbolBasedClass(symbol, this, symbol.classfile)
private fun findClassInSymbols(classId: ClassId): SymbolBasedClass? =
elements.getTypeElement(classId.asSingleFqName().asString())?.let { symbol ->
SymbolBasedClass(symbol, this, classId, symbol.classfile)
}
private fun findPackageInSymbols(fqName: String): SymbolBasedPackage? {
@@ -356,7 +347,8 @@ class JavacWrapper(
}
private fun Symbol.PackageSymbol.findClass(name: String): SymbolBasedClass? {
private fun Symbol.PackageSymbol.findClass(classId: ClassId): SymbolBasedClass? {
val name = classId.relativeClassName.asString()
val nameParts = name.replace("$", ".").split(".")
var symbol = members_field?.getElementsByName(names.fromString(nameParts.first()))
?.firstOrNull() as? Symbol.ClassSymbol ?: return null
@@ -368,7 +360,8 @@ class JavacWrapper(
}
}
return symbol.let { SymbolBasedClass(it, this@JavacWrapper, it.classfile) }
return symbol.let { SymbolBasedClass(it, this@JavacWrapper, classId, it.classfile) }
.apply { symbolBasedClassesCache[classId] = this }
}
}
@@ -19,9 +19,12 @@ package org.jetbrains.kotlin.javac
import org.jetbrains.kotlin.load.java.structure.JavaField
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtFile
interface JavacWrapperKotlinResolver {
fun resolveSupertypes(classOrObject: KtClassOrObject): List<ClassId>
fun findField(classOrObject: KtClassOrObject, name: String): JavaField?
fun findField(ktFile: KtFile?, name: String): JavaField?
}
@@ -238,7 +238,7 @@ private class CurrentClassAndInnerScope(javac: JavacWrapper,
override fun findClass(name: String, pathSegments: List<String>): JavaClassifier? {
val identifier = Name.identifier(name)
treePath.enclosingClasses.forEach {
treePath.enclosingClasses().forEach {
(it as? TreeBasedClass)?.typeParameters
?.find { typeParameter -> typeParameter.name == identifier }
?.let { typeParameter -> return typeParameter }
@@ -251,31 +251,30 @@ private class CurrentClassAndInnerScope(javac: JavacWrapper,
return parent.findClass(name, pathSegments)
}
private val TreePath.enclosingClasses: List<JavaClass>
get() {
val outerClasses = filterIsInstance<JCTree.JCClassDecl>()
.dropWhile { it.extending == leaf || leaf in it.implementing }
.asReversed()
.map { it.simpleName.toString() }
private fun TreePath.enclosingClasses(): List<JavaClass> {
val outerClasses = filterIsInstance<JCTree.JCClassDecl>()
.dropWhile { it.extending == leaf || leaf in it.implementing }
.asReversed()
.map { it.simpleName.toString() }
val packageName = compilationUnit.packageName?.toString() ?: ""
val outermostClassName = outerClasses.firstOrNull() ?: return emptyList()
val packageName = compilationUnit.packageName?.toString() ?: ""
val outermostClassName = outerClasses.firstOrNull() ?: return emptyList()
val outermostClassId = classId(packageName, outermostClassName)
var outermostClass = javac.findClass(outermostClassId) ?: return emptyList()
val outermostClassId = classId(packageName, outermostClassName)
var outermostClass = javac.findClass(outermostClassId) ?: return emptyList()
val classes = arrayListOf<JavaClass>()
val classes = arrayListOf<JavaClass>()
classes.add(outermostClass)
for (it in outerClasses.drop(1)) {
outermostClass = outermostClass.findInnerClass(Name.identifier(it))
?: throw AssertionError("Couldn't find a class ($it) that is surely defined in ${outermostClass.fqName?.asString()}")
classes.add(outermostClass)
for (it in outerClasses.drop(1)) {
outermostClass = outermostClass.findInnerClass(Name.identifier(it))
?: throw AssertionError("Couldn't find a class ($it) that is surely defined in ${outermostClass.fqName?.asString()}")
classes.add(outermostClass)
}
return classes.reversed()
}
return classes.reversed()
}
}
fun classId(packageName: String = "", className: String) = ClassId(FqName(packageName), Name.identifier(className))
@@ -0,0 +1,286 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* 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 org.jetbrains.kotlin.javac.resolve
import com.sun.source.util.TreePath
import com.sun.tools.javac.code.TypeTag
import com.sun.tools.javac.tree.JCTree
import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.load.java.structure.JavaClass
import kotlin.experimental.inv
class ConstantEvaluator(private val containingClass: JavaClass,
private val javac: JavacWrapper,
private val treePath: TreePath) {
fun getValue(expr: JCTree.JCExpression): Any? {
return when (expr) {
is JCTree.JCLiteral -> {
if (expr.typetag == TypeTag.BOOLEAN) {
expr.value != 0
}
else expr.value
}
is JCTree.JCIdent,
is JCTree.JCFieldAccess -> javac.resolveField(javac.getTreePath(expr, treePath.compilationUnit), containingClass)?.initializerValue
is JCTree.JCBinary -> binaryInitializerValue(expr)
is JCTree.JCParens -> getValue(expr.expr)
is JCTree.JCUnary -> unaryInitializerValue(expr)
else -> null
}
}
private fun unaryInitializerValue(value: JCTree.JCUnary): Any? {
val argValue = getValue(value.arg)
return when (value.tag) {
JCTree.Tag.COMPL -> {
when (argValue) {
is Int -> argValue.inv()
is Long -> argValue.inv()
is Short -> argValue.inv()
is Byte -> argValue.inv()
else -> null
}
}
JCTree.Tag.NOT -> (argValue as? Boolean)?.let { !it }
else -> null
}
}
private fun binaryInitializerValue(value: JCTree.JCBinary): Any? {
val lhsValue = getValue(value.lhs) ?: return null
val rhsValue = getValue(value.rhs) ?: return null
return evaluateValue(lhsValue, rhsValue, value.tag)
}
private fun evaluateValue(lhsValue: Any?, rhsValue: Any?, opcode: JCTree.Tag): Any? {
if (lhsValue is String && opcode == JCTree.Tag.PLUS) return lhsValue + rhsValue
else if (lhsValue is Boolean && rhsValue is Boolean) {
return when (opcode) {
JCTree.Tag.AND -> lhsValue && rhsValue
JCTree.Tag.OR -> lhsValue || rhsValue
JCTree.Tag.EQ -> lhsValue == rhsValue
JCTree.Tag.NE -> lhsValue != rhsValue
JCTree.Tag.BITXOR -> lhsValue xor rhsValue
JCTree.Tag.BITAND -> lhsValue and rhsValue
JCTree.Tag.BITOR -> lhsValue or rhsValue
else -> null
}
}
else if (lhsValue is Number && rhsValue is Number) {
val isInteger = !(lhsValue is Float || lhsValue is Double || rhsValue is Float || rhsValue is Double)
val isWide = if (isInteger) {
lhsValue is Long || rhsValue is Long
}
else {
lhsValue is Double || rhsValue is Double
}
return when (opcode) {
JCTree.Tag.PLUS -> {
if (isInteger) {
if (isWide) {
lhsValue.toLong() + rhsValue.toLong()
}
else {
lhsValue.toInt() + rhsValue.toInt()
}
}
else {
if (isWide) {
lhsValue.toDouble() + rhsValue.toDouble()
}
else {
lhsValue.toFloat() + rhsValue.toFloat()
}
}
}
JCTree.Tag.MINUS -> {
if (isInteger) {
if (isWide) {
lhsValue.toLong() - rhsValue.toLong()
}
else {
lhsValue.toInt() - rhsValue.toInt()
}
}
else {
if (isWide) {
lhsValue.toDouble() - rhsValue.toDouble()
}
else {
lhsValue.toFloat() - rhsValue.toFloat()
}
}
}
JCTree.Tag.MUL -> {
if (isInteger) {
if (isWide) {
lhsValue.toLong() * rhsValue.toLong()
}
else {
lhsValue.toInt() * rhsValue.toInt()
}
}
else {
if (isWide) {
lhsValue.toDouble() * rhsValue.toDouble()
}
else {
lhsValue.toFloat() * rhsValue.toFloat()
}
}
}
JCTree.Tag.DIV -> {
if (isInteger) {
if (isWide) {
lhsValue.toLong() / rhsValue.toLong()
}
else {
lhsValue.toInt() / rhsValue.toInt()
}
}
else {
if (isWide) {
lhsValue.toDouble() / rhsValue.toDouble()
}
else {
lhsValue.toFloat() / rhsValue.toFloat()
}
}
}
JCTree.Tag.MOD -> {
if (isInteger) {
if (isWide) {
lhsValue.toLong() % rhsValue.toLong()
}
else {
lhsValue.toInt() % rhsValue.toInt()
}
}
else {
if (isWide) {
lhsValue.toDouble() % rhsValue.toDouble()
}
else {
lhsValue.toFloat() % rhsValue.toFloat()
}
}
}
JCTree.Tag.SR -> {
if (isWide) {
lhsValue.toLong() shr rhsValue.toInt()
}
else {
lhsValue.toInt() shr rhsValue.toInt()
}
}
JCTree.Tag.SL -> {
if (isWide) {
lhsValue.toLong() shl rhsValue.toInt()
}
else {
lhsValue.toInt() shl rhsValue.toInt()
}
}
JCTree.Tag.BITAND -> {
if (isWide) {
lhsValue.toLong() and rhsValue.toLong()
}
else {
lhsValue.toInt() and rhsValue.toInt()
}
}
JCTree.Tag.BITOR -> {
if (isWide) {
lhsValue.toLong() or rhsValue.toLong()
}
else {
lhsValue.toInt() or rhsValue.toInt()
}
}
JCTree.Tag.BITXOR -> {
if (isWide) {
lhsValue.toLong() xor rhsValue.toLong()
}
else {
lhsValue.toInt() xor rhsValue.toInt()
}
}
JCTree.Tag.USR -> {
if (isWide) {
lhsValue.toLong() ushr rhsValue.toInt()
}
else {
lhsValue.toInt() ushr rhsValue.toInt()
}
}
JCTree.Tag.EQ -> {
if (isInteger) {
lhsValue.toLong() == rhsValue.toLong()
}
else {
lhsValue.toDouble() == rhsValue.toDouble()
}
}
JCTree.Tag.NE -> {
if (isInteger) {
lhsValue.toLong() != rhsValue.toLong()
}
else {
lhsValue.toDouble() != rhsValue.toDouble()
}
}
JCTree.Tag.LT -> {
if (isInteger) {
lhsValue.toLong() < rhsValue.toLong()
}
else {
lhsValue.toDouble() < rhsValue.toDouble()
}
}
JCTree.Tag.LE -> {
if (isInteger) {
lhsValue.toLong() <= rhsValue.toLong()
}
else {
lhsValue.toDouble() <= rhsValue.toDouble()
}
}
JCTree.Tag.GT -> {
if (isInteger) {
lhsValue.toLong() > rhsValue.toLong()
}
else {
lhsValue.toDouble() > rhsValue.toDouble()
}
}
JCTree.Tag.GE -> {
if (isInteger) {
lhsValue.toLong() >= rhsValue.toLong()
}
else {
lhsValue.toDouble() >= rhsValue.toDouble()
}
}
else -> null
}
}
else return null
}
}
@@ -65,7 +65,12 @@ private abstract class FieldScope(protected val javac: JavacWrapper,
.mapNotNull {
val classifier = it.classifier as? JavaClass
if (classifier !in checkedSupertypes) {
classifier?.findFieldIncludingSupertypes(name, checkedSupertypes)
if (classifier is MockKotlinClassifier) {
classifier.findField(name.asString())
}
else {
classifier?.findFieldIncludingSupertypes(name, checkedSupertypes)
}
}
else null
}.singleOrNull()
@@ -22,6 +22,8 @@ import com.intellij.psi.PsiLiteralExpression
import com.intellij.psi.search.SearchScope
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
import org.jetbrains.kotlin.javac.JavaClassWithClassId
import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.load.java.JavaVisibilities
@@ -29,7 +31,6 @@ import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
import org.jetbrains.kotlin.load.java.structure.impl.VirtualFileBoundJavaClass
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType
@@ -38,9 +39,12 @@ class KotlinClassifiersCache(sourceFiles: Collection<KtFile>,
private val javac: JavacWrapper) {
private val kotlinPackages = hashSetOf<FqName>()
private val kotlinFacadeClasses = hashMapOf<ClassId, KtFile>()
private val kotlinClasses: Map<ClassId?, KtClassOrObject?> =
sourceFiles.flatMap { ktFile ->
kotlinPackages.add(ktFile.packageFqName)
val facadeFqName = ktFile.javaFileFacadeFqName
kotlinFacadeClasses[ClassId(facadeFqName.parent(), facadeFqName.shortName())] = ktFile
ktFile.declarations
.filterIsInstance<KtClassOrObject>()
.map { it.computeClassId() to it }
@@ -50,9 +54,11 @@ class KotlinClassifiersCache(sourceFiles: Collection<KtFile>,
fun getKotlinClassifier(classId: ClassId) = classifiers[classId] ?: createClassifier(classId)
fun createMockKotlinClassifier(classifier: KtClassOrObject,
fun createMockKotlinClassifier(classifier: KtClassOrObject?,
ktFile: KtFile?,
classId: ClassId) = MockKotlinClassifier(classId,
classifier,
ktFile,
this,
javac)
.apply { classifiers[classId] = this }
@@ -60,11 +66,14 @@ class KotlinClassifiersCache(sourceFiles: Collection<KtFile>,
fun hasPackage(packageFqName: FqName) = kotlinPackages.contains(packageFqName)
private fun createClassifier(classId: ClassId): JavaClass? {
kotlinFacadeClasses[classId]?.let {
return createMockKotlinClassifier(null, it, classId)
}
if (classId.isNestedClass) {
classifiers[classId]?.let { return it }
val pathSegments = classId.relativeClassName.pathSegments().map { it.asString() }
val outerClassId = ClassId(classId.packageFqName, Name.identifier(pathSegments.first()))
var outerClass: JavaClass = kotlinClasses[outerClassId]?.let { createMockKotlinClassifier(it, outerClassId) } ?: return null
var outerClass: JavaClass = kotlinClasses[outerClassId]?.let { createMockKotlinClassifier(it, null, outerClassId) } ?: return null
pathSegments.drop(1).forEach {
outerClass = outerClass.findInnerClass(Name.identifier(it)) ?: return null
@@ -75,21 +84,25 @@ class KotlinClassifiersCache(sourceFiles: Collection<KtFile>,
val kotlinClassifier = kotlinClasses[classId] ?: return null
return createMockKotlinClassifier(kotlinClassifier, classId)
return createMockKotlinClassifier(kotlinClassifier, null, classId)
}
}
class MockKotlinClassifier(val classId: ClassId,
private val classOrObject: KtClassOrObject,
class MockKotlinClassifier(override val classId: ClassId,
private val classOrObject: KtClassOrObject?,
private val ktFile: KtFile?,
private val cache: KotlinClassifiersCache,
private val javac: JavacWrapper) : VirtualFileBoundJavaClass {
private val javac: JavacWrapper) : JavaClassWithClassId {
override val fqName: FqName
get() = classId.asSingleFqName()
override val visibility: Visibility
get() = when (classOrObject.visibilityModifierType()) {
get() = if (classOrObject == null) {
Visibilities.PUBLIC
}
else when (classOrObject.visibilityModifierType()) {
null, KtTokens.PUBLIC_KEYWORD -> Visibilities.PUBLIC
KtTokens.PRIVATE_KEYWORD -> Visibilities.PRIVATE
KtTokens.PROTECTED_KEYWORD -> Visibilities.PROTECTED
@@ -97,17 +110,19 @@ class MockKotlinClassifier(val classId: ClassId,
}
override val supertypes: Collection<JavaClassifierType>
get() = javac.kotlinResolver.resolveSupertypes(classOrObject)
get() = if (classOrObject == null) {
emptyList()
}
else javac.kotlinResolver.resolveSupertypes(classOrObject)
.mapNotNull { javac.getKotlinClassifier(it) ?: javac.findClass(it) }
.map { MockKotlinClassifierType(it) }
val innerClasses: Collection<JavaClass>
get() = classOrObject.declarations.filterIsInstance<KtClassOrObject>()
.mapNotNull { nestedClassOrObject ->
nestedClassOrObject.computeClassId()?.let {
cache.createMockKotlinClassifier(nestedClassOrObject, it)
}
}
get() = classOrObject?.declarations
?.filterIsInstance<KtClassOrObject>()
?.mapNotNull { nestedClassOrObject ->
cache.createMockKotlinClassifier(nestedClassOrObject, ktFile, classId.createNestedClassId(nestedClassOrObject.nameAsSafeName))
} ?: emptyList()
override val lightClassOriginKind
get() = LightClassOriginKind.SOURCE
@@ -127,12 +142,12 @@ class MockKotlinClassifier(val classId: ClassId,
innerClasses.find { it.name == name }
val typeParametersNumber: Int
get() = classOrObject.typeParameters.size
get() = classOrObject?.typeParameters?.size ?: 0
val hasTypeParameters: Boolean
get() = typeParametersNumber > 0
fun findField(name: String) = javac.kotlinResolver.findField(classOrObject, name)
fun findField(name: String) = classOrObject?.let { javac.kotlinResolver.findField(it, name) } ?: javac.kotlinResolver.findField(ktFile, name)
override val isAbstract: Boolean
get() = throw UnsupportedOperationException("Should not be called")
@@ -18,8 +18,8 @@ package org.jetbrains.kotlin.javac.resolve
import com.sun.source.util.TreePath
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.javac.JavaClassWithClassId
import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.javac.wrappers.trees.computeClassId
import org.jetbrains.kotlin.load.java.JavaVisibilities
import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.name.ClassId
@@ -82,7 +82,7 @@ internal class ResolveHelper(private val javac: JavacWrapper,
when (innerOrNestedClass.visibility) {
Visibilities.PRIVATE -> null
JavaVisibilities.PACKAGE_VISIBILITY -> {
val classId = (innerOrNestedClass as? MockKotlinClassifier)?.classId ?: innerOrNestedClass.computeClassId()
val classId = (innerOrNestedClass as? JavaClassWithClassId)?.classId
if (classId?.packageFqName?.asString() == (treePath.compilationUnit.packageName?.toString() ?: "")) innerOrNestedClass else null
}
else -> innerOrNestedClass
@@ -36,11 +36,9 @@ open class SymbolBasedAnnotation(
SymbolBasedAnnotationArgument.create(value.value, Name.identifier(key.simpleName.toString()), javac)
}
override val classId: ClassId?
get() = (annotationMirror.annotationType.asElement() as? TypeElement)?.computeClassId()
override val classId: ClassId
get() = (annotationMirror.annotationType.asElement() as TypeElement).computeClassId()!!
override fun resolve() = with(annotationMirror.annotationType.asElement() as Symbol.ClassSymbol) {
SymbolBasedClass(this, javac, classfile)
}
override fun resolve() = with(annotationMirror.annotationType.asElement() as Symbol.ClassSymbol) { javac.findClass(classId) }
}
@@ -20,9 +20,10 @@ import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.CommonClassNames
import com.intellij.psi.search.SearchScope
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.javac.JavaClassWithClassId
import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.load.java.structure.impl.VirtualFileBoundJavaClass
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import javax.lang.model.element.ElementKind
@@ -37,8 +38,9 @@ import javax.tools.JavaFileObject
class SymbolBasedClass(
element: TypeElement,
javac: JavacWrapper,
override val classId: ClassId?,
val file: JavaFileObject?
) : SymbolBasedClassifier<TypeElement>(element, javac), VirtualFileBoundJavaClass {
) : SymbolBasedClassifier<TypeElement>(element, javac), JavaClassWithClassId {
override val name: Name
get() = Name.identifier(element.simpleName.toString())
@@ -62,28 +64,34 @@ class SymbolBasedClass(
get() = FqName(element.qualifiedName.toString())
override val supertypes: Collection<JavaClassifierType>
get() = arrayListOf<TypeMirror>()
.apply {
element.superclass.takeIf { it !is NoType }?.let(this::add)
}
.apply { addAll(element.interfaces) }
.mapTo(arrayListOf()) { SymbolBasedClassifierType(it, javac) }
.apply {
if (isEmpty() && element.qualifiedName.toString() != CommonClassNames.JAVA_LANG_OBJECT) {
javac.JAVA_LANG_OBJECT?.let { add(it) }
}
}
by lazy {
arrayListOf<TypeMirror>()
.apply {
element.superclass.takeIf { it !is NoType }?.let(this::add)
addAll(element.interfaces)
}
.mapTo(arrayListOf()) { SymbolBasedClassifierType(it, javac) }
.apply {
if (isEmpty() && element.qualifiedName.toString() != CommonClassNames.JAVA_LANG_OBJECT) {
javac.JAVA_LANG_OBJECT?.let { add(it) }
}
}
}
val innerClasses: Map<Name, JavaClass>
get() = element.enclosedElements
.filterIsInstance(TypeElement::class.java)
.map { SymbolBasedClass(it, javac, file) }
.associateBy(JavaClass::name)
by lazy {
element.enclosedElements
.filterIsInstance(TypeElement::class.java)
.map { SymbolBasedClass(it, javac, classId?.createNestedClassId(Name.identifier(it.simpleName.toString())), file) }
.associateBy(JavaClass::name)
}
override val outerClass: JavaClass?
get() = element.enclosingElement?.let {
if (it.asType().kind != TypeKind.DECLARED) null else SymbolBasedClass(it as TypeElement, javac, file)
}
by lazy {
element.enclosingElement?.let {
if (it.asType().kind != TypeKind.DECLARED) null else SymbolBasedClass(it as TypeElement, javac, classId?.outerClassId, file)
}
}
override val isInterface: Boolean
get() = element.kind == ElementKind.INTERFACE
@@ -99,8 +107,8 @@ class SymbolBasedClass(
override val methods: Collection<JavaMethod>
get() = element.enclosedElements
.filter { it.kind == ElementKind.METHOD && !isEnumValuesOrValueOf(it as ExecutableElement)}
.map { SymbolBasedMethod(it as ExecutableElement, javac) }
.filter { it.kind == ElementKind.METHOD && !isEnumValuesOrValueOf(it as ExecutableElement) }
.map { SymbolBasedMethod(it as ExecutableElement, this, javac) }
private fun isEnumValuesOrValueOf(method: ExecutableElement): Boolean {
return isEnum && when (method.simpleName.toString()) {
@@ -113,12 +121,12 @@ class SymbolBasedClass(
override val fields: Collection<JavaField>
get() = element.enclosedElements
.filter { it.kind.isField && Name.isValidIdentifier(it.simpleName.toString()) }
.map { SymbolBasedField(it as VariableElement, javac) }
.map { SymbolBasedField(it as VariableElement, this, javac) }
override val constructors: Collection<JavaConstructor>
get() = element.enclosedElements
.filter { it.kind == ElementKind.CONSTRUCTOR }
.map { SymbolBasedConstructor(it as ExecutableElement, javac) }
.map { SymbolBasedConstructor(it as ExecutableElement, this, javac) }
override val innerClassNames: Collection<Name>
get() = innerClasses.keys
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.javac.wrappers.symbols
import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.load.java.structure.JavaConstructor
import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter
import org.jetbrains.kotlin.load.java.structure.JavaValueParameter
@@ -24,8 +25,9 @@ import javax.lang.model.element.ExecutableElement
class SymbolBasedConstructor(
element: ExecutableElement,
containingClass: JavaClass,
javac: JavacWrapper
) : SymbolBasedMember<ExecutableElement>(element, javac), JavaConstructor {
) : SymbolBasedMember<ExecutableElement>(element, containingClass, javac), JavaConstructor {
override val typeParameters: List<JavaTypeParameter>
get() = element.typeParameters.map { SymbolBasedTypeParameter(it, javac) }
@@ -17,17 +17,17 @@
package org.jetbrains.kotlin.javac.wrappers.symbols
import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.load.java.structure.JavaField
import org.jetbrains.kotlin.load.java.structure.JavaType
import javax.lang.model.element.ElementKind
import javax.lang.model.element.TypeElement
import javax.lang.model.element.VariableElement
import javax.lang.model.type.DeclaredType
class SymbolBasedField(
element: VariableElement,
containingClass: JavaClass,
javac: JavacWrapper
) : SymbolBasedMember<VariableElement>(element, javac), JavaField {
) : SymbolBasedMember<VariableElement>(element, containingClass, javac), JavaField {
override val isEnumEntry: Boolean
get() = element.kind == ElementKind.ENUM_CONSTANT
@@ -36,12 +36,9 @@ class SymbolBasedField(
get() = SymbolBasedType.create(element.asType(), javac)
override val initializerValue: Any?
get() = element.constantValue
by lazy { element.constantValue }
override val hasConstantNotNullInitializer: Boolean
get() = element.constantValue != null && element.asType().let {
it.kind.isPrimitive ||
((it as? DeclaredType)?.asElement() as? TypeElement)?.qualifiedName?.toString() == "java.lang.String"
}
get() = initializerValue != null
}
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.javac.wrappers.symbols
import com.sun.tools.javac.code.Symbol
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
@@ -28,14 +27,10 @@ import javax.lang.model.element.Element
abstract class SymbolBasedMember<out T : Element>(
element: T,
override val containingClass: JavaClass,
javac: JavacWrapper
) : SymbolBasedElement<T>(element, javac), JavaMember {
override val containingClass: JavaClass
get() = with(element.enclosingElement as Symbol.ClassSymbol) {
SymbolBasedClass(this, javac, classfile)
}
override val annotations: Collection<JavaAnnotation>
get() = element.annotationMirrors.map { SymbolBasedAnnotation(it, javac) }
@@ -22,8 +22,9 @@ import javax.lang.model.element.ExecutableElement
class SymbolBasedMethod(
element: ExecutableElement,
containingClass: JavaClass,
javac: JavacWrapper
) : SymbolBasedMember<ExecutableElement>(element, javac), JavaMethod {
) : SymbolBasedMember<ExecutableElement>(element, containingClass, javac), JavaMethod {
override val typeParameters: List<JavaTypeParameter>
get() = element.typeParameters.map { SymbolBasedTypeParameter(it, javac) }
@@ -34,7 +34,7 @@ class SymbolBasedPackage(
get() = FqName(element.qualifiedName.toString())
override val subPackages: Collection<JavaPackage>
get() = javac.findSubPackages(FqName(element.qualifiedName.toString()))
get() = javac.findSubPackages(fqName)
override val annotations: Collection<JavaAnnotation>
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.javac.wrappers.symbols
import com.sun.tools.javac.code.Symbol
import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.name.Name
@@ -26,7 +27,7 @@ import javax.lang.model.type.TypeMirror
sealed class SymbolBasedAnnotationArgument(
override val name: Name,
val javac: JavacWrapper
protected val javac: JavacWrapper
) : JavaAnnotationArgument, JavaElement {
companion object {
@@ -40,7 +41,7 @@ sealed class SymbolBasedAnnotationArgument(
}
private fun arrayAnnotationArguments(values: Collection<*>, name: Name, javac: JavacWrapper): JavaArrayAnnotationArgument =
values.map { if (it is Collection<*>) arrayAnnotationArguments(it, name, javac) else create(it!!, name, javac) }
values.map { create(it!!, name, javac) }
.let { argumentList -> SymbolBasedArrayAnnotationArgument(argumentList, name, javac) }
}
@@ -48,7 +49,7 @@ sealed class SymbolBasedAnnotationArgument(
}
class SymbolBasedAnnotationAsAnnotationArgument(
val mirror: AnnotationMirror,
private val mirror: AnnotationMirror,
name: Name,
javac: JavacWrapper
) : SymbolBasedAnnotationArgument(name, javac), JavaAnnotationAsAnnotationArgument {
@@ -65,12 +66,17 @@ class SymbolBasedReferenceAnnotationArgument(
override val entryName: Name?
get() = Name.identifier(name)
override fun resolve() = SymbolBasedField(element, javac)
override fun resolve(): SymbolBasedField {
val containingClass = (element.enclosingElement as Symbol.ClassSymbol).let {
SymbolBasedClass(it, javac, null, it.classfile)
}
return SymbolBasedField(element, containingClass, javac)
}
}
class SymbolBasedClassObjectAnnotationArgument(
val type: TypeMirror,
private val type: TypeMirror,
name : Name,
javac: JavacWrapper
) : SymbolBasedAnnotationArgument(name, javac), JavaClassObjectAnnotationArgument {
@@ -73,12 +73,17 @@ class SymbolBasedClassifierType<out T : TypeMirror>(
) : SymbolBasedType<T>(typeMirror, javac), JavaClassifierType {
override val classifier: JavaClassifier?
get() = when (typeMirror.kind) {
TypeKind.DECLARED -> ((typeMirror as DeclaredType).asElement() as Symbol.ClassSymbol).let { symbol ->
SymbolBasedClass(symbol, javac, symbol.classfile)
by lazy {
when (typeMirror.kind) {
TypeKind.DECLARED -> ((typeMirror as DeclaredType).asElement() as Symbol.ClassSymbol).let { symbol ->
// try to find cached javaClass
val classId = symbol.computeClassId()
classId?.let { javac.findClass(it) }
?: SymbolBasedClass(symbol, javac, classId, symbol.classfile)
}
TypeKind.TYPEVAR -> SymbolBasedTypeParameter((typeMirror as TypeVariable).asElement() as TypeParameterElement, javac)
else -> null
}
TypeKind.TYPEVAR -> SymbolBasedTypeParameter((typeMirror as TypeVariable).asElement() as TypeParameterElement, javac)
else -> null
}
override val typeArguments: List<JavaType>
@@ -36,21 +36,24 @@ internal val Element.isStatic: Boolean
internal val Element.isFinal: Boolean
get() = modifiers.contains(Modifier.FINAL)
internal fun Element.getVisibility(): Visibility = when {
Modifier.PUBLIC in modifiers -> Visibilities.PUBLIC
Modifier.PRIVATE in modifiers -> Visibilities.PRIVATE
Modifier.PROTECTED in modifiers -> {
if (Modifier.STATIC in modifiers) {
JavaVisibilities.PROTECTED_STATIC_VISIBILITY
}
else {
JavaVisibilities.PROTECTED_AND_PACKAGE
internal fun Element.getVisibility(): Visibility = modifiers.let { modifiers ->
when {
Modifier.PUBLIC in modifiers -> Visibilities.PUBLIC
Modifier.PRIVATE in modifiers -> Visibilities.PRIVATE
Modifier.PROTECTED in modifiers -> {
if (Modifier.STATIC in modifiers) {
JavaVisibilities.PROTECTED_STATIC_VISIBILITY
}
else {
JavaVisibilities.PROTECTED_AND_PACKAGE
}
}
else -> JavaVisibilities.PACKAGE_VISIBILITY
}
else -> JavaVisibilities.PACKAGE_VISIBILITY
}
internal fun TypeElement.computeClassId(): ClassId? {
val enclosingElement = enclosingElement
if (enclosingElement.kind != ElementKind.PACKAGE) {
val parentClassId = (enclosingElement as TypeElement).computeClassId() ?: return null
return parentClassId.createNestedClassId(Name.identifier(simpleName.toString()))
@@ -60,11 +63,16 @@ internal fun TypeElement.computeClassId(): ClassId? {
}
internal fun ExecutableElement.valueParameters(javac: JavacWrapper): List<JavaValueParameter> =
parameters.mapIndexed { index, parameter ->
SymbolBasedValueParameter(parameter,
if (!parameter.simpleName.contentEquals("arg$index")) parameter.simpleName.toString() else "p$index",
index == parameters.lastIndex && isVarArgs,
javac)
parameters.let { parameters ->
val isVarArgs = isVarArgs
val lastIndex = parameters.lastIndex
parameters.mapIndexed { index, parameter ->
val simpleName = parameter.simpleName.toString()
SymbolBasedValueParameter(parameter,
if (!simpleName.contentEquals("arg$index")) simpleName else "p$index",
index == lastIndex && isVarArgs,
javac)
}
}
internal fun AnnotatedConstruct.findAnnotation(fqName: FqName,
@@ -18,7 +18,9 @@ package org.jetbrains.kotlin.javac.wrappers.trees
import com.sun.source.util.TreePath
import com.sun.tools.javac.tree.JCTree
import org.jetbrains.kotlin.javac.JavaClassWithClassId
import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.javac.resolve.ConstantEvaluator
import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
@@ -34,7 +36,7 @@ class TreeBasedAnnotation(
get() = createAnnotationArguments(this, javac)
override val classId: ClassId?
get() = resolve()?.computeClassId() ?: ClassId.topLevel(FqName(annotation.annotationType.toString().substringAfter("@")))
get() = (resolve() as? JavaClassWithClassId)?.classId ?: ClassId.topLevel(FqName(annotation.annotationType.toString().substringAfter("@")))
override fun resolve() =
javac.resolve(TreePath.getPath(treePath.compilationUnit, annotation.annotationType)) as? JavaClass
@@ -130,11 +132,10 @@ private fun resolveArgumentValue(argument: JCTree.JCExpression,
name: Name,
treePath: TreePath,
javac: JavacWrapper): JavaAnnotationArgument? {
val containingAnnotation = annotation.resolve()
val type = containingAnnotation?.methods?.find { it.name == name }?.returnType ?: return null
val calculator = ValueCalculator(containingAnnotation, javac, treePath, type)
val containingAnnotation = annotation.resolve() ?: return null
val evaluator = ConstantEvaluator(containingAnnotation, javac, treePath)
return calculator.getValue(argument)?.let { TreeBasedLiteralAnnotationArgument(name, it, javac) }
return evaluator.getValue(argument)?.let { TreeBasedLiteralAnnotationArgument(name, it, javac) }
}
private fun arrayAnnotationArguments(values: List<JCTree.JCExpression>,
@@ -25,9 +25,10 @@ import com.sun.tools.javac.tree.JCTree
import com.sun.tools.javac.tree.TreeInfo
import org.jetbrains.kotlin.descriptors.Visibilities.PUBLIC
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.javac.JavaClassWithClassId
import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.load.java.structure.impl.VirtualFileBoundJavaClass
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import javax.tools.JavaFileObject
@@ -36,8 +37,9 @@ class TreeBasedClass(
tree: JCTree.JCClassDecl,
treePath: TreePath,
javac: JavacWrapper,
val file: JavaFileObject
) : TreeBasedElement<JCTree.JCClassDecl>(tree, treePath, javac), VirtualFileBoundJavaClass {
val file: JavaFileObject,
override val classId: ClassId?
) : TreeBasedElement<JCTree.JCClassDecl>(tree, treePath, javac), JavaClassWithClassId {
override val name: Name
get() = Name.identifier(tree.simpleName.toString())
@@ -70,45 +72,43 @@ class TreeBasedClass(
}
override val fqName: FqName
get() = treePath.reversed()
.filterIsInstance<JCTree.JCClassDecl>()
.joinToString(
separator = ".",
transform = JCTree.JCClassDecl::name
)
.let { treePath.compilationUnit.packageName?.let { packageName -> FqName("$packageName.$it") } ?: FqName.topLevel(Name.identifier(it))}
get() = classId?.asSingleFqName() ?: throw UnsupportedOperationException("classId of $name is null")
override val supertypes: Collection<JavaClassifierType>
get() = arrayListOf<JavaClassifierType>().also { list ->
if (isEnum) {
createEnumSupertype(this, javac).let { list.add(it) }
} else if (isAnnotationType) {
javac.JAVA_LANG_ANNOTATION_ANNOTATION?.let { list.add(it) }
}
by lazy {
arrayListOf<JavaClassifierType>().also { list ->
if (isEnum) {
createEnumSupertype(this, javac).let { list.add(it) }
}
else if (isAnnotationType) {
javac.JAVA_LANG_ANNOTATION_ANNOTATION?.let { list.add(it) }
}
tree.extending?.let {
(TreeBasedType.create(it, javac.getTreePath(it, treePath.compilationUnit), javac, emptyList()) as? JavaClassifierType)
?.let { list.add(it) }
}
tree.implementing?.mapNotNull {
TreeBasedType.create(it, javac.getTreePath(it, treePath.compilationUnit), javac, emptyList()) as? JavaClassifierType
}?.let { list.addAll(it) }
tree.extending?.let {
(TreeBasedType.create(it, javac.getTreePath(it, treePath.compilationUnit), javac, emptyList()) as? JavaClassifierType)
?.let { list.add(it) }
}
tree.implementing?.mapNotNull {
TreeBasedType.create(it, javac.getTreePath(it, treePath.compilationUnit), javac, emptyList()) as? JavaClassifierType
}?.let { list.addAll(it) }
if (list.isEmpty()) {
javac.JAVA_LANG_OBJECT?.let { list.add(it) }
if (list.isEmpty()) {
javac.JAVA_LANG_OBJECT?.let { list.add(it) }
}
}
}
}
val innerClasses: Map<Name, TreeBasedClass> by lazy {
tree.members
.filterIsInstance(JCTree.JCClassDecl::class.java)
.map { TreeBasedClass(it, TreePath(treePath, it), javac, file) }
.map { TreeBasedClass(it, TreePath(treePath, it), javac, file, classId?.createNestedClassId(Name.identifier(it.simpleName.toString()))) }
.associateBy(JavaClass::name)
}
override val outerClass: JavaClass? by lazy {
(treePath.parentPath.leaf as? JCTree.JCClassDecl)?.let { classDecl ->
TreeBasedClass(classDecl, treePath.parentPath, javac, file)
javac.findClass(classId!!.outerClassId!!)
?: TreeBasedClass(classDecl, treePath.parentPath, javac, file, classId.outerClassId)
}
}
@@ -156,7 +156,7 @@ class TreeBasedClass(
private fun createEnumSupertype(javaClass: JavaClass,
javac: JavacWrapper) = object : JavaClassifierType {
override val classifier: JavaClassifier?
override val classifier: JavaClass?
get() = javac.JAVA_LANG_ENUM
override val typeArguments: List<JavaType>
@@ -167,11 +167,12 @@ private fun createEnumSupertype(javaClass: JavaClass,
override val annotations: Collection<JavaAnnotation>
get() = emptyList()
override val classifierQualifiedName: String
get() = (classifier as? JavaClass)?.fqName?.asString() ?: ""
get() = classifier?.fqName?.asString() ?: ""
override val presentableText: String
get() = classifierQualifiedName
override val isDeprecatedInJavaDoc: Boolean
get() = false
override fun findAnnotation(fqName: FqName) = null
private inner class TypeArgument : JavaClassifierType {
@@ -189,6 +190,7 @@ private fun createEnumSupertype(javaClass: JavaClass,
get() = classifierQualifiedName
override val isDeprecatedInJavaDoc: Boolean
get() = false
override fun findAnnotation(fqName: FqName) = null
}
@@ -18,15 +18,13 @@ package org.jetbrains.kotlin.javac.wrappers.trees
import com.sun.source.util.TreePath
import com.sun.tools.javac.code.Flags
import com.sun.tools.javac.code.TypeTag
import com.sun.tools.javac.tree.JCTree
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.javac.resolve.ConstantEvaluator
import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.load.java.structure.JavaField
import org.jetbrains.kotlin.load.java.structure.JavaPrimitiveType
import org.jetbrains.kotlin.load.java.structure.JavaType
import org.jetbrains.kotlin.name.Name
@@ -60,7 +58,7 @@ class TreeBasedField(
override val initializerValue: Any?
get() = tree.init?.let { initExpr ->
if (hasConstantNotNullInitializer) ValueCalculator(containingClass, javac, treePath, type).getValue(initExpr) else null
if (hasConstantNotNullInitializer) ConstantEvaluator(containingClass, javac, treePath).getValue(initExpr) else null
}
override val hasConstantNotNullInitializer: Boolean
@@ -73,92 +71,4 @@ class TreeBasedField(
type.classifierQualifiedName == "java.lang.String"))
} ?: false
}
class ValueCalculator(private val containingClass: JavaClass,
private val javac: JavacWrapper,
private val treePath: TreePath,
private val type: JavaType) {
fun getValue(expr: JCTree.JCExpression): Any? {
return when (expr) {
is JCTree.JCLiteral -> {
if (expr.typetag == TypeTag.BOOLEAN) {
expr.value != 0
}
else expr.value
}
is JCTree.JCIdent,
is JCTree.JCFieldAccess -> javac.resolveField(javac.getTreePath(expr, treePath.compilationUnit), containingClass)?.initializerValue
is JCTree.JCBinary -> binaryInitializerValue(expr)
is JCTree.JCParens -> getValue(expr.expr)
is JCTree.JCUnary -> unaryInitializerValue(expr)
else -> null
}
}
private fun unaryInitializerValue(value: JCTree.JCUnary): Any? {
val argValue = getValue(value.arg)
return when (value.tag) {
JCTree.Tag.COMPL -> (argValue as? Int)?.inv()
JCTree.Tag.NOT -> (argValue as? Boolean)?.let { !it }
else -> null
}
}
private fun binaryInitializerValue(value: JCTree.JCBinary): Any? {
val lhsValue = getValue(value.lhs) ?: return null
val rhsValue = getValue(value.rhs) ?: return null
return calculateValue(lhsValue, rhsValue, value.tag)
}
private fun calculateValue(lhsValue: Any?, rhsValue: Any?, opcode: JCTree.Tag): Any? {
if (lhsValue is String && opcode == JCTree.Tag.PLUS) return lhsValue + rhsValue
if (lhsValue is Boolean && rhsValue is Boolean) {
return when (opcode) {
JCTree.Tag.AND -> lhsValue && rhsValue
JCTree.Tag.OR -> lhsValue || rhsValue
JCTree.Tag.EQ -> lhsValue == rhsValue
JCTree.Tag.NE -> lhsValue != rhsValue
else -> null
}
}
val l = (lhsValue as? Number)?.toInt() ?: return null
val r = (rhsValue as? Number)?.toInt() ?: return null
return when (opcode) {
JCTree.Tag.PLUS -> getExpressionType(l + r)
JCTree.Tag.MINUS -> getExpressionType(l - r)
JCTree.Tag.MUL -> getExpressionType(l * r)
JCTree.Tag.DIV -> getExpressionType(l / r)
JCTree.Tag.MOD -> getExpressionType(l % r)
JCTree.Tag.SR -> getExpressionType(l shr r)
JCTree.Tag.SL -> getExpressionType(l shl r)
JCTree.Tag.BITAND -> getExpressionType(l and r)
JCTree.Tag.BITOR -> getExpressionType(l or r)
JCTree.Tag.BITXOR -> getExpressionType(l xor r)
JCTree.Tag.USR -> getExpressionType(l ushr r)
JCTree.Tag.EQ -> l == r
JCTree.Tag.NE -> l != r
JCTree.Tag.LT -> l < r
JCTree.Tag.LE -> l <= r
JCTree.Tag.GT -> l > r
JCTree.Tag.GE -> l >= r
else -> null
}
}
private fun getExpressionType(expression: Int): Any? {
val type = type as? JavaPrimitiveType ?: return null
return when (type.type) {
PrimitiveType.DOUBLE -> expression.toDouble()
PrimitiveType.INT -> expression
PrimitiveType.FLOAT -> expression.toFloat()
PrimitiveType.LONG -> expression.toLong()
PrimitiveType.SHORT -> expression.toShort()
PrimitiveType.BYTE -> expression.toByte()
else -> null
}
}
}
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.javac.wrappers.trees
import com.sun.source.util.TreePath
import com.sun.tools.javac.tree.JCTree
import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.load.java.structure.JavaMember
import org.jetbrains.kotlin.name.FqName
@@ -34,11 +33,13 @@ abstract class TreeBasedMember<out T : JCTree>(
override val isDeprecatedInJavaDoc: Boolean
get() = javac.isDeprecatedInJavaDoc(treePath)
override val annotations: Collection<JavaAnnotation> by lazy {
override val annotations: Collection<TreeBasedAnnotation> by lazy {
tree.annotations().map { TreeBasedAnnotation(it, treePath, javac) }
}
override fun findAnnotation(fqName: FqName) =
annotations.find { it.classId?.asSingleFqName() == fqName }
annotations
.filter { it.annotation.annotationType.toString().endsWith(fqName.shortName().asString()) }
.find { it.classId?.asSingleFqName() == fqName }
}
@@ -20,7 +20,6 @@ import com.sun.source.util.TreePath
import com.sun.tools.javac.code.Flags
import com.sun.tools.javac.tree.JCTree
import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
import org.jetbrains.kotlin.load.java.structure.JavaType
import org.jetbrains.kotlin.load.java.structure.JavaValueParameter
import org.jetbrains.kotlin.name.FqName
@@ -32,12 +31,14 @@ class TreeBasedValueParameter(
javac: JavacWrapper
) : TreeBasedElement<JCTree.JCVariableDecl>(tree, treePath, javac), JavaValueParameter {
override val annotations: Collection<JavaAnnotation> by lazy {
override val annotations: Collection<TreeBasedAnnotation> by lazy {
tree.annotations().map { TreeBasedAnnotation(it, treePath, javac) }
}
override fun findAnnotation(fqName: FqName) =
annotations.find { it.classId?.asSingleFqName() == fqName }
annotations
.filter { it.annotation.annotationType.toString().endsWith(fqName.shortName().asString()) }
.find { it.classId?.asSingleFqName() == fqName }
override val isDeprecatedInJavaDoc: Boolean
get() = javac.isDeprecatedInJavaDoc(treePath)
@@ -31,25 +31,27 @@ abstract class TreeBasedType<out T : JCTree>(
val tree: T,
val treePath: TreePath,
val javac: JavacWrapper,
override val annotations: Collection<JavaAnnotation>
private val allAnnotations: Collection<JavaAnnotation>
) : JavaType, JavaAnnotationOwner {
override val annotations: Collection<JavaAnnotation>
get() = allAnnotations.filterTypeAnnotations()
companion object {
fun create(tree: JCTree, treePath: TreePath,
javac: JavacWrapper, annotations: Collection<JavaAnnotation>): JavaType {
val applicableAnnotations = annotations.filterTypeAnnotations()
return when (tree) {
is JCTree.JCPrimitiveTypeTree -> TreeBasedPrimitiveType(tree, javac.getTreePath(tree, treePath.compilationUnit), javac, applicableAnnotations)
is JCTree.JCArrayTypeTree -> TreeBasedArrayType(tree, javac.getTreePath(tree, treePath.compilationUnit), javac, applicableAnnotations)
is JCTree.JCWildcard -> TreeBasedWildcardType(tree, javac.getTreePath(tree, treePath.compilationUnit), javac, applicableAnnotations)
is JCTree.JCTypeApply -> TreeBasedGenericClassifierType(tree, javac.getTreePath(tree, treePath.compilationUnit), javac, applicableAnnotations)
is JCTree.JCPrimitiveTypeTree -> TreeBasedPrimitiveType(tree, javac.getTreePath(tree, treePath.compilationUnit), javac, annotations)
is JCTree.JCArrayTypeTree -> TreeBasedArrayType(tree, javac.getTreePath(tree, treePath.compilationUnit), javac, annotations)
is JCTree.JCWildcard -> TreeBasedWildcardType(tree, javac.getTreePath(tree, treePath.compilationUnit), javac, annotations)
is JCTree.JCTypeApply -> TreeBasedGenericClassifierType(tree, javac.getTreePath(tree, treePath.compilationUnit), javac, annotations)
is JCTree.JCAnnotatedType -> {
val underlyingType = tree.underlyingType
val newAnnotations = tree.annotations
.map { TreeBasedAnnotation(it, javac.getTreePath(it, treePath.compilationUnit), javac) }
create(underlyingType, javac.getTreePath(underlyingType, treePath.compilationUnit), javac, newAnnotations)
}
is JCTree.JCExpression -> TreeBasedNonGenericClassifierType(tree, javac.getTreePath(tree, treePath.compilationUnit), javac, applicableAnnotations)
is JCTree.JCExpression -> TreeBasedNonGenericClassifierType(tree, javac.getTreePath(tree, treePath.compilationUnit), javac, annotations)
else -> throw UnsupportedOperationException("Unsupported type: $tree")
}
}
@@ -72,8 +74,8 @@ class TreeBasedPrimitiveType(
tree: JCTree.JCPrimitiveTypeTree,
treePath: TreePath,
javac: JavacWrapper,
annotations: Collection<JavaAnnotation>
) : TreeBasedType<JCTree.JCPrimitiveTypeTree>(tree, treePath, javac, annotations), JavaPrimitiveType {
allAnnotations: Collection<JavaAnnotation>
) : TreeBasedType<JCTree.JCPrimitiveTypeTree>(tree, treePath, javac, allAnnotations), JavaPrimitiveType {
override val type: PrimitiveType?
get() = if (tree.primitiveTypeKind == TypeKind.VOID) {
@@ -89,8 +91,8 @@ class TreeBasedArrayType(
tree: JCTree.JCArrayTypeTree,
treePath: TreePath,
javac: JavacWrapper,
annotations: Collection<JavaAnnotation>
) : TreeBasedType<JCTree.JCArrayTypeTree>(tree, treePath, javac, annotations), JavaArrayType {
allAnnotations: Collection<JavaAnnotation>
) : TreeBasedType<JCTree.JCArrayTypeTree>(tree, treePath, javac, allAnnotations), JavaArrayType {
override val componentType: JavaType
get() = create(tree.elemtype, treePath, javac, annotations)
@@ -101,8 +103,8 @@ class TreeBasedWildcardType(
tree: JCTree.JCWildcard,
treePath: TreePath,
javac: JavacWrapper,
annotations: Collection<JavaAnnotation>
) : TreeBasedType<JCTree.JCWildcard>(tree, treePath, javac, annotations), JavaWildcardType {
allAnnotations: Collection<JavaAnnotation>
) : TreeBasedType<JCTree.JCWildcard>(tree, treePath, javac, allAnnotations), JavaWildcardType {
override val bound: JavaType?
get() = tree.bound?.let { create(it, treePath, javac, annotations) }
@@ -116,11 +118,11 @@ sealed class TreeBasedClassifierType<out T : JCTree>(
tree: T,
treePath: TreePath,
javac: JavacWrapper,
annotations: Collection<JavaAnnotation>
) : TreeBasedType<T>(tree, treePath, javac, annotations), JavaClassifierType {
allAnnotations: Collection<JavaAnnotation>
) : TreeBasedType<T>(tree, treePath, javac, allAnnotations), JavaClassifierType {
override val classifier: JavaClassifier?
get() = javac.resolve(treePath)
by lazy { javac.resolve(treePath) }
override val classifierQualifiedName: String
get() = (classifier as? JavaClass)?.fqName?.asString() ?: treePath.leaf.toString().substringBefore("<")
@@ -132,7 +134,7 @@ sealed class TreeBasedClassifierType<out T : JCTree>(
get() {
var tree: JCTree = tree
if (tree is JCTree.JCTypeApply) {
tree = tree.clazz
tree = tree.clazz
}
if (tree is JCTree.JCFieldAccess) {
val enclosingType = TreeBasedType.create(tree.selected, treePath, javac, annotations)
@@ -158,12 +160,12 @@ sealed class TreeBasedClassifierType<out T : JCTree>(
private val typeParameter: JCTree.JCTypeParameter?
get() = treePath.flatMap {
when (it) {
is JCTree.JCClassDecl -> it.typarams
is JCTree.JCMethodDecl -> it.typarams
else -> emptyList<JCTree.JCTypeParameter>()
}
}
when (it) {
is JCTree.JCClassDecl -> it.typarams
is JCTree.JCMethodDecl -> it.typarams
else -> emptyList<JCTree.JCTypeParameter>()
}
}
.find { it.toString().substringBefore(" ") == treePath.leaf.toString() }
}
@@ -213,13 +215,13 @@ class TreeBasedGenericClassifierType(
) : TreeBasedClassifierType<JCTree.JCTypeApply>(tree, treePath, javac, annotations) {
override val classifier: JavaClassifier?
get() {
val newTree = tree.clazz
return if (newTree is JCTree.JCAnnotatedType) {
javac.resolve(javac.getTreePath(newTree.underlyingType, treePath.compilationUnit))
by lazy {
val newTree = tree.clazz
if (newTree is JCTree.JCAnnotatedType) {
javac.resolve(javac.getTreePath(newTree.underlyingType, treePath.compilationUnit))
}
else super.classifier
}
else super.classifier
}
override val annotations: Collection<JavaAnnotation>
get() {
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.javac.wrappers.symbols.SymbolBasedField
import org.jetbrains.kotlin.javac.wrappers.symbols.SymbolBasedReferenceAnnotationArgument
import org.jetbrains.kotlin.load.java.JavaVisibilities
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
@@ -63,14 +62,12 @@ internal fun JCTree.annotations(): Collection<JCTree.JCAnnotation> = when (this)
else -> null
} ?: emptyList<JCTree.JCAnnotation>()
fun JavaClass.computeClassId(): ClassId? =
outerClass?.computeClassId()?.createNestedClassId(name) ?: fqName?.let { ClassId.topLevel(it) }
fun Collection<JavaAnnotation>.filterTypeAnnotations(): Collection<JavaAnnotation> {
val filteredAnnotations = arrayListOf<JavaAnnotation>()
val targetClassId = ClassId(FqName("java.lang.annotation"), Name.identifier("Target"))
for (annotation in this) {
val annotationClass = annotation.resolve()
val targetAnnotation = annotationClass?.annotations?.find { it.classId == ClassId(FqName("java.lang.annotation"), Name.identifier("Target")) } ?: continue
val targetAnnotation = annotationClass?.annotations?.find { it.classId == targetClassId } ?: continue
val elementTypeArg = targetAnnotation.arguments.firstOrNull() ?: continue
when (elementTypeArg) {
@@ -0,0 +1,24 @@
// FILE: a/x.java
package a;
public interface x {
double D = Double.MAX_VALUE;
double D2 = D - 32.12111;
float F = Float.MAX_VALUE;
float F2 = F - 1231.965f;
int I = Integer.MAX_VALUE;
int I2 = I - 42;
byte B = Byte.MAX_VALUE;
byte B2 = B - 3;
long L = Long.MAX_VALUE;
long L2 = L - 5545342;
short S = Short.MAX_VALUE;
short S2 = S - 5;
}
@@ -0,0 +1,24 @@
package
package a {
public interface x {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
public const final val B: kotlin.Byte = 127.toByte()
public const final val B2: kotlin.Byte = 124.toByte()
public const final val D: kotlin.Double = 1.7976931348623157E308.toDouble()
public const final val D2: kotlin.Double = 1.7976931348623157E308.toDouble()
public const final val F: kotlin.Float = 3.4028235E38.toFloat()
public const final val F2: kotlin.Float = 3.4028235E38.toFloat()
public const final val I: kotlin.Int = 2147483647
public const final val I2: kotlin.Int = 2147483605
public const final val L: kotlin.Long = 9223372036854775807.toLong()
public const final val L2: kotlin.Long = 9223372036849230465.toLong()
public const final val S: kotlin.Short = 32767.toShort()
public const final val S2: kotlin.Short = 32762.toShort()
}
}
@@ -0,0 +1,15 @@
// FILE: a/x.java
package a;
public class x {
public static class y {
public static final int I = 42;
}
}
// FILE: b/x.java
package b;
public class x {
public static final int I = a.x.y.I;
}
@@ -0,0 +1,34 @@
package
package a {
public open class x {
public constructor x()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public open class y {
public constructor y()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
public const final val I: kotlin.Int = 42
}
}
}
package b {
public open class x {
public constructor x()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
public const final val I: kotlin.Int = 42
}
}
@@ -0,0 +1,26 @@
// FILE: test.kt
package a
const val CONST = "CONST"
open class Test {
companion object {
const val CONST = 42
}
}
// FILE: a/x.java
package a;
public class x {
public static final String CONST1 = TestKt.CONST;
public static final int CONST2 = Test.CONST;
public class y extends Test {
public static final int I = CONST;
}
}
@@ -0,0 +1,41 @@
package
package a {
public const val CONST: kotlin.String = "CONST"
public open class Test {
public constructor Test()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public companion object Companion {
private constructor Companion()
public const final val CONST: kotlin.Int = 42
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
public open class x {
public constructor x()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public open inner class y : a.Test {
public constructor y()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
public const final val I: kotlin.Int = 42
}
// Static members
public const final val CONST1: kotlin.String = "CONST"
public const final val CONST2: kotlin.Int = 42
}
}
@@ -0,0 +1,27 @@
// FILE: a/X.java
package a;
public interface X {
int I = 42;
interface Y extends X {
int O = I;
class XY implements X, Y {
public static final int I = O + X.I;
public class XYZ extends XY implements Y {
int O = I;
}
}
}
class C {
public static final double Pi = 3.14;
interface I {
double Pi = 41.3;
class Z {
public static final double CONST = Pi;
}
}
}
}
@@ -0,0 +1,76 @@
package
package a {
public interface X {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public open class C {
public constructor C()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public/*package*/ interface I {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public open class Z {
public constructor Z()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
public const final val CONST: kotlin.Double = 41.3.toDouble()
}
// Static members
public const final val Pi: kotlin.Double = 41.3.toDouble()
}
// Static members
public const final val Pi: kotlin.Double = 3.14.toDouble()
}
public interface Y : a.X {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public open class XY : a.X, a.X.Y {
public constructor XY()
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
public open inner class XYZ : a.X.Y.XY, a.X.Y {
public constructor XYZ()
public/*package*/ final var O: kotlin.Int
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
public const final override /*1*/ /*fake_override*/ val I: kotlin.Int = 84
public const final override /*1*/ /*fake_override*/ val I: kotlin.Int = 42
public const final override /*2*/ /*fake_override*/ val O: kotlin.Int = 42
}
// Static members
public const final val I: kotlin.Int = 84
public const final override /*1*/ /*fake_override*/ val O: kotlin.Int = 42
}
// Static members
public const final override /*1*/ /*fake_override*/ val I: kotlin.Int = 42
public const final val O: kotlin.Int = 42
}
// Static members
public const final val I: kotlin.Int = 42
}
}
@@ -886,6 +886,12 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
doTest(fileName);
}
@TestMetadata("annotatedExpressionInsideAnnotation.kt")
public void testAnnotatedExpressionInsideAnnotation() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/annotatedExpressionInsideAnnotation.kt");
doTest(fileName);
}
@TestMetadata("AnnotatedLocalObjectFun.kt")
public void testAnnotatedLocalObjectFun() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/AnnotatedLocalObjectFun.kt");
@@ -44,12 +44,30 @@ public class JavacFieldResolutionTestGenerated extends AbstractJavacFieldResolut
doTest(fileName);
}
@TestMetadata("BinaryInitializers.kt")
public void testBinaryInitializers() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/javac/fieldsResolution/tests/BinaryInitializers.kt");
doTest(fileName);
}
@TestMetadata("ConstantByFqName.kt")
public void testConstantByFqName() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/javac/fieldsResolution/tests/ConstantByFqName.kt");
doTest(fileName);
}
@TestMetadata("ConstantValues.kt")
public void testConstantValues() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/javac/fieldsResolution/tests/ConstantValues.kt");
doTest(fileName);
}
@TestMetadata("ConstantValuesFromKtFile.kt")
public void testConstantValuesFromKtFile() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/javac/fieldsResolution/tests/ConstantValuesFromKtFile.kt");
doTest(fileName);
}
@TestMetadata("FieldFromOuterClass.kt")
public void testFieldFromOuterClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/javac/fieldsResolution/tests/FieldFromOuterClass.kt");
@@ -62,6 +80,12 @@ public class JavacFieldResolutionTestGenerated extends AbstractJavacFieldResolut
doTest(fileName);
}
@TestMetadata("MultipleOuters.kt")
public void testMultipleOuters() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/javac/fieldsResolution/tests/MultipleOuters.kt");
doTest(fileName);
}
@TestMetadata("ResolutionPriority.kt")
public void testResolutionPriority() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/javac/fieldsResolution/tests/ResolutionPriority.kt");
@@ -101,12 +125,30 @@ public class JavacFieldResolutionTestGenerated extends AbstractJavacFieldResolut
doTestWithoutJavacWrapper(fileName);
}
@TestMetadata("BinaryInitializers.kt")
public void testBinaryInitializers() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/javac/fieldsResolution/tests/BinaryInitializers.kt");
doTestWithoutJavacWrapper(fileName);
}
@TestMetadata("ConstantByFqName.kt")
public void testConstantByFqName() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/javac/fieldsResolution/tests/ConstantByFqName.kt");
doTestWithoutJavacWrapper(fileName);
}
@TestMetadata("ConstantValues.kt")
public void testConstantValues() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/javac/fieldsResolution/tests/ConstantValues.kt");
doTestWithoutJavacWrapper(fileName);
}
@TestMetadata("ConstantValuesFromKtFile.kt")
public void testConstantValuesFromKtFile() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/javac/fieldsResolution/tests/ConstantValuesFromKtFile.kt");
doTestWithoutJavacWrapper(fileName);
}
@TestMetadata("FieldFromOuterClass.kt")
public void testFieldFromOuterClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/javac/fieldsResolution/tests/FieldFromOuterClass.kt");
@@ -119,6 +161,12 @@ public class JavacFieldResolutionTestGenerated extends AbstractJavacFieldResolut
doTestWithoutJavacWrapper(fileName);
}
@TestMetadata("MultipleOuters.kt")
public void testMultipleOuters() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/javac/fieldsResolution/tests/MultipleOuters.kt");
doTestWithoutJavacWrapper(fileName);
}
@TestMetadata("ResolutionPriority.kt")
public void testResolutionPriority() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/javac/fieldsResolution/tests/ResolutionPriority.kt");