Introduce experimental -Xuse-javac compilation mode
In this mode, javac AST and Symbol files are used during Kotlin compilation instead of PSI / binary stuff. Later, they are reused for Java file compilation. javac in this mode is integrated into kotlinc.
This commit is contained in:
committed by
Mikhail Glukhikh
parent
c9a04fe1e2
commit
5eea3b6569
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="kotlin-runtime" level="project" />
|
||||
<orderEntry type="module" module-name="descriptors" />
|
||||
<orderEntry type="module" module-name="descriptor.loader.java" />
|
||||
<orderEntry type="module-library">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$MODULE_DIR$/../../ideaSDK/lib/openapi.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="library" name="intellij-core" level="project" />
|
||||
<orderEntry type="library" name="javax.inject" level="project" />
|
||||
<orderEntry type="module" module-name="frontend" />
|
||||
<orderEntry type="module" module-name="frontend.java" />
|
||||
<orderEntry type="module" module-name="cli-common" />
|
||||
<orderEntry type="module" module-name="cli" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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 com.sun.tools.javac.util.Context
|
||||
import com.sun.tools.javac.util.Log
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.GroupingMessageCollector
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import java.io.PrintWriter
|
||||
import java.io.Writer
|
||||
|
||||
class JavacLogger(context: Context,
|
||||
errorWriter: PrintWriter,
|
||||
warningWriter: PrintWriter,
|
||||
infoWriter: PrintWriter) : Log(context, errorWriter, warningWriter, infoWriter) {
|
||||
init {
|
||||
context.put(Log.outKey, infoWriter)
|
||||
}
|
||||
|
||||
override fun printLines(kind: WriterKind, message: String, vararg args: Any?) {}
|
||||
|
||||
companion object {
|
||||
fun preRegister(context: Context, messageCollector: MessageCollector) {
|
||||
context.put(Log.logKey, Context.Factory<Log> {
|
||||
JavacLogger(it,
|
||||
PrintWriter(MessageCollectorAdapter(messageCollector, CompilerMessageSeverity.ERROR)),
|
||||
PrintWriter(MessageCollectorAdapter(messageCollector, CompilerMessageSeverity.WARNING)),
|
||||
PrintWriter(MessageCollectorAdapter(messageCollector, CompilerMessageSeverity.INFO)))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class MessageCollectorAdapter(private val messageCollector: MessageCollector,
|
||||
private val severity: CompilerMessageSeverity) : Writer() {
|
||||
|
||||
override fun write(buffer: CharArray, offset: Int, length: Int) {
|
||||
if (length == 1 && buffer[0] == '\n') return
|
||||
|
||||
messageCollector.report(severity, String(buffer, offset, length))
|
||||
}
|
||||
|
||||
override fun flush() {
|
||||
(messageCollector as? GroupingMessageCollector)?.flush()
|
||||
}
|
||||
|
||||
override fun close() = flush()
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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 com.sun.tools.javac.util.Options
|
||||
import java.util.regex.Pattern
|
||||
|
||||
object JavacOptionsMapper {
|
||||
|
||||
fun map(options: Options, arguments: List<String>) {
|
||||
arguments.forEach { options.putOption(it) }
|
||||
}
|
||||
|
||||
private val optionPattern = Pattern.compile("\\s+")
|
||||
|
||||
private fun Options.putOption(option: String) =
|
||||
option.split(optionPattern)
|
||||
.filter { it.isNotEmpty() }
|
||||
.let { arg ->
|
||||
when(arg.size) {
|
||||
1 -> put(arg[0], arg[0])
|
||||
2 -> put(arg[0], arg[1])
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,330 @@
|
||||
/*
|
||||
* 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 com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.CommonClassNames
|
||||
import com.intellij.psi.search.EverythingGlobalScope
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.sun.source.tree.CompilationUnitTree
|
||||
import com.sun.source.util.TreePath
|
||||
import com.sun.tools.javac.api.JavacTrees
|
||||
import com.sun.tools.javac.code.Flags
|
||||
import com.sun.tools.javac.code.Symbol
|
||||
import com.sun.tools.javac.code.Symtab
|
||||
import com.sun.tools.javac.file.JavacFileManager
|
||||
import com.sun.tools.javac.jvm.ClassReader
|
||||
import com.sun.tools.javac.main.JavaCompiler
|
||||
import com.sun.tools.javac.model.JavacElements
|
||||
import com.sun.tools.javac.model.JavacTypes
|
||||
import com.sun.tools.javac.tree.JCTree
|
||||
import com.sun.tools.javac.util.Context
|
||||
import com.sun.tools.javac.util.List as JavacList
|
||||
import com.sun.tools.javac.util.Names
|
||||
import com.sun.tools.javac.util.Options
|
||||
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
|
||||
import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
||||
import org.jetbrains.kotlin.javac.wrappers.symbols.SymbolBasedClass
|
||||
import org.jetbrains.kotlin.javac.wrappers.symbols.SymbolBasedClassifierType
|
||||
import org.jetbrains.kotlin.javac.wrappers.symbols.SymbolBasedPackage
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.isSubpackageOf
|
||||
import org.jetbrains.kotlin.name.parentOrNull
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.javac.wrappers.trees.TreeBasedClass
|
||||
import org.jetbrains.kotlin.javac.wrappers.trees.TreeBasedPackage
|
||||
import org.jetbrains.kotlin.javac.wrappers.trees.TreePathResolverCache
|
||||
import org.jetbrains.kotlin.javac.wrappers.trees.computeClassId
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClassifier
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaPackage
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import java.io.Closeable
|
||||
import java.io.File
|
||||
import javax.lang.model.element.Element
|
||||
import javax.lang.model.type.TypeMirror
|
||||
import javax.tools.JavaFileManager
|
||||
import javax.tools.JavaFileObject
|
||||
import javax.tools.StandardLocation
|
||||
|
||||
class JavacWrapper(javaFiles: Collection<File>,
|
||||
kotlinFiles: Collection<KtFile>,
|
||||
arguments: Array<String>?,
|
||||
private val environment: KotlinCoreEnvironment) : Closeable {
|
||||
|
||||
companion object {
|
||||
fun getInstance(project: Project): JavacWrapper = ServiceManager.getService(project, JavacWrapper::class.java)
|
||||
}
|
||||
|
||||
private fun createCommonClassifierType(fqName: String) =
|
||||
findClassInSymbols(fqName)?.let {
|
||||
SymbolBasedClassifierType(it.element.asType(), this)
|
||||
}
|
||||
|
||||
val JAVA_LANG_OBJECT by lazy {
|
||||
createCommonClassifierType(CommonClassNames.JAVA_LANG_OBJECT)
|
||||
}
|
||||
|
||||
val JAVA_LANG_ENUM by lazy {
|
||||
createCommonClassifierType(CommonClassNames.JAVA_LANG_ENUM)
|
||||
}
|
||||
|
||||
val JAVA_LANG_ANNOTATION_ANNOTATION by lazy {
|
||||
createCommonClassifierType(CommonClassNames.JAVA_LANG_ANNOTATION_ANNOTATION)
|
||||
}
|
||||
|
||||
private val messageCollector = environment.configuration[CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY]
|
||||
|
||||
private val context = Context()
|
||||
|
||||
init {
|
||||
messageCollector?.let { JavacLogger.preRegister(context, it) }
|
||||
arguments?.toList()?.let { JavacOptionsMapper.map(Options.instance(context), it) }
|
||||
}
|
||||
|
||||
private val javac = object : JavaCompiler(context) {
|
||||
override fun parseFiles(files: Iterable<JavaFileObject>?) = compilationUnits
|
||||
}
|
||||
|
||||
private val fileManager = context[JavaFileManager::class.java] as JavacFileManager
|
||||
|
||||
init {
|
||||
// use rt.jar instead of lib/ct.sym
|
||||
fileManager.setSymbolFileEnabled(false)
|
||||
fileManager.setLocation(StandardLocation.CLASS_PATH, environment.configuration.jvmClasspathRoots)
|
||||
}
|
||||
|
||||
private val names = Names.instance(context)
|
||||
private val symbols = Symtab.instance(context)
|
||||
private val trees = JavacTrees.instance(context)
|
||||
private val elements = JavacElements.instance(context)
|
||||
private val types = JavacTypes.instance(context)
|
||||
private val fileObjects = fileManager.getJavaFileObjectsFromFiles(javaFiles).toJavacList()
|
||||
private val compilationUnits: JavacList<JCTree.JCCompilationUnit> = fileObjects.map(javac::parse).toJavacList()
|
||||
|
||||
private val javaClasses = compilationUnits
|
||||
.flatMap { unit ->
|
||||
unit.typeDecls.flatMap { classDecl ->
|
||||
TreeBasedClass(classDecl as JCTree.JCClassDecl,
|
||||
trees.getPath(unit, classDecl),
|
||||
this,
|
||||
unit.sourceFile).withInnerClasses()
|
||||
}
|
||||
}
|
||||
.associateBy(JavaClass::fqName)
|
||||
|
||||
private val javaClassesAssociatedByClassId =
|
||||
javaClasses.values.associateBy { it.computeClassId() }
|
||||
|
||||
private val javaPackages = compilationUnits
|
||||
.mapNotNullTo(hashSetOf()) { unit ->
|
||||
unit.packageName?.toString()?.let { packageName ->
|
||||
TreeBasedPackage(packageName, this, unit.sourcefile)
|
||||
}
|
||||
}
|
||||
.associateBy(TreeBasedPackage::fqName)
|
||||
|
||||
private val kotlinClassifiersCache = KotlinClassifiersCache(kotlinFiles, this)
|
||||
private val treePathResolverCache = TreePathResolverCache(this)
|
||||
private val symbolBasedClassesCache = hashMapOf<String, SymbolBasedClass?>()
|
||||
private val symbolBasedPackagesCache = hashMapOf<String, SymbolBasedPackage?>()
|
||||
|
||||
fun compile(outDir: File? = null): Boolean = with(javac) {
|
||||
if (errorCount() > 0) return false
|
||||
|
||||
fileManager.setClassPathForCompilation(outDir)
|
||||
messageCollector?.report(CompilerMessageSeverity.INFO,
|
||||
"Compiling Java sources")
|
||||
compile(fileObjects)
|
||||
errorCount() == 0
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
fileManager.close()
|
||||
javac.close()
|
||||
}
|
||||
|
||||
fun findClass(fqName: FqName, scope: GlobalSearchScope = EverythingGlobalScope()): JavaClass? {
|
||||
javaClasses[fqName]?.let { javaClass ->
|
||||
javaClass.virtualFile?.let { if (it in scope) return javaClass }
|
||||
}
|
||||
|
||||
findClassInSymbols(fqName.asString())?.let { javaClass ->
|
||||
javaClass.virtualFile?.let { if (it in scope) return javaClass }
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
fun findClass(classId: ClassId, scope: GlobalSearchScope = EverythingGlobalScope()): JavaClass? {
|
||||
javaClassesAssociatedByClassId[classId]?.let { javaClass ->
|
||||
javaClass.virtualFile?.let { if (it in scope) return javaClass }
|
||||
}
|
||||
|
||||
findPackageInSymbols(classId.packageFqName.asString())?.let {
|
||||
(it.element as Symbol.PackageSymbol).findClass(classId.relativeClassName.asString())?.let { javaClass ->
|
||||
javaClass.virtualFile?.let { file ->
|
||||
if (file in scope) return javaClass
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
fun findPackage(fqName: FqName, scope: GlobalSearchScope): JavaPackage? {
|
||||
javaPackages[fqName]?.let { javaPackage ->
|
||||
javaPackage.virtualFile?.let { file ->
|
||||
if (file in scope) return javaPackage
|
||||
}
|
||||
}
|
||||
|
||||
return findPackageInSymbols(fqName.asString())
|
||||
}
|
||||
|
||||
fun findSubPackages(fqName: FqName): List<JavaPackage> =
|
||||
symbols.packages
|
||||
.filterKeys { it.toString().startsWith("$fqName.") }
|
||||
.map { SymbolBasedPackage(it.value, this) } +
|
||||
javaPackages
|
||||
.filterKeys { it.isSubpackageOf(fqName) && it != fqName }
|
||||
.map { it.value }
|
||||
|
||||
fun findClassesFromPackage(fqName: FqName): List<JavaClass> =
|
||||
javaClasses
|
||||
.filterKeys { it?.parentOrNull() == fqName }
|
||||
.flatMap { it.value.withInnerClasses() } +
|
||||
elements.getPackageElement(fqName.asString())
|
||||
?.members()
|
||||
?.elements
|
||||
?.filterIsInstance(Symbol.ClassSymbol::class.java)
|
||||
?.map { SymbolBasedClass(it, this, it.classfile) }
|
||||
.orEmpty()
|
||||
|
||||
fun knownClassNamesInPackage(fqName: FqName): Set<String> =
|
||||
javaClasses.filterKeys { it?.parentOrNull() == fqName }
|
||||
.mapTo(hashSetOf()) { it.value.name.asString() } +
|
||||
elements.getPackageElement(fqName.asString())
|
||||
?.members_field
|
||||
?.elements
|
||||
?.filterIsInstance<Symbol.ClassSymbol>()
|
||||
?.map { it.name.toString() }
|
||||
.orEmpty()
|
||||
|
||||
fun getTreePath(tree: JCTree, compilationUnit: CompilationUnitTree): TreePath =
|
||||
trees.getPath(compilationUnit, tree)
|
||||
|
||||
fun getKotlinClassifier(fqName: FqName): JavaClass? =
|
||||
kotlinClassifiersCache.getKotlinClassifier(fqName)
|
||||
|
||||
fun isDeprecated(element: Element) = elements.isDeprecated(element)
|
||||
|
||||
fun isDeprecated(typeMirror: TypeMirror) = isDeprecated(types.asElement(typeMirror))
|
||||
|
||||
fun resolve(treePath: TreePath): JavaClassifier? =
|
||||
treePathResolverCache.resolve(treePath)
|
||||
|
||||
fun toVirtualFile(javaFileObject: JavaFileObject): VirtualFile? =
|
||||
javaFileObject.toUri().let { uri ->
|
||||
if (uri.scheme == "jar") {
|
||||
environment.findJarFile(uri.schemeSpecificPart.substring("file:".length))
|
||||
}
|
||||
else {
|
||||
environment.findLocalFile(uri.schemeSpecificPart)
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <reified T> Iterable<T>.toJavacList() = JavacList.from(this)
|
||||
|
||||
private fun findClassInSymbols(fqName: String): SymbolBasedClass? {
|
||||
if (symbolBasedClassesCache.containsKey(fqName)) return symbolBasedClassesCache[fqName]
|
||||
|
||||
elements.getTypeElement(fqName)?.let { symbol ->
|
||||
SymbolBasedClass(symbol, this, symbol.classfile)
|
||||
}.let { symbolBasedClass ->
|
||||
symbolBasedClassesCache[fqName] = symbolBasedClass
|
||||
return symbolBasedClass
|
||||
}
|
||||
}
|
||||
|
||||
private fun findPackageInSymbols(fqName: String): SymbolBasedPackage? {
|
||||
if (symbolBasedPackagesCache.containsKey(fqName)) return symbolBasedPackagesCache[fqName]
|
||||
|
||||
elements.getPackageElement(fqName)?.let { symbol ->
|
||||
SymbolBasedPackage(symbol, this)
|
||||
}.let { symbolBasedPackage ->
|
||||
symbolBasedPackagesCache[fqName] = symbolBasedPackage
|
||||
return symbolBasedPackage
|
||||
}
|
||||
}
|
||||
|
||||
private fun JavacFileManager.setClassPathForCompilation(outDir: File?) = apply {
|
||||
(outDir ?: environment.configuration[JVMConfigurationKeys.OUTPUT_DIRECTORY])?.let { outputDir ->
|
||||
outputDir.mkdirs()
|
||||
fileManager.setLocation(StandardLocation.CLASS_OUTPUT, listOf(outputDir))
|
||||
}
|
||||
|
||||
val reader = ClassReader.instance(context)
|
||||
val names = Names.instance(context)
|
||||
val outDirName = getLocation(StandardLocation.CLASS_OUTPUT)?.firstOrNull()?.path ?: ""
|
||||
|
||||
list(StandardLocation.CLASS_OUTPUT, "", setOf(JavaFileObject.Kind.CLASS), true)
|
||||
.forEach { fileObject ->
|
||||
val fqName = fileObject.name
|
||||
.substringAfter(outDirName)
|
||||
.substringBefore(".class")
|
||||
.replace(File.separator, ".")
|
||||
.let { className ->
|
||||
if (className.startsWith(".")) className.substring(1) else className
|
||||
}.let(names::fromString)
|
||||
|
||||
symbols.classes[fqName]?.let { symbols.classes[fqName] = null }
|
||||
val symbol = reader.enterClass(fqName, fileObject)
|
||||
|
||||
(elements.getPackageOf(symbol) as? Symbol.PackageSymbol)?.let { packageSymbol ->
|
||||
packageSymbol.members_field.enter(symbol)
|
||||
packageSymbol.flags_field = packageSymbol.flags_field or Flags.EXISTS.toLong()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun TreeBasedClass.withInnerClasses(): List<TreeBasedClass> =
|
||||
listOf(this) + innerClasses.values.flatMap { it.withInnerClasses() }
|
||||
|
||||
private fun Symbol.PackageSymbol.findClass(name: String): SymbolBasedClass? {
|
||||
val nameParts = name.replace("$", ".").split(".")
|
||||
var symbol = members_field.getElementsByName(names.fromString(nameParts.first()))
|
||||
?.firstOrNull() as? Symbol.ClassSymbol ?: return null
|
||||
if (nameParts.size > 1) {
|
||||
symbol.complete()
|
||||
for (it in nameParts.drop(1)) {
|
||||
symbol = symbol.members_field?.getElementsByName(names.fromString(it))?.firstOrNull() as? Symbol.ClassSymbol ?: return null
|
||||
symbol.complete()
|
||||
}
|
||||
}
|
||||
|
||||
return symbol?.let { SymbolBasedClass(it, this@JavacWrapper, it.classfile) }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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 com.intellij.mock.MockProject
|
||||
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import java.io.File
|
||||
|
||||
object JavacWrapperRegistrar {
|
||||
|
||||
private const val JAVAC_CONTEXT_CLASS = "com.sun.tools.javac.util.Context"
|
||||
|
||||
fun registerJavac(environment: KotlinCoreEnvironment,
|
||||
javaFiles: List<File>,
|
||||
kotlinFiles: List<KtFile>,
|
||||
arguments: Array<String>?): Boolean {
|
||||
try {
|
||||
Class.forName(JAVAC_CONTEXT_CLASS)
|
||||
} catch (e: ClassNotFoundException) {
|
||||
environment.configuration[CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY]
|
||||
?.report(CompilerMessageSeverity.STRONG_WARNING,
|
||||
"'$JAVAC_CONTEXT_CLASS' class can't be found ('tools.jar' is not found). ")
|
||||
return false
|
||||
}
|
||||
|
||||
(environment.project as MockProject).registerService(JavacWrapper::class.java,
|
||||
JavacWrapper(javaFiles, kotlinFiles, arguments, environment))
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* 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.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
|
||||
import org.jetbrains.kotlin.load.java.structure.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
import org.jetbrains.kotlin.javac.wrappers.trees.find
|
||||
import org.jetbrains.kotlin.javac.wrappers.trees.findInner
|
||||
import org.jetbrains.kotlin.javac.wrappers.trees.tryToResolveByFqName
|
||||
import org.jetbrains.kotlin.javac.wrappers.trees.tryToResolveInJavaLang
|
||||
|
||||
class KotlinClassifiersCache(sourceFiles: Collection<KtFile>,
|
||||
private val javac: JavacWrapper) {
|
||||
|
||||
private val kotlinClasses: Map<FqName?, KtClassOrObject?> = sourceFiles.flatMap { ktFile ->
|
||||
ktFile.collectDescendantsOfType<KtClassOrObject>().map { it.fqName to it } +
|
||||
(ktFile.javaFileFacadeFqName to null)
|
||||
}.toMap()
|
||||
|
||||
private val classifiers = hashMapOf<FqName, JavaClass>()
|
||||
|
||||
fun getKotlinClassifier(fqName: FqName) = classifiers[fqName] ?: createClassifier(fqName)
|
||||
|
||||
private fun createClassifier(fqName: FqName): JavaClass? {
|
||||
if (!kotlinClasses.containsKey(fqName)) return null
|
||||
val kotlinClassifier = kotlinClasses[fqName] ?: return null
|
||||
|
||||
return MockKotlinClassifier(fqName,
|
||||
kotlinClassifier,
|
||||
kotlinClassifier.typeParameters.isNotEmpty(),
|
||||
javac)
|
||||
.apply { classifiers[fqName] = this }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class MockKotlinClassifier(override val fqName: FqName,
|
||||
private val classOrObject: KtClassOrObject,
|
||||
val hasTypeParameters: Boolean,
|
||||
private val javac: JavacWrapper) : JavaClass {
|
||||
|
||||
override val isAbstract: Boolean
|
||||
get() = throw UnsupportedOperationException("Should not be called")
|
||||
|
||||
override val isStatic: Boolean
|
||||
get() = throw UnsupportedOperationException("Should not be called")
|
||||
|
||||
override val isFinal: Boolean
|
||||
get() = throw UnsupportedOperationException("Should not be called")
|
||||
|
||||
override val visibility: Visibility
|
||||
get() = throw UnsupportedOperationException("Should not be called")
|
||||
|
||||
override val typeParameters: List<JavaTypeParameter>
|
||||
get() = throw UnsupportedOperationException("Should not be called")
|
||||
|
||||
override val supertypes: Collection<JavaClassifierType>
|
||||
get() = classOrObject.superTypeListEntries
|
||||
.mapNotNull { superTypeListEntry ->
|
||||
val userType = superTypeListEntry.typeAsUserType
|
||||
arrayListOf<String>().apply {
|
||||
userType?.referencedName?.let { add(it) }
|
||||
var qualifier = userType?.qualifier
|
||||
while (qualifier != null) {
|
||||
qualifier.referencedName?.let { add(it) }
|
||||
qualifier = qualifier.qualifier
|
||||
}
|
||||
}.reversed().joinToString(separator = ".") { it }
|
||||
}
|
||||
.mapNotNull { resolveSupertype(it, classOrObject, javac) }
|
||||
.map { MockKotlinClassifierType(it) }
|
||||
|
||||
val innerClasses: Collection<JavaClass>
|
||||
get() = classOrObject.declarations.filterIsInstance<KtClassOrObject>()
|
||||
.mapNotNull { nestedClassOrObject ->
|
||||
nestedClassOrObject.fqName?.let {
|
||||
javac.getKotlinClassifier(it)
|
||||
}
|
||||
}
|
||||
|
||||
override val outerClass: JavaClass?
|
||||
get() = throw UnsupportedOperationException("Should not be called")
|
||||
|
||||
override val isInterface: Boolean
|
||||
get() = throw UnsupportedOperationException("Should not be called")
|
||||
|
||||
override val isAnnotationType: Boolean
|
||||
get() = throw UnsupportedOperationException("Should not be called")
|
||||
|
||||
override val isEnum: Boolean
|
||||
get() = throw UnsupportedOperationException("Should not be called")
|
||||
|
||||
override val lightClassOriginKind
|
||||
get() = LightClassOriginKind.SOURCE
|
||||
|
||||
override val methods: Collection<JavaMethod>
|
||||
get() = throw UnsupportedOperationException("Should not be called")
|
||||
|
||||
override val fields: Collection<JavaField>
|
||||
get() = throw UnsupportedOperationException("Should not be called")
|
||||
|
||||
override val constructors: Collection<JavaConstructor>
|
||||
get() = throw UnsupportedOperationException("Should not be called")
|
||||
|
||||
override val name
|
||||
get() = fqName.shortNameOrSpecial()
|
||||
|
||||
override val annotations
|
||||
get() = throw UnsupportedOperationException("Should not be called")
|
||||
|
||||
override val isDeprecatedInJavaDoc: Boolean
|
||||
get() = throw UnsupportedOperationException("Should not be called")
|
||||
|
||||
override fun findAnnotation(fqName: FqName) =
|
||||
throw UnsupportedOperationException("Should not be called")
|
||||
|
||||
override val innerClassNames
|
||||
get() = innerClasses.map(JavaClass::name)
|
||||
|
||||
override fun findInnerClass(name: Name) =
|
||||
innerClasses.find { it.name == name }
|
||||
|
||||
}
|
||||
|
||||
class MockKotlinClassifierType(override val classifier: JavaClassifier) : JavaClassifierType {
|
||||
|
||||
override val typeArguments: List<JavaType>
|
||||
get() = throw UnsupportedOperationException("Should not be called")
|
||||
|
||||
override val isRaw: Boolean
|
||||
get() = throw UnsupportedOperationException("Should not be called")
|
||||
|
||||
override val annotations: Collection<JavaAnnotation>
|
||||
get() = throw UnsupportedOperationException("Should not be called")
|
||||
|
||||
override val classifierQualifiedName: String
|
||||
get() = throw UnsupportedOperationException("Should not be called")
|
||||
|
||||
override val presentableText: String
|
||||
get() = throw UnsupportedOperationException("Should not be called")
|
||||
|
||||
override fun findAnnotation(fqName: FqName) =
|
||||
throw UnsupportedOperationException("Should not be called")
|
||||
|
||||
override val isDeprecatedInJavaDoc: Boolean
|
||||
get() = throw UnsupportedOperationException("Should not be called")
|
||||
|
||||
}
|
||||
|
||||
private fun resolveSupertype(name: String,
|
||||
classOrObject: KtClassOrObject,
|
||||
javac: JavacWrapper): JavaClass? {
|
||||
val nameParts = name.split(".")
|
||||
val ktFile = classOrObject.containingKtFile
|
||||
|
||||
tryToResolveInner(name, classOrObject, javac, nameParts)?.let { return it }
|
||||
ktFile.tryToResolvePackageClass(name, javac, nameParts)?.let { return it }
|
||||
tryToResolveByFqName(name, javac)?.let { return it }
|
||||
ktFile.tryToResolveSingleTypeImport(name, javac, nameParts)?.let { return it }
|
||||
ktFile.tryToResolveTypeImportOnDemand(name, javac, nameParts)?.let { return it }
|
||||
tryToResolveInJavaLang(name, javac)?.let { return it }
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private fun tryToResolveInner(name: String,
|
||||
classOrObject: KtClassOrObject,
|
||||
javac: JavacWrapper,
|
||||
nameParts: List<String>) =
|
||||
classOrObject.containingClassOrObject?.let { containingClass ->
|
||||
containingClass.fqName?.let {
|
||||
javac.findClass(it) ?: javac.getKotlinClassifier(it)
|
||||
}
|
||||
}?.findInner(name, javac, nameParts)
|
||||
|
||||
private fun KtFile.tryToResolvePackageClass(name: String,
|
||||
javac: JavacWrapper,
|
||||
nameParts: List<String> = emptyList()): JavaClass? {
|
||||
if (nameParts.size > 1) {
|
||||
return find(FqName("${packageFqName.asString()}.${nameParts.first()}"), javac, nameParts)
|
||||
}
|
||||
else {
|
||||
return javac.findClass(FqName("${packageFqName.asString()}.$name"))
|
||||
?: javac.getKotlinClassifier(FqName("${packageFqName.asString()}.$name"))
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtFile.tryToResolveSingleTypeImport(name: String,
|
||||
javac: JavacWrapper,
|
||||
nameParts: List<String> = emptyList()): JavaClass? {
|
||||
if (nameParts.size > 1) {
|
||||
val foundImports = importDirectives.filter { it.text.endsWith(".${nameParts.first()}") }
|
||||
foundImports.forEach { importDirective ->
|
||||
importDirective.importedFqName?.let { importedFqName ->
|
||||
find(importedFqName, javac, nameParts)?.let { importedClass ->
|
||||
return importedClass
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
else {
|
||||
return importDirectives.find { importDirective ->
|
||||
importDirective.text.endsWith(".$name")
|
||||
}?.let { importDirective ->
|
||||
importDirective.importedFqName?.let { fqName ->
|
||||
javac.findClass(fqName) ?: javac.getKotlinClassifier(fqName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtFile.tryToResolveTypeImportOnDemand(name: String,
|
||||
javac: JavacWrapper,
|
||||
nameParts: List<String> = emptyList()): JavaClass? {
|
||||
val packagesWithAsterisk = importDirectives.filter { it.text.endsWith("*") }
|
||||
|
||||
if (nameParts.size > 1) {
|
||||
packagesWithAsterisk.forEach { importDirective ->
|
||||
find(FqName("${importDirective.importedFqName?.asString()}.${nameParts.first()}"),
|
||||
javac,
|
||||
nameParts)?.let { return it }
|
||||
}
|
||||
return null
|
||||
}
|
||||
else {
|
||||
packagesWithAsterisk.forEach { importDirective ->
|
||||
val fqName = "${importDirective.importedFqName?.asString()}.$name".let(::FqName)
|
||||
javac.findClass(fqName)?.let { return it } ?: javac.getKotlinClassifier(fqName)?.let { return it }
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.components
|
||||
|
||||
import org.jetbrains.kotlin.javac.JavacWrapper
|
||||
import org.jetbrains.kotlin.load.java.AbstractJavaClassFinder
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer
|
||||
|
||||
class JavacBasedClassFinder : AbstractJavaClassFinder() {
|
||||
|
||||
private lateinit var javac: JavacWrapper
|
||||
|
||||
override fun initialize(trace: BindingTrace, codeAnalyzer: KotlinCodeAnalyzer) {
|
||||
javac = JavacWrapper.getInstance(project)
|
||||
super.initialize(trace, codeAnalyzer)
|
||||
}
|
||||
|
||||
override fun findClass(classId: ClassId) = javac.findClass(classId, javaSearchScope)
|
||||
|
||||
override fun findPackage(fqName: FqName) = javac.findPackage(fqName, javaSearchScope)
|
||||
|
||||
override fun knownClassNamesInPackage(packageFqName: FqName) = javac.knownClassNamesInPackage(packageFqName)
|
||||
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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.components
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.SourceFile
|
||||
import org.jetbrains.kotlin.load.java.sources.JavaSourceElement
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaElement
|
||||
|
||||
class JavacBasedSourceElement(override val javaElement: JavaElement) : JavaSourceElement {
|
||||
|
||||
override fun getContainingFile(): SourceFile = SourceFile.NO_SOURCE_FILE
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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.components
|
||||
|
||||
import org.jetbrains.kotlin.load.java.sources.JavaSourceElementFactory
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaElement
|
||||
|
||||
class JavacBasedSourceElementFactory : JavaSourceElementFactory {
|
||||
|
||||
override fun source(javaElement: JavaElement) = JavacBasedSourceElement(javaElement)
|
||||
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.components
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.load.java.components.AbstractJavaResolverCache
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaElement
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaField
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaMethod
|
||||
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
|
||||
|
||||
class StubJavaResolverCache(resolveSession: ResolveSession) : AbstractJavaResolverCache(resolveSession) {
|
||||
|
||||
override fun recordMethod(method: JavaMethod, descriptor: SimpleFunctionDescriptor) {}
|
||||
|
||||
override fun recordConstructor(element: JavaElement, descriptor: ConstructorDescriptor) {}
|
||||
|
||||
override fun recordField(field: JavaField, descriptor: PropertyDescriptor) {}
|
||||
|
||||
override fun recordClass(javaClass: JavaClass, descriptor: ClassDescriptor) {}
|
||||
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.wrappers.symbols
|
||||
|
||||
import com.sun.tools.javac.code.Symbol
|
||||
import org.jetbrains.kotlin.javac.JavacWrapper
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaAnnotationArgument
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaElement
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import javax.lang.model.element.AnnotationMirror
|
||||
import javax.lang.model.element.TypeElement
|
||||
|
||||
open class SymbolBasedAnnotation(
|
||||
val annotationMirror: AnnotationMirror,
|
||||
val javac: JavacWrapper
|
||||
) : JavaElement, JavaAnnotation {
|
||||
|
||||
override val arguments: Collection<JavaAnnotationArgument>
|
||||
get() = annotationMirror.elementValues.map { (key, value) ->
|
||||
SymbolBasedAnnotationArgument.create(value.value, Name.identifier(key.simpleName.toString()), javac)
|
||||
}
|
||||
|
||||
override val classId: ClassId?
|
||||
get() = (annotationMirror.annotationType.asElement() as? TypeElement)?.computeClassId()
|
||||
|
||||
override fun resolve() = with(annotationMirror.annotationType.asElement() as Symbol.ClassSymbol) {
|
||||
SymbolBasedClass(this, javac, classfile)
|
||||
}
|
||||
|
||||
}
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* 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.wrappers.symbols
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.CommonClassNames
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.javac.JavacWrapper
|
||||
import org.jetbrains.kotlin.load.java.structure.*
|
||||
import org.jetbrains.kotlin.load.java.structure.impl.VirtualFileBoundJavaClass
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import javax.lang.model.element.ElementKind
|
||||
import javax.lang.model.element.ExecutableElement
|
||||
import javax.lang.model.element.TypeElement
|
||||
import javax.lang.model.element.VariableElement
|
||||
import javax.lang.model.type.NoType
|
||||
import javax.lang.model.type.TypeKind
|
||||
import javax.tools.JavaFileObject
|
||||
|
||||
class SymbolBasedClass(
|
||||
element: TypeElement,
|
||||
javac: JavacWrapper,
|
||||
val file: JavaFileObject?
|
||||
) : SymbolBasedClassifier<TypeElement>(element, javac), VirtualFileBoundJavaClass {
|
||||
|
||||
override val name: Name
|
||||
get() = Name.identifier(element.simpleName.toString())
|
||||
|
||||
override val isAbstract: Boolean
|
||||
get() = element.isAbstract
|
||||
|
||||
override val isStatic: Boolean
|
||||
get() = element.isStatic
|
||||
|
||||
override val isFinal: Boolean
|
||||
get() = element.isFinal
|
||||
|
||||
override val visibility: Visibility
|
||||
get() = element.getVisibility()
|
||||
|
||||
override val typeParameters: List<JavaTypeParameter>
|
||||
get() = element.typeParameters.map { SymbolBasedTypeParameter(it, javac) }
|
||||
|
||||
override val fqName: FqName
|
||||
get() = FqName(element.qualifiedName.toString())
|
||||
|
||||
override val supertypes: Collection<JavaClassifierType>
|
||||
get() = element.interfaces.toMutableList()
|
||||
.apply {
|
||||
element.superclass.takeIf { it !is NoType }?.let(this::add)
|
||||
}
|
||||
.mapTo(arrayListOf()) { SymbolBasedClassifierType(it, javac) }
|
||||
.apply {
|
||||
if (isEmpty() && element.qualifiedName.toString() != CommonClassNames.JAVA_LANG_OBJECT) {
|
||||
javac.JAVA_LANG_OBJECT?.let { add(it) }
|
||||
}
|
||||
}
|
||||
|
||||
val innerClasses: Map<Name, JavaClass>
|
||||
get() = element.enclosedElements
|
||||
.filterIsInstance(TypeElement::class.java)
|
||||
.map { SymbolBasedClass(it, javac, file) }
|
||||
.associateBy(JavaClass::name)
|
||||
|
||||
override val outerClass: JavaClass?
|
||||
get() = element.enclosingElement?.let {
|
||||
if (it.asType().kind != TypeKind.DECLARED) null else SymbolBasedClass(it as TypeElement, javac, file)
|
||||
}
|
||||
|
||||
override val isInterface: Boolean
|
||||
get() = element.kind == ElementKind.INTERFACE
|
||||
|
||||
override val isAnnotationType: Boolean
|
||||
get() = element.kind == ElementKind.ANNOTATION_TYPE
|
||||
|
||||
override val isEnum: Boolean
|
||||
get() = element.kind == ElementKind.ENUM
|
||||
|
||||
override val lightClassOriginKind: LightClassOriginKind?
|
||||
get() = null
|
||||
|
||||
override val methods: Collection<JavaMethod>
|
||||
get() = element.enclosedElements
|
||||
.filter { it.kind == ElementKind.METHOD }
|
||||
.map { SymbolBasedMethod(it as ExecutableElement, javac) }
|
||||
|
||||
override val fields: Collection<JavaField>
|
||||
get() = element.enclosedElements
|
||||
.filter { it.kind.isField && Name.isValidIdentifier(it.simpleName.toString()) }
|
||||
.map { SymbolBasedField(it as VariableElement, javac) }
|
||||
|
||||
override val constructors: Collection<JavaConstructor>
|
||||
get() = element.enclosedElements
|
||||
.filter { it.kind == ElementKind.CONSTRUCTOR }
|
||||
.map { SymbolBasedConstructor(it as ExecutableElement, javac) }
|
||||
|
||||
override val innerClassNames: Collection<Name>
|
||||
get() = innerClasses.keys
|
||||
|
||||
override val virtualFile: VirtualFile? by lazy {
|
||||
file?.let { javac.toVirtualFile(it) }
|
||||
}
|
||||
|
||||
override fun findInnerClass(name: Name) = innerClasses[name]
|
||||
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.wrappers.symbols
|
||||
|
||||
import org.jetbrains.kotlin.javac.JavacWrapper
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaAnnotationOwner
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClassifier
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import javax.lang.model.element.Element
|
||||
|
||||
abstract class SymbolBasedClassifier<out T : Element>(
|
||||
element: T,
|
||||
javac: JavacWrapper
|
||||
) : SymbolBasedElement<T>(element, javac), JavaClassifier, JavaAnnotationOwner {
|
||||
|
||||
override val annotations: Collection<JavaAnnotation>
|
||||
get() = element.annotationMirrors.map { SymbolBasedAnnotation(it, javac) }
|
||||
|
||||
override fun findAnnotation(fqName: FqName) = element.findAnnotation(fqName, javac)
|
||||
|
||||
override val isDeprecatedInJavaDoc: Boolean
|
||||
get() = javac.isDeprecated(element)
|
||||
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.wrappers.symbols
|
||||
|
||||
import org.jetbrains.kotlin.javac.JavacWrapper
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaConstructor
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaValueParameter
|
||||
import javax.lang.model.element.ExecutableElement
|
||||
|
||||
class SymbolBasedConstructor(
|
||||
element: ExecutableElement,
|
||||
javac: JavacWrapper
|
||||
) : SymbolBasedMember<ExecutableElement>(element, javac), JavaConstructor {
|
||||
|
||||
override val typeParameters: List<JavaTypeParameter>
|
||||
get() = element.typeParameters.map { SymbolBasedTypeParameter(it, javac) }
|
||||
|
||||
override val valueParameters: List<JavaValueParameter>
|
||||
get() = element.valueParameters(javac)
|
||||
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.wrappers.symbols
|
||||
|
||||
import org.jetbrains.kotlin.javac.JavacWrapper
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaElement
|
||||
import javax.lang.model.element.Element
|
||||
|
||||
open class SymbolBasedElement<out T : Element>(
|
||||
val element: T,
|
||||
val javac: JavacWrapper
|
||||
) : JavaElement {
|
||||
|
||||
override fun equals(other: Any?) = (other as? SymbolBasedElement<*>)?.element == element
|
||||
|
||||
override fun hashCode() = element.hashCode()
|
||||
|
||||
override fun toString() = element.simpleName.toString()
|
||||
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.wrappers.symbols
|
||||
|
||||
import org.jetbrains.kotlin.javac.JavacWrapper
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaField
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaType
|
||||
import javax.lang.model.element.ElementKind
|
||||
import javax.lang.model.element.TypeElement
|
||||
import javax.lang.model.element.VariableElement
|
||||
import javax.lang.model.type.DeclaredType
|
||||
|
||||
class SymbolBasedField(
|
||||
element: VariableElement,
|
||||
javac: JavacWrapper
|
||||
) : SymbolBasedMember<VariableElement>(element, javac), JavaField {
|
||||
|
||||
override val isEnumEntry: Boolean
|
||||
get() = element.kind == ElementKind.ENUM_CONSTANT
|
||||
|
||||
override val type: JavaType
|
||||
get() = SymbolBasedType.create(element.asType(), javac)
|
||||
|
||||
override val initializerValue: Any?
|
||||
get() = element.constantValue
|
||||
|
||||
override val hasConstantNotNullInitializer: Boolean
|
||||
get() = element.constantValue != null && element.asType().let {
|
||||
it.kind.isPrimitive ||
|
||||
((it as? DeclaredType)?.asElement() as? TypeElement)?.qualifiedName?.toString() == "java.lang.String"
|
||||
}
|
||||
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.wrappers.symbols
|
||||
|
||||
import com.sun.tools.javac.code.Symbol
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.javac.JavacWrapper
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaMember
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import javax.lang.model.element.Element
|
||||
|
||||
abstract class SymbolBasedMember<out T : Element>(
|
||||
element: T,
|
||||
javac: JavacWrapper
|
||||
) : SymbolBasedElement<T>(element, javac), JavaMember {
|
||||
|
||||
override val containingClass: JavaClass
|
||||
get() = with(element.enclosingElement as Symbol.ClassSymbol) {
|
||||
SymbolBasedClass(this, javac, classfile)
|
||||
}
|
||||
|
||||
override val annotations: Collection<JavaAnnotation>
|
||||
get() = element.annotationMirrors.map { SymbolBasedAnnotation(it, javac) }
|
||||
|
||||
override fun findAnnotation(fqName: FqName) = element.findAnnotation(fqName, javac)
|
||||
|
||||
override val visibility: Visibility
|
||||
get() = element.getVisibility()
|
||||
|
||||
override val name: Name
|
||||
get() = Name.identifier(element.simpleName.toString())
|
||||
|
||||
override val isDeprecatedInJavaDoc: Boolean
|
||||
get() = javac.isDeprecated(element)
|
||||
|
||||
override val isAbstract: Boolean
|
||||
get() = element.isAbstract
|
||||
|
||||
override val isStatic: Boolean
|
||||
get() = element.isStatic
|
||||
|
||||
override val isFinal: Boolean
|
||||
get() = element.isFinal
|
||||
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.wrappers.symbols
|
||||
|
||||
import org.jetbrains.kotlin.javac.JavacWrapper
|
||||
import org.jetbrains.kotlin.load.java.structure.*
|
||||
import javax.lang.model.element.ExecutableElement
|
||||
|
||||
class SymbolBasedMethod(
|
||||
element: ExecutableElement,
|
||||
javac: JavacWrapper
|
||||
) : SymbolBasedMember<ExecutableElement>(element, javac), JavaMethod {
|
||||
|
||||
override val typeParameters: List<JavaTypeParameter>
|
||||
get() = element.typeParameters.map { SymbolBasedTypeParameter(it, javac) }
|
||||
|
||||
override val valueParameters: List<JavaValueParameter>
|
||||
get() = element.valueParameters(javac)
|
||||
|
||||
override val returnType: JavaType
|
||||
get() = SymbolBasedType.create(element.returnType, javac)
|
||||
|
||||
override val hasAnnotationParameterDefaultValue: Boolean
|
||||
get() = element.defaultValue != null
|
||||
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.wrappers.symbols
|
||||
|
||||
import org.jetbrains.kotlin.javac.JavacWrapper
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaPackage
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import javax.lang.model.element.PackageElement
|
||||
|
||||
class SymbolBasedPackage(
|
||||
element: PackageElement,
|
||||
javac: JavacWrapper
|
||||
) : SymbolBasedElement<PackageElement>(element, javac), JavaPackage {
|
||||
|
||||
override val fqName: FqName
|
||||
get() = FqName(element.qualifiedName.toString())
|
||||
|
||||
override val subPackages: Collection<JavaPackage>
|
||||
get() = javac.findSubPackages(FqName(element.qualifiedName.toString()))
|
||||
|
||||
override fun getClasses(nameFilter: (Name) -> Boolean) =
|
||||
javac.findClassesFromPackage(fqName).filter { nameFilter(it.name) }
|
||||
|
||||
override fun toString() = element.qualifiedName.toString()
|
||||
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.wrappers.symbols
|
||||
|
||||
import org.jetbrains.kotlin.javac.JavacWrapper
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClassifierType
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import javax.lang.model.element.TypeParameterElement
|
||||
|
||||
class SymbolBasedTypeParameter(
|
||||
element: TypeParameterElement,
|
||||
javac: JavacWrapper
|
||||
) : SymbolBasedClassifier<TypeParameterElement>(element, javac), JavaTypeParameter {
|
||||
|
||||
override val name: Name
|
||||
get() = Name.identifier(element.simpleName.toString())
|
||||
|
||||
override val upperBounds: Collection<JavaClassifierType>
|
||||
get() = element.bounds.map { SymbolBasedClassifierType(it, javac) }
|
||||
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.wrappers.symbols
|
||||
|
||||
import org.jetbrains.kotlin.javac.JavacWrapper
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaType
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaValueParameter
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import javax.lang.model.element.VariableElement
|
||||
|
||||
class SymbolBasedValueParameter(
|
||||
element: VariableElement,
|
||||
private val elementName : String,
|
||||
override val isVararg : Boolean,
|
||||
javac: JavacWrapper
|
||||
) : SymbolBasedElement<VariableElement>(element, javac), JavaValueParameter {
|
||||
|
||||
override val annotations: Collection<JavaAnnotation>
|
||||
get() = element.annotationMirrors.map { SymbolBasedAnnotation(it, javac) }
|
||||
|
||||
override fun findAnnotation(fqName: FqName) =
|
||||
element.findAnnotation(fqName, javac)
|
||||
|
||||
override val isDeprecatedInJavaDoc: Boolean
|
||||
get() = javac.isDeprecated(element)
|
||||
|
||||
override val name: Name
|
||||
get() = Name.identifier(elementName)
|
||||
|
||||
override val type: JavaType
|
||||
get() = SymbolBasedType.create(element.asType(), javac)
|
||||
|
||||
}
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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.wrappers.symbols
|
||||
|
||||
import org.jetbrains.kotlin.javac.JavacWrapper
|
||||
import org.jetbrains.kotlin.load.java.structure.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import javax.lang.model.element.AnnotationMirror
|
||||
import javax.lang.model.element.AnnotationValue
|
||||
import javax.lang.model.element.VariableElement
|
||||
import javax.lang.model.type.TypeMirror
|
||||
|
||||
sealed class SymbolBasedAnnotationArgument(
|
||||
override val name: Name,
|
||||
val javac: JavacWrapper
|
||||
) : JavaAnnotationArgument, JavaElement {
|
||||
|
||||
companion object {
|
||||
fun create(value: Any, name: Name, javac: JavacWrapper): JavaAnnotationArgument = when (value) {
|
||||
is AnnotationMirror -> SymbolBasedAnnotationAsAnnotationArgument(value, name, javac)
|
||||
is VariableElement -> SymbolBasedReferenceAnnotationArgument(value, javac)
|
||||
is TypeMirror -> SymbolBasedClassObjectAnnotationArgument(value, name, javac)
|
||||
is Collection<*> -> arrayAnnotationArguments(value, name, javac)
|
||||
is AnnotationValue -> create(value.value, name, javac)
|
||||
else -> SymbolBasedLiteralAnnotationArgument(value, name, javac)
|
||||
}
|
||||
|
||||
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) }
|
||||
.let { argumentList -> SymbolBasedArrayAnnotationArgument(argumentList, name, javac) }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class SymbolBasedAnnotationAsAnnotationArgument(
|
||||
val mirror: AnnotationMirror,
|
||||
name: Name,
|
||||
javac: JavacWrapper
|
||||
) : SymbolBasedAnnotationArgument(name, javac), JavaAnnotationAsAnnotationArgument {
|
||||
|
||||
override fun getAnnotation() = SymbolBasedAnnotation(mirror, javac)
|
||||
|
||||
}
|
||||
|
||||
class SymbolBasedReferenceAnnotationArgument(
|
||||
val element: VariableElement,
|
||||
javac: JavacWrapper
|
||||
) : SymbolBasedAnnotationArgument(Name.identifier(element.simpleName.toString()), javac), JavaEnumValueAnnotationArgument {
|
||||
|
||||
override fun resolve() = SymbolBasedField(element, javac)
|
||||
|
||||
}
|
||||
|
||||
class SymbolBasedClassObjectAnnotationArgument(
|
||||
val type: TypeMirror,
|
||||
name : Name,
|
||||
javac: JavacWrapper
|
||||
) : SymbolBasedAnnotationArgument(name, javac), JavaClassObjectAnnotationArgument {
|
||||
|
||||
override fun getReferencedType() = SymbolBasedType.create(type, javac)
|
||||
|
||||
}
|
||||
|
||||
class SymbolBasedArrayAnnotationArgument(
|
||||
val args : List<JavaAnnotationArgument>,
|
||||
name : Name,
|
||||
javac: JavacWrapper
|
||||
) : SymbolBasedAnnotationArgument(name, javac), JavaArrayAnnotationArgument {
|
||||
|
||||
override fun getElements() = args
|
||||
|
||||
}
|
||||
|
||||
class SymbolBasedLiteralAnnotationArgument(
|
||||
override val value : Any,
|
||||
name : Name,
|
||||
javac: JavacWrapper
|
||||
) : SymbolBasedAnnotationArgument(name, javac), JavaLiteralAnnotationArgument
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* 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.wrappers.symbols
|
||||
|
||||
import com.sun.tools.javac.code.Symbol
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||
import org.jetbrains.kotlin.javac.JavacWrapper
|
||||
import org.jetbrains.kotlin.load.java.structure.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
|
||||
import javax.lang.model.element.TypeElement
|
||||
import javax.lang.model.element.TypeParameterElement
|
||||
import javax.lang.model.type.*
|
||||
|
||||
sealed class SymbolBasedType<out T : TypeMirror>(
|
||||
val typeMirror: T,
|
||||
val javac: JavacWrapper
|
||||
) : JavaType, JavaAnnotationOwner {
|
||||
|
||||
companion object {
|
||||
fun <T : TypeMirror> create(t: T, javac: JavacWrapper) = when {
|
||||
t.kind.isPrimitive || t.kind == TypeKind.VOID -> SymbolBasedPrimitiveType(t, javac)
|
||||
t.kind == TypeKind.DECLARED || t.kind == TypeKind.TYPEVAR -> SymbolBasedClassifierType(t, javac)
|
||||
t.kind == TypeKind.WILDCARD -> SymbolBasedWildcardType(t as WildcardType, javac)
|
||||
t.kind == TypeKind.ARRAY -> SymbolBasedArrayType(t as ArrayType, javac)
|
||||
else -> throw UnsupportedOperationException("Unsupported type: $t")
|
||||
}
|
||||
}
|
||||
|
||||
override val annotations: Collection<JavaAnnotation>
|
||||
get() = typeMirror.annotationMirrors.map { SymbolBasedAnnotation(it, javac) }
|
||||
|
||||
override val isDeprecatedInJavaDoc: Boolean
|
||||
get() = javac.isDeprecated(typeMirror)
|
||||
|
||||
override fun findAnnotation(fqName: FqName) = typeMirror.findAnnotation(fqName, javac)
|
||||
|
||||
override fun equals(other: Any?) = (other as? SymbolBasedType<*>)?.typeMirror == typeMirror
|
||||
|
||||
override fun hashCode() = typeMirror.hashCode()
|
||||
|
||||
override fun toString() = typeMirror.toString()
|
||||
|
||||
}
|
||||
|
||||
class SymbolBasedPrimitiveType(
|
||||
typeMirror: TypeMirror,
|
||||
javac: JavacWrapper
|
||||
) : SymbolBasedType<TypeMirror>(typeMirror, javac), JavaPrimitiveType {
|
||||
|
||||
override val type: PrimitiveType?
|
||||
get() = if (typeMirror.kind == TypeKind.VOID) null else JvmPrimitiveType.get(typeMirror.toString()).primitiveType
|
||||
|
||||
}
|
||||
|
||||
class SymbolBasedClassifierType<out T : TypeMirror>(
|
||||
typeMirror: T,
|
||||
javac: JavacWrapper
|
||||
) : SymbolBasedType<T>(typeMirror, javac), JavaClassifierType {
|
||||
|
||||
override val classifier: JavaClassifier?
|
||||
get() = when (typeMirror.kind) {
|
||||
TypeKind.DECLARED -> ((typeMirror as DeclaredType).asElement() as Symbol.ClassSymbol).let { symbol ->
|
||||
SymbolBasedClass(symbol, javac, symbol.classfile)
|
||||
}
|
||||
TypeKind.TYPEVAR -> SymbolBasedTypeParameter((typeMirror as TypeVariable).asElement() as TypeParameterElement, javac)
|
||||
else -> null
|
||||
}
|
||||
|
||||
override val typeArguments: List<JavaType>
|
||||
get() = if (typeMirror.kind == TypeKind.DECLARED) {
|
||||
(typeMirror as DeclaredType).typeArguments.map { create(it, javac) }
|
||||
}
|
||||
else {
|
||||
emptyList()
|
||||
}
|
||||
|
||||
override val isRaw: Boolean
|
||||
get() = when {
|
||||
typeMirror !is DeclaredType -> false
|
||||
(typeMirror.asElement() as TypeElement).typeParameters.isEmpty() -> false
|
||||
else -> typeMirror.typeArguments.isEmpty()
|
||||
}
|
||||
|
||||
override val classifierQualifiedName: String
|
||||
get() = typeMirror.toString()
|
||||
|
||||
override val presentableText: String
|
||||
get() = typeMirror.toString()
|
||||
|
||||
}
|
||||
|
||||
class SymbolBasedWildcardType(
|
||||
typeMirror: WildcardType,
|
||||
javac: JavacWrapper
|
||||
) : SymbolBasedType<WildcardType>(typeMirror, javac), JavaWildcardType {
|
||||
|
||||
override val bound: JavaType?
|
||||
get() {
|
||||
val boundMirror = typeMirror.extendsBound ?: typeMirror.superBound
|
||||
return boundMirror?.let { create(it, javac) }
|
||||
}
|
||||
|
||||
override val isExtends: Boolean
|
||||
get() = typeMirror.extendsBound != null
|
||||
|
||||
}
|
||||
|
||||
class SymbolBasedArrayType(
|
||||
typeMirror: ArrayType,
|
||||
javac: JavacWrapper
|
||||
) : SymbolBasedType<ArrayType>(typeMirror, javac), JavaArrayType {
|
||||
|
||||
override val componentType: JavaType
|
||||
get() = create(typeMirror.componentType, javac)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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.wrappers.symbols
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.javac.JavacWrapper
|
||||
import org.jetbrains.kotlin.load.java.JavaVisibilities
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaValueParameter
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import javax.lang.model.AnnotatedConstruct
|
||||
import javax.lang.model.element.*
|
||||
|
||||
internal val Element.isAbstract: Boolean
|
||||
get() = modifiers.contains(Modifier.ABSTRACT)
|
||||
|
||||
internal val Element.isStatic: Boolean
|
||||
get() = modifiers.contains(Modifier.STATIC)
|
||||
|
||||
internal val Element.isFinal: Boolean
|
||||
get() = modifiers.contains(Modifier.FINAL)
|
||||
|
||||
internal fun Element.getVisibility(): Visibility = when {
|
||||
Modifier.PUBLIC in modifiers -> Visibilities.PUBLIC
|
||||
Modifier.PRIVATE in modifiers -> Visibilities.PRIVATE
|
||||
Modifier.PROTECTED in modifiers -> {
|
||||
if (Modifier.STATIC in modifiers) {
|
||||
JavaVisibilities.PROTECTED_STATIC_VISIBILITY
|
||||
}
|
||||
else {
|
||||
JavaVisibilities.PROTECTED_AND_PACKAGE
|
||||
}
|
||||
}
|
||||
else -> JavaVisibilities.PACKAGE_VISIBILITY
|
||||
}
|
||||
|
||||
internal fun TypeElement.computeClassId(): ClassId? {
|
||||
if (enclosingElement.kind != ElementKind.PACKAGE) {
|
||||
val parentClassId = (enclosingElement as TypeElement).computeClassId() ?: return null
|
||||
return parentClassId.createNestedClassId(Name.identifier(simpleName.toString()))
|
||||
}
|
||||
|
||||
return ClassId.topLevel(FqName(qualifiedName.toString()))
|
||||
}
|
||||
|
||||
internal fun ExecutableElement.valueParameters(javac: JavacWrapper): List<JavaValueParameter> =
|
||||
parameters.mapIndexed { index, parameter ->
|
||||
SymbolBasedValueParameter(parameter,
|
||||
parameter.simpleName.toString(),
|
||||
index == parameters.lastIndex && isVarArgs,
|
||||
javac)
|
||||
}
|
||||
|
||||
internal fun AnnotatedConstruct.findAnnotation(fqName: FqName,
|
||||
javac: JavacWrapper) =
|
||||
annotationMirrors.find {
|
||||
(it.annotationType.asElement() as TypeElement).qualifiedName.toString() == fqName.asString()
|
||||
}?.let { SymbolBasedAnnotation(it, javac) }
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.wrappers.trees
|
||||
|
||||
import com.sun.source.util.TreePath
|
||||
import com.sun.tools.javac.tree.JCTree
|
||||
import org.jetbrains.kotlin.javac.JavacWrapper
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaAnnotationArgument
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaElement
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class TreeBasedAnnotation(
|
||||
val annotation: JCTree.JCAnnotation,
|
||||
val treePath: TreePath,
|
||||
val javac: JavacWrapper
|
||||
) : JavaElement, JavaAnnotation {
|
||||
|
||||
override val arguments: Collection<JavaAnnotationArgument>
|
||||
get() = annotation.arguments.map { TreeBasedAnnotationArgument(Name.identifier(it.toString())) }
|
||||
|
||||
override val classId: ClassId?
|
||||
get() = resolve()?.computeClassId()
|
||||
|
||||
override fun resolve() =
|
||||
javac.resolve(TreePath.getPath(treePath.compilationUnit, annotation.annotationType)) as? JavaClass
|
||||
|
||||
}
|
||||
|
||||
class TreeBasedAnnotationArgument(override val name: Name) : JavaAnnotationArgument, JavaElement
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* 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.wrappers.trees
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.sun.source.tree.Tree
|
||||
import com.sun.source.util.TreePath
|
||||
import com.sun.tools.javac.code.Flags
|
||||
import com.sun.tools.javac.tree.JCTree
|
||||
import com.sun.tools.javac.tree.TreeInfo
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities.PUBLIC
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.javac.JavacWrapper
|
||||
import org.jetbrains.kotlin.load.java.structure.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import javax.tools.JavaFileObject
|
||||
|
||||
class TreeBasedClass(
|
||||
tree: JCTree.JCClassDecl,
|
||||
treePath: TreePath,
|
||||
javac: JavacWrapper,
|
||||
val file: JavaFileObject
|
||||
) : TreeBasedElement<JCTree.JCClassDecl>(tree, treePath, javac), JavaClass {
|
||||
|
||||
override val name: Name
|
||||
get() = Name.identifier(tree.simpleName.toString())
|
||||
|
||||
override val annotations: Collection<JavaAnnotation> by lazy {
|
||||
tree.annotations().map { annotation -> TreeBasedAnnotation(annotation, treePath, javac) }
|
||||
}
|
||||
|
||||
override fun findAnnotation(fqName: FqName) =
|
||||
annotations.find { it.classId?.asSingleFqName() == fqName }
|
||||
|
||||
override val isDeprecatedInJavaDoc: Boolean
|
||||
get() = false
|
||||
|
||||
override val isAbstract: Boolean
|
||||
get() = tree.modifiers.isAbstract || (isAnnotationType && methods.any { it.isAbstract })
|
||||
|
||||
override val isStatic: Boolean
|
||||
get() = (outerClass?.isInterface ?: false) || tree.modifiers.isStatic
|
||||
|
||||
override val isFinal: Boolean
|
||||
get() = tree.modifiers.isFinal
|
||||
|
||||
override val visibility: Visibility
|
||||
get() = if (outerClass?.isInterface ?: false) PUBLIC else tree.modifiers.visibility
|
||||
|
||||
override val typeParameters: List<JavaTypeParameter>
|
||||
get() = tree.typeParameters.map { parameter ->
|
||||
TreeBasedTypeParameter(parameter, TreePath(treePath, parameter), javac)
|
||||
}
|
||||
|
||||
override val fqName: FqName =
|
||||
treePath.reversed()
|
||||
.filterIsInstance<JCTree.JCClassDecl>()
|
||||
.joinToString(
|
||||
separator = ".",
|
||||
prefix = "${treePath.compilationUnit.packageName}.",
|
||||
transform = JCTree.JCClassDecl::name
|
||||
)
|
||||
.let(::FqName)
|
||||
|
||||
override val supertypes: Collection<JavaClassifierType>
|
||||
get() = arrayListOf<JavaClassifierType>().apply {
|
||||
fun JCTree.mapToJavaClassifierType() = when {
|
||||
this is JCTree.JCTypeApply -> TreeBasedGenericClassifierType(this, TreePath(treePath, this), javac)
|
||||
this is JCTree.JCExpression -> TreeBasedNonGenericClassifierType(this, TreePath(treePath, this), javac)
|
||||
else -> null
|
||||
}
|
||||
|
||||
if (isEnum) {
|
||||
javac.JAVA_LANG_ENUM?.let(this::add)
|
||||
} else if (isAnnotationType) {
|
||||
javac.JAVA_LANG_ANNOTATION_ANNOTATION?.let(this::add)
|
||||
}
|
||||
|
||||
tree.implementing?.mapNotNull { it.mapToJavaClassifierType() }?.let(this::addAll)
|
||||
tree.extending?.let { it.mapToJavaClassifierType()?.let(this::add) }
|
||||
|
||||
if (isEmpty()) {
|
||||
javac.JAVA_LANG_OBJECT?.let(this::add)
|
||||
}
|
||||
}
|
||||
|
||||
val innerClasses: Map<Name, TreeBasedClass> by lazy {
|
||||
tree.members
|
||||
.filterIsInstance(JCTree.JCClassDecl::class.java)
|
||||
.map { TreeBasedClass(it, TreePath(treePath, it), javac, file) }
|
||||
.associateBy(JavaClass::name)
|
||||
}
|
||||
|
||||
override val outerClass: JavaClass? by lazy {
|
||||
(treePath.parentPath.leaf as? JCTree.JCClassDecl)?.let { classDecl ->
|
||||
TreeBasedClass(classDecl, treePath.parentPath, javac, file)
|
||||
}
|
||||
}
|
||||
|
||||
override val isInterface: Boolean
|
||||
get() = tree.modifiers.flags and Flags.INTERFACE.toLong() != 0L
|
||||
|
||||
override val isAnnotationType: Boolean
|
||||
get() = tree.modifiers.flags and Flags.ANNOTATION.toLong() != 0L
|
||||
|
||||
override val isEnum: Boolean
|
||||
get() = tree.modifiers.flags and Flags.ENUM.toLong() != 0L
|
||||
|
||||
override val lightClassOriginKind: LightClassOriginKind?
|
||||
get() = null
|
||||
|
||||
override val methods: Collection<JavaMethod>
|
||||
get() = tree.members
|
||||
.filter { it.kind == Tree.Kind.METHOD && !TreeInfo.isConstructor(it) }
|
||||
.map { TreeBasedMethod(it as JCTree.JCMethodDecl, TreePath(treePath, it), this, javac) }
|
||||
|
||||
override val fields: Collection<JavaField>
|
||||
get() = tree.members
|
||||
.filterIsInstance(JCTree.JCVariableDecl::class.java)
|
||||
.map { TreeBasedField(it, TreePath(treePath, it), this, javac) }
|
||||
|
||||
override val constructors: Collection<JavaConstructor>
|
||||
get() = tree.members
|
||||
.filter { member -> TreeInfo.isConstructor(member) }
|
||||
.map { constructor ->
|
||||
TreeBasedConstructor(constructor as JCTree.JCMethodDecl, TreePath(treePath, constructor), this, javac)
|
||||
}
|
||||
|
||||
override val innerClassNames: Collection<Name>
|
||||
get() = innerClasses.keys
|
||||
|
||||
val virtualFile: VirtualFile? by lazy {
|
||||
javac.toVirtualFile(file)
|
||||
}
|
||||
|
||||
override fun findInnerClass(name: Name) = innerClasses[name]
|
||||
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.wrappers.trees
|
||||
|
||||
import com.sun.source.util.TreePath
|
||||
import com.sun.tools.javac.tree.JCTree
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.javac.JavacWrapper
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaConstructor
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaValueParameter
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class TreeBasedConstructor(
|
||||
tree: JCTree.JCMethodDecl,
|
||||
treePath: TreePath,
|
||||
containingClass: JavaClass,
|
||||
javac: JavacWrapper
|
||||
) : TreeBasedMember<JCTree.JCMethodDecl>(tree, treePath, containingClass, javac), JavaConstructor {
|
||||
|
||||
override val name: Name
|
||||
get() = Name.identifier(tree.name.toString())
|
||||
|
||||
override val isAbstract: Boolean
|
||||
get() = false
|
||||
|
||||
override val isStatic: Boolean
|
||||
get() = false
|
||||
|
||||
override val isFinal: Boolean
|
||||
get() = true
|
||||
|
||||
override val visibility: Visibility
|
||||
get() = tree.modifiers.visibility
|
||||
|
||||
override val typeParameters: List<JavaTypeParameter>
|
||||
get() = tree.typeParameters.map { TreeBasedTypeParameter(it, TreePath(treePath, it), javac) }
|
||||
|
||||
override val valueParameters: List<JavaValueParameter>
|
||||
get() = tree.parameters.map { TreeBasedValueParameter(it, TreePath(treePath, it), javac) }
|
||||
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.wrappers.trees
|
||||
|
||||
import com.sun.source.util.TreePath
|
||||
import com.sun.tools.javac.tree.JCTree
|
||||
import org.jetbrains.kotlin.javac.JavacWrapper
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaElement
|
||||
|
||||
abstract class TreeBasedElement<out T : JCTree>(
|
||||
val tree: T,
|
||||
val treePath: TreePath,
|
||||
val javac: JavacWrapper
|
||||
) : JavaElement {
|
||||
|
||||
override fun equals(other: Any?) = (other as? TreeBasedElement<*>)?.tree == tree
|
||||
|
||||
override fun hashCode() = tree.hashCode()
|
||||
|
||||
override fun toString() = tree.toString()
|
||||
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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.wrappers.trees
|
||||
|
||||
import com.sun.source.util.TreePath
|
||||
import com.sun.tools.javac.code.Flags
|
||||
import com.sun.tools.javac.tree.JCTree
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.javac.JavacWrapper
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaField
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaType
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class TreeBasedField(
|
||||
tree: JCTree.JCVariableDecl,
|
||||
treePath: TreePath,
|
||||
containingClass: JavaClass,
|
||||
javac: JavacWrapper
|
||||
) : TreeBasedMember<JCTree.JCVariableDecl>(tree, treePath, containingClass, javac), JavaField {
|
||||
|
||||
override val name: Name
|
||||
get() = Name.identifier(tree.name.toString())
|
||||
|
||||
override val isAbstract: Boolean
|
||||
get() = tree.modifiers.isAbstract
|
||||
|
||||
override val isStatic: Boolean
|
||||
get() = containingClass.isInterface || tree.modifiers.isStatic
|
||||
|
||||
override val isFinal: Boolean
|
||||
get() = containingClass.isInterface || tree.modifiers.isFinal
|
||||
|
||||
override val visibility: Visibility
|
||||
get() = if (containingClass.isInterface) Visibilities.PUBLIC else tree.modifiers.visibility
|
||||
|
||||
override val isEnumEntry: Boolean
|
||||
get() = tree.modifiers.flags and Flags.ENUM.toLong() != 0L
|
||||
|
||||
override val type: JavaType
|
||||
get() = TreeBasedType.create(tree.getType(), treePath, javac)
|
||||
|
||||
override val initializerValue: Any?
|
||||
get() = tree.init?.let { initExpr ->
|
||||
if (hasConstantNotNullInitializer && initExpr is JCTree.JCLiteral) {
|
||||
initExpr.value
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override val hasConstantNotNullInitializer: Boolean
|
||||
get() = tree.init?.let {
|
||||
val type = this.type
|
||||
|
||||
isFinal && ((type is TreeBasedPrimitiveType) ||
|
||||
(type is TreeBasedNonGenericClassifierType &&
|
||||
type.classifierQualifiedName == "java.lang.String"))
|
||||
} ?: false
|
||||
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.wrappers.trees
|
||||
|
||||
import com.sun.source.util.TreePath
|
||||
import com.sun.tools.javac.tree.JCTree
|
||||
import org.jetbrains.kotlin.javac.JavacWrapper
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaMember
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
abstract class TreeBasedMember<out T : JCTree>(
|
||||
tree: T,
|
||||
treePath: TreePath,
|
||||
override val containingClass: JavaClass,
|
||||
javac: JavacWrapper
|
||||
) : TreeBasedElement<T>(tree, treePath, javac), JavaMember {
|
||||
|
||||
override val isDeprecatedInJavaDoc: Boolean
|
||||
get() = false
|
||||
|
||||
override val annotations: Collection<JavaAnnotation> by lazy {
|
||||
tree.annotations().map { TreeBasedAnnotation(it, treePath, javac) }
|
||||
}
|
||||
|
||||
override fun findAnnotation(fqName: FqName) =
|
||||
annotations.find { it.classId?.asSingleFqName() == fqName }
|
||||
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.wrappers.trees
|
||||
|
||||
import com.sun.source.util.TreePath
|
||||
import com.sun.tools.javac.tree.JCTree
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.javac.JavacWrapper
|
||||
import org.jetbrains.kotlin.load.java.structure.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class TreeBasedMethod(
|
||||
tree: JCTree.JCMethodDecl,
|
||||
treePath: TreePath,
|
||||
containingClass: JavaClass,
|
||||
javac: JavacWrapper
|
||||
) : TreeBasedMember<JCTree.JCMethodDecl>(tree, treePath, containingClass, javac), JavaMethod {
|
||||
|
||||
override val name: Name
|
||||
get() = Name.identifier(tree.name.toString())
|
||||
|
||||
override val isAbstract: Boolean
|
||||
get() = (containingClass.isInterface && !tree.modifiers.hasDefaultModifier) || tree.modifiers.isAbstract
|
||||
|
||||
override val isStatic: Boolean
|
||||
get() = tree.modifiers.isStatic
|
||||
|
||||
override val isFinal: Boolean
|
||||
get() = tree.modifiers.isFinal
|
||||
|
||||
override val visibility: Visibility
|
||||
get() = if (containingClass.isInterface) Visibilities.PUBLIC else tree.modifiers.visibility
|
||||
|
||||
override val typeParameters: List<JavaTypeParameter>
|
||||
get() = tree.typeParameters.map { TreeBasedTypeParameter(it, TreePath(treePath, it), javac) }
|
||||
|
||||
override val valueParameters: List<JavaValueParameter>
|
||||
get() = tree.parameters.map { TreeBasedValueParameter(it, TreePath(treePath, it), javac) }
|
||||
|
||||
override val returnType: JavaType
|
||||
get() = TreeBasedType.create(tree.returnType, treePath, javac)
|
||||
|
||||
override val hasAnnotationParameterDefaultValue: Boolean
|
||||
get() = tree.defaultValue != null
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.wrappers.trees
|
||||
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import org.jetbrains.kotlin.javac.JavacWrapper
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaPackage
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import javax.tools.JavaFileObject
|
||||
|
||||
class TreeBasedPackage(val name: String, val javac: JavacWrapper, val file: JavaFileObject) : JavaPackage {
|
||||
|
||||
override val fqName: FqName
|
||||
get() = FqName(name)
|
||||
|
||||
override val subPackages: Collection<JavaPackage>
|
||||
get() = javac.findSubPackages(fqName)
|
||||
|
||||
val virtualFile: VirtualFile? by lazy {
|
||||
javac.toVirtualFile(file)
|
||||
}
|
||||
|
||||
override fun getClasses(nameFilter: (Name) -> Boolean) =
|
||||
javac.findClassesFromPackage(fqName).filter { nameFilter(it.fqName!!.shortName()) }
|
||||
|
||||
override fun equals(other: Any?) = (other as? TreeBasedPackage)?.name == name
|
||||
|
||||
override fun hashCode() = name.hashCode()
|
||||
|
||||
override fun toString() = name
|
||||
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.wrappers.trees
|
||||
|
||||
import com.sun.source.util.TreePath
|
||||
import com.sun.tools.javac.tree.JCTree
|
||||
import org.jetbrains.kotlin.javac.JavacWrapper
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClassifierType
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class TreeBasedTypeParameter(
|
||||
tree: JCTree.JCTypeParameter,
|
||||
treePath: TreePath,
|
||||
javac: JavacWrapper
|
||||
) : TreeBasedElement<JCTree.JCTypeParameter>(tree, treePath, javac), JavaTypeParameter {
|
||||
|
||||
override val name: Name
|
||||
get() = Name.identifier(tree.name.toString())
|
||||
|
||||
override val annotations: Collection<JavaAnnotation> by lazy {
|
||||
tree.annotations().map { TreeBasedAnnotation(it, treePath, javac) }
|
||||
}
|
||||
|
||||
override fun findAnnotation(fqName: FqName) =
|
||||
annotations.firstOrNull { it.classId?.asSingleFqName() == fqName }
|
||||
|
||||
override val isDeprecatedInJavaDoc: Boolean
|
||||
get() = false
|
||||
|
||||
override val upperBounds: Collection<JavaClassifierType>
|
||||
get() = tree.bounds.map {
|
||||
when (it) {
|
||||
is JCTree.JCTypeApply -> TreeBasedGenericClassifierType(it, TreePath(treePath, it), javac)
|
||||
is JCTree.JCIdent -> TreeBasedNonGenericClassifierType(it, TreePath(treePath, it), javac)
|
||||
else -> null
|
||||
}
|
||||
}.filterNotNull()
|
||||
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.wrappers.trees
|
||||
|
||||
import com.sun.source.util.TreePath
|
||||
import com.sun.tools.javac.code.Flags
|
||||
import com.sun.tools.javac.tree.JCTree
|
||||
import org.jetbrains.kotlin.javac.JavacWrapper
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaType
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaValueParameter
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class TreeBasedValueParameter(
|
||||
tree: JCTree.JCVariableDecl,
|
||||
treePath: TreePath,
|
||||
javac: JavacWrapper
|
||||
) : TreeBasedElement<JCTree.JCVariableDecl>(tree, treePath, javac), JavaValueParameter {
|
||||
|
||||
override val annotations: Collection<JavaAnnotation> by lazy {
|
||||
tree.annotations().map { TreeBasedAnnotation(it, treePath, javac) }
|
||||
}
|
||||
|
||||
override fun findAnnotation(fqName: FqName) =
|
||||
annotations.find { it.classId?.asSingleFqName() == fqName }
|
||||
|
||||
override val isDeprecatedInJavaDoc: Boolean
|
||||
get() = false
|
||||
|
||||
override val name: Name
|
||||
get() = Name.identifier(tree.name.toString())
|
||||
|
||||
override val type: JavaType
|
||||
get() = TreeBasedType.create(tree.getType(), treePath, javac)
|
||||
|
||||
override val isVararg: Boolean
|
||||
get() = tree.modifiers.flags and Flags.VARARGS != 0L
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* 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.wrappers.trees
|
||||
|
||||
import com.sun.source.tree.Tree
|
||||
import com.sun.source.util.TreePath
|
||||
import com.sun.tools.javac.tree.JCTree
|
||||
import org.jetbrains.kotlin.javac.JavacWrapper
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClassifier
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
class TreePathResolverCache(private val javac: JavacWrapper) {
|
||||
|
||||
private val cache = hashMapOf<Tree, JavaClassifier?>()
|
||||
|
||||
fun resolve(treePath: TreePath): JavaClassifier? = with(treePath) {
|
||||
if (cache.containsKey(leaf)) return cache[leaf]
|
||||
|
||||
return tryToGetClassifier().apply { cache[leaf] = this }
|
||||
}
|
||||
|
||||
private fun TreePath.tryToGetClassifier(): JavaClassifier? {
|
||||
val name = leaf.toString().substringBefore("<").substringAfter("@")
|
||||
val nameParts = name.split(".")
|
||||
|
||||
with(compilationUnit as JCTree.JCCompilationUnit) {
|
||||
tryToResolveInner(name, javac, nameParts)?.let { return it }
|
||||
tryToResolvePackageClass(name, javac, nameParts)?.let { return it }
|
||||
tryToResolveByFqName(name, javac)?.let { return it }
|
||||
tryToResolveSingleTypeImport(name, javac, nameParts)?.let { return it }
|
||||
tryToResolveTypeImportOnDemand(name, javac, nameParts)?.let { return it }
|
||||
tryToResolveInJavaLang(name, javac)?.let { return it }
|
||||
}
|
||||
|
||||
return tryToResolveTypeParameter(javac)
|
||||
}
|
||||
|
||||
private fun TreePath.tryToResolveInner(
|
||||
name: String,
|
||||
javac: JavacWrapper,
|
||||
nameParts: List<String> = emptyList()
|
||||
): JavaClass? = findEnclosingClasses(javac)?.forEach { javaClass ->
|
||||
javaClass.findInner(name, javac, nameParts)?.let { inner -> return inner }
|
||||
}.let { return null }
|
||||
|
||||
private fun TreePath.findEnclosingClasses(javac: JavacWrapper) =
|
||||
filterIsInstance<JCTree.JCClassDecl>()
|
||||
.filter { it.extending != leaf && !it.implementing.contains(leaf) }
|
||||
.reversed()
|
||||
.joinToString(separator = ".", prefix = "${compilationUnit.packageName}.") { it.simpleName }
|
||||
.let { javac.findClass(FqName(it)) }
|
||||
?.let {
|
||||
arrayListOf(it).apply {
|
||||
var enclosingClass = it.outerClass
|
||||
while (enclosingClass != null) {
|
||||
add(enclosingClass)
|
||||
enclosingClass = enclosingClass.outerClass
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun JCTree.JCCompilationUnit.tryToResolveSingleTypeImport(
|
||||
name: String,
|
||||
javac: JavacWrapper,
|
||||
nameParts: List<String> = emptyList()
|
||||
): JavaClass? {
|
||||
nameParts.size.takeIf { it > 1 }?.let {
|
||||
imports.filter { it.qualifiedIdentifier.toString().endsWith(".${nameParts.first()}") }
|
||||
.forEach { import ->
|
||||
find(FqName("${import.qualifiedIdentifier}"), javac, nameParts)?.let { javaClass ->
|
||||
return javaClass
|
||||
}
|
||||
}
|
||||
.let { return null }
|
||||
}
|
||||
|
||||
return imports
|
||||
.find { it.qualifiedIdentifier.toString().endsWith(".$name") }
|
||||
?.let { import ->
|
||||
FqName(import.qualifiedIdentifier.toString()).let { fqName ->
|
||||
javac.findClass(fqName) ?: javac.getKotlinClassifier(fqName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun JCTree.JCCompilationUnit.tryToResolvePackageClass(
|
||||
name: String,
|
||||
javac: JavacWrapper,
|
||||
nameParts: List<String> = emptyList()
|
||||
): JavaClass? {
|
||||
return nameParts.size.takeIf { it > 1 }?.let {
|
||||
find(FqName("$packageName.${nameParts.first()}"), javac, nameParts)
|
||||
}
|
||||
?: javac.findClass(FqName("$packageName.$name"))
|
||||
?: javac.getKotlinClassifier(FqName("$packageName.$name"))
|
||||
}
|
||||
|
||||
private fun JCTree.JCCompilationUnit.tryToResolveTypeImportOnDemand(
|
||||
name: String,
|
||||
javac: JavacWrapper,
|
||||
nameParts: List<String> = emptyList()
|
||||
): JavaClass? {
|
||||
with(imports.filter { it.qualifiedIdentifier.toString().endsWith("*") }) {
|
||||
nameParts.size.takeIf { it > 1 }
|
||||
?.let {
|
||||
forEach { pack ->
|
||||
find(FqName("${pack.qualifiedIdentifier.toString().substringBefore("*")}${nameParts.first()}"),
|
||||
javac,
|
||||
nameParts)?.let { return it }
|
||||
}.let { return null }
|
||||
}
|
||||
|
||||
this.forEach {
|
||||
val fqName = "${it.qualifiedIdentifier.toString().substringBefore("*")}$name".let(::FqName)
|
||||
(javac.findClass(fqName) ?: javac.getKotlinClassifier(fqName))?.let { return it }
|
||||
}.let { return null }
|
||||
}
|
||||
}
|
||||
|
||||
private fun TreePath.tryToResolveTypeParameter(javac: JavacWrapper) =
|
||||
flatMap {
|
||||
when (it) {
|
||||
is JCTree.JCClassDecl -> it.typarams
|
||||
is JCTree.JCMethodDecl -> it.typarams
|
||||
else -> emptyList<JCTree.JCTypeParameter>()
|
||||
}
|
||||
}
|
||||
.find { it.toString().substringBefore(" ") == leaf.toString() }
|
||||
?.let {
|
||||
TreeBasedTypeParameter(it,
|
||||
javac.getTreePath(it, compilationUnit),
|
||||
javac)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun JavaClass.findInner(name: String,
|
||||
javac: JavacWrapper,
|
||||
nameParts: List<String> = emptyList()) : JavaClass? {
|
||||
nameParts.size.takeIf { it > 1 }?.let {
|
||||
return find(FqName("${fqName!!.asString()}.${nameParts[0]}"), javac, nameParts)
|
||||
}
|
||||
|
||||
if (name == this.fqName?.shortName()?.asString()) return this
|
||||
|
||||
with(FqName("${fqName!!.asString()}.$name")) {
|
||||
javac.findClass(this)?.let { return it }
|
||||
javac.getKotlinClassifier(this)?.let { return it }
|
||||
}
|
||||
|
||||
supertypes.mapNotNull { it.classifier as? JavaClass }
|
||||
.forEach { javaClass ->
|
||||
javaClass.findInner(name, javac)?.let { inner -> return inner }
|
||||
}.let { return null }
|
||||
}
|
||||
|
||||
fun tryToResolveByFqName(name: String,
|
||||
javac: JavacWrapper) = with(FqName(name)) {
|
||||
javac.findClass(this) ?: javac.getKotlinClassifier(this)
|
||||
}
|
||||
|
||||
fun tryToResolveInJavaLang(name: String,
|
||||
javac: JavacWrapper) = javac.findClass(FqName("java.lang.$name"))
|
||||
|
||||
|
||||
fun find(fqName: FqName,
|
||||
javac: JavacWrapper,
|
||||
nameParts: List<String>): JavaClass? {
|
||||
val initial = with(fqName) {
|
||||
javac.findClass(this)
|
||||
?: javac.getKotlinClassifier(this)
|
||||
?: return null
|
||||
}
|
||||
|
||||
nameParts.drop(1).fold(initial) {
|
||||
javaClass, namePart -> javaClass.findInner(namePart, javac) ?: return null
|
||||
}.let { return it }
|
||||
}
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* 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.wrappers.trees
|
||||
|
||||
import com.sun.source.util.TreePath
|
||||
import com.sun.tools.javac.code.BoundKind
|
||||
import com.sun.tools.javac.tree.JCTree
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||
import org.jetbrains.kotlin.javac.JavacWrapper
|
||||
import org.jetbrains.kotlin.javac.MockKotlinClassifier
|
||||
import org.jetbrains.kotlin.load.java.structure.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
|
||||
import javax.lang.model.type.TypeKind
|
||||
|
||||
abstract class TreeBasedType<out T : JCTree>(
|
||||
val tree: T,
|
||||
val treePath: TreePath,
|
||||
val javac: JavacWrapper
|
||||
) : JavaType, JavaAnnotationOwner {
|
||||
|
||||
companion object {
|
||||
fun <Type : JCTree> create(tree: Type, treePath: TreePath, javac: JavacWrapper) = when (tree) {
|
||||
is JCTree.JCPrimitiveTypeTree -> TreeBasedPrimitiveType(tree, TreePath(treePath, tree), javac)
|
||||
is JCTree.JCArrayTypeTree -> TreeBasedArrayType(tree, TreePath(treePath, tree), javac)
|
||||
is JCTree.JCWildcard -> TreeBasedWildcardType(tree, TreePath(treePath, tree), javac)
|
||||
is JCTree.JCTypeApply -> TreeBasedGenericClassifierType(tree, TreePath(treePath, tree), javac)
|
||||
is JCTree.JCExpression -> TreeBasedNonGenericClassifierType(tree, TreePath(treePath, tree), javac)
|
||||
else -> throw UnsupportedOperationException("Unsupported type: $tree")
|
||||
}
|
||||
}
|
||||
|
||||
override val annotations: Collection<JavaAnnotation>
|
||||
get() = emptyList()
|
||||
|
||||
override val isDeprecatedInJavaDoc: Boolean
|
||||
get() = false
|
||||
|
||||
override fun findAnnotation(fqName: FqName) = annotations.find { it.classId?.asSingleFqName() == fqName }
|
||||
|
||||
override fun equals(other: Any?) = (other as? TreeBasedType<*>)?.tree == tree
|
||||
|
||||
override fun hashCode() = tree.hashCode()
|
||||
|
||||
override fun toString() = tree.toString()
|
||||
|
||||
}
|
||||
|
||||
class TreeBasedPrimitiveType(
|
||||
tree: JCTree.JCPrimitiveTypeTree,
|
||||
treePath: TreePath,
|
||||
javac: JavacWrapper
|
||||
) : TreeBasedType<JCTree.JCPrimitiveTypeTree>(tree, treePath, javac), JavaPrimitiveType {
|
||||
|
||||
override val type: PrimitiveType?
|
||||
get() = if (tree.primitiveTypeKind == TypeKind.VOID) {
|
||||
null
|
||||
}
|
||||
else {
|
||||
JvmPrimitiveType.get(tree.toString()).primitiveType
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class TreeBasedArrayType(
|
||||
tree: JCTree.JCArrayTypeTree,
|
||||
treePath: TreePath,
|
||||
javac: JavacWrapper
|
||||
) : TreeBasedType<JCTree.JCArrayTypeTree>(tree, treePath, javac), JavaArrayType {
|
||||
|
||||
override val componentType: JavaType
|
||||
get() = create(tree.elemtype, treePath, javac)
|
||||
|
||||
}
|
||||
|
||||
class TreeBasedWildcardType(
|
||||
tree: JCTree.JCWildcard,
|
||||
treePath: TreePath,
|
||||
javac: JavacWrapper
|
||||
) : TreeBasedType<JCTree.JCWildcard>(tree, treePath, javac), JavaWildcardType {
|
||||
|
||||
override val bound: JavaType?
|
||||
get() = tree.bound?.let { create(it, treePath, javac) }
|
||||
|
||||
override val isExtends: Boolean
|
||||
get() = tree.kind.kind == BoundKind.EXTENDS
|
||||
|
||||
}
|
||||
|
||||
sealed class TreeBasedClassifierType<out T : JCTree>(
|
||||
tree: T,
|
||||
treePath: TreePath,
|
||||
javac: JavacWrapper
|
||||
) : TreeBasedType<T>(tree, treePath, javac), JavaClassifierType {
|
||||
|
||||
override val classifier: JavaClassifier?
|
||||
get() = javac.resolve(treePath)
|
||||
|
||||
override val classifierQualifiedName: String
|
||||
get() = (classifier as? JavaClass)?.fqName?.asString() ?: treePath.leaf.toString()
|
||||
|
||||
override val presentableText: String
|
||||
get() = classifierQualifiedName
|
||||
|
||||
private val typeParameter: JCTree.JCTypeParameter?
|
||||
get() = treePath.flatMap {
|
||||
when (it) {
|
||||
is JCTree.JCClassDecl -> it.typarams
|
||||
is JCTree.JCMethodDecl -> it.typarams
|
||||
else -> emptyList<JCTree.JCTypeParameter>()
|
||||
}
|
||||
}
|
||||
.find { it.toString().substringBefore(" ") == treePath.leaf.toString() }
|
||||
|
||||
}
|
||||
|
||||
class TreeBasedNonGenericClassifierType(
|
||||
tree: JCTree.JCExpression,
|
||||
treePath: TreePath,
|
||||
javac: JavacWrapper
|
||||
) : TreeBasedClassifierType<JCTree.JCExpression>(tree, treePath, javac) {
|
||||
|
||||
override val typeArguments: List<JavaType>
|
||||
get() = emptyList()
|
||||
|
||||
override val isRaw: Boolean
|
||||
get() = (classifier as? MockKotlinClassifier)?.hasTypeParameters
|
||||
?: (classifier as? JavaClass)?.typeParameters?.isNotEmpty()
|
||||
?: false
|
||||
|
||||
}
|
||||
|
||||
class TreeBasedGenericClassifierType(
|
||||
tree: JCTree.JCTypeApply,
|
||||
treePath: TreePath,
|
||||
javac: JavacWrapper
|
||||
) : TreeBasedClassifierType<JCTree.JCTypeApply>(tree, treePath, javac) {
|
||||
|
||||
override val typeArguments: List<JavaType>
|
||||
get() = tree.arguments.map { create(it, treePath, javac) }
|
||||
|
||||
override val isRaw: Boolean
|
||||
get() = false
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.wrappers.trees
|
||||
|
||||
import com.sun.tools.javac.tree.JCTree
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.load.java.JavaVisibilities
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import javax.lang.model.element.Modifier
|
||||
|
||||
internal val JCTree.JCModifiers.isAbstract: Boolean
|
||||
get() = Modifier.ABSTRACT in getFlags()
|
||||
|
||||
internal val JCTree.JCModifiers.isFinal: Boolean
|
||||
get() = Modifier.FINAL in getFlags()
|
||||
|
||||
internal val JCTree.JCModifiers.isStatic: Boolean
|
||||
get() = Modifier.STATIC in getFlags()
|
||||
|
||||
internal val JCTree.JCModifiers.hasDefaultModifier: Boolean
|
||||
get() = Modifier.DEFAULT in getFlags()
|
||||
|
||||
internal val JCTree.JCModifiers.visibility: Visibility
|
||||
get() = getFlags().let {
|
||||
when {
|
||||
Modifier.PUBLIC in it -> Visibilities.PUBLIC
|
||||
Modifier.PRIVATE in it -> Visibilities.PRIVATE
|
||||
Modifier.PROTECTED in it -> {
|
||||
if (Modifier.STATIC in it) JavaVisibilities.PROTECTED_STATIC_VISIBILITY
|
||||
else JavaVisibilities.PROTECTED_AND_PACKAGE
|
||||
}
|
||||
else -> JavaVisibilities.PACKAGE_VISIBILITY
|
||||
}
|
||||
}
|
||||
|
||||
internal fun JCTree.annotations(): Collection<JCTree.JCAnnotation> = when (this) {
|
||||
is JCTree.JCMethodDecl -> mods?.annotations
|
||||
is JCTree.JCClassDecl -> mods?.annotations
|
||||
is JCTree.JCVariableDecl -> mods?.annotations
|
||||
is JCTree.JCTypeParameter -> annotations
|
||||
else -> null
|
||||
} ?: emptyList<JCTree.JCAnnotation>()
|
||||
|
||||
fun JavaClass.computeClassId(): ClassId? =
|
||||
outerClass?.computeClassId()?.createNestedClassId(name) ?: fqName?.let { ClassId.topLevel(it) }
|
||||
Reference in New Issue
Block a user