[FIR IDE] Implement own fir light classes support

This commit is contained in:
Igor Yakovlev
2021-07-01 12:57:11 +02:00
parent 7fff282565
commit b64f7909b8
15 changed files with 209 additions and 73 deletions
@@ -129,4 +129,7 @@ class CliKotlinAsJavaSupport(
PsiSearchScopeUtil.isInScope(searchScope, it) PsiSearchScopeUtil.isInScope(searchScope, it)
}.orEmpty() }.orEmpty()
} }
override fun createFacadeForSyntheticFile(facadeClassFqName: FqName, file: KtFile): PsiClass =
error("Should not be called")
} }
@@ -1,3 +1,4 @@
// FIR_IDE_IGNORE
// FILE: K1.kt // FILE: K1.kt
class KSub : J1() class KSub : J1()
@@ -8,9 +8,11 @@ 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.PsiClass
import com.intellij.psi.PsiManager
import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.asJava.classes.KtFakeLightClass import org.jetbrains.kotlin.asJava.classes.KtFakeLightClass
import org.jetbrains.kotlin.asJava.classes.KtLightClass import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
@@ -56,6 +58,8 @@ abstract class KotlinAsJavaSupport {
abstract fun getFakeLightClass(classOrObject: KtClassOrObject): KtFakeLightClass abstract fun getFakeLightClass(classOrObject: KtClassOrObject): KtFakeLightClass
abstract fun createFacadeForSyntheticFile(facadeClassFqName: FqName, file: KtFile): PsiClass
companion object { companion object {
@JvmStatic @JvmStatic
fun getInstance(project: Project): KotlinAsJavaSupport { fun getInstance(project: Project): KotlinAsJavaSupport {
@@ -282,15 +282,15 @@ open class KtLightClassForFacadeImpl constructor(
} }
fun createForSyntheticFile( fun createForSyntheticFile(
manager: PsiManager,
facadeClassFqName: FqName, facadeClassFqName: FqName,
file: KtFile file: KtFile
): KtLightClassForFacade { ): KtLightClassForFacade {
val project = file.project
// TODO: refactor, using cached value doesn't make sense for this case // TODO: refactor, using cached value doesn't make sense for this case
val cachedValue = CachedValuesManager.getManager(manager.project).createCachedValue( val cachedValue = CachedValuesManager.getManager(project).createCachedValue(
LightClassDataProviderForFileFacade.ByFile(manager.project, facadeClassFqName, file), false LightClassDataProviderForFileFacade.ByFile(project, facadeClassFqName, file), false
) )
return KtLightClassForFacadeImpl(manager, facadeClassFqName, cachedValue, listOf(file)) return KtLightClassForFacadeImpl(PsiManager.getInstance(project), facadeClassFqName, cachedValue, listOf(file))
} }
} }
} }
@@ -1,38 +0,0 @@
/*
* Copyright 2000-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.psi.PsiManager
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.asJava.classes.KtFakeLightClass
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.idea.asJava.KtFirBasedFakeLightClass
import org.jetbrains.kotlin.idea.asJava.classes.getOrCreateFirLightClass
import org.jetbrains.kotlin.idea.asJava.classes.getOrCreateFirLightFacade
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtScript
class IDEKotlinAsJavaFirSupport(project: Project) : IDEKotlinAsJavaSupport(project) {
override fun createLightClassForFacade(manager: PsiManager, facadeClassFqName: FqName, searchScope: GlobalSearchScope): KtLightClass? {
val sources = findFilesForFacade(facadeClassFqName, searchScope)
.filterNot { it.isCompiled }
if (sources.isEmpty()) return null
return getOrCreateFirLightFacade(sources, facadeClassFqName)
}
override fun createLightClassForScript(script: KtScript): KtLightClass? = null
override fun createLightClassForSourceDeclaration(classOrObject: KtClassOrObject): KtLightClass? =
getOrCreateFirLightClass(classOrObject)
override fun getFakeLightClass(classOrObject: KtClassOrObject): KtFakeLightClass =
KtFirBasedFakeLightClass(classOrObject)
}
@@ -14,6 +14,7 @@ dependencies {
compile(project(":compiler:fir:java")) compile(project(":compiler:fir:java"))
compile(project(":compiler:fir:jvm")) compile(project(":compiler:fir:jvm"))
compile(project(":compiler:backend.common.jvm")) compile(project(":compiler:backend.common.jvm"))
testCompile(project(":idea-frontend-fir"))
implementation(project(":compiler:ir.psi2ir")) implementation(project(":compiler:ir.psi2ir"))
implementation(project(":compiler:fir:entrypoint")) implementation(project(":compiler:fir:entrypoint"))
@@ -12,10 +12,7 @@ import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtTypeAlias
abstract class DeclarationProvider { abstract class DeclarationProvider {
abstract val searchScope: GlobalSearchScope abstract val searchScope: GlobalSearchScope
@@ -31,6 +28,8 @@ abstract class DeclarationProvider {
abstract fun getPropertyNamesInPackage(packageFqName: FqName): Set<Name> abstract fun getPropertyNamesInPackage(packageFqName: FqName): Set<Name>
abstract fun getFunctionsNamesInPackage(packageFqName: FqName): Set<Name> abstract fun getFunctionsNamesInPackage(packageFqName: FqName): Set<Name>
abstract fun getFacadeFilesInPackage(packageFqName: FqName): Collection<KtFile>
abstract fun findFilesForFacade(facadeFqName: FqName): Collection<KtFile>
} }
abstract class KtDeclarationProviderFactory { abstract class KtDeclarationProviderFactory {
@@ -14,7 +14,7 @@ import org.jetbrains.kotlin.platform.TargetPlatform
abstract class KtPackageProvider { abstract class KtPackageProvider {
abstract fun isPackageExists(packageFqName: FqName): Boolean abstract fun isPackageExists(packageFqName: FqName): Boolean
abstract fun getJavaAndKotlinSubPackageFqNames(packageFqName: FqName, targetPlatform: TargetPlatform): Set<Name> abstract fun getKotlinSubPackageFqNames(packageFqName: FqName): Set<Name>
} }
abstract class KtPackageProviderFactory { abstract class KtPackageProviderFactory {
@@ -7,31 +7,33 @@ package org.jetbrains.kotlin.idea.fir.low.level.api.compiler.based
import com.intellij.mock.MockProject import com.intellij.mock.MockProject
import com.intellij.openapi.Disposable import com.intellij.openapi.Disposable
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.Disposer
import com.intellij.psi.PsiElementFinder import com.intellij.psi.PsiElementFinder
import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.ProjectScope import com.intellij.psi.search.ProjectScope
import org.jetbrains.annotations.NotNull
import org.jetbrains.kotlin.analyzer.ModuleInfo import org.jetbrains.kotlin.analyzer.ModuleInfo
import org.jetbrains.kotlin.analyzer.ModuleSourceInfoBase import org.jetbrains.kotlin.analyzer.ModuleSourceInfoBase
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
import org.jetbrains.kotlin.cli.jvm.compiler.JvmPackagePartProvider
import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM
import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
import org.jetbrains.kotlin.cli.jvm.config.jvmModularRoots import org.jetbrains.kotlin.cli.jvm.config.jvmModularRoots
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.fir.DependencyListForCliModule import org.jetbrains.kotlin.fir.DependencyListForCliModule
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.FirAnalyzerFacade
import org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProvider import org.jetbrains.kotlin.fir.declarations.SealedClassInheritorsProvider
import org.jetbrains.kotlin.fir.deserialization.ModuleDataProvider import org.jetbrains.kotlin.fir.deserialization.ModuleDataProvider
import org.jetbrains.kotlin.fir.java.FirJavaElementFinder
import org.jetbrains.kotlin.fir.session.FirModuleInfoBasedModuleData import org.jetbrains.kotlin.fir.session.FirModuleInfoBasedModuleData
import org.jetbrains.kotlin.idea.asJava.IDEKotlinAsJavaFirSupport
import org.jetbrains.kotlin.idea.fir.low.level.api.* import org.jetbrains.kotlin.idea.fir.low.level.api.*
import org.jetbrains.kotlin.idea.fir.low.level.api.api.* import org.jetbrains.kotlin.idea.fir.low.level.api.api.DiagnosticCheckerFilter
import org.jetbrains.kotlin.idea.fir.low.level.api.sessions.FirIdeSession import org.jetbrains.kotlin.idea.fir.low.level.api.api.FirModuleResolveStateConfigurator
import org.jetbrains.kotlin.idea.fir.low.level.api.api.KotlinOutOfBlockModificationTrackerFactory
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFirFile
import org.jetbrains.kotlin.idea.fir.low.level.api.test.base.*
import org.jetbrains.kotlin.idea.fir.low.level.api.test.base.AbstractLowLevelApiTest.Companion.reRegisterJavaElementFinder
import org.jetbrains.kotlin.idea.fir.low.level.api.test.base.DeclarationProviderTestImpl import org.jetbrains.kotlin.idea.fir.low.level.api.test.base.DeclarationProviderTestImpl
import org.jetbrains.kotlin.idea.fir.low.level.api.test.base.KotlinOutOfBlockModificationTrackerFactoryTestImpl import org.jetbrains.kotlin.idea.fir.low.level.api.test.base.KotlinOutOfBlockModificationTrackerFactoryTestImpl
import org.jetbrains.kotlin.idea.fir.low.level.api.test.base.KtPackageProviderTestImpl import org.jetbrains.kotlin.idea.fir.low.level.api.test.base.KtPackageProviderTestImpl
@@ -44,22 +46,21 @@ import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
import org.jetbrains.kotlin.test.TestConfiguration import org.jetbrains.kotlin.test.TestConfiguration
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.builders.testConfiguration import org.jetbrains.kotlin.test.builders.testConfiguration
import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives
import org.jetbrains.kotlin.test.directives.model.DirectivesContainer import org.jetbrains.kotlin.test.directives.model.DirectivesContainer
import org.jetbrains.kotlin.test.frontend.fir.* import org.jetbrains.kotlin.test.frontend.fir.FirModuleInfoProvider
import org.jetbrains.kotlin.test.frontend.fir.FirOutputArtifact
import org.jetbrains.kotlin.test.frontend.fir.firModuleInfoProvider
import org.jetbrains.kotlin.test.frontend.fir.getAnalyzerServices
import org.jetbrains.kotlin.test.model.* import org.jetbrains.kotlin.test.model.*
import org.jetbrains.kotlin.test.runners.AbstractKotlinCompilerTest import org.jetbrains.kotlin.test.runners.AbstractKotlinCompilerTest
import org.jetbrains.kotlin.test.services.* import org.jetbrains.kotlin.test.services.*
import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.TestInfo import org.junit.jupiter.api.TestInfo
import java.nio.file.Path
import java.nio.file.Paths
import kotlin.io.path.nameWithoutExtension
abstract class AbstractCompilerBasedTest : AbstractKotlinCompilerTest() { abstract class AbstractCompilerBasedTest : AbstractKotlinCompilerTest() {
private var _disposable: Disposable? = null private var _disposable: Disposable? = null
@@ -104,7 +105,8 @@ abstract class AbstractCompilerBasedTest : AbstractKotlinCompilerTest() {
override fun analyze(module: TestModule): FirOutputArtifact { override fun analyze(module: TestModule): FirOutputArtifact {
val project = testServices.compilerConfigurationProvider.getProject(module) val project = testServices.compilerConfigurationProvider.getProject(module)
val ktFiles = testServices.sourceFileProvider.getKtFilesForSourceFiles(module.files, project) val ktFiles = testServices.sourceFileProvider.getKtFilesForSourceFiles(module.files, project)
PsiElementFinder.EP.getPoint(project).unregisterExtension(JavaElementFinder::class.java)
reRegisterJavaElementFinder(project)
val moduleInfo = TestModuleInfo(module) val moduleInfo = TestModuleInfo(module)
testServices.firModuleInfoProvider.registerModuleData(module, FirModuleInfoBasedModuleData(moduleInfo)) testServices.firModuleInfoProvider.registerModuleData(module, FirModuleInfoBasedModuleData(moduleInfo))
@@ -241,7 +243,6 @@ class FirModuleResolveStateConfiguratorForSingleModuleTestImpl(
} }
override fun configureSourceSession(session: FirSession) { override fun configureSourceSession(session: FirSession) {
PsiElementFinder.EP.getPoint(project).registerExtension(FirJavaElementFinder(session, project), parentDisposable)
} }
} }
@@ -6,14 +6,18 @@
package org.jetbrains.kotlin.idea.fir.low.level.api.test.base package org.jetbrains.kotlin.idea.fir.low.level.api.test.base
import com.intellij.mock.MockProject import com.intellij.mock.MockProject
import com.intellij.openapi.Disposable import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Disposer
import com.intellij.psi.PsiElementFinder import com.intellij.psi.PsiElementFinder
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
import org.jetbrains.kotlin.fir.session.FirModuleInfoBasedModuleData import org.jetbrains.kotlin.fir.session.FirModuleInfoBasedModuleData
import org.jetbrains.kotlin.idea.asJava.IDEKotlinAsJavaFirSupport
import org.jetbrains.kotlin.idea.fir.low.level.api.compiler.based.FirModuleResolveStateConfiguratorForSingleModuleTestImpl import org.jetbrains.kotlin.idea.fir.low.level.api.compiler.based.FirModuleResolveStateConfiguratorForSingleModuleTestImpl
import org.jetbrains.kotlin.idea.fir.low.level.api.compiler.based.TestModuleInfo import org.jetbrains.kotlin.idea.fir.low.level.api.compiler.based.TestModuleInfo
import org.jetbrains.kotlin.idea.fir.low.level.api.compiler.based.registerTestServices import org.jetbrains.kotlin.idea.fir.low.level.api.compiler.based.registerTestServices
import org.jetbrains.kotlin.idea.frontend.api.InvalidWayOfUsingAnalysisSession
import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSessionProvider
import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSessionProvider
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
@@ -32,7 +36,7 @@ import java.nio.file.Path
import java.nio.file.Paths import java.nio.file.Paths
import kotlin.io.path.nameWithoutExtension import kotlin.io.path.nameWithoutExtension
abstract class AbstractLowLevelApiTest: TestWithDisposable() { abstract class AbstractLowLevelApiTest : TestWithDisposable() {
private lateinit var testInfo: KotlinTestInfo private lateinit var testInfo: KotlinTestInfo
private val configure: TestConfigurationBuilder.() -> Unit = { private val configure: TestConfigurationBuilder.() -> Unit = {
@@ -66,6 +70,24 @@ abstract class AbstractLowLevelApiTest: TestWithDisposable() {
open fun configureTest(builder: TestConfigurationBuilder) {} open fun configureTest(builder: TestConfigurationBuilder) {}
companion object {
@OptIn(InvalidWayOfUsingAnalysisSession::class)
fun reRegisterJavaElementFinder(project: Project) {
PsiElementFinder.EP.getPoint(project).unregisterExtension(JavaElementFinder::class.java)
with(project as MockProject) {
picoContainer.registerComponentInstance(
KtAnalysisSessionProvider::class.qualifiedName,
KtFirAnalysisSessionProvider(this)
)
picoContainer.unregisterComponent(KotlinAsJavaSupport::class.qualifiedName)
picoContainer.registerComponentInstance(
KotlinAsJavaSupport::class.qualifiedName,
IDEKotlinAsJavaFirSupport(project)
)
}
PsiElementFinder.EP.getPoint(project).registerExtension(JavaElementFinder(project))
}
}
protected fun runTest(path: String) { protected fun runTest(path: String) {
testDataPath = Paths.get(path) testDataPath = Paths.get(path)
@@ -82,7 +104,7 @@ abstract class AbstractLowLevelApiTest: TestWithDisposable() {
val project = testServices.compilerConfigurationProvider.getProject(singleModule) val project = testServices.compilerConfigurationProvider.getProject(singleModule)
val ktFiles = testServices.sourceFileProvider.getKtFilesForSourceFiles(singleModule.files, project) val ktFiles = testServices.sourceFileProvider.getKtFilesForSourceFiles(singleModule.files, project)
PsiElementFinder.EP.getPoint(project).unregisterExtension(JavaElementFinder::class.java) reRegisterJavaElementFinder(project)
val moduleInfo = TestModuleInfo(singleModule) val moduleInfo = TestModuleInfo(singleModule)
testServices.firModuleInfoProvider.registerModuleData(singleModule, FirModuleInfoBasedModuleData(moduleInfo)) testServices.firModuleInfoProvider.registerModuleData(singleModule, FirModuleInfoBasedModuleData(moduleInfo))
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.idea.fir.low.level.api.test.base package org.jetbrains.kotlin.idea.fir.low.level.api.test.base
import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
import org.jetbrains.kotlin.idea.fir.low.level.api.DeclarationProvider import org.jetbrains.kotlin.idea.fir.low.level.api.DeclarationProvider
import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
@@ -59,6 +60,17 @@ internal class DeclarationProviderTestImpl(
.filterIsInstance<KtNamedFunction>() .filterIsInstance<KtNamedFunction>()
.mapNotNullTo(mutableSetOf()) { it.nameAsName } .mapNotNullTo(mutableSetOf()) { it.nameAsName }
override fun getFacadeFilesInPackage(packageFqName: FqName): Collection<KtFile> =
filesByPackage(packageFqName)
.filter { file -> file.hasTopLevelCallables() }
.toSet()
override fun findFilesForFacade(facadeFqName: FqName): Collection<KtFile> {
if (facadeFqName.shortNameOrSpecial().isSpecial) return emptyList()
return getFacadeFilesInPackage(facadeFqName.parent()) //TODO Not work correctly for classes with JvmPackageName
.filter { it.javaFileFacadeFqName == facadeFqName }
}
override fun getTopLevelProperties(callableId: CallableId): Collection<KtProperty> = override fun getTopLevelProperties(callableId: CallableId): Collection<KtProperty> =
filesByPackage(callableId.packageName) filesByPackage(callableId.packageName)
.flatMap { it.declarations } .flatMap { it.declarations }
@@ -9,7 +9,6 @@ import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.idea.fir.low.level.api.KtPackageProvider import org.jetbrains.kotlin.idea.fir.low.level.api.KtPackageProvider
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
internal class KtPackageProviderTestImpl( internal class KtPackageProviderTestImpl(
@@ -22,7 +21,7 @@ internal class KtPackageProviderTestImpl(
return filesInScope.any { it.packageFqName == packageFqName } return filesInScope.any { it.packageFqName == packageFqName }
} }
override fun getJavaAndKotlinSubPackageFqNames(packageFqName: FqName, targetPlatform: TargetPlatform): Set<Name> { override fun getKotlinSubPackageFqNames(packageFqName: FqName): Set<Name> {
TODO("Not yet implemented") TODO("Not yet implemented")
} }
} }
@@ -0,0 +1,117 @@
/*
* Copyright 2000-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.asJava
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Key
import com.intellij.psi.PsiClass
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.util.SmartList
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport
import org.jetbrains.kotlin.asJava.classes.KtFakeLightClass
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
import org.jetbrains.kotlin.idea.asJava.classes.getOrCreateFirLightClass
import org.jetbrains.kotlin.idea.asJava.classes.getOrCreateFirLightFacade
import org.jetbrains.kotlin.idea.fir.low.level.api.createDeclarationProvider
import org.jetbrains.kotlin.idea.fir.low.level.api.createPackageProvider
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.parentOrNull
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtScript
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
class IDEKotlinAsJavaFirSupport(private val project: Project) : KotlinAsJavaSupport() {
override fun findClassOrObjectDeclarationsInPackage(
packageFqName: FqName,
searchScope: GlobalSearchScope
): Collection<KtClassOrObject> = project.createDeclarationProvider(searchScope).run {
getClassNamesInPackage(packageFqName).flatMap {
getClassesByClassId(ClassId.topLevel(packageFqName.child(it)))
}
}
@OptIn(ExperimentalStdlibApi::class)
override fun findFilesForPackage(fqName: FqName, searchScope: GlobalSearchScope): Collection<KtFile> =
buildSet {
addAll(project.createDeclarationProvider(searchScope).getFacadeFilesInPackage(fqName))
findClassOrObjectDeclarationsInPackage(fqName, searchScope).mapTo(this) {
it.containingKtFile
}
}
private fun FqName.toClassIdSequence(): Sequence<ClassId> {
var currentName = shortNameOrSpecial()
if (currentName.isSpecial) return emptySequence()
var currentParent = parentOrNull() ?: return emptySequence()
var currentRelativeName = currentName.asString()
return sequence {
while (true) {
yield(ClassId(currentParent, FqName(currentRelativeName), false))
currentName = currentParent.shortNameOrSpecial()
if (currentName.isSpecial) break
currentParent = currentParent.parentOrNull() ?: break
currentRelativeName = "${currentName.asString()}.$currentRelativeName"
}
}
}
override fun findClassOrObjectDeclarations(fqName: FqName, searchScope: GlobalSearchScope): Collection<KtClassOrObject> =
fqName.toClassIdSequence().flatMap {
project.createDeclarationProvider(searchScope).getClassesByClassId(it)
}.toSet()
override fun packageExists(fqName: FqName, scope: GlobalSearchScope): Boolean =
project.createPackageProvider(scope).isPackageExists(fqName)
override fun getSubPackages(fqn: FqName, scope: GlobalSearchScope): Collection<FqName> =
project.createPackageProvider(scope)
.getKotlinSubPackageFqNames(fqn)
.map { fqn.child(it) }
override fun getLightClass(classOrObject: KtClassOrObject): KtLightClass? =
getOrCreateFirLightClass(classOrObject)
override fun getLightClassForScript(script: KtScript): KtLightClass =
error("Should not be called")
override fun getFacadeClasses(facadeFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> =
//TODO Split by modules
findFilesForFacade(facadeFqName, scope).ifNotEmpty {
listOfNotNull(getOrCreateFirLightFacade(this.toList(), facadeFqName))
} ?: emptyList()
override fun getScriptClasses(scriptFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> =
error("Should not be called")
override fun getKotlinInternalClasses(fqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> =
emptyList() //TODO Implement if necessary for fir
override fun getFacadeClassesInPackage(packageFqName: FqName, scope: GlobalSearchScope): Collection<PsiClass> =
project.createDeclarationProvider(scope)
.getFacadeFilesInPackage(packageFqName)
.groupBy { it.javaFileFacadeFqName }
.mapNotNull { getOrCreateFirLightFacade(it.value, it.key) }
override fun getFacadeNames(packageFqName: FqName, scope: GlobalSearchScope): Collection<String> =
project.createDeclarationProvider(scope)
.getFacadeFilesInPackage(packageFqName)
.mapTo(mutableSetOf()) { it.javaFileFacadeFqName.shortName().asString() }
override fun findFilesForFacade(facadeFqName: FqName, scope: GlobalSearchScope): Collection<KtFile> =
project.createDeclarationProvider(scope)
.findFilesForFacade(facadeFqName)
override fun getFakeLightClass(classOrObject: KtClassOrObject): KtFakeLightClass =
KtFirBasedFakeLightClass(classOrObject)
override fun createFacadeForSyntheticFile(facadeClassFqName: FqName, file: KtFile): PsiClass =
TODO("Not implemented")
}
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.idea.frontend.api.fir.scopes package org.jetbrains.kotlin.idea.frontend.api.fir.scopes
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.psi.JavaPsiFacade import com.intellij.psi.*
import com.intellij.psi.search.GlobalSearchScope import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.fir.scopes.impl.FirPackageMemberScope import org.jetbrains.kotlin.fir.scopes.impl.FirPackageMemberScope
import org.jetbrains.kotlin.idea.fir.low.level.api.createDeclarationProvider import org.jetbrains.kotlin.idea.fir.low.level.api.createDeclarationProvider
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.idea.frontend.api.withValidityAssertion
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.TargetPlatform import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.jvm.isJvm
internal class KtFirPackageScope( internal class KtFirPackageScope(
override val fqName: FqName, override val fqName: FqName,
@@ -73,9 +74,23 @@ internal class KtFirPackageScope(
} }
override fun getPackageSymbols(nameFilter: KtScopeNameFilter): Sequence<KtPackageSymbol> = withValidityAssertion { override fun getPackageSymbols(nameFilter: KtScopeNameFilter): Sequence<KtPackageSymbol> = withValidityAssertion {
packageProvider.getJavaAndKotlinSubPackageFqNames(fqName, targetPlatform) sequence {
.filter(nameFilter) if (targetPlatform.isJvm()) {
.map { builder.createPackageSymbol(fqName.child(it)) } val javaPackage = JavaPsiFacade.getInstance(project).findPackage(fqName.asString())
.asSequence() if (javaPackage != null) {
for (psiPackage in javaPackage.getSubPackages(searchScope)) {
val fqName = FqName(psiPackage.qualifiedName)
if (nameFilter(fqName.shortName())) {
yield(builder.createPackageSymbol(fqName))
}
}
}
}
packageProvider.getKotlinSubPackageFqNames(fqName).forEach {
if (nameFilter(it)) {
yield(builder.createPackageSymbol(fqName.child(it)))
}
}
}
} }
} }
+1 -1
View File
@@ -263,7 +263,7 @@ The Kotlin FIR plugin provides language support in IntelliJ IDEA and Android Stu
<java.elementFinder implementation="org.jetbrains.kotlin.asJava.finder.JavaElementFinder"/> <java.elementFinder implementation="org.jetbrains.kotlin.asJava.finder.JavaElementFinder"/>
<projectService serviceInterface="org.jetbrains.kotlin.asJava.KotlinAsJavaSupport" <projectService serviceInterface="org.jetbrains.kotlin.asJava.KotlinAsJavaSupport"
serviceImplementation="org.jetbrains.kotlin.idea.caches.resolve.IDEKotlinAsJavaFirSupport"/> serviceImplementation="org.jetbrains.kotlin.idea.asJava.IDEKotlinAsJavaFirSupport"/>
<projectService serviceInterface="org.jetbrains.kotlin.asJava.LightClassGenerationSupport" <projectService serviceInterface="org.jetbrains.kotlin.asJava.LightClassGenerationSupport"
serviceImplementation="org.jetbrains.kotlin.idea.asJava.FirLightClassGenerationSupport"/> serviceImplementation="org.jetbrains.kotlin.idea.asJava.FirLightClassGenerationSupport"/>