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
Generated
+1
@@ -64,6 +64,7 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/ir/ir.tree/ir.tree.iml" filepath="$PROJECT_DIR$/compiler/ir/ir.tree/ir.tree.iml" group="compiler/ir" />
|
||||
<module fileurl="file://$PROJECT_DIR$/j2k/j2k.iml" filepath="$PROJECT_DIR$/j2k/j2k.iml" group="j2k" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/java-model-wrappers/java-model-wrappers.iml" filepath="$PROJECT_DIR$/plugins/java-model-wrappers/java-model-wrappers.iml" group="plugins" />
|
||||
<module fileurl="file://$PROJECT_DIR$/compiler/javac-wrapper/javac-wrapper.iml" filepath="$PROJECT_DIR$/compiler/javac-wrapper/javac-wrapper.iml" group="compiler" />
|
||||
<module fileurl="file://$PROJECT_DIR$/jps-plugin/jps-plugin.iml" filepath="$PROJECT_DIR$/jps-plugin/jps-plugin.iml" group="ide/jps" />
|
||||
<module fileurl="file://$PROJECT_DIR$/jps-plugin/jps-tests/jps-tests.iml" filepath="$PROJECT_DIR$/jps-plugin/jps-tests/jps-tests.iml" group="ide/jps" />
|
||||
<module fileurl="file://$PROJECT_DIR$/js/js.ast/js.ast.iml" filepath="$PROJECT_DIR$/js/js.ast/js.ast.iml" group="compiler/js" />
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
<property name="javax.inject.jar" value="${basedir}/lib/javax.inject.jar"/>
|
||||
<property name="gradle.logging.level" value=""/>
|
||||
|
||||
<property environment="env"/>
|
||||
<property name="tools.jar" value="${env.JDK_18}/lib/tools.jar"/>
|
||||
|
||||
<property name="java.target" value="1.8"/>
|
||||
<property name="java.target.1.6" value="1.6"/>
|
||||
|
||||
@@ -56,6 +59,7 @@
|
||||
<file file="${bootstrap.script.runtime}"/>
|
||||
<fileset dir="${idea.sdk}" includes="core/*.jar"/>
|
||||
<pathelement location="${protobuf.jar}"/>
|
||||
<pathelement location="${tools.jar}"/>
|
||||
|
||||
<fileset dir="${basedir}/lib" includes="**/*.jar"/>
|
||||
<fileset dir="${dependencies}" includes="jansi.jar"/>
|
||||
@@ -85,6 +89,7 @@
|
||||
<include name="compiler/ir/ir.psi2ir/src"/>
|
||||
<include name="compiler/ir/ir.tree/src"/>
|
||||
<include name="compiler/builtins-serializer/src"/>
|
||||
<include name="compiler/javac-wrapper/src"/>
|
||||
<include name="compiler/cli/src"/>
|
||||
<include name="compiler/cli/cli-common/src"/>
|
||||
<include name="compiler/conditional-preprocessor/src/"/>
|
||||
@@ -140,6 +145,7 @@
|
||||
<include name="plugin-api/**"/>
|
||||
<include name="annotation-collector/**"/>
|
||||
<include name="builtins-serializer/**"/>
|
||||
<include name="javac-wrapper/**"/>
|
||||
<include name="js.ast/**"/>
|
||||
<include name="js.translator/**"/>
|
||||
<include name="js.frontend/**"/>
|
||||
@@ -235,6 +241,7 @@
|
||||
<fileset dir="compiler/ir/ir.psi2ir/src"/>
|
||||
<fileset dir="compiler/ir/ir.tree/src"/>
|
||||
<fileset dir="compiler/builtins-serializer/src"/>
|
||||
<fileset dir="compiler/javac-wrapper/src"/>
|
||||
<fileset dir="compiler/cli/src"/>
|
||||
<fileset dir="compiler/cli/cli-common/src"/>
|
||||
<fileset dir="compiler/conditional-preprocessor/src"/>
|
||||
|
||||
+10
@@ -137,6 +137,16 @@ public class K2JVMCompilerArguments extends CommonCompilerArguments {
|
||||
)
|
||||
public String[] scriptResolverEnvironment;
|
||||
|
||||
// Javac options
|
||||
@Argument(value = "-Xuse-javac", description = "Use javac for Java source and class files analysis")
|
||||
public boolean useJavac;
|
||||
|
||||
@Argument(
|
||||
value = "-Xjavac-arguments",
|
||||
valueDescription = "<option[,]>",
|
||||
description = "Java compiler arguments")
|
||||
public String[] javacArguments;
|
||||
|
||||
// Paths to output directories for friend modules.
|
||||
public String[] friendPaths;
|
||||
|
||||
|
||||
@@ -23,5 +23,6 @@
|
||||
<orderEntry type="module" module-name="annotation-collector" />
|
||||
<orderEntry type="module" module-name="builtins-serializer" />
|
||||
<orderEntry type="module" module-name="frontend.script" />
|
||||
<orderEntry type="module" module-name="javac-wrapper" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.compiler.plugin.CliOptionProcessingException
|
||||
import org.jetbrains.kotlin.compiler.plugin.PluginCliOptionProcessingException
|
||||
import org.jetbrains.kotlin.compiler.plugin.cliPluginUsageString
|
||||
import org.jetbrains.kotlin.config.*
|
||||
import org.jetbrains.kotlin.javac.JavacWrapper
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinitionFromAnnotatedTemplate
|
||||
@@ -158,6 +159,10 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
val environment = createEnvironmentWithScriptingSupport(rootDisposable, configuration, arguments, messageCollector)
|
||||
?: return COMPILATION_ERROR
|
||||
|
||||
registerJavacIfNeeded(environment, arguments).let {
|
||||
if (!it) return COMPILATION_ERROR
|
||||
}
|
||||
|
||||
KotlinToJVMBytecodeCompiler.compileModules(environment, directory)
|
||||
}
|
||||
else if (arguments.script) {
|
||||
@@ -183,6 +188,10 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
val environment = createEnvironmentWithScriptingSupport(rootDisposable, configuration, arguments, messageCollector)
|
||||
?: return COMPILATION_ERROR
|
||||
|
||||
registerJavacIfNeeded(environment, arguments).let {
|
||||
if (!it) return COMPILATION_ERROR
|
||||
}
|
||||
|
||||
if (environment.getSourceFiles().isEmpty()) {
|
||||
if (arguments.version) {
|
||||
return OK
|
||||
@@ -192,6 +201,10 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
}
|
||||
|
||||
KotlinToJVMBytecodeCompiler.compileBunchOfSources(environment)
|
||||
|
||||
compileJavaFilesIfNeeded(environment, arguments).let {
|
||||
if (!it) return COMPILATION_ERROR
|
||||
}
|
||||
}
|
||||
|
||||
if (arguments.reportPerf) {
|
||||
@@ -211,6 +224,23 @@ class K2JVMCompiler : CLICompiler<K2JVMCompilerArguments>() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun registerJavacIfNeeded(environment: KotlinCoreEnvironment,
|
||||
arguments: K2JVMCompilerArguments): Boolean {
|
||||
if (arguments.useJavac) {
|
||||
environment.configuration.put(JVMConfigurationKeys.USE_JAVAC, true)
|
||||
return environment.registerJavac(arguments = arguments.javacArguments)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun compileJavaFilesIfNeeded(environment: KotlinCoreEnvironment,
|
||||
arguments: K2JVMCompilerArguments): Boolean {
|
||||
if (arguments.useJavac) {
|
||||
return JavacWrapper.getInstance(environment.project).use { it.compile() }
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun createEnvironmentWithScriptingSupport(rootDisposable: Disposable,
|
||||
configuration: CompilerConfiguration,
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.intellij.core.CoreApplicationEnvironment
|
||||
import com.intellij.core.CoreJavaFileManager
|
||||
import com.intellij.core.JavaCoreApplicationEnvironment
|
||||
import com.intellij.core.JavaCoreProjectEnvironment
|
||||
import com.intellij.ide.highlighter.JavaFileType
|
||||
import com.intellij.ide.plugins.PluginManagerCore
|
||||
import com.intellij.lang.MetaLanguage
|
||||
import com.intellij.lang.java.JavaParserDefinition
|
||||
@@ -70,10 +71,7 @@ import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
|
||||
import org.jetbrains.kotlin.cli.common.toBooleanLenient
|
||||
import org.jetbrains.kotlin.cli.jvm.JvmRuntimeVersionsConsistencyChecker
|
||||
import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot
|
||||
import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot
|
||||
import org.jetbrains.kotlin.cli.jvm.config.JvmContentRoot
|
||||
import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots
|
||||
import org.jetbrains.kotlin.cli.jvm.config.*
|
||||
import org.jetbrains.kotlin.cli.jvm.index.JavaRoot
|
||||
import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesDynamicCompoundIndex
|
||||
import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesIndex
|
||||
@@ -89,6 +87,7 @@ import org.jetbrains.kotlin.extensions.DeclarationAttributeAltererExtension
|
||||
import org.jetbrains.kotlin.extensions.PreprocessedVirtualFileFactoryExtension
|
||||
import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.javac.JavacWrapperRegistrar
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache
|
||||
import org.jetbrains.kotlin.load.kotlin.MetadataFinderFactory
|
||||
import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityManager
|
||||
@@ -219,6 +218,28 @@ class KotlinCoreEnvironment private constructor(
|
||||
project.registerService(VirtualFileFinderFactory::class.java, finderFactory)
|
||||
}
|
||||
|
||||
private val VirtualFile.javaFiles: List<VirtualFile>
|
||||
get() = mutableListOf<VirtualFile>().apply {
|
||||
VfsUtilCore.processFilesRecursively(this@javaFiles) { file ->
|
||||
if (file.fileType == JavaFileType.INSTANCE) {
|
||||
add(file)
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
private val allJavaFiles: List<File>
|
||||
get() = configuration.javaSourceRoots
|
||||
.mapNotNull(this::findLocalDirectory)
|
||||
.flatMap { it.javaFiles }
|
||||
.map { File(it.canonicalPath) }
|
||||
|
||||
fun registerJavac(javaFiles: List<File> = allJavaFiles,
|
||||
kotlinFiles: List<KtFile> = sourceFiles,
|
||||
arguments: Array<String>? = null): Boolean {
|
||||
return JavacWrapperRegistrar.registerJavac(this, javaFiles, kotlinFiles, arguments)
|
||||
}
|
||||
|
||||
private val applicationEnvironment: CoreApplicationEnvironment
|
||||
get() = projectEnvironment.environment
|
||||
|
||||
@@ -327,6 +348,10 @@ class KotlinCoreEnvironment private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun findLocalFile(path: String) = applicationEnvironment.localFileSystem.findFileByPath(path)
|
||||
|
||||
fun findJarFile(path: String) = applicationEnvironment.jarFileSystem.findFileByPath(path)
|
||||
|
||||
private fun findLocalDirectory(root: JvmContentRoot): VirtualFile? {
|
||||
val path = root.file
|
||||
val localFile = findLocalDirectory(path.absolutePath)
|
||||
|
||||
+18
-2
@@ -33,8 +33,7 @@ import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||
import org.jetbrains.kotlin.cli.common.checkKotlinPackageUsage
|
||||
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.OUTPUT
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil
|
||||
import org.jetbrains.kotlin.cli.common.output.outputUtils.writeAll
|
||||
@@ -52,6 +51,7 @@ import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.addKotlinSourceRoots
|
||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
||||
import org.jetbrains.kotlin.idea.MainFunctionDetector
|
||||
import org.jetbrains.kotlin.javac.JavacWrapper
|
||||
import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityManager
|
||||
import org.jetbrains.kotlin.modules.Module
|
||||
import org.jetbrains.kotlin.modules.TargetId
|
||||
@@ -164,6 +164,22 @@ object KotlinToJVMBytecodeCompiler {
|
||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
|
||||
writeOutput(state.configuration, state.factory, null)
|
||||
}
|
||||
|
||||
if (projectConfiguration.getBoolean(JVMConfigurationKeys.USE_JAVAC)) {
|
||||
val singleModule = chunk.singleOrNull()
|
||||
if (singleModule != null) {
|
||||
return JavacWrapper.getInstance(environment.project).use {
|
||||
it.compile(File(singleModule.getOutputDirectory()))
|
||||
}
|
||||
}
|
||||
else {
|
||||
projectConfiguration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).let {
|
||||
it.report(WARNING, "A chunk contains multiple modules (${chunk.joinToString { it.getModuleName() }}). -Xuse-javac option couldn't be used to compile java files")
|
||||
}
|
||||
JavacWrapper.getInstance(environment.project).close()
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
finally {
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.cli.jvm.config
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.ContentRoot
|
||||
import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.KotlinSourceRoot
|
||||
import java.io.File
|
||||
|
||||
data class JvmClasspathRoot(override val file: File): JvmContentRoot
|
||||
@@ -46,3 +47,10 @@ val CompilerConfiguration.jvmClasspathRoots: List<File>
|
||||
|
||||
@JvmOverloads fun CompilerConfiguration.addJavaSourceRoots(files: List<File>, packagePrefix: String? = null): Unit =
|
||||
files.forEach { addJavaSourceRoot(it, packagePrefix) }
|
||||
|
||||
val CompilerConfiguration.javaSourceRoots: Set<String>
|
||||
get() = get(JVMConfigurationKeys.CONTENT_ROOTS)
|
||||
?.mapNotNullTo(hashSetOf<String>()) {
|
||||
(it as? KotlinSourceRoot)?.path ?: (it as? JavaSourceRoot)?.file?.path
|
||||
}
|
||||
.orEmpty()
|
||||
@@ -57,6 +57,7 @@ messages/**)
|
||||
-libraryjars '<bootstrap.runtime>'
|
||||
-libraryjars '<bootstrap.reflect>'
|
||||
-libraryjars '<bootstrap.script.runtime>'
|
||||
-libraryjars '<tools.jar>'
|
||||
|
||||
-dontoptimize
|
||||
-dontobfuscate
|
||||
@@ -199,3 +200,7 @@ messages/**)
|
||||
|
||||
# for building kotlin-build-common-test
|
||||
-keep class org.jetbrains.kotlin.build.SerializationUtilsKt { *; }
|
||||
|
||||
# for tools.jar
|
||||
-keep class com.sun.tools.javac.** { *; }
|
||||
-keep class com.sun.source.** { *; }
|
||||
@@ -11,5 +11,6 @@
|
||||
<orderEntry type="library" scope="PROVIDED" name="intellij-core" level="project" />
|
||||
<orderEntry type="module" module-name="descriptor.loader.java" exported="" />
|
||||
<orderEntry type="module" module-name="util" />
|
||||
<orderEntry type="module" module-name="javac-wrapper" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -113,4 +113,8 @@ public class JVMConfigurationKeys {
|
||||
|
||||
public static final CompilerConfigurationKey<Boolean> USE_FAST_CLASS_FILES_READING =
|
||||
CompilerConfigurationKey.create("use fast class files reading implementation [experimental]");
|
||||
|
||||
public static final CompilerConfigurationKey<Boolean> USE_JAVAC =
|
||||
CompilerConfigurationKey.create("use javac");
|
||||
|
||||
}
|
||||
|
||||
@@ -19,6 +19,9 @@ package org.jetbrains.kotlin.frontend.java.di
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.builtins.JvmBuiltInsPackageFragmentProvider
|
||||
import org.jetbrains.kotlin.javac.components.JavacBasedClassFinder
|
||||
import org.jetbrains.kotlin.javac.components.StubJavaResolverCache
|
||||
import org.jetbrains.kotlin.javac.components.JavacBasedSourceElementFactory
|
||||
import org.jetbrains.kotlin.config.JvmTarget
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
@@ -48,7 +51,8 @@ import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
|
||||
private fun StorageComponentContainer.configureJavaTopDownAnalysis(
|
||||
moduleContentScope: GlobalSearchScope,
|
||||
project: Project,
|
||||
lookupTracker: LookupTracker
|
||||
lookupTracker: LookupTracker,
|
||||
useJavac: Boolean
|
||||
) {
|
||||
useInstance(moduleContentScope)
|
||||
useInstance(lookupTracker)
|
||||
@@ -60,17 +64,23 @@ private fun StorageComponentContainer.configureJavaTopDownAnalysis(
|
||||
|
||||
useInstance(VirtualFileFinderFactory.getInstance(project).create(moduleContentScope))
|
||||
|
||||
useImpl<AnnotationResolverImpl>()
|
||||
if (useJavac) {
|
||||
useImpl<JavacBasedClassFinder>()
|
||||
useImpl<StubJavaResolverCache>()
|
||||
useImpl<JavacBasedSourceElementFactory>()
|
||||
} else {
|
||||
useImpl<JavaClassFinderImpl>()
|
||||
useImpl<LazyResolveBasedCache>()
|
||||
useImpl<JavaSourceElementFactoryImpl>()
|
||||
}
|
||||
|
||||
useImpl<JavaClassFinderImpl>()
|
||||
useImpl<JavaPropertyInitializerEvaluatorImpl>()
|
||||
useImpl<AnnotationResolverImpl>()
|
||||
useImpl<SignaturePropagatorImpl>()
|
||||
useImpl<LazyResolveBasedCache>()
|
||||
useImpl<TraceBasedErrorReporter>()
|
||||
useImpl<PsiBasedExternalAnnotationResolver>()
|
||||
useImpl<JavaPropertyInitializerEvaluatorImpl>()
|
||||
useInstance(SamWithReceiverResolver())
|
||||
useImpl<SamConversionResolverImpl>()
|
||||
useImpl<JavaSourceElementFactoryImpl>()
|
||||
useInstance(InternalFlexibleTypeTransformer)
|
||||
|
||||
useImpl<CompilerDeserializationConfiguration>()
|
||||
@@ -88,10 +98,11 @@ fun createContainerForLazyResolveWithJava(
|
||||
jvmTarget: JvmTarget,
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
useBuiltInsProvider: Boolean,
|
||||
useLazyResolve: Boolean
|
||||
useLazyResolve: Boolean,
|
||||
useJavac: Boolean = false
|
||||
): StorageComponentContainer = createContainer("LazyResolveWithJava", JvmPlatform) {
|
||||
configureModule(moduleContext, JvmPlatform, jvmTarget, bindingTrace)
|
||||
configureJavaTopDownAnalysis(moduleContentScope, moduleContext.project, lookupTracker)
|
||||
configureJavaTopDownAnalysis(moduleContentScope, moduleContext.project, lookupTracker, useJavac)
|
||||
|
||||
useInstance(packagePartProvider)
|
||||
useInstance(moduleClassResolver)
|
||||
@@ -110,7 +121,10 @@ fun createContainerForLazyResolveWithJava(
|
||||
useImpl<LazyResolveToken>()
|
||||
}
|
||||
}.apply {
|
||||
get<JavaClassFinderImpl>().initialize(bindingTrace, get<KotlinCodeAnalyzer>())
|
||||
if (useJavac)
|
||||
get<JavacBasedClassFinder>().initialize(bindingTrace, get<KotlinCodeAnalyzer>())
|
||||
else
|
||||
get<JavaClassFinderImpl>().initialize(bindingTrace, get<KotlinCodeAnalyzer>())
|
||||
}
|
||||
|
||||
|
||||
@@ -123,11 +137,12 @@ fun createContainerForTopDownAnalyzerForJvm(
|
||||
packagePartProvider: PackagePartProvider,
|
||||
moduleClassResolver: ModuleClassResolver,
|
||||
jvmTarget: JvmTarget,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
useJavac: Boolean = false
|
||||
): ComponentProvider = createContainerForLazyResolveWithJava(
|
||||
moduleContext, bindingTrace, declarationProviderFactory, moduleContentScope, moduleClassResolver,
|
||||
CompilerEnvironment, lookupTracker, packagePartProvider, jvmTarget, languageVersionSettings,
|
||||
useBuiltInsProvider = true, useLazyResolve = false
|
||||
useBuiltInsProvider = true, useLazyResolve = false, useJavac = useJavac
|
||||
)
|
||||
|
||||
|
||||
|
||||
+8
-3
@@ -41,6 +41,7 @@ import org.jetbrains.kotlin.frontend.java.di.createContainerForTopDownAnalyzerFo
|
||||
import org.jetbrains.kotlin.frontend.java.di.initJvmBuiltInsForTopDownAnalysis
|
||||
import org.jetbrains.kotlin.frontend.java.di.initialize
|
||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
import org.jetbrains.kotlin.javac.MockKotlinClassifier
|
||||
import org.jetbrains.kotlin.load.java.lazy.ModuleClassResolver
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
||||
import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl
|
||||
@@ -61,6 +62,7 @@ import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
|
||||
import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory
|
||||
import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration
|
||||
import org.jetbrains.kotlin.storage.StorageManager
|
||||
import org.jetbrains.kotlin.javac.wrappers.trees.TreeBasedClass
|
||||
import java.util.*
|
||||
|
||||
object TopDownAnalyzerFacadeForJVM {
|
||||
@@ -143,6 +145,8 @@ object TopDownAnalyzerFacadeForJVM {
|
||||
}
|
||||
else null
|
||||
|
||||
val useJavac = configuration.getBoolean(JVMConfigurationKeys.USE_JAVAC)
|
||||
|
||||
val dependencyModule = if (separateModules) {
|
||||
val dependenciesContext = ContextForNewModule(
|
||||
moduleContext, Name.special("<dependencies of ${configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME)}>"),
|
||||
@@ -154,7 +158,7 @@ object TopDownAnalyzerFacadeForJVM {
|
||||
|
||||
val dependenciesContainer = createContainerForTopDownAnalyzerForJvm(
|
||||
dependenciesContext, trace, DeclarationProviderFactory.EMPTY, dependencyScope, lookupTracker,
|
||||
packagePartProvider(dependencyScope), moduleClassResolver, jvmTarget, languageVersionSettings
|
||||
packagePartProvider(dependencyScope), moduleClassResolver, jvmTarget, languageVersionSettings, useJavac
|
||||
)
|
||||
|
||||
StorageComponentContainerContributor.getInstances(project).forEach { it.onContainerComposed(dependenciesContainer, null) }
|
||||
@@ -181,7 +185,7 @@ object TopDownAnalyzerFacadeForJVM {
|
||||
// TODO: get rid of duplicate invocation of CodeAnalyzerInitializer#initialize, or refactor CliLightClassGenerationSupport
|
||||
val container = createContainerForTopDownAnalyzerForJvm(
|
||||
moduleContext, trace, declarationProviderFactory(storageManager, files), sourceScope, lookupTracker,
|
||||
partProvider, moduleClassResolver, jvmTarget, languageVersionSettings
|
||||
partProvider, moduleClassResolver, jvmTarget, languageVersionSettings, useJavac
|
||||
).apply {
|
||||
initJvmBuiltInsForTopDownAnalysis()
|
||||
(partProvider as? IncrementalPackagePartProvider)?.deserializationConfiguration = get<DeserializationConfiguration>()
|
||||
@@ -243,7 +247,8 @@ object TopDownAnalyzerFacadeForJVM {
|
||||
lateinit var sourceCodeResolver: JavaDescriptorResolver
|
||||
|
||||
override fun resolveClass(javaClass: JavaClass): ClassDescriptor? {
|
||||
val resolver = if (javaClass is JavaClassImpl && javaClass.psi.containingFile.virtualFile in sourceScope)
|
||||
val resolver = if (javaClass is JavaClassImpl && javaClass.psi.containingFile.virtualFile in sourceScope
|
||||
|| javaClass is TreeBasedClass || javaClass is MockKotlinClassifier)
|
||||
sourceCodeResolver
|
||||
else
|
||||
compiledCodeResolver
|
||||
|
||||
@@ -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) }
|
||||
+2
@@ -14,6 +14,8 @@ where advanced options include:
|
||||
Load definitions of built-in declarations from module dependencies, instead of from the compiler
|
||||
-Xscript-resolver-environment=<key=value[,]>
|
||||
Script resolver environment in key-value pairs (the value could be quoted and escaped)
|
||||
-Xuse-javac Use javac for Java source and class files analysis
|
||||
-Xjavac-arguments=<option[,]> Java compiler arguments
|
||||
-Xno-inline Disable method inlining
|
||||
-Xrepeat=<count> Repeat compilation (for performance analysis)
|
||||
-Xskip-metadata-version-check Load classes with bad metadata version anyway (incl. pre-release classes)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package test
|
||||
|
||||
// extra parameter is to preserve generic signature
|
||||
fun anyany(a: Any, ignore: java.util.List<String>) = a
|
||||
fun anyany(a: kotlin.Any, ignore: java.util.List<String>) = a
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
package test
|
||||
|
||||
fun lll(a: Int) = a
|
||||
fun lll(a: kotlin.Int) = a
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package test
|
||||
|
||||
// extra parameter is to make sure generic signature is not erased
|
||||
fun doNothing(array: IntArray, ignore: java.util.List<String>) = array
|
||||
fun doNothing(array: kotlin.IntArray, ignore: java.util.List<String>) = array
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package test;
|
||||
|
||||
public abstract class AbstractClass {
|
||||
|
||||
public abstract void implementMe();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package test
|
||||
|
||||
class AbstractClassImpl : AbstractClass() {
|
||||
|
||||
override fun implementMe() {}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package test
|
||||
|
||||
public abstract class AbstractClass {
|
||||
public constructor AbstractClass()
|
||||
public abstract fun implementMe(): kotlin.Unit
|
||||
}
|
||||
|
||||
public final class AbstractClassImpl : test.AbstractClass {
|
||||
public constructor AbstractClassImpl()
|
||||
public open fun implementMe(): kotlin.Unit
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package test;
|
||||
|
||||
public enum AbstractEnum {
|
||||
|
||||
ONE {
|
||||
@Override
|
||||
String getString() { return null; }
|
||||
};
|
||||
|
||||
abstract String getString();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package test
|
||||
|
||||
fun useEnum() = AbstractEnum.ONE.getString()
|
||||
@@ -0,0 +1,22 @@
|
||||
package test
|
||||
|
||||
public fun useEnum(): kotlin.String!
|
||||
|
||||
public abstract enum class AbstractEnum : kotlin.Enum<test.AbstractEnum!> {
|
||||
enum entry ONE
|
||||
|
||||
private constructor AbstractEnum()
|
||||
public final /*fake_override*/ val name: kotlin.String
|
||||
public final /*fake_override*/ val ordinal: kotlin.Int
|
||||
protected final /*fake_override*/ fun clone(): kotlin.Any
|
||||
public final /*fake_override*/ fun compareTo(/*0*/ test.AbstractEnum!): kotlin.Int
|
||||
protected/*protected and package*/ final /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit
|
||||
public final /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class<test.AbstractEnum!>!
|
||||
public/*package*/ abstract fun getString(): kotlin.String!
|
||||
|
||||
// Static members
|
||||
public final /*synthesized*/ fun valueOf(/*0*/ kotlin.String): test.AbstractEnum
|
||||
public open fun valueOf(/*0*/ kotlin.String!): test.AbstractEnum!
|
||||
public open fun values(): kotlin.Array<(out) test.AbstractEnum!>!
|
||||
public final /*synthesized*/ fun values(): kotlin.Array<test.AbstractEnum>
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package test;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Target(value=ElementType.TYPE)
|
||||
public @interface AnnotationWithArguments {
|
||||
|
||||
String name();
|
||||
|
||||
String arg() default "default";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package test
|
||||
|
||||
@AnnotationWithArguments(name="withDefault")
|
||||
class ClassWithDefault
|
||||
|
||||
@AnnotationWithArguments(name="withoutDefault", arg="non")
|
||||
class ClassWithoutDefault
|
||||
@@ -0,0 +1,15 @@
|
||||
package test
|
||||
|
||||
@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS, AnnotationTarget.FILE}) public final annotation class AnnotationWithArguments : kotlin.Annotation {
|
||||
public constructor AnnotationWithArguments(/*0*/ kotlin.String, /*1*/ kotlin.String = ...)
|
||||
public final val arg: kotlin.String
|
||||
public final val name: kotlin.String
|
||||
}
|
||||
|
||||
@test.AnnotationWithArguments(name = "withDefault") public final class ClassWithDefault {
|
||||
public constructor ClassWithDefault()
|
||||
}
|
||||
|
||||
@test.AnnotationWithArguments(arg = "non", name = "withoutDefault") public final class ClassWithoutDefault {
|
||||
public constructor ClassWithoutDefault()
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package test;
|
||||
|
||||
public @interface AnnotationWithField {
|
||||
|
||||
String text();
|
||||
|
||||
int ANSWER = 42;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package test
|
||||
|
||||
@AnnotationWithField(text="desc")
|
||||
class SomeClass
|
||||
@@ -0,0 +1,13 @@
|
||||
package test
|
||||
|
||||
public final annotation class AnnotationWithField : kotlin.Annotation {
|
||||
public constructor AnnotationWithField(/*0*/ kotlin.String)
|
||||
public final val text: kotlin.String
|
||||
|
||||
// Static members
|
||||
public const final val ANSWER: kotlin.Int
|
||||
}
|
||||
|
||||
@test.AnnotationWithField(text = "desc") public final class SomeClass {
|
||||
public constructor SomeClass()
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package test;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class AsteriskInImport {
|
||||
|
||||
public static List<String> getStrings() { return null; }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package test
|
||||
|
||||
fun getStrings() = AsteriskInImport.getStrings()
|
||||
@@ -0,0 +1,10 @@
|
||||
package test
|
||||
|
||||
public fun getStrings(): kotlin.collections.(Mutable)List<kotlin.String!>!
|
||||
|
||||
public open class AsteriskInImport {
|
||||
public constructor AsteriskInImport()
|
||||
|
||||
// Static members
|
||||
public open fun getStrings(): kotlin.collections.(Mutable)List<kotlin.String!>!
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package test;
|
||||
|
||||
import test2.*;
|
||||
|
||||
public class CheckKotlinStub {
|
||||
public KotlinStub getKotlinStub() { return null; }
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package test2
|
||||
|
||||
import test.*
|
||||
|
||||
class KotlinStub
|
||||
|
||||
fun checkKotlinStub() = CheckKotlinStub().getKotlinStub()
|
||||
@@ -0,0 +1,6 @@
|
||||
package test
|
||||
|
||||
public open class CheckKotlinStub {
|
||||
public constructor CheckKotlinStub()
|
||||
public open fun getKotlinStub(): test2.KotlinStub!
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package test;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class CheckNotNull {
|
||||
|
||||
@NotNull
|
||||
public String returnNotNull() { return "42"; }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package test
|
||||
|
||||
fun notNullable(): String = CheckNotNull().returnNotNull()
|
||||
@@ -0,0 +1,8 @@
|
||||
package test
|
||||
|
||||
public fun notNullable(): kotlin.String
|
||||
|
||||
public open class CheckNotNull {
|
||||
public constructor CheckNotNull()
|
||||
@org.jetbrains.annotations.NotNull public open fun returnNotNull(): kotlin.String
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package test;
|
||||
|
||||
public class Class {
|
||||
|
||||
private final String str;
|
||||
|
||||
public Class(String str) {
|
||||
this.str = str;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package test
|
||||
|
||||
fun useClass() = Class("Hello")
|
||||
@@ -0,0 +1,8 @@
|
||||
package test
|
||||
|
||||
public fun useClass(): test.Class
|
||||
|
||||
public open class Class {
|
||||
public constructor Class(/*0*/ kotlin.String!)
|
||||
private final val str: kotlin.String!
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package test;
|
||||
|
||||
public class ClassWithNestedEnum {
|
||||
|
||||
public enum NestedEnum {
|
||||
ONE, TWO, THREE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package test
|
||||
|
||||
fun test() = ClassWithNestedEnum.NestedEnum.ONE
|
||||
@@ -0,0 +1,29 @@
|
||||
package test
|
||||
|
||||
public fun test(): test.ClassWithNestedEnum.NestedEnum
|
||||
|
||||
public open class ClassWithNestedEnum {
|
||||
public constructor ClassWithNestedEnum()
|
||||
|
||||
public final enum class NestedEnum : kotlin.Enum<test.ClassWithNestedEnum.NestedEnum!> {
|
||||
enum entry ONE
|
||||
|
||||
enum entry TWO
|
||||
|
||||
enum entry THREE
|
||||
|
||||
private constructor NestedEnum()
|
||||
public final /*fake_override*/ val name: kotlin.String
|
||||
public final /*fake_override*/ val ordinal: kotlin.Int
|
||||
protected final /*fake_override*/ fun clone(): kotlin.Any
|
||||
public final /*fake_override*/ fun compareTo(/*0*/ test.ClassWithNestedEnum.NestedEnum!): kotlin.Int
|
||||
protected/*protected and package*/ final /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit
|
||||
public final /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class<test.ClassWithNestedEnum.NestedEnum!>!
|
||||
|
||||
// Static members
|
||||
public final /*synthesized*/ fun valueOf(/*0*/ kotlin.String): test.ClassWithNestedEnum.NestedEnum
|
||||
public open fun valueOf(/*0*/ kotlin.String!): test.ClassWithNestedEnum.NestedEnum!
|
||||
public open fun values(): kotlin.Array<(out) test.ClassWithNestedEnum.NestedEnum!>!
|
||||
public final /*synthesized*/ fun values(): kotlin.Array<test.ClassWithNestedEnum.NestedEnum>
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package test;
|
||||
|
||||
public class ClassWithTypeParameter<T extends KotlinInterface> {
|
||||
|
||||
public ClassWithTypeParameter(T kotlinInterface) {}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package test
|
||||
|
||||
interface KotlinInterface
|
||||
|
||||
class Impl1 : KotlinInterface
|
||||
|
||||
class Impl2 : KotlinInterface
|
||||
|
||||
class Impl3 : KotlinInterface
|
||||
|
||||
fun getProducer1() = Impl1().let(::ClassWithTypeParameter)
|
||||
|
||||
fun getProducer2() = Impl2().let(::ClassWithTypeParameter)
|
||||
|
||||
fun getProducer3() = Impl3().let(::ClassWithTypeParameter)
|
||||
@@ -0,0 +1,24 @@
|
||||
package test
|
||||
|
||||
public fun getProducer1(): test.ClassWithTypeParameter<test.Impl1>
|
||||
public fun getProducer2(): test.ClassWithTypeParameter<test.Impl2>
|
||||
public fun getProducer3(): test.ClassWithTypeParameter<test.Impl3>
|
||||
|
||||
public open class ClassWithTypeParameter</*0*/ T : test.KotlinInterface!> {
|
||||
public constructor ClassWithTypeParameter</*0*/ T : test.KotlinInterface!>(/*0*/ T!)
|
||||
}
|
||||
|
||||
public final class Impl1 : test.KotlinInterface {
|
||||
public constructor Impl1()
|
||||
}
|
||||
|
||||
public final class Impl2 : test.KotlinInterface {
|
||||
public constructor Impl2()
|
||||
}
|
||||
|
||||
public final class Impl3 : test.KotlinInterface {
|
||||
public constructor Impl3()
|
||||
}
|
||||
|
||||
public interface KotlinInterface {
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package test;
|
||||
|
||||
public class CyclicDependencies {
|
||||
|
||||
public KotlinClass useKotlinClass() {
|
||||
return new KotlinClass().getKotlinClass();
|
||||
}
|
||||
|
||||
public KotlinClass2 useKotlinClass2(KotlinClass kotlinClass) {
|
||||
return new KotlinClass2();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package test
|
||||
|
||||
class KotlinClass {
|
||||
fun getKotlinClass() = KotlinClass()
|
||||
}
|
||||
|
||||
class KotlinClass2 {
|
||||
val str = "HELLO"
|
||||
}
|
||||
|
||||
fun useJavaClass() = CyclicDependencies().apply {
|
||||
useKotlinClass().let { useKotlinClass2(it) }
|
||||
}.let { it.useKotlinClass2(it.useKotlinClass()) }
|
||||
@@ -0,0 +1,19 @@
|
||||
package test
|
||||
|
||||
public fun useJavaClass(): test.KotlinClass2!
|
||||
|
||||
public open class CyclicDependencies {
|
||||
public constructor CyclicDependencies()
|
||||
public open fun useKotlinClass(): test.KotlinClass!
|
||||
public open fun useKotlinClass2(/*0*/ test.KotlinClass!): test.KotlinClass2!
|
||||
}
|
||||
|
||||
public final class KotlinClass {
|
||||
public constructor KotlinClass()
|
||||
public final fun getKotlinClass(): test.KotlinClass
|
||||
}
|
||||
|
||||
public final class KotlinClass2 {
|
||||
public constructor KotlinClass2()
|
||||
public final val str: kotlin.String
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package test;
|
||||
|
||||
public class DefaultModifier implements WithDefault {
|
||||
|
||||
}
|
||||
|
||||
interface WithDefault {
|
||||
|
||||
default String getString() { return "str"; }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package test
|
||||
|
||||
fun useDefaultMethod() = DefaultModifier().getString()
|
||||
@@ -0,0 +1,12 @@
|
||||
package test
|
||||
|
||||
public fun useDefaultMethod(): kotlin.String!
|
||||
|
||||
public open class DefaultModifier : test.WithDefault {
|
||||
public constructor DefaultModifier()
|
||||
public open /*fake_override*/ fun getString(): kotlin.String!
|
||||
}
|
||||
|
||||
public/*package*/ interface WithDefault {
|
||||
public open fun getString(): kotlin.String!
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package test;
|
||||
|
||||
class InterfaceImpl implements Interface {
|
||||
|
||||
interface BuilderImpl extends Interface.Builder {
|
||||
@Override
|
||||
Builder setKind(Kind kind);
|
||||
}
|
||||
|
||||
Builder getBuilder() { return null; }
|
||||
|
||||
}
|
||||
|
||||
interface Interface {
|
||||
|
||||
enum Kind { DECLARATION; }
|
||||
|
||||
interface Builder {
|
||||
Builder setKind(Kind kind);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package test
|
||||
|
||||
private class Impl : InterfaceImpl() {
|
||||
|
||||
private fun kind(kind: Interface.Kind) = getBuilder().setKind(kind)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package test
|
||||
|
||||
private final class Impl : test.InterfaceImpl {
|
||||
public constructor Impl()
|
||||
public/*package*/ open /*fake_override*/ fun getBuilder(): test.Interface.Builder!
|
||||
private final fun kind(/*0*/ test.Interface.Kind): test.Interface.Builder!
|
||||
}
|
||||
|
||||
public/*package*/ interface Interface {
|
||||
|
||||
public interface Builder {
|
||||
public abstract fun setKind(/*0*/ test.Interface.Kind!): test.Interface.Builder!
|
||||
}
|
||||
|
||||
public final enum class Kind : kotlin.Enum<test.Interface.Kind!> {
|
||||
enum entry DECLARATION
|
||||
|
||||
private constructor Kind()
|
||||
public final /*fake_override*/ val name: kotlin.String
|
||||
public final /*fake_override*/ val ordinal: kotlin.Int
|
||||
protected final /*fake_override*/ fun clone(): kotlin.Any
|
||||
public final /*fake_override*/ fun compareTo(/*0*/ test.Interface.Kind!): kotlin.Int
|
||||
protected/*protected and package*/ final /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit
|
||||
public final /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class<test.Interface.Kind!>!
|
||||
|
||||
// Static members
|
||||
public final /*synthesized*/ fun valueOf(/*0*/ kotlin.String): test.Interface.Kind
|
||||
public open fun valueOf(/*0*/ kotlin.String!): test.Interface.Kind!
|
||||
public open fun values(): kotlin.Array<(out) test.Interface.Kind!>!
|
||||
public final /*synthesized*/ fun values(): kotlin.Array<test.Interface.Kind>
|
||||
}
|
||||
}
|
||||
|
||||
public/*package*/ open class InterfaceImpl : test.Interface {
|
||||
public/*package*/ constructor InterfaceImpl()
|
||||
public/*package*/ open fun getBuilder(): test.Interface.Builder!
|
||||
|
||||
public/*package*/ interface BuilderImpl : test.Interface.Builder {
|
||||
public abstract fun setKind(/*0*/ test.Interface.Kind!): test.Interface.Builder!
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package test;
|
||||
|
||||
public enum Enum {
|
||||
NORTH, SOUTH, WEST, EAST;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package test
|
||||
|
||||
fun checkEnum(e: Enum) = when(e) {
|
||||
Enum.SOUTH -> println(1)
|
||||
Enum.NORTH -> println(2)
|
||||
Enum.WEST -> println(3)
|
||||
Enum.EAST -> println(42)
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package test
|
||||
|
||||
public fun checkEnum(/*0*/ test.Enum): kotlin.Unit
|
||||
|
||||
public final enum class Enum : kotlin.Enum<test.Enum!> {
|
||||
enum entry NORTH
|
||||
|
||||
enum entry SOUTH
|
||||
|
||||
enum entry WEST
|
||||
|
||||
enum entry EAST
|
||||
|
||||
private constructor Enum()
|
||||
public final /*fake_override*/ val name: kotlin.String
|
||||
public final /*fake_override*/ val ordinal: kotlin.Int
|
||||
protected final /*fake_override*/ fun clone(): kotlin.Any
|
||||
public final /*fake_override*/ fun compareTo(/*0*/ test.Enum!): kotlin.Int
|
||||
protected/*protected and package*/ final /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit
|
||||
public final /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class<test.Enum!>!
|
||||
|
||||
// Static members
|
||||
public final /*synthesized*/ fun valueOf(/*0*/ kotlin.String): test.Enum
|
||||
public open fun valueOf(/*0*/ kotlin.String!): test.Enum!
|
||||
public open fun values(): kotlin.Array<(out) test.Enum!>!
|
||||
public final /*synthesized*/ fun values(): kotlin.Array<test.Enum>
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package test;
|
||||
|
||||
public enum EnumName {
|
||||
FIRST, SECOND;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package test
|
||||
|
||||
fun func(enum: EnumName) = enum.name
|
||||
@@ -0,0 +1,23 @@
|
||||
package test
|
||||
|
||||
public fun func(/*0*/ test.EnumName): kotlin.String
|
||||
|
||||
public final enum class EnumName : kotlin.Enum<test.EnumName!> {
|
||||
enum entry FIRST
|
||||
|
||||
enum entry SECOND
|
||||
|
||||
private constructor EnumName()
|
||||
public final /*fake_override*/ val name: kotlin.String
|
||||
public final /*fake_override*/ val ordinal: kotlin.Int
|
||||
protected final /*fake_override*/ fun clone(): kotlin.Any
|
||||
public final /*fake_override*/ fun compareTo(/*0*/ test.EnumName!): kotlin.Int
|
||||
protected/*protected and package*/ final /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit
|
||||
public final /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class<test.EnumName!>!
|
||||
|
||||
// Static members
|
||||
public final /*synthesized*/ fun valueOf(/*0*/ kotlin.String): test.EnumName
|
||||
public open fun valueOf(/*0*/ kotlin.String!): test.EnumName!
|
||||
public open fun values(): kotlin.Array<(out) test.EnumName!>!
|
||||
public final /*synthesized*/ fun values(): kotlin.Array<test.EnumName>
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package test;
|
||||
|
||||
public class Inheritance extends AbstractInheritance { }
|
||||
|
||||
abstract class AbstractInheritance implements Interface {
|
||||
|
||||
@Override public int getAnswer() { return 42; }
|
||||
|
||||
}
|
||||
|
||||
interface Interface extends I {
|
||||
@Override
|
||||
int getAnswer();
|
||||
}
|
||||
|
||||
interface I {
|
||||
int getAnswer();
|
||||
}
|
||||
|
||||
interface I2 extends I {
|
||||
|
||||
@Override
|
||||
int getAnswer();
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user