Refactor: split *LightClassGenerationSupport into separate files
Move cli binding trace implementation to top level
This commit is contained in:
@@ -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<PsiClass> {
|
||||||
|
return findFacadeFilesInPackage(packageFqName, scope)
|
||||||
|
.groupBy { it.javaFileFacadeFqName }
|
||||||
|
.mapNotNull {
|
||||||
|
KtLightClassForFacade.createForFacade(
|
||||||
|
psiManager,
|
||||||
|
it.key,
|
||||||
|
scope,
|
||||||
|
it.value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getFacadeNames(packageFqName: FqName, scope: GlobalSearchScope): Collection<String> {
|
||||||
|
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<PsiClass> {
|
||||||
|
val filesForFacade = findFilesForFacade(facadeFqName, scope)
|
||||||
|
if (filesForFacade.isEmpty()) return emptyList()
|
||||||
|
|
||||||
|
return listOfNotNull<PsiClass>(
|
||||||
|
KtLightClassForFacade.createForFacade(
|
||||||
|
psiManager,
|
||||||
|
facadeFqName,
|
||||||
|
scope,
|
||||||
|
filesForFacade
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getScriptClasses(scriptFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> {
|
||||||
|
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<PsiClass> {
|
||||||
|
//
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun findFilesForFacade(facadeFqName: FqName, scope: GlobalSearchScope): Collection<KtFile> {
|
||||||
|
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<KtClassOrObject> {
|
||||||
|
val files = findFilesForPackage(packageFqName, searchScope)
|
||||||
|
val result = SmartList<KtClassOrObject>()
|
||||||
|
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<FqName> {
|
||||||
|
val packageView = traceHolder.module.getPackage(fqn)
|
||||||
|
val members = packageView.memberScope.getContributedDescriptors(
|
||||||
|
DescriptorKindFilter.PACKAGES,
|
||||||
|
MemberScope.ALL_NAME_FILTER
|
||||||
|
)
|
||||||
|
return ContainerUtil.mapNotNull(
|
||||||
|
members,
|
||||||
|
object : Function<DeclarationDescriptor, FqName> {
|
||||||
|
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<KtClassOrObject> {
|
||||||
|
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<KtFile> {
|
||||||
|
return traceHolder.bindingContext.get(BindingContext.PACKAGE_TO_FILES, fqName)?.filter {
|
||||||
|
PsiSearchScopeUtil.isInScope(searchScope, it)
|
||||||
|
} ?: emptyList()
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-202
@@ -16,41 +16,15 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.cli.jvm.compiler
|
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.LightClassBuilder
|
||||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||||
import org.jetbrains.kotlin.asJava.builder.InvalidLightClassDataHolder
|
import org.jetbrains.kotlin.asJava.builder.InvalidLightClassDataHolder
|
||||||
import org.jetbrains.kotlin.asJava.builder.LightClassConstructionContext
|
import org.jetbrains.kotlin.asJava.builder.LightClassConstructionContext
|
||||||
import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder
|
import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder
|
||||||
import org.jetbrains.kotlin.asJava.builder.LightClassDataHolderImpl
|
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.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.psi.*
|
||||||
import org.jetbrains.kotlin.resolve.*
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
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
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class solves the problem of interdependency between analyzing Kotlin code and generating JetLightClasses
|
* 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
|
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 <K, V> record(slice: WritableSlice<K, V>, 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 <K, V> get(slice: ReadOnlySlice<K, V>, 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<K, V>(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<PsiClass> {
|
|
||||||
return findFacadeFilesInPackage(packageFqName, scope)
|
|
||||||
.groupBy { it.javaFileFacadeFqName }
|
|
||||||
.mapNotNull { KtLightClassForFacade.createForFacade(psiManager, it.key, scope, it.value) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getFacadeNames(packageFqName: FqName, scope: GlobalSearchScope): Collection<String> {
|
|
||||||
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<PsiClass> {
|
|
||||||
val filesForFacade = findFilesForFacade(facadeFqName, scope)
|
|
||||||
if (filesForFacade.isEmpty()) return emptyList()
|
|
||||||
|
|
||||||
return listOfNotNull<PsiClass>(
|
|
||||||
KtLightClassForFacade.createForFacade(psiManager, facadeFqName, scope, filesForFacade))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getScriptClasses(scriptFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> {
|
|
||||||
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<PsiClass> {
|
|
||||||
//
|
|
||||||
return emptyList()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun findFilesForFacade(facadeFqName: FqName, scope: GlobalSearchScope): Collection<KtFile> {
|
|
||||||
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<KtClassOrObject> {
|
|
||||||
val files = findFilesForPackage(packageFqName, searchScope)
|
|
||||||
val result = SmartList<KtClassOrObject>()
|
|
||||||
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<FqName> {
|
|
||||||
val packageView = traceHolder.module.getPackage(fqn)
|
|
||||||
val members = packageView.memberScope.getContributedDescriptors(DescriptorKindFilter.PACKAGES, MemberScope.ALL_NAME_FILTER)
|
|
||||||
return ContainerUtil.mapNotNull(members, object : Function<DeclarationDescriptor, FqName> {
|
|
||||||
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<KtClassOrObject> {
|
|
||||||
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<KtFile> {
|
|
||||||
return traceHolder.bindingContext.get(BindingContext.PACKAGE_TO_FILES, fqName)?.filter {
|
|
||||||
PsiSearchScopeUtil.isInScope(searchScope, it)
|
|
||||||
} ?: emptyList()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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 <K, V> record(slice: WritableSlice<K, V>, 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 <K, V> get(slice: ReadOnlySlice<K, V>, 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<K, V>(slice, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
-6
@@ -372,12 +372,12 @@ object KotlinToJVMBytecodeCompiler {
|
|||||||
// of the compiled modules (.class) to the list of scopes of the source module
|
// 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))
|
val scope = if (moduleOutputs.isEmpty()) sourcesOnly else sourcesOnly.uniteWith(DirectoriesScope(project, moduleOutputs))
|
||||||
TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(
|
TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(
|
||||||
project,
|
project,
|
||||||
sourceFiles,
|
sourceFiles,
|
||||||
CliTraceHolder.NoScopeRecordCliBindingTrace(),
|
NoScopeRecordCliBindingTrace(),
|
||||||
environment.configuration,
|
environment.configuration,
|
||||||
environment::createPackagePartProvider,
|
environment::createPackagePartProvider,
|
||||||
sourceModuleSearchScope = scope
|
sourceModuleSearchScope = scope
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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.ILineId
|
||||||
import org.jetbrains.kotlin.cli.common.repl.ReplCodeLine
|
import org.jetbrains.kotlin.cli.common.repl.ReplCodeLine
|
||||||
import org.jetbrains.kotlin.cli.common.repl.ReplHistory
|
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.KotlinCoreEnvironment
|
||||||
|
import org.jetbrains.kotlin.cli.jvm.compiler.NoScopeRecordCliBindingTrace
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM
|
import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM
|
||||||
import org.jetbrains.kotlin.container.get
|
import org.jetbrains.kotlin.container.get
|
||||||
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
|
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
|
||||||
@@ -56,7 +56,7 @@ class ReplCodeAnalyzer(environment: KotlinCoreEnvironment) {
|
|||||||
|
|
||||||
val module: ModuleDescriptorImpl
|
val module: ModuleDescriptorImpl
|
||||||
|
|
||||||
val trace: BindingTraceContext = CliTraceHolder.NoScopeRecordCliBindingTrace()
|
val trace: BindingTraceContext = NoScopeRecordCliBindingTrace()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// Module source scope is empty because all binary classes are in the dependency module, and all source classes are guaranteed
|
// Module source scope is empty because all binary classes are in the dependency module, and all source classes are guaranteed
|
||||||
|
|||||||
@@ -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<KtClassOrObject>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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<KtFile>
|
||||||
|
|
||||||
|
abstract fun findClassOrObjectDeclarations(fqName: FqName, searchScope: GlobalSearchScope): Collection<KtClassOrObject>
|
||||||
|
|
||||||
|
abstract fun packageExists(fqName: FqName, scope: GlobalSearchScope): Boolean
|
||||||
|
|
||||||
|
abstract fun getSubPackages(fqn: FqName, scope: GlobalSearchScope): Collection<FqName>
|
||||||
|
|
||||||
|
abstract fun getLightClass(classOrObject: KtClassOrObject): KtLightClass?
|
||||||
|
|
||||||
|
abstract fun getLightClassForScript(script: KtScript): KtLightClass?
|
||||||
|
|
||||||
|
abstract fun getFacadeClasses(facadeFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass>
|
||||||
|
|
||||||
|
abstract fun getScriptClasses(scriptFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass>
|
||||||
|
|
||||||
|
abstract fun getKotlinInternalClasses(fqName: FqName, scope: GlobalSearchScope): Collection<PsiClass>
|
||||||
|
|
||||||
|
abstract fun getFacadeClassesInPackage(packageFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass>
|
||||||
|
|
||||||
|
abstract fun getFacadeNames(packageFqName: FqName, scope: GlobalSearchScope): Collection<String>
|
||||||
|
|
||||||
|
abstract fun findFilesForFacade(facadeFqName: FqName, scope: GlobalSearchScope): Collection<KtFile>
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@JvmStatic
|
||||||
|
fun getInstance(project: Project): KotlinAsJavaSupport {
|
||||||
|
return ServiceManager.getService(
|
||||||
|
project,
|
||||||
|
KotlinAsJavaSupport::class.java
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,66 +18,15 @@ package org.jetbrains.kotlin.asJava
|
|||||||
|
|
||||||
import com.intellij.openapi.components.ServiceManager
|
import com.intellij.openapi.components.ServiceManager
|
||||||
import com.intellij.openapi.project.Project
|
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.LightClassBuilderResult
|
||||||
import org.jetbrains.kotlin.asJava.builder.LightClassConstructionContext
|
import org.jetbrains.kotlin.asJava.builder.LightClassConstructionContext
|
||||||
import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder
|
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.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.name.FqName
|
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
|
||||||
typealias LightClassBuilder = (LightClassConstructionContext) -> LightClassBuilderResult
|
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<KtClassOrObject>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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<KtFile>
|
|
||||||
|
|
||||||
abstract fun findClassOrObjectDeclarations(fqName: FqName, searchScope: GlobalSearchScope): Collection<KtClassOrObject>
|
|
||||||
|
|
||||||
abstract fun packageExists(fqName: FqName, scope: GlobalSearchScope): Boolean
|
|
||||||
|
|
||||||
abstract fun getSubPackages(fqn: FqName, scope: GlobalSearchScope): Collection<FqName>
|
|
||||||
|
|
||||||
abstract fun getLightClass(classOrObject: KtClassOrObject): KtLightClass?
|
|
||||||
|
|
||||||
abstract fun getLightClassForScript(script: KtScript): KtLightClassForScript?
|
|
||||||
|
|
||||||
abstract fun getFacadeClasses(facadeFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass>
|
|
||||||
|
|
||||||
abstract fun getScriptClasses(scriptFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass>
|
|
||||||
|
|
||||||
abstract fun getKotlinInternalClasses(fqName: FqName, scope: GlobalSearchScope): Collection<PsiClass>
|
|
||||||
|
|
||||||
abstract fun getFacadeClassesInPackage(packageFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass>
|
|
||||||
|
|
||||||
abstract fun getFacadeNames(packageFqName: FqName, scope: GlobalSearchScope): Collection<String>
|
|
||||||
|
|
||||||
abstract fun findFilesForFacade(facadeFqName: FqName, scope: GlobalSearchScope): Collection<KtFile>
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
@JvmStatic
|
|
||||||
fun getInstance(project: Project): KotlinAsJavaSupport {
|
|
||||||
return ServiceManager.getService(project, KotlinAsJavaSupport::class.java)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class LightClassGenerationSupport {
|
abstract class LightClassGenerationSupport {
|
||||||
abstract fun createDataHolderForClass(classOrObject: KtClassOrObject, builder: LightClassBuilder): LightClassDataHolder.ForClass
|
abstract fun createDataHolderForClass(classOrObject: KtClassOrObject, builder: LightClassBuilder): LightClassDataHolder.ForClass
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -21,7 +21,7 @@ import com.intellij.openapi.util.text.StringUtil
|
|||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
||||||
import org.jetbrains.kotlin.analyzer.common.CommonAnalyzerFacade
|
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.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM
|
||||||
import org.jetbrains.kotlin.config.*
|
import org.jetbrains.kotlin.config.*
|
||||||
import org.jetbrains.kotlin.container.get
|
import org.jetbrains.kotlin.container.get
|
||||||
@@ -104,7 +104,7 @@ abstract class AbstractDiagnosticsTest : BaseDiagnosticsTest() {
|
|||||||
|
|
||||||
val separateModules = groupedByModule.size == 1 && groupedByModule.keys.single() == null
|
val separateModules = groupedByModule.size == 1 && groupedByModule.keys.single() == null
|
||||||
val result = analyzeModuleContents(
|
val result = analyzeModuleContents(
|
||||||
moduleContext, ktFiles, CliTraceHolder.NoScopeRecordCliBindingTrace(),
|
moduleContext, ktFiles, NoScopeRecordCliBindingTrace(),
|
||||||
languageVersionSettings, separateModules, loadJvmTarget(testFilesInModule)
|
languageVersionSettings, separateModules, loadJvmTarget(testFilesInModule)
|
||||||
)
|
)
|
||||||
if (oldModule != result.moduleDescriptor) {
|
if (oldModule != result.moduleDescriptor) {
|
||||||
|
|||||||
@@ -35,9 +35,9 @@ import org.jetbrains.kotlin.checkers.CheckerTestUtil;
|
|||||||
import org.jetbrains.kotlin.checkers.CompilerTestLanguageVersionSettings;
|
import org.jetbrains.kotlin.checkers.CompilerTestLanguageVersionSettings;
|
||||||
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys;
|
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys;
|
||||||
import org.jetbrains.kotlin.cli.common.output.outputUtils.OutputUtilsKt;
|
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.EnvironmentConfigFiles;
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment;
|
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.forTestCompile.ForTestCompileRuntime;
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||||
import org.jetbrains.kotlin.config.*;
|
import org.jetbrains.kotlin.config.*;
|
||||||
@@ -466,7 +466,7 @@ public abstract class CodegenTestCase extends KtUsefulTestCase {
|
|||||||
try {
|
try {
|
||||||
GenerationState generationState = GenerationUtils.compileFiles(
|
GenerationState generationState = GenerationUtils.compileFiles(
|
||||||
myFiles.getPsiFiles(), myEnvironment, getClassBuilderFactory(),
|
myFiles.getPsiFiles(), myEnvironment, getClassBuilderFactory(),
|
||||||
new CliTraceHolder.NoScopeRecordCliBindingTrace()
|
new NoScopeRecordCliBindingTrace()
|
||||||
);
|
);
|
||||||
classFileFactory = generationState.getFactory();
|
classFileFactory = generationState.getFactory();
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.codegen
|
|||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory
|
import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory
|
||||||
import org.jetbrains.kotlin.cli.common.output.outputUtils.writeAllTo
|
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.cli.jvm.compiler.KotlinCoreEnvironment
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
@@ -48,7 +48,7 @@ object GenerationUtils {
|
|||||||
files: List<KtFile>,
|
files: List<KtFile>,
|
||||||
environment: KotlinCoreEnvironment,
|
environment: KotlinCoreEnvironment,
|
||||||
classBuilderFactory: ClassBuilderFactory = ClassBuilderFactories.TEST,
|
classBuilderFactory: ClassBuilderFactory = ClassBuilderFactories.TEST,
|
||||||
trace: BindingTrace = CliTraceHolder.CliBindingTrace()
|
trace: BindingTrace = CliBindingTrace()
|
||||||
): GenerationState =
|
): GenerationState =
|
||||||
compileFiles(files, environment.configuration, classBuilderFactory, environment::createPackagePartProvider, trace)
|
compileFiles(files, environment.configuration, classBuilderFactory, environment::createPackagePartProvider, trace)
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ object GenerationUtils {
|
|||||||
configuration: CompilerConfiguration,
|
configuration: CompilerConfiguration,
|
||||||
classBuilderFactory: ClassBuilderFactory,
|
classBuilderFactory: ClassBuilderFactory,
|
||||||
packagePartProvider: (GlobalSearchScope) -> PackagePartProvider,
|
packagePartProvider: (GlobalSearchScope) -> PackagePartProvider,
|
||||||
trace: BindingTrace = CliTraceHolder.CliBindingTrace()
|
trace: BindingTrace = CliBindingTrace()
|
||||||
): GenerationState {
|
): GenerationState {
|
||||||
val analysisResult =
|
val analysisResult =
|
||||||
JvmResolveUtil.analyzeAndCheckForErrors(files.first().project, files, configuration, packagePartProvider, trace)
|
JvmResolveUtil.analyzeAndCheckForErrors(files.first().project, files, configuration, packagePartProvider, trace)
|
||||||
|
|||||||
+2
-2
@@ -21,9 +21,9 @@ import com.intellij.openapi.util.io.FileUtil;
|
|||||||
import junit.framework.ComparisonFailure;
|
import junit.framework.ComparisonFailure;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.kotlin.analyzer.AnalysisResult;
|
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.EnvironmentConfigFiles;
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment;
|
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.compiler.TopDownAnalyzerFacadeForJVM;
|
||||||
import org.jetbrains.kotlin.cli.jvm.config.JvmContentRootsKt;
|
import org.jetbrains.kotlin.cli.jvm.config.JvmContentRootsKt;
|
||||||
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime;
|
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);
|
KotlinCoreEnvironment.createForTests(getTestRootDisposable(), configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES);
|
||||||
registerJavacIfNeeded(environment);
|
registerJavacIfNeeded(environment);
|
||||||
AnalysisResult result = TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(
|
AnalysisResult result = TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(
|
||||||
environment.getProject(), environment.getSourceFiles(), new CliTraceHolder.NoScopeRecordCliBindingTrace(),
|
environment.getProject(), environment.getSourceFiles(), new NoScopeRecordCliBindingTrace(),
|
||||||
configuration, environment::createPackagePartProvider
|
configuration, environment::createPackagePartProvider
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -18,8 +18,8 @@ package org.jetbrains.kotlin.renderer
|
|||||||
|
|
||||||
import com.intellij.openapi.editor.impl.DocumentImpl
|
import com.intellij.openapi.editor.impl.DocumentImpl
|
||||||
import com.intellij.openapi.util.io.FileUtil
|
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.KotlinCoreEnvironment
|
||||||
|
import org.jetbrains.kotlin.cli.jvm.compiler.NoScopeRecordCliBindingTrace
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM
|
import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM
|
||||||
import org.jetbrains.kotlin.config.JvmTarget
|
import org.jetbrains.kotlin.config.JvmTarget
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
|
||||||
@@ -60,7 +60,7 @@ abstract class AbstractDescriptorRendererTest : KotlinTestWithEnvironment() {
|
|||||||
val container = createContainerForLazyResolve(
|
val container = createContainerForLazyResolve(
|
||||||
context,
|
context,
|
||||||
FileBasedDeclarationProviderFactory(context.storageManager, listOf(psiFile)),
|
FileBasedDeclarationProviderFactory(context.storageManager, listOf(psiFile)),
|
||||||
CliTraceHolder.NoScopeRecordCliBindingTrace(),
|
NoScopeRecordCliBindingTrace(),
|
||||||
JvmPlatform,
|
JvmPlatform,
|
||||||
JvmTarget.JVM_1_6,
|
JvmTarget.JVM_1_6,
|
||||||
targetEnvironment,
|
targetEnvironment,
|
||||||
|
|||||||
@@ -19,8 +19,9 @@ package org.jetbrains.kotlin.resolve.lazy
|
|||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
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.KotlinCoreEnvironment
|
||||||
|
import org.jetbrains.kotlin.cli.jvm.compiler.NoScopeRecordCliBindingTrace
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM
|
import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
import org.jetbrains.kotlin.container.ComponentProvider
|
import org.jetbrains.kotlin.container.ComponentProvider
|
||||||
@@ -35,7 +36,7 @@ object JvmResolveUtil {
|
|||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun createContainer(environment: KotlinCoreEnvironment, files: Collection<KtFile> = emptyList()): ComponentProvider =
|
fun createContainer(environment: KotlinCoreEnvironment, files: Collection<KtFile> = emptyList()): ComponentProvider =
|
||||||
TopDownAnalyzerFacadeForJVM.createContainer(
|
TopDownAnalyzerFacadeForJVM.createContainer(
|
||||||
environment.project, files, CliTraceHolder.NoScopeRecordCliBindingTrace(),
|
environment.project, files, NoScopeRecordCliBindingTrace(),
|
||||||
environment.configuration, { PackagePartProvider.Empty }, ::FileBasedDeclarationProviderFactory
|
environment.configuration, { PackagePartProvider.Empty }, ::FileBasedDeclarationProviderFactory
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -53,7 +54,7 @@ object JvmResolveUtil {
|
|||||||
files: Collection<KtFile>,
|
files: Collection<KtFile>,
|
||||||
configuration: CompilerConfiguration,
|
configuration: CompilerConfiguration,
|
||||||
packagePartProvider: (GlobalSearchScope) -> PackagePartProvider,
|
packagePartProvider: (GlobalSearchScope) -> PackagePartProvider,
|
||||||
trace: BindingTrace = CliTraceHolder.CliBindingTrace()
|
trace: BindingTrace = CliBindingTrace()
|
||||||
): AnalysisResult {
|
): AnalysisResult {
|
||||||
for (file in files) {
|
for (file in files) {
|
||||||
AnalyzingUtils.checkForSyntacticErrors(file)
|
AnalyzingUtils.checkForSyntacticErrors(file)
|
||||||
@@ -85,7 +86,7 @@ object JvmResolveUtil {
|
|||||||
files: Collection<KtFile>,
|
files: Collection<KtFile>,
|
||||||
configuration: CompilerConfiguration,
|
configuration: CompilerConfiguration,
|
||||||
packagePartProviderFactory: (GlobalSearchScope) -> PackagePartProvider,
|
packagePartProviderFactory: (GlobalSearchScope) -> PackagePartProvider,
|
||||||
trace: BindingTrace = CliTraceHolder.CliBindingTrace()
|
trace: BindingTrace = CliBindingTrace()
|
||||||
): AnalysisResult {
|
): AnalysisResult {
|
||||||
return TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(
|
return TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(
|
||||||
project, files, trace, configuration, packagePartProviderFactory
|
project, files, trace, configuration, packagePartProviderFactory
|
||||||
|
|||||||
+308
@@ -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<String> {
|
||||||
|
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<PsiClass> {
|
||||||
|
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<KtClassOrObject> {
|
||||||
|
return runReadAction {
|
||||||
|
KotlinFullClassNameIndex.getInstance().get(
|
||||||
|
fqName.asString(),
|
||||||
|
project,
|
||||||
|
KotlinSourceFilterScope.sourceAndClassFiles(searchScope, project)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun findFilesForPackage(fqName: FqName, searchScope: GlobalSearchScope): Collection<KtFile> {
|
||||||
|
return runReadAction {
|
||||||
|
PackageIndexUtil.findFilesWithExactPackage(
|
||||||
|
fqName,
|
||||||
|
KotlinSourceFilterScope.sourceAndClassFiles(
|
||||||
|
searchScope,
|
||||||
|
project
|
||||||
|
),
|
||||||
|
project
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun findClassOrObjectDeclarationsInPackage(
|
||||||
|
packageFqName: FqName,
|
||||||
|
searchScope: GlobalSearchScope
|
||||||
|
): Collection<KtClassOrObject> {
|
||||||
|
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<FqName> {
|
||||||
|
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<KtFile>
|
||||||
|
): List<PsiClass> {
|
||||||
|
if (lightClassForFacade == null) return emptyList()
|
||||||
|
|
||||||
|
val lightClasses = ArrayList<PsiClass>()
|
||||||
|
lightClasses.add(lightClassForFacade)
|
||||||
|
if (facadeFiles.size > 1) {
|
||||||
|
lightClasses.addAll(facadeFiles.map {
|
||||||
|
FakeLightClassForFileOfPackage(lightClassForFacade, it)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return lightClasses
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getFacadeClasses(facadeFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> {
|
||||||
|
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<PsiClass> {
|
||||||
|
return KotlinScriptFqnIndex.instance.get(scriptFqName.asString(), project, scope).mapNotNull {
|
||||||
|
getLightClassForScript(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getKotlinInternalClasses(fqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> {
|
||||||
|
if (fqName.isRoot) return emptyList()
|
||||||
|
|
||||||
|
return findPackageParts(fqName, scope) + findPlatformWrapper(fqName, scope)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findPackageParts(fqName: FqName, scope: GlobalSearchScope): List<KtLightClassForDecompiledDeclaration> {
|
||||||
|
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<PsiClass> {
|
||||||
|
return platformMutabilityWrapper(fqName) {
|
||||||
|
JavaPsiFacade.getInstance(
|
||||||
|
project
|
||||||
|
).findClass(it, scope)
|
||||||
|
}?.let { listOf(it) }.orEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createLightClassForFileFacade(
|
||||||
|
facadeFqName: FqName,
|
||||||
|
facadeFiles: List<KtFile>,
|
||||||
|
moduleInfo: IdeaModuleInfo
|
||||||
|
): List<PsiClass> {
|
||||||
|
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<KtFile> {
|
||||||
|
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<KtClassOrObject>().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
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-298
@@ -17,41 +17,19 @@
|
|||||||
package org.jetbrains.kotlin.idea.caches.resolve
|
package org.jetbrains.kotlin.idea.caches.resolve
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
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.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.LightClassBuilder
|
||||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
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.InvalidLightClassDataHolder
|
||||||
import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder
|
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.finder.JavaElementFinder
|
||||||
import org.jetbrains.kotlin.asJava.toLightClass
|
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
|
import org.jetbrains.kotlin.idea.caches.lightClasses.IDELightClassContexts
|
||||||
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
|
import org.jetbrains.kotlin.idea.caches.lightClasses.LazyLightClassDataHolder
|
||||||
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.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
import org.jetbrains.kotlin.resolve.lazy.NoDescriptorForDeclarationException
|
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() {
|
class IDELightClassGenerationSupport(project: Project) : LightClassGenerationSupport() {
|
||||||
private val scopeFileComparator = JavaElementFinder.byClasspathComparator(GlobalSearchScope.allScope(project))
|
private val scopeFileComparator = JavaElementFinder.byClasspathComparator(GlobalSearchScope.allScope(project))
|
||||||
@@ -113,276 +91,3 @@ class IDELightClassGenerationSupport(project: Project) : LightClassGenerationSup
|
|||||||
override fun analyzeWithContent(element: KtClassOrObject) = element.analyzeWithContent()
|
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<String> {
|
|
||||||
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<PsiClass> {
|
|
||||||
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<KtClassOrObject> {
|
|
||||||
return runReadAction {
|
|
||||||
KotlinFullClassNameIndex.getInstance().get(fqName.asString(), project, sourceAndClassFiles(searchScope, project))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun findFilesForPackage(fqName: FqName, searchScope: GlobalSearchScope): Collection<KtFile> {
|
|
||||||
return runReadAction {
|
|
||||||
PackageIndexUtil.findFilesWithExactPackage(fqName, sourceAndClassFiles(searchScope, project), project)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun findClassOrObjectDeclarationsInPackage(
|
|
||||||
packageFqName: FqName,
|
|
||||||
searchScope: GlobalSearchScope
|
|
||||||
): Collection<KtClassOrObject> {
|
|
||||||
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<FqName> {
|
|
||||||
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<KtFile>
|
|
||||||
): List<PsiClass> {
|
|
||||||
if (lightClassForFacade == null) return emptyList()
|
|
||||||
|
|
||||||
val lightClasses = ArrayList<PsiClass>()
|
|
||||||
lightClasses.add(lightClassForFacade)
|
|
||||||
if (facadeFiles.size > 1) {
|
|
||||||
lightClasses.addAll(facadeFiles.map {
|
|
||||||
FakeLightClassForFileOfPackage(lightClassForFacade, it)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return lightClasses
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getFacadeClasses(facadeFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> {
|
|
||||||
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<PsiClass> {
|
|
||||||
return KotlinScriptFqnIndex.instance.get(scriptFqName.asString(), project, scope).mapNotNull {
|
|
||||||
getLightClassForScript(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getKotlinInternalClasses(fqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> {
|
|
||||||
if (fqName.isRoot) return emptyList()
|
|
||||||
|
|
||||||
return findPackageParts(fqName, scope) + findPlatformWrapper(fqName, scope)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun findPackageParts(fqName: FqName, scope: GlobalSearchScope): List<KtLightClassForDecompiledDeclaration> {
|
|
||||||
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<PsiClass> {
|
|
||||||
return platformMutabilityWrapper(fqName) { JavaPsiFacade.getInstance(project).findClass(it, scope) }?.let { listOf(it) }.orEmpty()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun createLightClassForFileFacade(
|
|
||||||
facadeFqName: FqName,
|
|
||||||
facadeFiles: List<KtFile>,
|
|
||||||
moduleInfo: IdeaModuleInfo
|
|
||||||
): List<PsiClass> {
|
|
||||||
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<KtFile> {
|
|
||||||
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<KtClassOrObject>().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<PsiClass> {
|
|
||||||
// TODO We don't currently support finding light classes for scripts
|
|
||||||
if (file.isCompiled || file.isScript()) {
|
|
||||||
return PsiClass.EMPTY_ARRAY
|
|
||||||
}
|
|
||||||
|
|
||||||
val result = arrayListOf<PsiClass>()
|
|
||||||
file.declarations.filterIsInstance<KtClassOrObject>().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<PsiClass>()
|
|
||||||
}
|
|
||||||
|
|
||||||
facadeClasses.filterTo(result) {
|
|
||||||
it is KtLightClassForFacade && file in it.files
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.toTypedArray()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+63
@@ -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<PsiClass> {
|
||||||
|
// TODO We don't currently support finding light classes for scripts
|
||||||
|
if (file.isCompiled || file.isScript()) {
|
||||||
|
return PsiClass.EMPTY_ARRAY
|
||||||
|
}
|
||||||
|
|
||||||
|
val result = arrayListOf<PsiClass>()
|
||||||
|
file.declarations.filterIsInstance<KtClassOrObject>().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<PsiClass>()
|
||||||
|
}
|
||||||
|
|
||||||
|
facadeClasses.filterTo(result) {
|
||||||
|
it is KtLightClassForFacade && file in it.files
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.toTypedArray()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,9 +11,9 @@ import com.intellij.util.io.URLUtil
|
|||||||
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||||
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
|
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
|
||||||
import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector
|
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.EnvironmentConfigFiles
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
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.compiler.TopDownAnalyzerFacadeForJVM
|
||||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
@@ -49,7 +49,7 @@ abstract class AbstractKotlinUastTest : AbstractUastTest() {
|
|||||||
|
|
||||||
initializeKotlinEnvironment()
|
initializeKotlinEnvironment()
|
||||||
|
|
||||||
val trace = CliLightClassGenerationSupport.NoScopeRecordCliBindingTrace()
|
val trace = NoScopeRecordCliBindingTrace()
|
||||||
|
|
||||||
val environment = kotlinCoreEnvironment!!
|
val environment = kotlinCoreEnvironment!!
|
||||||
TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(
|
TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration(
|
||||||
|
|||||||
Reference in New Issue
Block a user