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) var useJavac: Boolean by FreezableVar(false)
@Argument(value = "-Xcompile-java", description = "Reuse javac analysis and compile Java source files") @Argument(value = "-Xcompile-java", description = "Reuse javac analysis and compile Java source files")
public boolean compileJava; var compileJava by FreezableVar(false)
@Argument( @Argument(
value = "-Xjavac-arguments", value = "-Xjavac-arguments",
@@ -253,7 +253,7 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
private fun compileJavaFilesIfNeeded(environment: KotlinCoreEnvironment, private fun compileJavaFilesIfNeeded(environment: KotlinCoreEnvironment,
arguments: K2JVMCompilerArguments): Boolean { arguments: K2JVMCompilerArguments): Boolean {
if (arguments.useJavac) { if (arguments.compileJava) {
return JavacWrapper.getInstance(environment.project).use { it.compile() } return JavacWrapper.getInstance(environment.project).use { it.compile() }
} }
return true return true
@@ -279,7 +279,7 @@ class KotlinCoreEnvironment private constructor(
bootClasspath: List<File>? = null, bootClasspath: List<File>? = null,
sourcePath: List<File>? = null sourcePath: List<File>? = null
): Boolean { ): 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 private val applicationEnvironment: CoreApplicationEnvironment
@@ -17,8 +17,9 @@
package org.jetbrains.kotlin.cli.jvm.javac package org.jetbrains.kotlin.cli.jvm.javac
import com.intellij.psi.PsiClass import com.intellij.psi.PsiClass
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
import org.jetbrains.kotlin.asJava.classes.KtLightClass 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.JavacWrapperKotlinResolver
import org.jetbrains.kotlin.javac.resolve.MockKotlinField import org.jetbrains.kotlin.javac.resolve.MockKotlinField
import org.jetbrains.kotlin.load.java.structure.JavaField 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.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtClassOrObject 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>() 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) 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? = private fun KtClassOrObject.getLightClass(): KtLightClass? =
cache[this] ?: lightClassGenerationSupport.getLightClass(this)?.also { cache[this] = it } 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.intellij.mock.MockProject
import com.sun.tools.javac.util.Context 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.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.STRONG_WARNING 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.cli.jvm.config.jvmClasspathRoots
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys import org.jetbrains.kotlin.config.JVMConfigurationKeys
@@ -40,7 +40,7 @@ object JavacWrapperRegistrar {
arguments: Array<String>?, arguments: Array<String>?,
bootClasspath: List<File>?, bootClasspath: List<File>?,
sourcePath: List<File>?, sourcePath: List<File>?,
lightClassGenerationSupport: CliLightClassGenerationSupport lightClassGenerationSupport: LightClassGenerationSupport
): Boolean { ): Boolean {
val messageCollector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) 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.StandardFileSystems
import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.psi.CommonClassNames
import com.intellij.psi.search.EverythingGlobalScope import com.intellij.psi.search.EverythingGlobalScope
import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.GlobalSearchScope
import com.sun.source.tree.CompilationUnitTree import com.sun.source.tree.CompilationUnitTree
@@ -80,21 +79,21 @@ class JavacWrapper(
fun getInstance(project: Project): JavacWrapper = ServiceManager.getService(project, JavacWrapper::class.java) fun getInstance(project: Project): JavacWrapper = ServiceManager.getService(project, JavacWrapper::class.java)
} }
private fun createCommonClassifierType(fqName: String) = private fun createCommonClassifierType(classId: ClassId) =
findClassInSymbols(fqName)?.let { findClassInSymbols(classId)?.let {
SymbolBasedClassifierType(it.element.asType(), this) SymbolBasedClassifierType(it.element.asType(), this)
} }
val JAVA_LANG_OBJECT by lazy { val JAVA_LANG_OBJECT by lazy {
createCommonClassifierType(CommonClassNames.JAVA_LANG_OBJECT) createCommonClassifierType(classId("java.lang", "Object"))
} }
val JAVA_LANG_ENUM by lazy { val JAVA_LANG_ENUM by lazy {
findClassInSymbols(CommonClassNames.JAVA_LANG_ENUM) findClassInSymbols(classId("java.lang", "Enum"))
} }
val JAVA_LANG_ANNOTATION_ANNOTATION by lazy { val JAVA_LANG_ANNOTATION_ANNOTATION by lazy {
createCommonClassifierType(CommonClassNames.JAVA_LANG_ANNOTATION_ANNOTATION) createCommonClassifierType(classId("java.lang.annotation", "Annotation"))
} }
init { init {
@@ -133,31 +132,15 @@ class JavacWrapper(
private val fileObjects = fileManager.getJavaFileObjectsFromFiles(javaFiles).toJavacList() private val fileObjects = fileManager.getJavaFileObjectsFromFiles(javaFiles).toJavacList()
private val compilationUnits: JavacList<JCTree.JCCompilationUnit> = fileObjects.map(javac::parse).toJavacList() private val compilationUnits: JavacList<JCTree.JCCompilationUnit> = fileObjects.map(javac::parse).toJavacList()
private val treeBasedJavaClasses = hashMapOf<ClassId, TreeBasedClass>() private val treeBasedJavaClasses = compilationUnits.flatMap { unit ->
private val javaClassDeclarations = compilationUnits.flatMap { unit ->
unit.typeDecls.map { classDeclaration -> unit.typeDecls.map { classDeclaration ->
val packageName = unit.packageName?.toString() ?: "" val packageName = unit.packageName?.toString() ?: ""
val className = (classDeclaration as JCTree.JCClassDecl).simpleName.toString() val className = (classDeclaration as JCTree.JCClassDecl).simpleName.toString()
val classId = classId(packageName, className) val classId = classId(packageName, className)
classId to Pair(classDeclaration, unit) classId to TreeBasedClass(classDeclaration, trees.getPath(unit, classDeclaration), this, unit.sourceFile, classId)
} }
}.toMap() }.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 private val javaPackages = compilationUnits
.mapTo(hashSetOf<TreeBasedPackage>()) { unit -> .mapTo(hashSetOf<TreeBasedPackage>()) { unit ->
unit.packageName?.toString()?.let { packageName -> unit.packageName?.toString()?.let { packageName ->
@@ -176,8 +159,9 @@ class JavacWrapper(
val classifierResolver = ClassifierResolver(this) val classifierResolver = ClassifierResolver(this)
private val identifierResolver = IdentifierResolver(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 symbolBasedPackagesCache = hashMapOf<String, SymbolBasedPackage?>()
private val symbolBasedClassesCache = hashMapOf<ClassId, SymbolBasedClass>()
fun compile(outDir: File? = null): Boolean = with(javac) { fun compile(outDir: File? = null): Boolean = with(javac) {
if (!compileJava) return true if (!compileJava) return true
@@ -211,12 +195,19 @@ class JavacWrapper(
return outerClass return outerClass
} }
getTreeBasedClass(classId)?.let { javaClass -> treeBasedJavaClasses[classId]?.let { javaClass ->
javaClass.virtualFile?.let { if (it in scope) return 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 { 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 -> javaClass.virtualFile?.let { file ->
if (file in scope) return javaClass if (file in scope) return javaClass
} }
@@ -249,20 +240,20 @@ class JavacWrapper(
packageSourceAnnotations[fqName] ?: emptyList() packageSourceAnnotations[fqName] ?: emptyList()
fun findClassesFromPackage(fqName: FqName): List<JavaClass> = fun findClassesFromPackage(fqName: FqName): List<JavaClass> =
javaClassDeclarations treeBasedJavaClasses
.filterKeys { it.packageFqName == fqName } .filterKeys { it.packageFqName == fqName }
.map { getTreeBasedClass(it.key)!! } + .map { treeBasedJavaClasses[it.key]!! } +
elements.getPackageElement(fqName.asString()) elements.getPackageElement(fqName.asString())
?.members() ?.members()
?.elements ?.elements
?.filterIsInstance(Symbol.ClassSymbol::class.java) ?.filterIsInstance(Symbol.ClassSymbol::class.java)
?.map { SymbolBasedClass(it, this, it.classfile) } ?.map { SymbolBasedClass(it, this, null, it.classfile) }
.orEmpty() .orEmpty()
fun knownClassNamesInPackage(fqName: FqName): Set<String> = fun knownClassNamesInPackage(fqName: FqName): Set<String> =
javaClassDeclarations treeBasedJavaClasses
.filterKeys { it.packageFqName == fqName } .filterKeys { it.packageFqName == fqName }
.mapTo(hashSetOf()) { it.key.shortClassName.asString() } + .mapTo(hashSetOf()) { it.value.name.asString() } +
elements.getPackageElement(fqName.asString()) elements.getPackageElement(fqName.asString())
?.members_field ?.members_field
?.elements ?.elements
@@ -309,9 +300,9 @@ class JavacWrapper(
private inline fun <reified T> Iterable<T>.toJavacList() = JavacList.from(this) private inline fun <reified T> Iterable<T>.toJavacList() = JavacList.from(this)
private fun findClassInSymbols(fqName: String): SymbolBasedClass? = private fun findClassInSymbols(classId: ClassId): SymbolBasedClass? =
elements.getTypeElement(fqName)?.let { symbol -> elements.getTypeElement(classId.asSingleFqName().asString())?.let { symbol ->
SymbolBasedClass(symbol, this, symbol.classfile) SymbolBasedClass(symbol, this, classId, symbol.classfile)
} }
private fun findPackageInSymbols(fqName: String): SymbolBasedPackage? { 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(".") val nameParts = name.replace("$", ".").split(".")
var symbol = members_field?.getElementsByName(names.fromString(nameParts.first())) var symbol = members_field?.getElementsByName(names.fromString(nameParts.first()))
?.firstOrNull() as? Symbol.ClassSymbol ?: return null ?.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.load.java.structure.JavaField
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtFile
interface JavacWrapperKotlinResolver { interface JavacWrapperKotlinResolver {
fun resolveSupertypes(classOrObject: KtClassOrObject): List<ClassId> fun resolveSupertypes(classOrObject: KtClassOrObject): List<ClassId>
fun findField(classOrObject: KtClassOrObject, name: String): JavaField? 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? { override fun findClass(name: String, pathSegments: List<String>): JavaClassifier? {
val identifier = Name.identifier(name) val identifier = Name.identifier(name)
treePath.enclosingClasses.forEach { treePath.enclosingClasses().forEach {
(it as? TreeBasedClass)?.typeParameters (it as? TreeBasedClass)?.typeParameters
?.find { typeParameter -> typeParameter.name == identifier } ?.find { typeParameter -> typeParameter.name == identifier }
?.let { typeParameter -> return typeParameter } ?.let { typeParameter -> return typeParameter }
@@ -251,31 +251,30 @@ private class CurrentClassAndInnerScope(javac: JavacWrapper,
return parent.findClass(name, pathSegments) return parent.findClass(name, pathSegments)
} }
private val TreePath.enclosingClasses: List<JavaClass> private fun TreePath.enclosingClasses(): List<JavaClass> {
get() { val outerClasses = filterIsInstance<JCTree.JCClassDecl>()
val outerClasses = filterIsInstance<JCTree.JCClassDecl>() .dropWhile { it.extending == leaf || leaf in it.implementing }
.dropWhile { it.extending == leaf || leaf in it.implementing } .asReversed()
.asReversed() .map { it.simpleName.toString() }
.map { it.simpleName.toString() }
val packageName = compilationUnit.packageName?.toString() ?: "" val packageName = compilationUnit.packageName?.toString() ?: ""
val outermostClassName = outerClasses.firstOrNull() ?: return emptyList() val outermostClassName = outerClasses.firstOrNull() ?: return emptyList()
val outermostClassId = classId(packageName, outermostClassName) val outermostClassId = classId(packageName, outermostClassName)
var outermostClass = javac.findClass(outermostClassId) ?: return emptyList() 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) 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)) 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 { .mapNotNull {
val classifier = it.classifier as? JavaClass val classifier = it.classifier as? JavaClass
if (classifier !in checkedSupertypes) { if (classifier !in checkedSupertypes) {
classifier?.findFieldIncludingSupertypes(name, checkedSupertypes) if (classifier is MockKotlinClassifier) {
classifier.findField(name.asString())
}
else {
classifier?.findFieldIncludingSupertypes(name, checkedSupertypes)
}
} }
else null else null
}.singleOrNull() }.singleOrNull()
@@ -22,6 +22,8 @@ import com.intellij.psi.PsiLiteralExpression
import com.intellij.psi.search.SearchScope import com.intellij.psi.search.SearchScope
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility 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.javac.JavacWrapper
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.load.java.JavaVisibilities 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.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject 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.name.ClassId
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType
@@ -38,9 +39,12 @@ class KotlinClassifiersCache(sourceFiles: Collection<KtFile>,
private val javac: JavacWrapper) { private val javac: JavacWrapper) {
private val kotlinPackages = hashSetOf<FqName>() private val kotlinPackages = hashSetOf<FqName>()
private val kotlinFacadeClasses = hashMapOf<ClassId, KtFile>()
private val kotlinClasses: Map<ClassId?, KtClassOrObject?> = private val kotlinClasses: Map<ClassId?, KtClassOrObject?> =
sourceFiles.flatMap { ktFile -> sourceFiles.flatMap { ktFile ->
kotlinPackages.add(ktFile.packageFqName) kotlinPackages.add(ktFile.packageFqName)
val facadeFqName = ktFile.javaFileFacadeFqName
kotlinFacadeClasses[ClassId(facadeFqName.parent(), facadeFqName.shortName())] = ktFile
ktFile.declarations ktFile.declarations
.filterIsInstance<KtClassOrObject>() .filterIsInstance<KtClassOrObject>()
.map { it.computeClassId() to it } .map { it.computeClassId() to it }
@@ -50,9 +54,11 @@ class KotlinClassifiersCache(sourceFiles: Collection<KtFile>,
fun getKotlinClassifier(classId: ClassId) = classifiers[classId] ?: createClassifier(classId) fun getKotlinClassifier(classId: ClassId) = classifiers[classId] ?: createClassifier(classId)
fun createMockKotlinClassifier(classifier: KtClassOrObject, fun createMockKotlinClassifier(classifier: KtClassOrObject?,
ktFile: KtFile?,
classId: ClassId) = MockKotlinClassifier(classId, classId: ClassId) = MockKotlinClassifier(classId,
classifier, classifier,
ktFile,
this, this,
javac) javac)
.apply { classifiers[classId] = this } .apply { classifiers[classId] = this }
@@ -60,11 +66,14 @@ class KotlinClassifiersCache(sourceFiles: Collection<KtFile>,
fun hasPackage(packageFqName: FqName) = kotlinPackages.contains(packageFqName) fun hasPackage(packageFqName: FqName) = kotlinPackages.contains(packageFqName)
private fun createClassifier(classId: ClassId): JavaClass? { private fun createClassifier(classId: ClassId): JavaClass? {
kotlinFacadeClasses[classId]?.let {
return createMockKotlinClassifier(null, it, classId)
}
if (classId.isNestedClass) { if (classId.isNestedClass) {
classifiers[classId]?.let { return it } classifiers[classId]?.let { return it }
val pathSegments = classId.relativeClassName.pathSegments().map { it.asString() } val pathSegments = classId.relativeClassName.pathSegments().map { it.asString() }
val outerClassId = ClassId(classId.packageFqName, Name.identifier(pathSegments.first())) 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 { pathSegments.drop(1).forEach {
outerClass = outerClass.findInnerClass(Name.identifier(it)) ?: return null outerClass = outerClass.findInnerClass(Name.identifier(it)) ?: return null
@@ -75,21 +84,25 @@ class KotlinClassifiersCache(sourceFiles: Collection<KtFile>,
val kotlinClassifier = kotlinClasses[classId] ?: return null val kotlinClassifier = kotlinClasses[classId] ?: return null
return createMockKotlinClassifier(kotlinClassifier, classId) return createMockKotlinClassifier(kotlinClassifier, null, classId)
} }
} }
class MockKotlinClassifier(val classId: ClassId, class MockKotlinClassifier(override val classId: ClassId,
private val classOrObject: KtClassOrObject, private val classOrObject: KtClassOrObject?,
private val ktFile: KtFile?,
private val cache: KotlinClassifiersCache, private val cache: KotlinClassifiersCache,
private val javac: JavacWrapper) : VirtualFileBoundJavaClass { private val javac: JavacWrapper) : JavaClassWithClassId {
override val fqName: FqName override val fqName: FqName
get() = classId.asSingleFqName() get() = classId.asSingleFqName()
override val visibility: Visibility override val visibility: Visibility
get() = when (classOrObject.visibilityModifierType()) { get() = if (classOrObject == null) {
Visibilities.PUBLIC
}
else when (classOrObject.visibilityModifierType()) {
null, KtTokens.PUBLIC_KEYWORD -> Visibilities.PUBLIC null, KtTokens.PUBLIC_KEYWORD -> Visibilities.PUBLIC
KtTokens.PRIVATE_KEYWORD -> Visibilities.PRIVATE KtTokens.PRIVATE_KEYWORD -> Visibilities.PRIVATE
KtTokens.PROTECTED_KEYWORD -> Visibilities.PROTECTED KtTokens.PROTECTED_KEYWORD -> Visibilities.PROTECTED
@@ -97,17 +110,19 @@ class MockKotlinClassifier(val classId: ClassId,
} }
override val supertypes: Collection<JavaClassifierType> 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) } .mapNotNull { javac.getKotlinClassifier(it) ?: javac.findClass(it) }
.map { MockKotlinClassifierType(it) } .map { MockKotlinClassifierType(it) }
val innerClasses: Collection<JavaClass> val innerClasses: Collection<JavaClass>
get() = classOrObject.declarations.filterIsInstance<KtClassOrObject>() get() = classOrObject?.declarations
.mapNotNull { nestedClassOrObject -> ?.filterIsInstance<KtClassOrObject>()
nestedClassOrObject.computeClassId()?.let { ?.mapNotNull { nestedClassOrObject ->
cache.createMockKotlinClassifier(nestedClassOrObject, it) cache.createMockKotlinClassifier(nestedClassOrObject, ktFile, classId.createNestedClassId(nestedClassOrObject.nameAsSafeName))
} } ?: emptyList()
}
override val lightClassOriginKind override val lightClassOriginKind
get() = LightClassOriginKind.SOURCE get() = LightClassOriginKind.SOURCE
@@ -127,12 +142,12 @@ class MockKotlinClassifier(val classId: ClassId,
innerClasses.find { it.name == name } innerClasses.find { it.name == name }
val typeParametersNumber: Int val typeParametersNumber: Int
get() = classOrObject.typeParameters.size get() = classOrObject?.typeParameters?.size ?: 0
val hasTypeParameters: Boolean val hasTypeParameters: Boolean
get() = typeParametersNumber > 0 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 override val isAbstract: Boolean
get() = throw UnsupportedOperationException("Should not be called") get() = throw UnsupportedOperationException("Should not be called")
@@ -18,8 +18,8 @@ package org.jetbrains.kotlin.javac.resolve
import com.sun.source.util.TreePath import com.sun.source.util.TreePath
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.javac.JavaClassWithClassId
import org.jetbrains.kotlin.javac.JavacWrapper 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.JavaVisibilities
import org.jetbrains.kotlin.load.java.structure.JavaClass import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
@@ -82,7 +82,7 @@ internal class ResolveHelper(private val javac: JavacWrapper,
when (innerOrNestedClass.visibility) { when (innerOrNestedClass.visibility) {
Visibilities.PRIVATE -> null Visibilities.PRIVATE -> null
JavaVisibilities.PACKAGE_VISIBILITY -> { 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 if (classId?.packageFqName?.asString() == (treePath.compilationUnit.packageName?.toString() ?: "")) innerOrNestedClass else null
} }
else -> innerOrNestedClass else -> innerOrNestedClass
@@ -36,11 +36,9 @@ open class SymbolBasedAnnotation(
SymbolBasedAnnotationArgument.create(value.value, Name.identifier(key.simpleName.toString()), javac) SymbolBasedAnnotationArgument.create(value.value, Name.identifier(key.simpleName.toString()), javac)
} }
override val classId: ClassId? override val classId: ClassId
get() = (annotationMirror.annotationType.asElement() as? TypeElement)?.computeClassId() get() = (annotationMirror.annotationType.asElement() as TypeElement).computeClassId()!!
override fun resolve() = with(annotationMirror.annotationType.asElement() as Symbol.ClassSymbol) { override fun resolve() = with(annotationMirror.annotationType.asElement() as Symbol.ClassSymbol) { javac.findClass(classId) }
SymbolBasedClass(this, javac, classfile)
}
} }
@@ -20,9 +20,10 @@ import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.CommonClassNames import com.intellij.psi.CommonClassNames
import com.intellij.psi.search.SearchScope import com.intellij.psi.search.SearchScope
import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.javac.JavaClassWithClassId
import org.jetbrains.kotlin.javac.JavacWrapper import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.load.java.structure.* 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.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import javax.lang.model.element.ElementKind import javax.lang.model.element.ElementKind
@@ -37,8 +38,9 @@ import javax.tools.JavaFileObject
class SymbolBasedClass( class SymbolBasedClass(
element: TypeElement, element: TypeElement,
javac: JavacWrapper, javac: JavacWrapper,
override val classId: ClassId?,
val file: JavaFileObject? val file: JavaFileObject?
) : SymbolBasedClassifier<TypeElement>(element, javac), VirtualFileBoundJavaClass { ) : SymbolBasedClassifier<TypeElement>(element, javac), JavaClassWithClassId {
override val name: Name override val name: Name
get() = Name.identifier(element.simpleName.toString()) get() = Name.identifier(element.simpleName.toString())
@@ -62,28 +64,34 @@ class SymbolBasedClass(
get() = FqName(element.qualifiedName.toString()) get() = FqName(element.qualifiedName.toString())
override val supertypes: Collection<JavaClassifierType> override val supertypes: Collection<JavaClassifierType>
get() = arrayListOf<TypeMirror>() by lazy {
.apply { arrayListOf<TypeMirror>()
element.superclass.takeIf { it !is NoType }?.let(this::add) .apply {
} element.superclass.takeIf { it !is NoType }?.let(this::add)
.apply { addAll(element.interfaces) } addAll(element.interfaces)
.mapTo(arrayListOf()) { SymbolBasedClassifierType(it, javac) } }
.apply { .mapTo(arrayListOf()) { SymbolBasedClassifierType(it, javac) }
if (isEmpty() && element.qualifiedName.toString() != CommonClassNames.JAVA_LANG_OBJECT) { .apply {
javac.JAVA_LANG_OBJECT?.let { add(it) } if (isEmpty() && element.qualifiedName.toString() != CommonClassNames.JAVA_LANG_OBJECT) {
} javac.JAVA_LANG_OBJECT?.let { add(it) }
} }
}
}
val innerClasses: Map<Name, JavaClass> val innerClasses: Map<Name, JavaClass>
get() = element.enclosedElements by lazy {
.filterIsInstance(TypeElement::class.java) element.enclosedElements
.map { SymbolBasedClass(it, javac, file) } .filterIsInstance(TypeElement::class.java)
.associateBy(JavaClass::name) .map { SymbolBasedClass(it, javac, classId?.createNestedClassId(Name.identifier(it.simpleName.toString())), file) }
.associateBy(JavaClass::name)
}
override val outerClass: JavaClass? override val outerClass: JavaClass?
get() = element.enclosingElement?.let { by lazy {
if (it.asType().kind != TypeKind.DECLARED) null else SymbolBasedClass(it as TypeElement, javac, file) element.enclosingElement?.let {
} if (it.asType().kind != TypeKind.DECLARED) null else SymbolBasedClass(it as TypeElement, javac, classId?.outerClassId, file)
}
}
override val isInterface: Boolean override val isInterface: Boolean
get() = element.kind == ElementKind.INTERFACE get() = element.kind == ElementKind.INTERFACE
@@ -99,8 +107,8 @@ class SymbolBasedClass(
override val methods: Collection<JavaMethod> override val methods: Collection<JavaMethod>
get() = element.enclosedElements get() = element.enclosedElements
.filter { it.kind == ElementKind.METHOD && !isEnumValuesOrValueOf(it as ExecutableElement)} .filter { it.kind == ElementKind.METHOD && !isEnumValuesOrValueOf(it as ExecutableElement) }
.map { SymbolBasedMethod(it as ExecutableElement, javac) } .map { SymbolBasedMethod(it as ExecutableElement, this, javac) }
private fun isEnumValuesOrValueOf(method: ExecutableElement): Boolean { private fun isEnumValuesOrValueOf(method: ExecutableElement): Boolean {
return isEnum && when (method.simpleName.toString()) { return isEnum && when (method.simpleName.toString()) {
@@ -113,12 +121,12 @@ class SymbolBasedClass(
override val fields: Collection<JavaField> override val fields: Collection<JavaField>
get() = element.enclosedElements get() = element.enclosedElements
.filter { it.kind.isField && Name.isValidIdentifier(it.simpleName.toString()) } .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> override val constructors: Collection<JavaConstructor>
get() = element.enclosedElements get() = element.enclosedElements
.filter { it.kind == ElementKind.CONSTRUCTOR } .filter { it.kind == ElementKind.CONSTRUCTOR }
.map { SymbolBasedConstructor(it as ExecutableElement, javac) } .map { SymbolBasedConstructor(it as ExecutableElement, this, javac) }
override val innerClassNames: Collection<Name> override val innerClassNames: Collection<Name>
get() = innerClasses.keys get() = innerClasses.keys
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.javac.wrappers.symbols package org.jetbrains.kotlin.javac.wrappers.symbols
import org.jetbrains.kotlin.javac.JavacWrapper 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.JavaConstructor
import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter
import org.jetbrains.kotlin.load.java.structure.JavaValueParameter import org.jetbrains.kotlin.load.java.structure.JavaValueParameter
@@ -24,8 +25,9 @@ import javax.lang.model.element.ExecutableElement
class SymbolBasedConstructor( class SymbolBasedConstructor(
element: ExecutableElement, element: ExecutableElement,
containingClass: JavaClass,
javac: JavacWrapper javac: JavacWrapper
) : SymbolBasedMember<ExecutableElement>(element, javac), JavaConstructor { ) : SymbolBasedMember<ExecutableElement>(element, containingClass, javac), JavaConstructor {
override val typeParameters: List<JavaTypeParameter> override val typeParameters: List<JavaTypeParameter>
get() = element.typeParameters.map { SymbolBasedTypeParameter(it, javac) } get() = element.typeParameters.map { SymbolBasedTypeParameter(it, javac) }
@@ -17,17 +17,17 @@
package org.jetbrains.kotlin.javac.wrappers.symbols package org.jetbrains.kotlin.javac.wrappers.symbols
import org.jetbrains.kotlin.javac.JavacWrapper 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.JavaField
import org.jetbrains.kotlin.load.java.structure.JavaType import org.jetbrains.kotlin.load.java.structure.JavaType
import javax.lang.model.element.ElementKind import javax.lang.model.element.ElementKind
import javax.lang.model.element.TypeElement
import javax.lang.model.element.VariableElement import javax.lang.model.element.VariableElement
import javax.lang.model.type.DeclaredType
class SymbolBasedField( class SymbolBasedField(
element: VariableElement, element: VariableElement,
containingClass: JavaClass,
javac: JavacWrapper javac: JavacWrapper
) : SymbolBasedMember<VariableElement>(element, javac), JavaField { ) : SymbolBasedMember<VariableElement>(element, containingClass, javac), JavaField {
override val isEnumEntry: Boolean override val isEnumEntry: Boolean
get() = element.kind == ElementKind.ENUM_CONSTANT get() = element.kind == ElementKind.ENUM_CONSTANT
@@ -36,12 +36,9 @@ class SymbolBasedField(
get() = SymbolBasedType.create(element.asType(), javac) get() = SymbolBasedType.create(element.asType(), javac)
override val initializerValue: Any? override val initializerValue: Any?
get() = element.constantValue by lazy { element.constantValue }
override val hasConstantNotNullInitializer: Boolean override val hasConstantNotNullInitializer: Boolean
get() = element.constantValue != null && element.asType().let { get() = initializerValue != null
it.kind.isPrimitive ||
((it as? DeclaredType)?.asElement() as? TypeElement)?.qualifiedName?.toString() == "java.lang.String"
}
} }
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.javac.wrappers.symbols package org.jetbrains.kotlin.javac.wrappers.symbols
import com.sun.tools.javac.code.Symbol
import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.javac.JavacWrapper import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
@@ -28,14 +27,10 @@ import javax.lang.model.element.Element
abstract class SymbolBasedMember<out T : Element>( abstract class SymbolBasedMember<out T : Element>(
element: T, element: T,
override val containingClass: JavaClass,
javac: JavacWrapper javac: JavacWrapper
) : SymbolBasedElement<T>(element, javac), JavaMember { ) : 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> override val annotations: Collection<JavaAnnotation>
get() = element.annotationMirrors.map { SymbolBasedAnnotation(it, javac) } get() = element.annotationMirrors.map { SymbolBasedAnnotation(it, javac) }
@@ -22,8 +22,9 @@ import javax.lang.model.element.ExecutableElement
class SymbolBasedMethod( class SymbolBasedMethod(
element: ExecutableElement, element: ExecutableElement,
containingClass: JavaClass,
javac: JavacWrapper javac: JavacWrapper
) : SymbolBasedMember<ExecutableElement>(element, javac), JavaMethod { ) : SymbolBasedMember<ExecutableElement>(element, containingClass, javac), JavaMethod {
override val typeParameters: List<JavaTypeParameter> override val typeParameters: List<JavaTypeParameter>
get() = element.typeParameters.map { SymbolBasedTypeParameter(it, javac) } get() = element.typeParameters.map { SymbolBasedTypeParameter(it, javac) }
@@ -34,7 +34,7 @@ class SymbolBasedPackage(
get() = FqName(element.qualifiedName.toString()) get() = FqName(element.qualifiedName.toString())
override val subPackages: Collection<JavaPackage> override val subPackages: Collection<JavaPackage>
get() = javac.findSubPackages(FqName(element.qualifiedName.toString())) get() = javac.findSubPackages(fqName)
override val annotations: Collection<JavaAnnotation> override val annotations: Collection<JavaAnnotation>
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.javac.wrappers.symbols package org.jetbrains.kotlin.javac.wrappers.symbols
import com.sun.tools.javac.code.Symbol
import org.jetbrains.kotlin.javac.JavacWrapper import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.load.java.structure.* import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -26,7 +27,7 @@ import javax.lang.model.type.TypeMirror
sealed class SymbolBasedAnnotationArgument( sealed class SymbolBasedAnnotationArgument(
override val name: Name, override val name: Name,
val javac: JavacWrapper protected val javac: JavacWrapper
) : JavaAnnotationArgument, JavaElement { ) : JavaAnnotationArgument, JavaElement {
companion object { companion object {
@@ -40,7 +41,7 @@ sealed class SymbolBasedAnnotationArgument(
} }
private fun arrayAnnotationArguments(values: Collection<*>, name: Name, javac: JavacWrapper): JavaArrayAnnotationArgument = 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) } .let { argumentList -> SymbolBasedArrayAnnotationArgument(argumentList, name, javac) }
} }
@@ -48,7 +49,7 @@ sealed class SymbolBasedAnnotationArgument(
} }
class SymbolBasedAnnotationAsAnnotationArgument( class SymbolBasedAnnotationAsAnnotationArgument(
val mirror: AnnotationMirror, private val mirror: AnnotationMirror,
name: Name, name: Name,
javac: JavacWrapper javac: JavacWrapper
) : SymbolBasedAnnotationArgument(name, javac), JavaAnnotationAsAnnotationArgument { ) : SymbolBasedAnnotationArgument(name, javac), JavaAnnotationAsAnnotationArgument {
@@ -65,12 +66,17 @@ class SymbolBasedReferenceAnnotationArgument(
override val entryName: Name? override val entryName: Name?
get() = Name.identifier(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( class SymbolBasedClassObjectAnnotationArgument(
val type: TypeMirror, private val type: TypeMirror,
name : Name, name : Name,
javac: JavacWrapper javac: JavacWrapper
) : SymbolBasedAnnotationArgument(name, javac), JavaClassObjectAnnotationArgument { ) : SymbolBasedAnnotationArgument(name, javac), JavaClassObjectAnnotationArgument {
@@ -73,12 +73,17 @@ class SymbolBasedClassifierType<out T : TypeMirror>(
) : SymbolBasedType<T>(typeMirror, javac), JavaClassifierType { ) : SymbolBasedType<T>(typeMirror, javac), JavaClassifierType {
override val classifier: JavaClassifier? override val classifier: JavaClassifier?
get() = when (typeMirror.kind) { by lazy {
TypeKind.DECLARED -> ((typeMirror as DeclaredType).asElement() as Symbol.ClassSymbol).let { symbol -> when (typeMirror.kind) {
SymbolBasedClass(symbol, javac, symbol.classfile) 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> override val typeArguments: List<JavaType>
@@ -36,21 +36,24 @@ internal val Element.isStatic: Boolean
internal val Element.isFinal: Boolean internal val Element.isFinal: Boolean
get() = modifiers.contains(Modifier.FINAL) get() = modifiers.contains(Modifier.FINAL)
internal fun Element.getVisibility(): Visibility = when { internal fun Element.getVisibility(): Visibility = modifiers.let { modifiers ->
Modifier.PUBLIC in modifiers -> Visibilities.PUBLIC when {
Modifier.PRIVATE in modifiers -> Visibilities.PRIVATE Modifier.PUBLIC in modifiers -> Visibilities.PUBLIC
Modifier.PROTECTED in modifiers -> { Modifier.PRIVATE in modifiers -> Visibilities.PRIVATE
if (Modifier.STATIC in modifiers) { Modifier.PROTECTED in modifiers -> {
JavaVisibilities.PROTECTED_STATIC_VISIBILITY if (Modifier.STATIC in modifiers) {
} JavaVisibilities.PROTECTED_STATIC_VISIBILITY
else { }
JavaVisibilities.PROTECTED_AND_PACKAGE else {
JavaVisibilities.PROTECTED_AND_PACKAGE
}
} }
else -> JavaVisibilities.PACKAGE_VISIBILITY
} }
else -> JavaVisibilities.PACKAGE_VISIBILITY
} }
internal fun TypeElement.computeClassId(): ClassId? { internal fun TypeElement.computeClassId(): ClassId? {
val enclosingElement = enclosingElement
if (enclosingElement.kind != ElementKind.PACKAGE) { if (enclosingElement.kind != ElementKind.PACKAGE) {
val parentClassId = (enclosingElement as TypeElement).computeClassId() ?: return null val parentClassId = (enclosingElement as TypeElement).computeClassId() ?: return null
return parentClassId.createNestedClassId(Name.identifier(simpleName.toString())) return parentClassId.createNestedClassId(Name.identifier(simpleName.toString()))
@@ -60,11 +63,16 @@ internal fun TypeElement.computeClassId(): ClassId? {
} }
internal fun ExecutableElement.valueParameters(javac: JavacWrapper): List<JavaValueParameter> = internal fun ExecutableElement.valueParameters(javac: JavacWrapper): List<JavaValueParameter> =
parameters.mapIndexed { index, parameter -> parameters.let { parameters ->
SymbolBasedValueParameter(parameter, val isVarArgs = isVarArgs
if (!parameter.simpleName.contentEquals("arg$index")) parameter.simpleName.toString() else "p$index", val lastIndex = parameters.lastIndex
index == parameters.lastIndex && isVarArgs, parameters.mapIndexed { index, parameter ->
javac) 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, 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.source.util.TreePath
import com.sun.tools.javac.tree.JCTree import com.sun.tools.javac.tree.JCTree
import org.jetbrains.kotlin.javac.JavaClassWithClassId
import org.jetbrains.kotlin.javac.JavacWrapper import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.javac.resolve.ConstantEvaluator
import org.jetbrains.kotlin.load.java.structure.* import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
@@ -34,7 +36,7 @@ class TreeBasedAnnotation(
get() = createAnnotationArguments(this, javac) get() = createAnnotationArguments(this, javac)
override val classId: ClassId? 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() = override fun resolve() =
javac.resolve(TreePath.getPath(treePath.compilationUnit, annotation.annotationType)) as? JavaClass javac.resolve(TreePath.getPath(treePath.compilationUnit, annotation.annotationType)) as? JavaClass
@@ -130,11 +132,10 @@ private fun resolveArgumentValue(argument: JCTree.JCExpression,
name: Name, name: Name,
treePath: TreePath, treePath: TreePath,
javac: JavacWrapper): JavaAnnotationArgument? { javac: JavacWrapper): JavaAnnotationArgument? {
val containingAnnotation = annotation.resolve() val containingAnnotation = annotation.resolve() ?: return null
val type = containingAnnotation?.methods?.find { it.name == name }?.returnType ?: return null val evaluator = ConstantEvaluator(containingAnnotation, javac, treePath)
val calculator = ValueCalculator(containingAnnotation, javac, treePath, type)
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>, 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 com.sun.tools.javac.tree.TreeInfo
import org.jetbrains.kotlin.descriptors.Visibilities.PUBLIC import org.jetbrains.kotlin.descriptors.Visibilities.PUBLIC
import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.javac.JavaClassWithClassId
import org.jetbrains.kotlin.javac.JavacWrapper import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.load.java.structure.* 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.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import javax.tools.JavaFileObject import javax.tools.JavaFileObject
@@ -36,8 +37,9 @@ class TreeBasedClass(
tree: JCTree.JCClassDecl, tree: JCTree.JCClassDecl,
treePath: TreePath, treePath: TreePath,
javac: JavacWrapper, javac: JavacWrapper,
val file: JavaFileObject val file: JavaFileObject,
) : TreeBasedElement<JCTree.JCClassDecl>(tree, treePath, javac), VirtualFileBoundJavaClass { override val classId: ClassId?
) : TreeBasedElement<JCTree.JCClassDecl>(tree, treePath, javac), JavaClassWithClassId {
override val name: Name override val name: Name
get() = Name.identifier(tree.simpleName.toString()) get() = Name.identifier(tree.simpleName.toString())
@@ -70,45 +72,43 @@ class TreeBasedClass(
} }
override val fqName: FqName override val fqName: FqName
get() = treePath.reversed() get() = classId?.asSingleFqName() ?: throw UnsupportedOperationException("classId of $name is null")
.filterIsInstance<JCTree.JCClassDecl>()
.joinToString(
separator = ".",
transform = JCTree.JCClassDecl::name
)
.let { treePath.compilationUnit.packageName?.let { packageName -> FqName("$packageName.$it") } ?: FqName.topLevel(Name.identifier(it))}
override val supertypes: Collection<JavaClassifierType> override val supertypes: Collection<JavaClassifierType>
get() = arrayListOf<JavaClassifierType>().also { list -> by lazy {
if (isEnum) { arrayListOf<JavaClassifierType>().also { list ->
createEnumSupertype(this, javac).let { list.add(it) } if (isEnum) {
} else if (isAnnotationType) { createEnumSupertype(this, javac).let { list.add(it) }
javac.JAVA_LANG_ANNOTATION_ANNOTATION?.let { list.add(it) } }
} else if (isAnnotationType) {
javac.JAVA_LANG_ANNOTATION_ANNOTATION?.let { list.add(it) }
}
tree.extending?.let { tree.extending?.let {
(TreeBasedType.create(it, javac.getTreePath(it, treePath.compilationUnit), javac, emptyList()) as? JavaClassifierType) (TreeBasedType.create(it, javac.getTreePath(it, treePath.compilationUnit), javac, emptyList()) as? JavaClassifierType)
?.let { list.add(it) } ?.let { list.add(it) }
} }
tree.implementing?.mapNotNull { tree.implementing?.mapNotNull {
TreeBasedType.create(it, javac.getTreePath(it, treePath.compilationUnit), javac, emptyList()) as? JavaClassifierType TreeBasedType.create(it, javac.getTreePath(it, treePath.compilationUnit), javac, emptyList()) as? JavaClassifierType
}?.let { list.addAll(it) } }?.let { list.addAll(it) }
if (list.isEmpty()) { if (list.isEmpty()) {
javac.JAVA_LANG_OBJECT?.let { list.add(it) } javac.JAVA_LANG_OBJECT?.let { list.add(it) }
}
}
} }
}
val innerClasses: Map<Name, TreeBasedClass> by lazy { val innerClasses: Map<Name, TreeBasedClass> by lazy {
tree.members tree.members
.filterIsInstance(JCTree.JCClassDecl::class.java) .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) .associateBy(JavaClass::name)
} }
override val outerClass: JavaClass? by lazy { override val outerClass: JavaClass? by lazy {
(treePath.parentPath.leaf as? JCTree.JCClassDecl)?.let { classDecl -> (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, private fun createEnumSupertype(javaClass: JavaClass,
javac: JavacWrapper) = object : JavaClassifierType { javac: JavacWrapper) = object : JavaClassifierType {
override val classifier: JavaClassifier? override val classifier: JavaClass?
get() = javac.JAVA_LANG_ENUM get() = javac.JAVA_LANG_ENUM
override val typeArguments: List<JavaType> override val typeArguments: List<JavaType>
@@ -167,11 +167,12 @@ private fun createEnumSupertype(javaClass: JavaClass,
override val annotations: Collection<JavaAnnotation> override val annotations: Collection<JavaAnnotation>
get() = emptyList() get() = emptyList()
override val classifierQualifiedName: String override val classifierQualifiedName: String
get() = (classifier as? JavaClass)?.fqName?.asString() ?: "" get() = classifier?.fqName?.asString() ?: ""
override val presentableText: String override val presentableText: String
get() = classifierQualifiedName get() = classifierQualifiedName
override val isDeprecatedInJavaDoc: Boolean override val isDeprecatedInJavaDoc: Boolean
get() = false get() = false
override fun findAnnotation(fqName: FqName) = null override fun findAnnotation(fqName: FqName) = null
private inner class TypeArgument : JavaClassifierType { private inner class TypeArgument : JavaClassifierType {
@@ -189,6 +190,7 @@ private fun createEnumSupertype(javaClass: JavaClass,
get() = classifierQualifiedName get() = classifierQualifiedName
override val isDeprecatedInJavaDoc: Boolean override val isDeprecatedInJavaDoc: Boolean
get() = false get() = false
override fun findAnnotation(fqName: FqName) = null 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.source.util.TreePath
import com.sun.tools.javac.code.Flags import com.sun.tools.javac.code.Flags
import com.sun.tools.javac.code.TypeTag
import com.sun.tools.javac.tree.JCTree import com.sun.tools.javac.tree.JCTree
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.javac.JavacWrapper 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.JavaClass
import org.jetbrains.kotlin.load.java.structure.JavaField 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.load.java.structure.JavaType
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -60,7 +58,7 @@ class TreeBasedField(
override val initializerValue: Any? override val initializerValue: Any?
get() = tree.init?.let { initExpr -> 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 override val hasConstantNotNullInitializer: Boolean
@@ -73,92 +71,4 @@ class TreeBasedField(
type.classifierQualifiedName == "java.lang.String")) type.classifierQualifiedName == "java.lang.String"))
} ?: false } ?: 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.source.util.TreePath
import com.sun.tools.javac.tree.JCTree import com.sun.tools.javac.tree.JCTree
import org.jetbrains.kotlin.javac.JavacWrapper 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.JavaClass
import org.jetbrains.kotlin.load.java.structure.JavaMember import org.jetbrains.kotlin.load.java.structure.JavaMember
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
@@ -34,11 +33,13 @@ abstract class TreeBasedMember<out T : JCTree>(
override val isDeprecatedInJavaDoc: Boolean override val isDeprecatedInJavaDoc: Boolean
get() = javac.isDeprecatedInJavaDoc(treePath) 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) } tree.annotations().map { TreeBasedAnnotation(it, treePath, javac) }
} }
override fun findAnnotation(fqName: FqName) = 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.code.Flags
import com.sun.tools.javac.tree.JCTree import com.sun.tools.javac.tree.JCTree
import org.jetbrains.kotlin.javac.JavacWrapper 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.JavaType
import org.jetbrains.kotlin.load.java.structure.JavaValueParameter import org.jetbrains.kotlin.load.java.structure.JavaValueParameter
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
@@ -32,12 +31,14 @@ class TreeBasedValueParameter(
javac: JavacWrapper javac: JavacWrapper
) : TreeBasedElement<JCTree.JCVariableDecl>(tree, treePath, javac), JavaValueParameter { ) : 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) } tree.annotations().map { TreeBasedAnnotation(it, treePath, javac) }
} }
override fun findAnnotation(fqName: FqName) = 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 override val isDeprecatedInJavaDoc: Boolean
get() = javac.isDeprecatedInJavaDoc(treePath) get() = javac.isDeprecatedInJavaDoc(treePath)
@@ -31,25 +31,27 @@ abstract class TreeBasedType<out T : JCTree>(
val tree: T, val tree: T,
val treePath: TreePath, val treePath: TreePath,
val javac: JavacWrapper, val javac: JavacWrapper,
override val annotations: Collection<JavaAnnotation> private val allAnnotations: Collection<JavaAnnotation>
) : JavaType, JavaAnnotationOwner { ) : JavaType, JavaAnnotationOwner {
override val annotations: Collection<JavaAnnotation>
get() = allAnnotations.filterTypeAnnotations()
companion object { companion object {
fun create(tree: JCTree, treePath: TreePath, fun create(tree: JCTree, treePath: TreePath,
javac: JavacWrapper, annotations: Collection<JavaAnnotation>): JavaType { javac: JavacWrapper, annotations: Collection<JavaAnnotation>): JavaType {
val applicableAnnotations = annotations.filterTypeAnnotations()
return when (tree) { return when (tree) {
is JCTree.JCPrimitiveTypeTree -> TreeBasedPrimitiveType(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, applicableAnnotations) is JCTree.JCArrayTypeTree -> TreeBasedArrayType(tree, javac.getTreePath(tree, treePath.compilationUnit), javac, annotations)
is JCTree.JCWildcard -> TreeBasedWildcardType(tree, javac.getTreePath(tree, treePath.compilationUnit), javac, applicableAnnotations) is JCTree.JCWildcard -> TreeBasedWildcardType(tree, javac.getTreePath(tree, treePath.compilationUnit), javac, annotations)
is JCTree.JCTypeApply -> TreeBasedGenericClassifierType(tree, javac.getTreePath(tree, treePath.compilationUnit), javac, applicableAnnotations) is JCTree.JCTypeApply -> TreeBasedGenericClassifierType(tree, javac.getTreePath(tree, treePath.compilationUnit), javac, annotations)
is JCTree.JCAnnotatedType -> { is JCTree.JCAnnotatedType -> {
val underlyingType = tree.underlyingType val underlyingType = tree.underlyingType
val newAnnotations = tree.annotations val newAnnotations = tree.annotations
.map { TreeBasedAnnotation(it, javac.getTreePath(it, treePath.compilationUnit), javac) } .map { TreeBasedAnnotation(it, javac.getTreePath(it, treePath.compilationUnit), javac) }
create(underlyingType, javac.getTreePath(underlyingType, treePath.compilationUnit), javac, newAnnotations) 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") else -> throw UnsupportedOperationException("Unsupported type: $tree")
} }
} }
@@ -72,8 +74,8 @@ class TreeBasedPrimitiveType(
tree: JCTree.JCPrimitiveTypeTree, tree: JCTree.JCPrimitiveTypeTree,
treePath: TreePath, treePath: TreePath,
javac: JavacWrapper, javac: JavacWrapper,
annotations: Collection<JavaAnnotation> allAnnotations: Collection<JavaAnnotation>
) : TreeBasedType<JCTree.JCPrimitiveTypeTree>(tree, treePath, javac, annotations), JavaPrimitiveType { ) : TreeBasedType<JCTree.JCPrimitiveTypeTree>(tree, treePath, javac, allAnnotations), JavaPrimitiveType {
override val type: PrimitiveType? override val type: PrimitiveType?
get() = if (tree.primitiveTypeKind == TypeKind.VOID) { get() = if (tree.primitiveTypeKind == TypeKind.VOID) {
@@ -89,8 +91,8 @@ class TreeBasedArrayType(
tree: JCTree.JCArrayTypeTree, tree: JCTree.JCArrayTypeTree,
treePath: TreePath, treePath: TreePath,
javac: JavacWrapper, javac: JavacWrapper,
annotations: Collection<JavaAnnotation> allAnnotations: Collection<JavaAnnotation>
) : TreeBasedType<JCTree.JCArrayTypeTree>(tree, treePath, javac, annotations), JavaArrayType { ) : TreeBasedType<JCTree.JCArrayTypeTree>(tree, treePath, javac, allAnnotations), JavaArrayType {
override val componentType: JavaType override val componentType: JavaType
get() = create(tree.elemtype, treePath, javac, annotations) get() = create(tree.elemtype, treePath, javac, annotations)
@@ -101,8 +103,8 @@ class TreeBasedWildcardType(
tree: JCTree.JCWildcard, tree: JCTree.JCWildcard,
treePath: TreePath, treePath: TreePath,
javac: JavacWrapper, javac: JavacWrapper,
annotations: Collection<JavaAnnotation> allAnnotations: Collection<JavaAnnotation>
) : TreeBasedType<JCTree.JCWildcard>(tree, treePath, javac, annotations), JavaWildcardType { ) : TreeBasedType<JCTree.JCWildcard>(tree, treePath, javac, allAnnotations), JavaWildcardType {
override val bound: JavaType? override val bound: JavaType?
get() = tree.bound?.let { create(it, treePath, javac, annotations) } get() = tree.bound?.let { create(it, treePath, javac, annotations) }
@@ -116,11 +118,11 @@ sealed class TreeBasedClassifierType<out T : JCTree>(
tree: T, tree: T,
treePath: TreePath, treePath: TreePath,
javac: JavacWrapper, javac: JavacWrapper,
annotations: Collection<JavaAnnotation> allAnnotations: Collection<JavaAnnotation>
) : TreeBasedType<T>(tree, treePath, javac, annotations), JavaClassifierType { ) : TreeBasedType<T>(tree, treePath, javac, allAnnotations), JavaClassifierType {
override val classifier: JavaClassifier? override val classifier: JavaClassifier?
get() = javac.resolve(treePath) by lazy { javac.resolve(treePath) }
override val classifierQualifiedName: String override val classifierQualifiedName: String
get() = (classifier as? JavaClass)?.fqName?.asString() ?: treePath.leaf.toString().substringBefore("<") get() = (classifier as? JavaClass)?.fqName?.asString() ?: treePath.leaf.toString().substringBefore("<")
@@ -132,7 +134,7 @@ sealed class TreeBasedClassifierType<out T : JCTree>(
get() { get() {
var tree: JCTree = tree var tree: JCTree = tree
if (tree is JCTree.JCTypeApply) { if (tree is JCTree.JCTypeApply) {
tree = tree.clazz tree = tree.clazz
} }
if (tree is JCTree.JCFieldAccess) { if (tree is JCTree.JCFieldAccess) {
val enclosingType = TreeBasedType.create(tree.selected, treePath, javac, annotations) val enclosingType = TreeBasedType.create(tree.selected, treePath, javac, annotations)
@@ -158,12 +160,12 @@ sealed class TreeBasedClassifierType<out T : JCTree>(
private val typeParameter: JCTree.JCTypeParameter? private val typeParameter: JCTree.JCTypeParameter?
get() = treePath.flatMap { get() = treePath.flatMap {
when (it) { when (it) {
is JCTree.JCClassDecl -> it.typarams is JCTree.JCClassDecl -> it.typarams
is JCTree.JCMethodDecl -> it.typarams is JCTree.JCMethodDecl -> it.typarams
else -> emptyList<JCTree.JCTypeParameter>() else -> emptyList<JCTree.JCTypeParameter>()
} }
} }
.find { it.toString().substringBefore(" ") == treePath.leaf.toString() } .find { it.toString().substringBefore(" ") == treePath.leaf.toString() }
} }
@@ -213,13 +215,13 @@ class TreeBasedGenericClassifierType(
) : TreeBasedClassifierType<JCTree.JCTypeApply>(tree, treePath, javac, annotations) { ) : TreeBasedClassifierType<JCTree.JCTypeApply>(tree, treePath, javac, annotations) {
override val classifier: JavaClassifier? override val classifier: JavaClassifier?
get() { by lazy {
val newTree = tree.clazz val newTree = tree.clazz
return if (newTree is JCTree.JCAnnotatedType) { if (newTree is JCTree.JCAnnotatedType) {
javac.resolve(javac.getTreePath(newTree.underlyingType, treePath.compilationUnit)) javac.resolve(javac.getTreePath(newTree.underlyingType, treePath.compilationUnit))
}
else super.classifier
} }
else super.classifier
}
override val annotations: Collection<JavaAnnotation> override val annotations: Collection<JavaAnnotation>
get() { 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.javac.wrappers.symbols.SymbolBasedReferenceAnnotationArgument
import org.jetbrains.kotlin.load.java.JavaVisibilities import org.jetbrains.kotlin.load.java.JavaVisibilities
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation 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.ClassId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -63,14 +62,12 @@ internal fun JCTree.annotations(): Collection<JCTree.JCAnnotation> = when (this)
else -> null else -> null
} ?: emptyList<JCTree.JCAnnotation>() } ?: emptyList<JCTree.JCAnnotation>()
fun JavaClass.computeClassId(): ClassId? =
outerClass?.computeClassId()?.createNestedClassId(name) ?: fqName?.let { ClassId.topLevel(it) }
fun Collection<JavaAnnotation>.filterTypeAnnotations(): Collection<JavaAnnotation> { fun Collection<JavaAnnotation>.filterTypeAnnotations(): Collection<JavaAnnotation> {
val filteredAnnotations = arrayListOf<JavaAnnotation>() val filteredAnnotations = arrayListOf<JavaAnnotation>()
val targetClassId = ClassId(FqName("java.lang.annotation"), Name.identifier("Target"))
for (annotation in this) { for (annotation in this) {
val annotationClass = annotation.resolve() 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 val elementTypeArg = targetAnnotation.arguments.firstOrNull() ?: continue
when (elementTypeArg) { 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); 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") @TestMetadata("AnnotatedLocalObjectFun.kt")
public void testAnnotatedLocalObjectFun() throws Exception { public void testAnnotatedLocalObjectFun() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/AnnotatedLocalObjectFun.kt"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/AnnotatedLocalObjectFun.kt");
@@ -44,12 +44,30 @@ public class JavacFieldResolutionTestGenerated extends AbstractJavacFieldResolut
doTest(fileName); 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") @TestMetadata("ConstantValues.kt")
public void testConstantValues() throws Exception { public void testConstantValues() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/javac/fieldsResolution/tests/ConstantValues.kt"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/javac/fieldsResolution/tests/ConstantValues.kt");
doTest(fileName); 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") @TestMetadata("FieldFromOuterClass.kt")
public void testFieldFromOuterClass() throws Exception { public void testFieldFromOuterClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/javac/fieldsResolution/tests/FieldFromOuterClass.kt"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/javac/fieldsResolution/tests/FieldFromOuterClass.kt");
@@ -62,6 +80,12 @@ public class JavacFieldResolutionTestGenerated extends AbstractJavacFieldResolut
doTest(fileName); 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") @TestMetadata("ResolutionPriority.kt")
public void testResolutionPriority() throws Exception { public void testResolutionPriority() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/javac/fieldsResolution/tests/ResolutionPriority.kt"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/javac/fieldsResolution/tests/ResolutionPriority.kt");
@@ -101,12 +125,30 @@ public class JavacFieldResolutionTestGenerated extends AbstractJavacFieldResolut
doTestWithoutJavacWrapper(fileName); 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") @TestMetadata("ConstantValues.kt")
public void testConstantValues() throws Exception { public void testConstantValues() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/javac/fieldsResolution/tests/ConstantValues.kt"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/javac/fieldsResolution/tests/ConstantValues.kt");
doTestWithoutJavacWrapper(fileName); 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") @TestMetadata("FieldFromOuterClass.kt")
public void testFieldFromOuterClass() throws Exception { public void testFieldFromOuterClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/javac/fieldsResolution/tests/FieldFromOuterClass.kt"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/javac/fieldsResolution/tests/FieldFromOuterClass.kt");
@@ -119,6 +161,12 @@ public class JavacFieldResolutionTestGenerated extends AbstractJavacFieldResolut
doTestWithoutJavacWrapper(fileName); 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") @TestMetadata("ResolutionPriority.kt")
public void testResolutionPriority() throws Exception { public void testResolutionPriority() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/javac/fieldsResolution/tests/ResolutionPriority.kt"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/javac/fieldsResolution/tests/ResolutionPriority.kt");