diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliKotlinAsJavaSupport.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliKotlinAsJavaSupport.kt new file mode 100644 index 00000000000..e61f25c2cb9 --- /dev/null +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliKotlinAsJavaSupport.kt @@ -0,0 +1,167 @@ +/* + * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.cli.jvm.compiler + +import com.intellij.openapi.project.Project +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiManager +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.psi.search.PsiSearchScopeUtil +import com.intellij.util.Function +import com.intellij.util.SmartList +import com.intellij.util.containers.ContainerUtil +import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport +import org.jetbrains.kotlin.asJava.classes.KtLightClass +import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade +import org.jetbrains.kotlin.asJava.classes.KtLightClassForScript +import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.PackageViewDescriptor +import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName +import org.jetbrains.kotlin.load.java.components.FilesByFacadeFqNameIndexer +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.KtClassOrObject +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.KtScript +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils +import org.jetbrains.kotlin.resolve.lazy.ResolveSessionUtils +import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter +import org.jetbrains.kotlin.resolve.scopes.MemberScope + +class CliKotlinAsJavaSupport( + project: Project, + private val traceHolder: CliTraceHolder +): KotlinAsJavaSupport() { + private val psiManager = PsiManager.getInstance(project) + + override fun getFacadeClassesInPackage(packageFqName: FqName, scope: GlobalSearchScope): Collection { + return findFacadeFilesInPackage(packageFqName, scope) + .groupBy { it.javaFileFacadeFqName } + .mapNotNull { + KtLightClassForFacade.createForFacade( + psiManager, + it.key, + scope, + it.value + ) + } + } + + override fun getFacadeNames(packageFqName: FqName, scope: GlobalSearchScope): Collection { + return findFacadeFilesInPackage(packageFqName, scope) + .map { it.javaFileFacadeFqName.shortName().asString() } + } + + private fun findFacadeFilesInPackage( + packageFqName: FqName, + scope: GlobalSearchScope + ) = traceHolder.bindingContext.get(FilesByFacadeFqNameIndexer.FACADE_FILES_BY_PACKAGE_NAME, packageFqName) + ?.filter { PsiSearchScopeUtil.isInScope(scope, it) } + .orEmpty() + + override fun getFacadeClasses(facadeFqName: FqName, scope: GlobalSearchScope): Collection { + val filesForFacade = findFilesForFacade(facadeFqName, scope) + if (filesForFacade.isEmpty()) return emptyList() + + return listOfNotNull( + KtLightClassForFacade.createForFacade( + psiManager, + facadeFqName, + scope, + filesForFacade + ) + ) + } + + override fun getScriptClasses(scriptFqName: FqName, scope: GlobalSearchScope): Collection { + if (scriptFqName.isRoot) { + return emptyList() + } + + return findFilesForPackage(scriptFqName.parent(), scope).mapNotNull { file -> + file.script?.takeIf { it.fqName == scriptFqName }?.let { it -> getLightClassForScript(it) } + } + } + + override fun getKotlinInternalClasses(fqName: FqName, scope: GlobalSearchScope): Collection { + // + return emptyList() + } + + override fun findFilesForFacade(facadeFqName: FqName, scope: GlobalSearchScope): Collection { + if (facadeFqName.isRoot) return emptyList() + + return traceHolder.bindingContext.get(FilesByFacadeFqNameIndexer.FACADE_FILES_BY_FQ_NAME, facadeFqName)?.filter { + PsiSearchScopeUtil.isInScope(scope, it) + } ?: emptyList() + } + + + override fun findClassOrObjectDeclarationsInPackage( + packageFqName: FqName, searchScope: GlobalSearchScope + ): Collection { + val files = findFilesForPackage(packageFqName, searchScope) + val result = SmartList() + for (file in files) { + for (declaration in file.declarations) { + if (declaration is KtClassOrObject) { + result.add(declaration) + } + } + } + return result + } + + override fun packageExists(fqName: FqName, scope: GlobalSearchScope): Boolean { + return !traceHolder.module.getPackage(fqName).isEmpty() + } + + override fun getSubPackages(fqn: FqName, scope: GlobalSearchScope): Collection { + val packageView = traceHolder.module.getPackage(fqn) + val members = packageView.memberScope.getContributedDescriptors( + DescriptorKindFilter.PACKAGES, + MemberScope.ALL_NAME_FILTER + ) + return ContainerUtil.mapNotNull( + members, + object : Function { + override fun `fun`(member: DeclarationDescriptor): FqName? { + if (member is PackageViewDescriptor) { + return member.fqName + } + return null + } + }) + } + + override fun getLightClass(classOrObject: KtClassOrObject): KtLightClass? = + KtLightClassForSourceDeclaration.create(classOrObject) + + override fun getLightClassForScript(script: KtScript): KtLightClassForScript? = + KtLightClassForScript.create(script) + + + override fun findClassOrObjectDeclarations(fqName: FqName, searchScope: GlobalSearchScope): Collection { + return ResolveSessionUtils.getClassDescriptorsByFqName(traceHolder.module, fqName).mapNotNull { + val element = DescriptorToSourceUtils.getSourceFromDescriptor(it) + if (element is KtClassOrObject && PsiSearchScopeUtil.isInScope( + searchScope, + element + ) + ) { + element + } + else null + } + } + + override fun findFilesForPackage(fqName: FqName, searchScope: GlobalSearchScope): Collection { + return traceHolder.bindingContext.get(BindingContext.PACKAGE_TO_FILES, fqName)?.filter { + PsiSearchScopeUtil.isInScope(searchScope, it) + } ?: emptyList() + } +} \ No newline at end of file diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliLightClassGenerationSupport.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliLightClassGenerationSupport.kt index 8809957f864..ca3508e474e 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliLightClassGenerationSupport.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliLightClassGenerationSupport.kt @@ -16,41 +16,15 @@ package org.jetbrains.kotlin.cli.jvm.compiler -import com.intellij.openapi.project.Project -import com.intellij.psi.PsiClass -import com.intellij.psi.PsiManager -import com.intellij.psi.search.GlobalSearchScope -import com.intellij.psi.search.PsiSearchScopeUtil -import com.intellij.util.Function -import com.intellij.util.SmartList -import com.intellij.util.containers.ContainerUtil -import org.jetbrains.annotations.TestOnly -import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport import org.jetbrains.kotlin.asJava.LightClassBuilder import org.jetbrains.kotlin.asJava.LightClassGenerationSupport import org.jetbrains.kotlin.asJava.builder.InvalidLightClassDataHolder import org.jetbrains.kotlin.asJava.builder.LightClassConstructionContext import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder import org.jetbrains.kotlin.asJava.builder.LightClassDataHolderImpl -import org.jetbrains.kotlin.asJava.classes.KtLightClass -import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade -import org.jetbrains.kotlin.asJava.classes.KtLightClassForScript -import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.descriptors.PackageViewDescriptor -import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName -import org.jetbrains.kotlin.load.java.components.FilesByFacadeFqNameIndexer -import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.resolve.* -import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer -import org.jetbrains.kotlin.resolve.lazy.ResolveSessionUtils -import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter -import org.jetbrains.kotlin.resolve.scopes.MemberScope -import org.jetbrains.kotlin.util.slicedMap.ReadOnlySlice -import org.jetbrains.kotlin.util.slicedMap.WritableSlice -import kotlin.properties.Delegates +import org.jetbrains.kotlin.resolve.BindingContext /** * This class solves the problem of interdependency between analyzing Kotlin code and generating JetLightClasses @@ -102,179 +76,4 @@ class CliLightClassGenerationSupport(private val traceHolder: CliTraceHolder) : override fun analyzeWithContent(element: KtClassOrObject) = traceHolder.bindingContext } -class CliTraceHolder : CodeAnalyzerInitializer { - var bindingContext: BindingContext by Delegates.notNull() - private set - var module: ModuleDescriptor by Delegates.notNull() - private set - - override fun initialize(trace: BindingTrace, module: ModuleDescriptor, codeAnalyzer: KotlinCodeAnalyzer) { - this.bindingContext = trace.bindingContext - this.module = module - - if (trace !is CliBindingTrace) { - throw IllegalArgumentException("Shared trace is expected to be subclass of ${CliBindingTrace::class.java.simpleName} class") - } - - trace.setKotlinCodeAnalyzer(codeAnalyzer) - } - - override fun createTrace(): BindingTraceContext { - return NoScopeRecordCliBindingTrace() - } - - // TODO: needs better name + list of keys to skip somewhere - class NoScopeRecordCliBindingTrace : CliBindingTrace() { - override fun record(slice: WritableSlice, key: K, value: V) { - if (slice === BindingContext.LEXICAL_SCOPE || slice == BindingContext.DATA_FLOW_INFO_BEFORE) { - // In the compiler there's no need to keep scopes - return - } - super.record(slice, key, value) - } - - override fun toString(): String { - return NoScopeRecordCliBindingTrace::class.java.name - } - } - - open class CliBindingTrace @TestOnly constructor() : BindingTraceContext() { - private var kotlinCodeAnalyzer: KotlinCodeAnalyzer? = null - - override fun toString(): String { - return CliBindingTrace::class.java.name - } - - fun setKotlinCodeAnalyzer(kotlinCodeAnalyzer: KotlinCodeAnalyzer) { - this.kotlinCodeAnalyzer = kotlinCodeAnalyzer - } - - override fun get(slice: ReadOnlySlice, key: K): V? { - val value = super.get(slice, key) - - if (value == null) { - if (BindingContext.FUNCTION === slice || BindingContext.VARIABLE === slice) { - if (key is KtDeclaration) { - if (!KtPsiUtil.isLocal(key)) { - kotlinCodeAnalyzer!!.resolveToDescriptor(key) - return super.get(slice, key) - } - } - } - } - - return value - } - } -} - - -class CliKotlinAsJavaSupport( - project: Project, - private val traceHolder: CliTraceHolder -): KotlinAsJavaSupport() { - private val psiManager = PsiManager.getInstance(project) - - override fun getFacadeClassesInPackage(packageFqName: FqName, scope: GlobalSearchScope): Collection { - return findFacadeFilesInPackage(packageFqName, scope) - .groupBy { it.javaFileFacadeFqName } - .mapNotNull { KtLightClassForFacade.createForFacade(psiManager, it.key, scope, it.value) } - } - - override fun getFacadeNames(packageFqName: FqName, scope: GlobalSearchScope): Collection { - return findFacadeFilesInPackage(packageFqName, scope) - .map { it.javaFileFacadeFqName.shortName().asString() } - } - - private fun findFacadeFilesInPackage( - packageFqName: FqName, - scope: GlobalSearchScope - ) = traceHolder.bindingContext.get(FilesByFacadeFqNameIndexer.FACADE_FILES_BY_PACKAGE_NAME, packageFqName) - ?.filter { PsiSearchScopeUtil.isInScope(scope, it) } - .orEmpty() - - override fun getFacadeClasses(facadeFqName: FqName, scope: GlobalSearchScope): Collection { - val filesForFacade = findFilesForFacade(facadeFqName, scope) - if (filesForFacade.isEmpty()) return emptyList() - - return listOfNotNull( - KtLightClassForFacade.createForFacade(psiManager, facadeFqName, scope, filesForFacade)) - } - - override fun getScriptClasses(scriptFqName: FqName, scope: GlobalSearchScope): Collection { - if (scriptFqName.isRoot) { - return emptyList() - } - - return findFilesForPackage(scriptFqName.parent(), scope).mapNotNull { file -> - file.script?.takeIf { it.fqName == scriptFqName }?.let { it -> getLightClassForScript(it) } - } - } - - override fun getKotlinInternalClasses(fqName: FqName, scope: GlobalSearchScope): Collection { - // - return emptyList() - } - - override fun findFilesForFacade(facadeFqName: FqName, scope: GlobalSearchScope): Collection { - if (facadeFqName.isRoot) return emptyList() - - return traceHolder.bindingContext.get(FilesByFacadeFqNameIndexer.FACADE_FILES_BY_FQ_NAME, facadeFqName)?.filter { - PsiSearchScopeUtil.isInScope(scope, it) - } ?: emptyList() - } - - - override fun findClassOrObjectDeclarationsInPackage( - packageFqName: FqName, searchScope: GlobalSearchScope): Collection { - val files = findFilesForPackage(packageFqName, searchScope) - val result = SmartList() - for (file in files) { - for (declaration in file.declarations) { - if (declaration is KtClassOrObject) { - result.add(declaration) - } - } - } - return result - } - - override fun packageExists(fqName: FqName, scope: GlobalSearchScope): Boolean { - return !traceHolder.module.getPackage(fqName).isEmpty() - } - - override fun getSubPackages(fqn: FqName, scope: GlobalSearchScope): Collection { - val packageView = traceHolder.module.getPackage(fqn) - val members = packageView.memberScope.getContributedDescriptors(DescriptorKindFilter.PACKAGES, MemberScope.ALL_NAME_FILTER) - return ContainerUtil.mapNotNull(members, object : Function { - override fun `fun`(member: DeclarationDescriptor): FqName? { - if (member is PackageViewDescriptor) { - return member.fqName - } - return null - } - }) - } - - override fun getLightClass(classOrObject: KtClassOrObject): KtLightClass? = KtLightClassForSourceDeclaration.create(classOrObject) - - override fun getLightClassForScript(script: KtScript): KtLightClassForScript? = KtLightClassForScript.create(script) - - - override fun findClassOrObjectDeclarations(fqName: FqName, searchScope: GlobalSearchScope): Collection { - return ResolveSessionUtils.getClassDescriptorsByFqName(traceHolder.module, fqName).mapNotNull { - val element = DescriptorToSourceUtils.getSourceFromDescriptor(it) - if (element is KtClassOrObject && PsiSearchScopeUtil.isInScope(searchScope, element)) { - element - } - else null - } - } - - override fun findFilesForPackage(fqName: FqName, searchScope: GlobalSearchScope): Collection { - return traceHolder.bindingContext.get(BindingContext.PACKAGE_TO_FILES, fqName)?.filter { - PsiSearchScopeUtil.isInScope(searchScope, it) - } ?: emptyList() - } -} \ No newline at end of file diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliTrace.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliTrace.kt new file mode 100644 index 00000000000..398c563982d --- /dev/null +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/CliTrace.kt @@ -0,0 +1,87 @@ +/* + * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.cli.jvm.compiler + +import org.jetbrains.annotations.TestOnly +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.psi.KtDeclaration +import org.jetbrains.kotlin.psi.KtPsiUtil +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.BindingTrace +import org.jetbrains.kotlin.resolve.BindingTraceContext +import org.jetbrains.kotlin.resolve.CodeAnalyzerInitializer +import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer +import org.jetbrains.kotlin.util.slicedMap.ReadOnlySlice +import org.jetbrains.kotlin.util.slicedMap.WritableSlice +import kotlin.properties.Delegates + +class CliTraceHolder : CodeAnalyzerInitializer { + var bindingContext: BindingContext by Delegates.notNull() + private set + var module: ModuleDescriptor by Delegates.notNull() + private set + + + override fun initialize(trace: BindingTrace, module: ModuleDescriptor, codeAnalyzer: KotlinCodeAnalyzer) { + this.bindingContext = trace.bindingContext + this.module = module + + if (trace !is CliBindingTrace) { + throw IllegalArgumentException("Shared trace is expected to be subclass of ${CliBindingTrace::class.java.simpleName} class") + } + + trace.setKotlinCodeAnalyzer(codeAnalyzer) + } + + override fun createTrace(): BindingTraceContext { + return NoScopeRecordCliBindingTrace() + } +} + + +// TODO: needs better name + list of keys to skip somewhere +class NoScopeRecordCliBindingTrace : CliBindingTrace() { + override fun record(slice: WritableSlice, key: K, value: V) { + if (slice === BindingContext.LEXICAL_SCOPE || slice == BindingContext.DATA_FLOW_INFO_BEFORE) { + // In the compiler there's no need to keep scopes + return + } + super.record(slice, key, value) + } + + override fun toString(): String { + return NoScopeRecordCliBindingTrace::class.java.name + } +} + +open class CliBindingTrace @TestOnly constructor() : BindingTraceContext() { + private var kotlinCodeAnalyzer: KotlinCodeAnalyzer? = null + + override fun toString(): String { + return CliBindingTrace::class.java.name + } + + fun setKotlinCodeAnalyzer(kotlinCodeAnalyzer: KotlinCodeAnalyzer) { + this.kotlinCodeAnalyzer = kotlinCodeAnalyzer + } + + override fun get(slice: ReadOnlySlice, key: K): V? { + val value = super.get(slice, key) + + if (value == null) { + if (BindingContext.FUNCTION === slice || BindingContext.VARIABLE === slice) { + if (key is KtDeclaration) { + if (!KtPsiUtil.isLocal(key)) { + kotlinCodeAnalyzer!!.resolveToDescriptor(key) + return super.get(slice, key) + } + } + } + } + + return value + } +} diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt index e3e8143681b..fc9ab29bc33 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/compiler/KotlinToJVMBytecodeCompiler.kt @@ -372,12 +372,12 @@ object KotlinToJVMBytecodeCompiler { // of the compiled modules (.class) to the list of scopes of the source module val scope = if (moduleOutputs.isEmpty()) sourcesOnly else sourcesOnly.uniteWith(DirectoriesScope(project, moduleOutputs)) TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration( - project, - sourceFiles, - CliTraceHolder.NoScopeRecordCliBindingTrace(), - environment.configuration, - environment::createPackagePartProvider, - sourceModuleSearchScope = scope + project, + sourceFiles, + NoScopeRecordCliBindingTrace(), + environment.configuration, + environment::createPackagePartProvider, + sourceModuleSearchScope = scope ) } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplCodeAnalyzer.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplCodeAnalyzer.kt index fb7c3a67d30..60f4ffa4ac1 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplCodeAnalyzer.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/ReplCodeAnalyzer.kt @@ -22,8 +22,8 @@ import org.jetbrains.kotlin.cli.common.repl.CompiledReplCodeLine import org.jetbrains.kotlin.cli.common.repl.ILineId import org.jetbrains.kotlin.cli.common.repl.ReplCodeLine import org.jetbrains.kotlin.cli.common.repl.ReplHistory -import org.jetbrains.kotlin.cli.jvm.compiler.CliTraceHolder import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment +import org.jetbrains.kotlin.cli.jvm.compiler.NoScopeRecordCliBindingTrace import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM import org.jetbrains.kotlin.container.get import org.jetbrains.kotlin.descriptors.ScriptDescriptor @@ -56,7 +56,7 @@ class ReplCodeAnalyzer(environment: KotlinCoreEnvironment) { val module: ModuleDescriptorImpl - val trace: BindingTraceContext = CliTraceHolder.NoScopeRecordCliBindingTrace() + val trace: BindingTraceContext = NoScopeRecordCliBindingTrace() init { // Module source scope is empty because all binary classes are in the dependency module, and all source classes are guaranteed diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KotlinAsJavaSupport.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KotlinAsJavaSupport.kt new file mode 100644 index 00000000000..1f849c952d3 --- /dev/null +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/KotlinAsJavaSupport.kt @@ -0,0 +1,65 @@ +/* + * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.asJava + +import com.intellij.openapi.components.ServiceManager +import com.intellij.openapi.project.Project +import com.intellij.psi.PsiClass +import com.intellij.psi.search.GlobalSearchScope +import org.jetbrains.kotlin.asJava.classes.KtLightClass +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.KtClassOrObject +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.KtScript + +abstract class KotlinAsJavaSupport { + // Returns only immediately declared classes/objects, package classes are not included (they have no declarations) + abstract fun findClassOrObjectDeclarationsInPackage( + packageFqName: FqName, + searchScope: GlobalSearchScope + ): Collection + + /* + * Finds files whose package declaration is exactly {@code fqName}. For example, if a file declares + * package a.b.c + * it will not be returned for fqName "a.b" + * + * If the resulting collection is empty, it means that this package has not other declarations than sub-packages + */ + abstract fun findFilesForPackage(fqName: FqName, searchScope: GlobalSearchScope): Collection + + abstract fun findClassOrObjectDeclarations(fqName: FqName, searchScope: GlobalSearchScope): Collection + + abstract fun packageExists(fqName: FqName, scope: GlobalSearchScope): Boolean + + abstract fun getSubPackages(fqn: FqName, scope: GlobalSearchScope): Collection + + abstract fun getLightClass(classOrObject: KtClassOrObject): KtLightClass? + + abstract fun getLightClassForScript(script: KtScript): KtLightClass? + + abstract fun getFacadeClasses(facadeFqName: FqName, scope: GlobalSearchScope): Collection + + abstract fun getScriptClasses(scriptFqName: FqName, scope: GlobalSearchScope): Collection + + abstract fun getKotlinInternalClasses(fqName: FqName, scope: GlobalSearchScope): Collection + + abstract fun getFacadeClassesInPackage(packageFqName: FqName, scope: GlobalSearchScope): Collection + + abstract fun getFacadeNames(packageFqName: FqName, scope: GlobalSearchScope): Collection + + abstract fun findFilesForFacade(facadeFqName: FqName, scope: GlobalSearchScope): Collection + + companion object { + @JvmStatic + fun getInstance(project: Project): KotlinAsJavaSupport { + return ServiceManager.getService( + project, + KotlinAsJavaSupport::class.java + ) + } + } +} \ No newline at end of file diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassGenerationSupport.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassGenerationSupport.kt index 3a140596ad2..ef078ce44ec 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassGenerationSupport.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/LightClassGenerationSupport.kt @@ -18,66 +18,15 @@ package org.jetbrains.kotlin.asJava import com.intellij.openapi.components.ServiceManager import com.intellij.openapi.project.Project -import com.intellij.psi.PsiClass -import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.kotlin.asJava.builder.LightClassBuilderResult import org.jetbrains.kotlin.asJava.builder.LightClassConstructionContext import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder -import org.jetbrains.kotlin.asJava.classes.KtLightClass -import org.jetbrains.kotlin.asJava.classes.KtLightClassForScript import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingContext typealias LightClassBuilder = (LightClassConstructionContext) -> LightClassBuilderResult -abstract class KotlinAsJavaSupport { - // Returns only immediately declared classes/objects, package classes are not included (they have no declarations) - abstract fun findClassOrObjectDeclarationsInPackage( - packageFqName: FqName, - searchScope: GlobalSearchScope - ): Collection - - /* - * Finds files whose package declaration is exactly {@code fqName}. For example, if a file declares - * package a.b.c - * it will not be returned for fqName "a.b" - * - * If the resulting collection is empty, it means that this package has not other declarations than sub-packages - */ - abstract fun findFilesForPackage(fqName: FqName, searchScope: GlobalSearchScope): Collection - - abstract fun findClassOrObjectDeclarations(fqName: FqName, searchScope: GlobalSearchScope): Collection - - abstract fun packageExists(fqName: FqName, scope: GlobalSearchScope): Boolean - - abstract fun getSubPackages(fqn: FqName, scope: GlobalSearchScope): Collection - - abstract fun getLightClass(classOrObject: KtClassOrObject): KtLightClass? - - abstract fun getLightClassForScript(script: KtScript): KtLightClassForScript? - - abstract fun getFacadeClasses(facadeFqName: FqName, scope: GlobalSearchScope): Collection - - abstract fun getScriptClasses(scriptFqName: FqName, scope: GlobalSearchScope): Collection - - abstract fun getKotlinInternalClasses(fqName: FqName, scope: GlobalSearchScope): Collection - - abstract fun getFacadeClassesInPackage(packageFqName: FqName, scope: GlobalSearchScope): Collection - - abstract fun getFacadeNames(packageFqName: FqName, scope: GlobalSearchScope): Collection - - abstract fun findFilesForFacade(facadeFqName: FqName, scope: GlobalSearchScope): Collection - - companion object { - @JvmStatic - fun getInstance(project: Project): KotlinAsJavaSupport { - return ServiceManager.getService(project, KotlinAsJavaSupport::class.java) - } - } -} - abstract class LightClassGenerationSupport { abstract fun createDataHolderForClass(classOrObject: KtClassOrObject, builder: LightClassBuilder): LightClassDataHolder.ForClass diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.kt index b959275476b..64d901a806c 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.kt @@ -21,7 +21,7 @@ import com.intellij.openapi.util.text.StringUtil import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.kotlin.analyzer.AnalysisResult import org.jetbrains.kotlin.analyzer.common.CommonAnalyzerFacade -import org.jetbrains.kotlin.cli.jvm.compiler.CliTraceHolder +import org.jetbrains.kotlin.cli.jvm.compiler.NoScopeRecordCliBindingTrace import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.container.get @@ -104,7 +104,7 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() { val separateModules = groupedByModule.size == 1 && groupedByModule.keys.single() == null val result = analyzeModuleContents( - moduleContext, ktFiles, CliTraceHolder.NoScopeRecordCliBindingTrace(), + moduleContext, ktFiles, NoScopeRecordCliBindingTrace(), languageVersionSettings, separateModules, loadJvmTarget(testFilesInModule) ) if (oldModule != result.moduleDescriptor) { diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/CodegenTestCase.java b/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/CodegenTestCase.java index e74215bdba2..cdcc567921f 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/CodegenTestCase.java +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/CodegenTestCase.java @@ -35,9 +35,9 @@ import org.jetbrains.kotlin.checkers.CheckerTestUtil; import org.jetbrains.kotlin.checkers.CompilerTestLanguageVersionSettings; import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys; import org.jetbrains.kotlin.cli.common.output.outputUtils.OutputUtilsKt; -import org.jetbrains.kotlin.cli.jvm.compiler.CliTraceHolder; import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles; import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment; +import org.jetbrains.kotlin.cli.jvm.compiler.NoScopeRecordCliBindingTrace; import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime; import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.config.*; @@ -466,7 +466,7 @@ public abstract class CodegenTestCase extends KtUsefulTestCase { try { GenerationState generationState = GenerationUtils.compileFiles( myFiles.getPsiFiles(), myEnvironment, getClassBuilderFactory(), - new CliTraceHolder.NoScopeRecordCliBindingTrace() + new NoScopeRecordCliBindingTrace() ); classFileFactory = generationState.getFactory(); diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/GenerationUtils.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/GenerationUtils.kt index 9a6379383f1..adebfa7c20b 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/GenerationUtils.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/GenerationUtils.kt @@ -19,7 +19,7 @@ package org.jetbrains.kotlin.codegen import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory import org.jetbrains.kotlin.cli.common.output.outputUtils.writeAllTo -import org.jetbrains.kotlin.cli.jvm.compiler.CliTraceHolder +import org.jetbrains.kotlin.cli.jvm.compiler.CliBindingTrace import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.config.CompilerConfiguration @@ -48,7 +48,7 @@ object GenerationUtils { files: List, environment: KotlinCoreEnvironment, classBuilderFactory: ClassBuilderFactory = ClassBuilderFactories.TEST, - trace: BindingTrace = CliTraceHolder.CliBindingTrace() + trace: BindingTrace = CliBindingTrace() ): GenerationState = compileFiles(files, environment.configuration, classBuilderFactory, environment::createPackagePartProvider, trace) @@ -59,7 +59,7 @@ object GenerationUtils { configuration: CompilerConfiguration, classBuilderFactory: ClassBuilderFactory, packagePartProvider: (GlobalSearchScope) -> PackagePartProvider, - trace: BindingTrace = CliTraceHolder.CliBindingTrace() + trace: BindingTrace = CliBindingTrace() ): GenerationState { val analysisResult = JvmResolveUtil.analyzeAndCheckForErrors(files.first().project, files, configuration, packagePartProvider, trace) diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/jvm/compiler/AbstractLoadJavaTest.java b/compiler/tests-common/tests/org/jetbrains/kotlin/jvm/compiler/AbstractLoadJavaTest.java index 1218f0b96b8..5cf6787adc2 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/jvm/compiler/AbstractLoadJavaTest.java +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/jvm/compiler/AbstractLoadJavaTest.java @@ -21,9 +21,9 @@ import com.intellij.openapi.util.io.FileUtil; import junit.framework.ComparisonFailure; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.analyzer.AnalysisResult; -import org.jetbrains.kotlin.cli.jvm.compiler.CliTraceHolder; import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles; import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment; +import org.jetbrains.kotlin.cli.jvm.compiler.NoScopeRecordCliBindingTrace; import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM; import org.jetbrains.kotlin.cli.jvm.config.JvmContentRootsKt; import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime; @@ -189,7 +189,7 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir { KotlinCoreEnvironment.createForTests(getTestRootDisposable(), configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES); registerJavacIfNeeded(environment); AnalysisResult result = TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration( - environment.getProject(), environment.getSourceFiles(), new CliTraceHolder.NoScopeRecordCliBindingTrace(), + environment.getProject(), environment.getSourceFiles(), new NoScopeRecordCliBindingTrace(), configuration, environment::createPackagePartProvider ); diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/renderer/AbstractDescriptorRendererTest.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/renderer/AbstractDescriptorRendererTest.kt index 27997e0cd2c..10b34bebb90 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/renderer/AbstractDescriptorRendererTest.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/renderer/AbstractDescriptorRendererTest.kt @@ -18,8 +18,8 @@ package org.jetbrains.kotlin.renderer import com.intellij.openapi.editor.impl.DocumentImpl import com.intellij.openapi.util.io.FileUtil -import org.jetbrains.kotlin.cli.jvm.compiler.CliTraceHolder import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment +import org.jetbrains.kotlin.cli.jvm.compiler.NoScopeRecordCliBindingTrace import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM import org.jetbrains.kotlin.config.JvmTarget import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl @@ -60,7 +60,7 @@ abstract class AbstractDescriptorRendererTest : KotlinTestWithEnvironment() { val container = createContainerForLazyResolve( context, FileBasedDeclarationProviderFactory(context.storageManager, listOf(psiFile)), - CliTraceHolder.NoScopeRecordCliBindingTrace(), + NoScopeRecordCliBindingTrace(), JvmPlatform, JvmTarget.JVM_1_6, targetEnvironment, diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/resolve/lazy/JvmResolveUtil.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/resolve/lazy/JvmResolveUtil.kt index 184efa6041a..dfa462dff0f 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/resolve/lazy/JvmResolveUtil.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/resolve/lazy/JvmResolveUtil.kt @@ -19,8 +19,9 @@ package org.jetbrains.kotlin.resolve.lazy import com.intellij.openapi.project.Project import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.kotlin.analyzer.AnalysisResult -import org.jetbrains.kotlin.cli.jvm.compiler.CliTraceHolder +import org.jetbrains.kotlin.cli.jvm.compiler.CliBindingTrace import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment +import org.jetbrains.kotlin.cli.jvm.compiler.NoScopeRecordCliBindingTrace import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.container.ComponentProvider @@ -35,7 +36,7 @@ object JvmResolveUtil { @JvmOverloads fun createContainer(environment: KotlinCoreEnvironment, files: Collection = emptyList()): ComponentProvider = TopDownAnalyzerFacadeForJVM.createContainer( - environment.project, files, CliTraceHolder.NoScopeRecordCliBindingTrace(), + environment.project, files, NoScopeRecordCliBindingTrace(), environment.configuration, { PackagePartProvider.Empty }, ::FileBasedDeclarationProviderFactory ) @@ -53,7 +54,7 @@ object JvmResolveUtil { files: Collection, configuration: CompilerConfiguration, packagePartProvider: (GlobalSearchScope) -> PackagePartProvider, - trace: BindingTrace = CliTraceHolder.CliBindingTrace() + trace: BindingTrace = CliBindingTrace() ): AnalysisResult { for (file in files) { AnalyzingUtils.checkForSyntacticErrors(file) @@ -85,7 +86,7 @@ object JvmResolveUtil { files: Collection, configuration: CompilerConfiguration, packagePartProviderFactory: (GlobalSearchScope) -> PackagePartProvider, - trace: BindingTrace = CliTraceHolder.CliBindingTrace() + trace: BindingTrace = CliBindingTrace() ): AnalysisResult { return TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration( project, files, trace, configuration, packagePartProviderFactory diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IDEKotlinAsJavaSupport.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IDEKotlinAsJavaSupport.kt new file mode 100644 index 00000000000..bbe6e647012 --- /dev/null +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IDEKotlinAsJavaSupport.kt @@ -0,0 +1,308 @@ +/* + * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.caches.resolve + +import com.intellij.openapi.project.Project +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.psi.* +import com.intellij.psi.impl.compiled.ClsClassImpl +import com.intellij.psi.impl.compiled.ClsFileImpl +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.psi.util.PsiTreeUtil +import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport +import org.jetbrains.kotlin.asJava.builder.ClsWrapperStubPsiFactory +import org.jetbrains.kotlin.asJava.classes.* +import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName +import org.jetbrains.kotlin.idea.caches.lightClasses.ClsJavaStubByVirtualFileCache +import org.jetbrains.kotlin.idea.caches.lightClasses.KtLightClassForDecompiledDeclaration +import org.jetbrains.kotlin.idea.caches.lightClasses.platformMutabilityWrapper +import org.jetbrains.kotlin.idea.caches.project.IdeaModuleInfo +import org.jetbrains.kotlin.idea.caches.project.ModuleSourceInfo +import org.jetbrains.kotlin.idea.caches.project.getModuleInfo +import org.jetbrains.kotlin.idea.decompiler.classFile.KtClsFile +import org.jetbrains.kotlin.idea.decompiler.navigation.SourceNavigationHelper +import org.jetbrains.kotlin.idea.stubindex.* +import org.jetbrains.kotlin.idea.util.ProjectRootsUtil +import org.jetbrains.kotlin.idea.util.application.runReadAction +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.resolve.scopes.MemberScope +import org.jetbrains.kotlin.utils.sure +import java.util.* + +class IDEKotlinAsJavaSupport(private val project: Project): KotlinAsJavaSupport() { + private val psiManager: PsiManager = PsiManager.getInstance(project) + + override fun getFacadeNames(packageFqName: FqName, scope: GlobalSearchScope): Collection { + val facadeFilesInPackage = runReadAction { + KotlinFileFacadeClassByPackageIndex.getInstance() + .get(packageFqName.asString(), project, scope) + } + return facadeFilesInPackage.map { it.javaFileFacadeFqName.shortName().asString() } + } + + override fun getFacadeClassesInPackage(packageFqName: FqName, scope: GlobalSearchScope): Collection { + val facadeFilesInPackage = runReadAction { + KotlinFileFacadeClassByPackageIndex.getInstance() + .get(packageFqName.asString(), project, scope) + } + val groupedByFqNameAndModuleInfo = facadeFilesInPackage.groupBy { + Pair(it.javaFileFacadeFqName, it.getModuleInfo()) + } + + return groupedByFqNameAndModuleInfo.flatMap { + val (key, files) = it + val (fqName, moduleInfo) = key + createLightClassForFileFacade(fqName, files, moduleInfo) + } + } + + override fun findClassOrObjectDeclarations(fqName: FqName, searchScope: GlobalSearchScope): Collection { + return runReadAction { + KotlinFullClassNameIndex.getInstance().get( + fqName.asString(), + project, + KotlinSourceFilterScope.sourceAndClassFiles(searchScope, project) + ) + } + } + + override fun findFilesForPackage(fqName: FqName, searchScope: GlobalSearchScope): Collection { + return runReadAction { + PackageIndexUtil.findFilesWithExactPackage( + fqName, + KotlinSourceFilterScope.sourceAndClassFiles( + searchScope, + project + ), + project + ) + } + } + + override fun findClassOrObjectDeclarationsInPackage( + packageFqName: FqName, + searchScope: GlobalSearchScope + ): Collection { + return KotlinTopLevelClassByPackageIndex.getInstance().get( + packageFqName.asString(), project, + KotlinSourceFilterScope.sourceAndClassFiles(searchScope, project) + ) + } + + override fun packageExists(fqName: FqName, scope: GlobalSearchScope): Boolean { + return PackageIndexUtil.packageExists( + fqName, + KotlinSourceFilterScope.sourceAndClassFiles( + scope, + project + ), + project + ) + } + + override fun getSubPackages(fqn: FqName, scope: GlobalSearchScope): Collection { + return PackageIndexUtil.getSubPackageFqNames( + fqn, + KotlinSourceFilterScope.sourceAndClassFiles( + scope, + project + ), + project, + MemberScope.ALL_NAME_FILTER + ) + } + + override fun getLightClass(classOrObject: KtClassOrObject): KtLightClass? { + val virtualFile = classOrObject.containingFile.virtualFile + if (virtualFile != null) { + when { + ProjectRootsUtil.isProjectSourceFile(project, virtualFile) -> + return KtLightClassForSourceDeclaration.create(classOrObject) + ProjectRootsUtil.isLibraryClassFile(project, virtualFile) -> + return getLightClassForDecompiledClassOrObject(classOrObject) + ProjectRootsUtil.isLibrarySourceFile(project, virtualFile) -> + return SourceNavigationHelper.getOriginalClass(classOrObject) as? KtLightClass + } + } + if ((classOrObject.containingFile as? KtFile)?.analysisContext != null || + classOrObject.containingFile.originalFile.virtualFile != null + ) { + // explicit request to create light class from dummy.kt + return KtLightClassForSourceDeclaration.create(classOrObject) + } + return null + } + + override fun getLightClassForScript(script: KtScript): KtLightClassForScript? = + KtLightClassForScript.create(script) + + private fun withFakeLightClasses( + lightClassForFacade: KtLightClassForFacade?, + facadeFiles: List + ): List { + if (lightClassForFacade == null) return emptyList() + + val lightClasses = ArrayList() + lightClasses.add(lightClassForFacade) + if (facadeFiles.size > 1) { + lightClasses.addAll(facadeFiles.map { + FakeLightClassForFileOfPackage(lightClassForFacade, it) + }) + } + return lightClasses + } + + override fun getFacadeClasses(facadeFqName: FqName, scope: GlobalSearchScope): Collection { + val filesByModule = findFilesForFacade(facadeFqName, scope).groupBy(KtFile::getModuleInfo) + + return filesByModule.flatMap { + createLightClassForFileFacade(facadeFqName, it.value, it.key) + } + } + + override fun getScriptClasses(scriptFqName: FqName, scope: GlobalSearchScope): Collection { + return KotlinScriptFqnIndex.instance.get(scriptFqName.asString(), project, scope).mapNotNull { + getLightClassForScript(it) + } + } + + override fun getKotlinInternalClasses(fqName: FqName, scope: GlobalSearchScope): Collection { + if (fqName.isRoot) return emptyList() + + return findPackageParts(fqName, scope) + findPlatformWrapper(fqName, scope) + } + + private fun findPackageParts(fqName: FqName, scope: GlobalSearchScope): List { + val facadeKtFiles = StaticFacadeIndexUtil.getMultifileClassForPart(fqName, scope, project) + val partShortName = fqName.shortName().asString() + val partClassFileShortName = partShortName + ".class" + + return facadeKtFiles.mapNotNull { facadeKtFile -> + if (facadeKtFile is KtClsFile) { + val partClassFile = facadeKtFile.virtualFile.parent.findChild(partClassFileShortName) ?: return@mapNotNull null + val javaClsClass = createClsJavaClassFromVirtualFile(facadeKtFile, partClassFile, null) ?: return@mapNotNull null + KtLightClassForDecompiledDeclaration(javaClsClass, null, facadeKtFile) + } else { + // TODO should we build light classes for parts from source? + null + } + } + } + + private fun findPlatformWrapper(fqName: FqName, scope: GlobalSearchScope): Collection { + return platformMutabilityWrapper(fqName) { + JavaPsiFacade.getInstance( + project + ).findClass(it, scope) + }?.let { listOf(it) }.orEmpty() + } + + fun createLightClassForFileFacade( + facadeFqName: FqName, + facadeFiles: List, + moduleInfo: IdeaModuleInfo + ): List { + val (clsFiles, sourceFiles) = facadeFiles.partition { it is KtClsFile } + val lightClassesForClsFacades = clsFiles.mapNotNull { createLightClassForDecompiledKotlinFile(it as KtClsFile) } + if (moduleInfo is ModuleSourceInfo && sourceFiles.isNotEmpty()) { + val lightClassForFacade = KtLightClassForFacade.createForFacade( + psiManager, facadeFqName, moduleInfo.contentScope(), sourceFiles + ) + return withFakeLightClasses(lightClassForFacade, sourceFiles) + lightClassesForClsFacades + } else { + return lightClassesForClsFacades + } + } + + override fun findFilesForFacade(facadeFqName: FqName, scope: GlobalSearchScope): Collection { + return runReadAction { + KotlinFileFacadeFqNameIndex.INSTANCE.get(facadeFqName.asString(), project, scope) + } + } + + private fun getLightClassForDecompiledClassOrObject(decompiledClassOrObject: KtClassOrObject): KtLightClassForDecompiledDeclaration? { + if (decompiledClassOrObject is KtEnumEntry) { + return null + } + val containingKtFile = decompiledClassOrObject.containingFile as? KtClsFile ?: return null + val rootLightClassForDecompiledFile = createLightClassForDecompiledKotlinFile(containingKtFile) ?: return null + + return findCorrespondingLightClass(decompiledClassOrObject, rootLightClassForDecompiledFile) + } + + private fun findCorrespondingLightClass( + decompiledClassOrObject: KtClassOrObject, + rootLightClassForDecompiledFile: KtLightClassForDecompiledDeclaration + ): KtLightClassForDecompiledDeclaration { + val relativeFqName = getClassRelativeName(decompiledClassOrObject) + val iterator = relativeFqName.pathSegments().iterator() + val base = iterator.next() + assert(rootLightClassForDecompiledFile.name == base.asString()) { "Light class for file:\n" + decompiledClassOrObject.containingKtFile.virtualFile.canonicalPath + "\nwas expected to have name: " + base.asString() + "\n Actual: " + rootLightClassForDecompiledFile.name } + var current: KtLightClassForDecompiledDeclaration = rootLightClassForDecompiledFile + while (iterator.hasNext()) { + val name = iterator.next() + val innerClass = current.findInnerClassByName(name.asString(), false).sure { + "Could not find corresponding inner/nested class " + relativeFqName + " in class " + decompiledClassOrObject.fqName + "\n" + "File: " + decompiledClassOrObject.containingKtFile.virtualFile.name + } + current = innerClass as KtLightClassForDecompiledDeclaration + } + return current + } + + private fun getClassRelativeName(decompiledClassOrObject: KtClassOrObject): FqName { + val name = decompiledClassOrObject.nameAsName!! + val parent = PsiTreeUtil.getParentOfType( + decompiledClassOrObject, + KtClassOrObject::class.java, + true + ) + if (parent == null) { + assert(decompiledClassOrObject.isTopLevel()) + return FqName.topLevel(name) + } + return getClassRelativeName(parent).child(name) + } + + private fun createLightClassForDecompiledKotlinFile(file: KtClsFile): KtLightClassForDecompiledDeclaration? { + val virtualFile = file.virtualFile ?: return null + + val classOrObject = file.declarations.filterIsInstance().singleOrNull() + + val javaClsClass = createClsJavaClassFromVirtualFile( + file, virtualFile, + correspondingClassOrObject = classOrObject + ) ?: return null + + return KtLightClassForDecompiledDeclaration(javaClsClass, classOrObject, file) + } + + private fun createClsJavaClassFromVirtualFile( + mirrorFile: KtFile, + classFile: VirtualFile, + correspondingClassOrObject: KtClassOrObject? + ): ClsClassImpl? { + val javaFileStub = ClsJavaStubByVirtualFileCache.getInstance(project).get(classFile) ?: return null + javaFileStub.psiFactory = ClsWrapperStubPsiFactory.INSTANCE + val manager = PsiManager.getInstance(mirrorFile.project) + val fakeFile = object : ClsFileImpl(ClassFileViewProvider(manager, classFile)) { + override fun getNavigationElement(): PsiElement { + if (correspondingClassOrObject != null) { + return correspondingClassOrObject.navigationElement.containingFile + } + return super.getNavigationElement() + } + + override fun getStub() = javaFileStub + + override fun getMirror() = mirrorFile + + override fun isPhysical() = false + } + javaFileStub.psi = fakeFile + return fakeFile.classes.single() as ClsClassImpl + } +} \ No newline at end of file diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IDELightClassGenerationSupport.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IDELightClassGenerationSupport.kt index c9e10211d84..8a66fa6d187 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IDELightClassGenerationSupport.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/IDELightClassGenerationSupport.kt @@ -17,41 +17,19 @@ package org.jetbrains.kotlin.idea.caches.resolve import com.intellij.openapi.project.Project -import com.intellij.openapi.vfs.VirtualFile -import com.intellij.psi.* -import com.intellij.psi.impl.compiled.ClsClassImpl -import com.intellij.psi.impl.compiled.ClsFileImpl import com.intellij.psi.search.GlobalSearchScope -import com.intellij.psi.util.PsiTreeUtil -import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport import org.jetbrains.kotlin.asJava.LightClassBuilder import org.jetbrains.kotlin.asJava.LightClassGenerationSupport -import org.jetbrains.kotlin.asJava.builder.ClsWrapperStubPsiFactory import org.jetbrains.kotlin.asJava.builder.InvalidLightClassDataHolder import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder -import org.jetbrains.kotlin.asJava.classes.* +import org.jetbrains.kotlin.asJava.classes.shouldNotBeVisibleAsLightClass import org.jetbrains.kotlin.asJava.finder.JavaElementFinder -import org.jetbrains.kotlin.asJava.toLightClass import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil -import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName -import org.jetbrains.kotlin.idea.caches.lightClasses.* -import org.jetbrains.kotlin.idea.caches.project.IdeaModuleInfo -import org.jetbrains.kotlin.idea.caches.project.ModuleSourceInfo -import org.jetbrains.kotlin.idea.caches.project.getModuleInfo -import org.jetbrains.kotlin.idea.decompiler.classFile.KtClsFile -import org.jetbrains.kotlin.idea.decompiler.navigation.SourceNavigationHelper -import org.jetbrains.kotlin.idea.stubindex.* -import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope.Companion.sourceAndClassFiles -import org.jetbrains.kotlin.idea.util.ProjectRootsUtil -import org.jetbrains.kotlin.idea.util.application.runReadAction -import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.idea.caches.lightClasses.IDELightClassContexts +import org.jetbrains.kotlin.idea.caches.lightClasses.LazyLightClassDataHolder import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.resolve.lazy.NoDescriptorForDeclarationException -import org.jetbrains.kotlin.resolve.scopes.MemberScope -import org.jetbrains.kotlin.utils.sure -import java.util.* class IDELightClassGenerationSupport(project: Project) : LightClassGenerationSupport() { private val scopeFileComparator = JavaElementFinder.byClasspathComparator(GlobalSearchScope.allScope(project)) @@ -113,276 +91,3 @@ class IDELightClassGenerationSupport(project: Project) : LightClassGenerationSup override fun analyzeWithContent(element: KtClassOrObject) = element.analyzeWithContent() } -class IDEKotlinAsJavaSupport(private val project: Project): KotlinAsJavaSupport() { - private val psiManager: PsiManager = PsiManager.getInstance(project) - - override fun getFacadeNames(packageFqName: FqName, scope: GlobalSearchScope): Collection { - val facadeFilesInPackage = runReadAction { - KotlinFileFacadeClassByPackageIndex.getInstance().get(packageFqName.asString(), project, scope) - } - return facadeFilesInPackage.map { it.javaFileFacadeFqName.shortName().asString() } - } - - override fun getFacadeClassesInPackage(packageFqName: FqName, scope: GlobalSearchScope): Collection { - val facadeFilesInPackage = runReadAction { - KotlinFileFacadeClassByPackageIndex.getInstance().get(packageFqName.asString(), project, scope) - } - val groupedByFqNameAndModuleInfo = facadeFilesInPackage.groupBy { - Pair(it.javaFileFacadeFqName, it.getModuleInfo()) - } - - return groupedByFqNameAndModuleInfo.flatMap { - val (key, files) = it - val (fqName, moduleInfo) = key - createLightClassForFileFacade(fqName, files, moduleInfo) - } - } - - override fun findClassOrObjectDeclarations(fqName: FqName, searchScope: GlobalSearchScope): Collection { - return runReadAction { - KotlinFullClassNameIndex.getInstance().get(fqName.asString(), project, sourceAndClassFiles(searchScope, project)) - } - } - - override fun findFilesForPackage(fqName: FqName, searchScope: GlobalSearchScope): Collection { - return runReadAction { - PackageIndexUtil.findFilesWithExactPackage(fqName, sourceAndClassFiles(searchScope, project), project) - } - } - - override fun findClassOrObjectDeclarationsInPackage( - packageFqName: FqName, - searchScope: GlobalSearchScope - ): Collection { - return KotlinTopLevelClassByPackageIndex.getInstance().get( - packageFqName.asString(), project, sourceAndClassFiles(searchScope, project) - ) - } - - override fun packageExists(fqName: FqName, scope: GlobalSearchScope): Boolean { - return PackageIndexUtil.packageExists(fqName, sourceAndClassFiles(scope, project), project) - } - - override fun getSubPackages(fqn: FqName, scope: GlobalSearchScope): Collection { - return PackageIndexUtil.getSubPackageFqNames(fqn, sourceAndClassFiles(scope, project), project, MemberScope.ALL_NAME_FILTER) - } - - override fun getLightClass(classOrObject: KtClassOrObject): KtLightClass? { - val virtualFile = classOrObject.containingFile.virtualFile - if (virtualFile != null) { - when { - ProjectRootsUtil.isProjectSourceFile(project, virtualFile) -> - return KtLightClassForSourceDeclaration.create(classOrObject) - ProjectRootsUtil.isLibraryClassFile(project, virtualFile) -> - return getLightClassForDecompiledClassOrObject(classOrObject) - ProjectRootsUtil.isLibrarySourceFile(project, virtualFile) -> - return SourceNavigationHelper.getOriginalClass(classOrObject) as? KtLightClass - } - } - if ((classOrObject.containingFile as? KtFile)?.analysisContext != null || - classOrObject.containingFile.originalFile.virtualFile != null - ) { - // explicit request to create light class from dummy.kt - return KtLightClassForSourceDeclaration.create(classOrObject) - } - return null - } - - override fun getLightClassForScript(script: KtScript): KtLightClassForScript? = KtLightClassForScript.create(script) - - private fun withFakeLightClasses( - lightClassForFacade: KtLightClassForFacade?, - facadeFiles: List - ): List { - if (lightClassForFacade == null) return emptyList() - - val lightClasses = ArrayList() - lightClasses.add(lightClassForFacade) - if (facadeFiles.size > 1) { - lightClasses.addAll(facadeFiles.map { - FakeLightClassForFileOfPackage(lightClassForFacade, it) - }) - } - return lightClasses - } - - override fun getFacadeClasses(facadeFqName: FqName, scope: GlobalSearchScope): Collection { - val filesByModule = findFilesForFacade(facadeFqName, scope).groupBy(KtFile::getModuleInfo) - - return filesByModule.flatMap { - createLightClassForFileFacade(facadeFqName, it.value, it.key) - } - } - - override fun getScriptClasses(scriptFqName: FqName, scope: GlobalSearchScope): Collection { - return KotlinScriptFqnIndex.instance.get(scriptFqName.asString(), project, scope).mapNotNull { - getLightClassForScript(it) - } - } - - override fun getKotlinInternalClasses(fqName: FqName, scope: GlobalSearchScope): Collection { - if (fqName.isRoot) return emptyList() - - return findPackageParts(fqName, scope) + findPlatformWrapper(fqName, scope) - } - - private fun findPackageParts(fqName: FqName, scope: GlobalSearchScope): List { - val facadeKtFiles = StaticFacadeIndexUtil.getMultifileClassForPart(fqName, scope, project) - val partShortName = fqName.shortName().asString() - val partClassFileShortName = partShortName + ".class" - - return facadeKtFiles.mapNotNull { facadeKtFile -> - if (facadeKtFile is KtClsFile) { - val partClassFile = facadeKtFile.virtualFile.parent.findChild(partClassFileShortName) ?: return@mapNotNull null - val javaClsClass = createClsJavaClassFromVirtualFile(facadeKtFile, partClassFile, null) ?: return@mapNotNull null - KtLightClassForDecompiledDeclaration(javaClsClass, null, facadeKtFile) - } else { - // TODO should we build light classes for parts from source? - null - } - } - } - - private fun findPlatformWrapper(fqName: FqName, scope: GlobalSearchScope): Collection { - return platformMutabilityWrapper(fqName) { JavaPsiFacade.getInstance(project).findClass(it, scope) }?.let { listOf(it) }.orEmpty() - } - - fun createLightClassForFileFacade( - facadeFqName: FqName, - facadeFiles: List, - moduleInfo: IdeaModuleInfo - ): List { - val (clsFiles, sourceFiles) = facadeFiles.partition { it is KtClsFile } - val lightClassesForClsFacades = clsFiles.mapNotNull { createLightClassForDecompiledKotlinFile(it as KtClsFile) } - if (moduleInfo is ModuleSourceInfo && sourceFiles.isNotEmpty()) { - val lightClassForFacade = KtLightClassForFacade.createForFacade( - psiManager, facadeFqName, moduleInfo.contentScope(), sourceFiles - ) - return withFakeLightClasses(lightClassForFacade, sourceFiles) + lightClassesForClsFacades - } else { - return lightClassesForClsFacades - } - } - - override fun findFilesForFacade(facadeFqName: FqName, scope: GlobalSearchScope): Collection { - return runReadAction { - KotlinFileFacadeFqNameIndex.INSTANCE.get(facadeFqName.asString(), project, scope) - } - } - - private fun getLightClassForDecompiledClassOrObject(decompiledClassOrObject: KtClassOrObject): KtLightClassForDecompiledDeclaration? { - if (decompiledClassOrObject is KtEnumEntry) { - return null - } - val containingKtFile = decompiledClassOrObject.containingFile as? KtClsFile ?: return null - val rootLightClassForDecompiledFile = createLightClassForDecompiledKotlinFile(containingKtFile) ?: return null - - return findCorrespondingLightClass(decompiledClassOrObject, rootLightClassForDecompiledFile) - } - - private fun findCorrespondingLightClass( - decompiledClassOrObject: KtClassOrObject, - rootLightClassForDecompiledFile: KtLightClassForDecompiledDeclaration - ): KtLightClassForDecompiledDeclaration { - val relativeFqName = getClassRelativeName(decompiledClassOrObject) - val iterator = relativeFqName.pathSegments().iterator() - val base = iterator.next() - assert(rootLightClassForDecompiledFile.name == base.asString()) { "Light class for file:\n" + decompiledClassOrObject.containingKtFile.virtualFile.canonicalPath + "\nwas expected to have name: " + base.asString() + "\n Actual: " + rootLightClassForDecompiledFile.name } - var current: KtLightClassForDecompiledDeclaration = rootLightClassForDecompiledFile - while (iterator.hasNext()) { - val name = iterator.next() - val innerClass = current.findInnerClassByName(name.asString(), false).sure { - "Could not find corresponding inner/nested class " + relativeFqName + " in class " + decompiledClassOrObject.fqName + "\n" + "File: " + decompiledClassOrObject.containingKtFile.virtualFile.name - } - current = innerClass as KtLightClassForDecompiledDeclaration - } - return current - } - - private fun getClassRelativeName(decompiledClassOrObject: KtClassOrObject): FqName { - val name = decompiledClassOrObject.nameAsName!! - val parent = PsiTreeUtil.getParentOfType(decompiledClassOrObject, KtClassOrObject::class.java, true) - if (parent == null) { - assert(decompiledClassOrObject.isTopLevel()) - return FqName.topLevel(name) - } - return getClassRelativeName(parent).child(name) - } - - private fun createLightClassForDecompiledKotlinFile(file: KtClsFile): KtLightClassForDecompiledDeclaration? { - val virtualFile = file.virtualFile ?: return null - - val classOrObject = file.declarations.filterIsInstance().singleOrNull() - - val javaClsClass = createClsJavaClassFromVirtualFile( - file, virtualFile, - correspondingClassOrObject = classOrObject - ) ?: return null - - return KtLightClassForDecompiledDeclaration(javaClsClass, classOrObject, file) - } - - private fun createClsJavaClassFromVirtualFile( - mirrorFile: KtFile, - classFile: VirtualFile, - correspondingClassOrObject: KtClassOrObject? - ): ClsClassImpl? { - val javaFileStub = ClsJavaStubByVirtualFileCache.getInstance(project).get(classFile) ?: return null - javaFileStub.psiFactory = ClsWrapperStubPsiFactory.INSTANCE - val manager = PsiManager.getInstance(mirrorFile.project) - val fakeFile = object : ClsFileImpl(ClassFileViewProvider(manager, classFile)) { - override fun getNavigationElement(): PsiElement { - if (correspondingClassOrObject != null) { - return correspondingClassOrObject.navigationElement.containingFile - } - return super.getNavigationElement() - } - - override fun getStub() = javaFileStub - - override fun getMirror() = mirrorFile - - override fun isPhysical() = false - } - javaFileStub.psi = fakeFile - return fakeFile.classes.single() as ClsClassImpl - } -} - - -class KtFileClassProviderImpl(val kotlinAsJavaSupport: KotlinAsJavaSupport) : KtFileClassProvider { - override fun getFileClasses(file: KtFile): Array { - // TODO We don't currently support finding light classes for scripts - if (file.isCompiled || file.isScript()) { - return PsiClass.EMPTY_ARRAY - } - - val result = arrayListOf() - file.declarations.filterIsInstance().map { it.toLightClass() }.filterNotNullTo(result) - - val moduleInfo = file.getModuleInfo() - val jvmClassInfo = JvmFileClassUtil.getFileClassInfoNoResolve(file) - val fileClassFqName = file.javaFileFacadeFqName - - val facadeClasses = when { - file.analysisContext != null && file.hasTopLevelCallables() -> - listOf(KtLightClassForFacade.createForSyntheticFile(PsiManager.getInstance(file.project), fileClassFqName, file)) - - jvmClassInfo.withJvmMultifileClass -> - kotlinAsJavaSupport.getFacadeClasses(fileClassFqName, moduleInfo.contentScope()) - - file.hasTopLevelCallables() -> - (kotlinAsJavaSupport as IDEKotlinAsJavaSupport).createLightClassForFileFacade( - fileClassFqName, listOf(file), moduleInfo - ) - - else -> emptyList() - } - - facadeClasses.filterTo(result) { - it is KtLightClassForFacade && file in it.files - } - - return result.toTypedArray() - } -} diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KtFileClassProviderImpl.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KtFileClassProviderImpl.kt new file mode 100644 index 00000000000..4921eab7d9f --- /dev/null +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/caches/resolve/KtFileClassProviderImpl.kt @@ -0,0 +1,63 @@ +/* + * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.caches.resolve + +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiManager +import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport +import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade +import org.jetbrains.kotlin.asJava.toLightClass +import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil +import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName +import org.jetbrains.kotlin.idea.caches.project.getModuleInfo +import org.jetbrains.kotlin.psi.KtClassOrObject +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.KtFileClassProvider +import org.jetbrains.kotlin.psi.analysisContext + +class KtFileClassProviderImpl(val kotlinAsJavaSupport: KotlinAsJavaSupport) : + KtFileClassProvider { + override fun getFileClasses(file: KtFile): Array { + // TODO We don't currently support finding light classes for scripts + if (file.isCompiled || file.isScript()) { + return PsiClass.EMPTY_ARRAY + } + + val result = arrayListOf() + file.declarations.filterIsInstance().map { it.toLightClass() }.filterNotNullTo(result) + + val moduleInfo = file.getModuleInfo() + val jvmClassInfo = JvmFileClassUtil.getFileClassInfoNoResolve(file) + val fileClassFqName = file.javaFileFacadeFqName + + val facadeClasses = when { + file.analysisContext != null && file.hasTopLevelCallables() -> + listOf( + KtLightClassForFacade.createForSyntheticFile( + PsiManager.getInstance( + file.project + ), fileClassFqName, file + ) + ) + + jvmClassInfo.withJvmMultifileClass -> + kotlinAsJavaSupport.getFacadeClasses(fileClassFqName, moduleInfo.contentScope()) + + file.hasTopLevelCallables() -> + (kotlinAsJavaSupport as IDEKotlinAsJavaSupport).createLightClassForFileFacade( + fileClassFqName, listOf(file), moduleInfo + ) + + else -> emptyList() + } + + facadeClasses.filterTo(result) { + it is KtLightClassForFacade && file in it.files + } + + return result.toTypedArray() + } +} \ No newline at end of file diff --git a/plugins/uast-kotlin/tests/AbstractKotlinUastTest.kt b/plugins/uast-kotlin/tests/AbstractKotlinUastTest.kt index baa7575ea36..ad281f07c74 100644 --- a/plugins/uast-kotlin/tests/AbstractKotlinUastTest.kt +++ b/plugins/uast-kotlin/tests/AbstractKotlinUastTest.kt @@ -11,9 +11,9 @@ import com.intellij.util.io.URLUtil import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.messages.MessageRenderer import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector -import org.jetbrains.kotlin.cli.jvm.compiler.CliLightClassGenerationSupport import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment +import org.jetbrains.kotlin.cli.jvm.compiler.NoScopeRecordCliBindingTrace import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.config.CompilerConfiguration @@ -49,7 +49,7 @@ abstract class AbstractKotlinUastTest : AbstractUastTest() { initializeKotlinEnvironment() - val trace = CliLightClassGenerationSupport.NoScopeRecordCliBindingTrace() + val trace = NoScopeRecordCliBindingTrace() val environment = kotlinCoreEnvironment!! TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(