提交 09f94896 编写于 作者: A Andrei Klunnyi

[FIR]: sealed hierarchy processor for IDE

From now on sealed declarations get resolved with the help of
FirIdeSealedHierarchyProcessor. This change entails correct IDE side
check for sealed when exhaustiveness.
上级 98b2c000
......@@ -46,14 +46,4 @@ abstract class FirAbstractPhaseTransformer<D>(
"File ${file.name} and transformer ${this::class} have inconsistent sessions"
}
}
}
fun FirFile.runResolve(toPhase: FirResolvePhase, fromPhase: FirResolvePhase = FirResolvePhase.RAW_FIR) {
val scopeSession = ScopeSession()
var currentPhase = fromPhase
while (currentPhase < toPhase) {
currentPhase = currentPhase.next
val phaseProcessor = currentPhase.createTransformerBasedProcessorByPhase(session, scopeSession)
phaseProcessor.processFile(this)
}
}
}
\ No newline at end of file
/*
* Copyright 2010-2019 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.fir.resolve.transformers
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.fir.visitors.compose
import org.jetbrains.kotlin.name.ClassId
/*
* This processor is needed only for IDE until there won't be proper IDE implementation
* for detecting sealed inheritors in multiple files
*/
class FirLegacySealedClassInheritorsProcessor(session: FirSession, scopeSession: ScopeSession) : FirTransformerBasedResolveProcessor(session, scopeSession) {
override val transformer = FirLegacySealedClassInheritorsTransformer()
}
class FirLegacySealedClassInheritorsTransformer : FirTransformer<Nothing?>() {
override fun <E : FirElement> transformElement(element: E, data: Nothing?): CompositeTransformResult<E> {
throw IllegalStateException("Should not be there")
}
override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult<FirDeclaration> {
val sealedClassInheritorsMap = mutableMapOf<FirRegularClass, MutableList<ClassId>>()
file.accept(FirSealedClassInheritorsProcessor.InheritorsCollector, sealedClassInheritorsMap)
if (sealedClassInheritorsMap.isEmpty()) return file.compose()
return file.transform(FirSealedClassInheritorsProcessor.InheritorsTransformer(sealedClassInheritorsMap), null)
}
}
......@@ -41,17 +41,7 @@ fun createAllCompilerResolveProcessors(
}
}
fun createAllTransformerBasedResolveProcessors(
session: FirSession,
scopeSession: ScopeSession? = null,
pluginPhasesEnabled: Boolean = false,
): List<FirTransformerBasedResolveProcessor> {
return createAllResolveProcessors(scopeSession, pluginPhasesEnabled) {
createTransformerBasedProcessorByPhase(session, it)
}
}
private inline fun <T : FirResolveProcessor> createAllResolveProcessors(
inline fun <T : FirResolveProcessor> createAllResolveProcessors(
scopeSession: ScopeSession? = null,
pluginPhasesEnabled: Boolean,
creator: FirResolvePhase.(ScopeSession) -> T
......
......@@ -40,29 +40,7 @@ fun FirResolvePhase.createCompilerProcessorByPhase(
}
}
fun FirResolvePhase.createTransformerBasedProcessorByPhase(
session: FirSession,
scopeSession: ScopeSession
): FirTransformerBasedResolveProcessor {
return when (this) {
RAW_FIR -> throw IllegalStateException("Raw FIR building phase does not have a transformer")
ANNOTATIONS_FOR_PLUGINS -> FirPluginAnnotationsResolveProcessor(session, scopeSession)
CLASS_GENERATION -> FirDummyTransformerBasedProcessor(session, scopeSession) // TODO: remove
IMPORTS -> FirImportResolveProcessor(session, scopeSession)
SUPER_TYPES -> FirSupertypeResolverProcessor(session, scopeSession)
SEALED_CLASS_INHERITORS -> FirLegacySealedClassInheritorsProcessor(session, scopeSession)
TYPES -> FirTypeResolveProcessor(session, scopeSession)
ARGUMENTS_OF_PLUGIN_ANNOTATIONS -> FirAnnotationArgumentsResolveProcessor(session, scopeSession)
EXTENSION_STATUS_UPDATE -> FirTransformerBasedExtensionStatusProcessor(session, scopeSession)
STATUS -> FirStatusResolveProcessor(session, scopeSession)
CONTRACTS -> FirContractResolveProcessor(session, scopeSession)
NEW_MEMBERS_GENERATION -> FirDummyTransformerBasedProcessor(session, scopeSession) // TODO: remove
IMPLICIT_TYPES_BODY_RESOLVE -> FirImplicitTypeBodyResolveProcessor(session, scopeSession)
BODY_RESOLVE -> FirBodyResolveProcessor(session, scopeSession)
}
}
private class FirDummyTransformerBasedProcessor(
class FirDummyTransformerBasedProcessor(
session: FirSession,
scopeSession: ScopeSession
) : FirTransformerBasedResolveProcessor(session, scopeSession) {
......
......@@ -79,6 +79,7 @@ import org.jetbrains.kotlin.idea.editor.backspaceHandler.AbstractBackspaceHandle
import org.jetbrains.kotlin.idea.editor.quickDoc.AbstractQuickDocProviderTest
import org.jetbrains.kotlin.idea.filters.AbstractKotlinExceptionFilterTest
import org.jetbrains.kotlin.idea.fir.AbstractKtDeclarationAndFirDeclarationEqualityChecker
import org.jetbrains.kotlin.idea.fir.low.level.api.*
import org.jetbrains.kotlin.idea.fir.low.level.api.AbstractFirLazyDeclarationResolveTest
import org.jetbrains.kotlin.idea.fir.low.level.api.AbstractFirLazyResolveTest
import org.jetbrains.kotlin.idea.fir.low.level.api.AbstractFirMultiModuleLazyResolveTest
......@@ -1068,6 +1069,9 @@ fun main(args: Array<String>) {
testClass<AbstractFirMultiModuleLazyResolveTest> {
model("multiModuleLazyResolve", recursive = false, extension = null)
}
testClass<AbstractFirSealedInheritorsTest> {
model("resolveSealed", recursive = false, extension = null)
}
testClass<AbstractFirLazyDeclarationResolveTest> {
model("lazyResolve")
}
......
/*
* Copyright 2010-2021 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.fir.low.level.api
import com.intellij.openapi.module.Module
import com.intellij.psi.JavaDirectoryService
import com.intellij.psi.PsiPackage
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.PackageScope
import com.intellij.psi.search.SearchScope
import com.intellij.psi.search.searches.ClassInheritorsSearch
import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.transformers.FirSealedClassInheritorsProcessor
import org.jetbrains.kotlin.fir.resolve.transformers.FirTransformerBasedResolveProcessor
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
import org.jetbrains.kotlin.fir.visitors.FirDefaultVisitor
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.fir.visitors.compose
import org.jetbrains.kotlin.idea.util.classIdIfNonLocal
import org.jetbrains.kotlin.idea.util.module
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade
class FirIdeSealedHierarchyProcessor(session: FirSession, scopeSession: ScopeSession) :
FirTransformerBasedResolveProcessor(session, scopeSession) {
override val transformer: FirTransformer<Nothing?> = SealedClassInheritorsTransformer
private object SealedClassInheritorsTransformer : FirTransformer<Nothing?>() {
override fun <E : FirElement> transformElement(element: E, data: Nothing?): CompositeTransformResult<E> {
throw IllegalStateException("Should not be there")
}
override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult<FirDeclaration> {
val sealedClassInheritorsMap = mutableMapOf<FirRegularClass, MutableList<ClassId>>()
file.accept(SealedInheritorsCollector, sealedClassInheritorsMap)
if (sealedClassInheritorsMap.isEmpty()) return file.compose()
return file.transform(FirSealedClassInheritorsProcessor.InheritorsTransformer(sealedClassInheritorsMap), null)
}
}
private object SealedInheritorsCollector : FirDefaultVisitor<Unit, MutableMap<FirRegularClass, MutableList<ClassId>>>() {
override fun visitElement(element: FirElement, data: MutableMap<FirRegularClass, MutableList<ClassId>>) {}
override fun visitFile(file: FirFile, data: MutableMap<FirRegularClass, MutableList<ClassId>>) {
file.declarations.forEach { it.accept(this, data) }
}
override fun visitRegularClass(regularClass: FirRegularClass, data: MutableMap<FirRegularClass, MutableList<ClassId>>) {
if (!regularClass.isSealed) {
regularClass.acceptChildren(this, data)
return
}
val sealedKtClass = regularClass.psi as? KtClass ?: return
val module = sealedKtClass.module ?: return
val containingPackage = regularClass.classId.packageFqName
val psiPackage = KotlinJavaPsiFacade.getInstance(sealedKtClass.project)
.findPackage(containingPackage.asString(), GlobalSearchScope.moduleScope(module))
?: getPackageViaDirectoryService(sealedKtClass)
?: return
val kotlinAsJavaSupport = KotlinAsJavaSupport.getInstance(sealedKtClass.project)
val lightClass = sealedKtClass.toLightClass() ?: kotlinAsJavaSupport.getFakeLightClass(sealedKtClass)
val searchScope: SearchScope = getSearchScope(module, psiPackage)
val searchParameters = ClassInheritorsSearch.SearchParameters(lightClass, searchScope, false, true, false)
val subclasses = ClassInheritorsSearch.search(searchParameters)
.mapNotNull { it.classIdIfNonLocal() }
.toMutableList()
data[regularClass] = subclasses
}
private fun getSearchScope(module: Module, psiPackage: PsiPackage): GlobalSearchScope {
val packageScope = PackageScope(psiPackage, false, false)
// MPP multiple common modules are not supported!!
return module.moduleScope.intersectWith(packageScope)
}
}
}
private fun getPackageViaDirectoryService(ktClass: KtClass): PsiPackage? {
val directory = ktClass.containingFile.containingDirectory ?: return null
return JavaDirectoryService.getInstance().getPackage(directory)
}
\ No newline at end of file
......@@ -5,10 +5,17 @@
package org.jetbrains.kotlin.idea.fir.low.level.api
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.transformers.createTransformerBasedProcessorByPhase
import org.jetbrains.kotlin.fir.resolve.transformers.*
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirBodyResolveProcessor
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirImplicitTypeBodyResolveProcessor
import org.jetbrains.kotlin.fir.resolve.transformers.contracts.FirContractResolveProcessor
import org.jetbrains.kotlin.fir.resolve.transformers.plugin.FirAnnotationArgumentsResolveProcessor
import org.jetbrains.kotlin.fir.resolve.transformers.plugin.FirPluginAnnotationsResolveProcessor
import org.jetbrains.kotlin.fir.resolve.transformers.plugin.FirTransformerBasedExtensionStatusProcessor
import org.jetbrains.kotlin.idea.fir.low.level.api.lazy.resolve.FirLazyBodiesCalculator
import org.jetbrains.kotlin.idea.fir.low.level.api.util.executeWithoutPCE
import java.util.concurrent.locks.ReentrantLock
......@@ -55,7 +62,6 @@ internal class FirPhaseRunner {
}
}
private fun runPhaseWithoutLock(firFile: FirFile, phase: FirResolvePhase, scopeSession: ScopeSession) {
val phaseProcessor = phase.createTransformerBasedProcessorByPhase(firFile.session, scopeSession)
executeWithoutPCE {
......@@ -64,3 +70,25 @@ internal class FirPhaseRunner {
}
}
}
internal fun FirResolvePhase.createTransformerBasedProcessorByPhase(
session: FirSession,
scopeSession: ScopeSession
): FirTransformerBasedResolveProcessor {
return when (this) {
FirResolvePhase.RAW_FIR -> throw IllegalStateException("Raw FIR building phase does not have a transformer")
FirResolvePhase.ANNOTATIONS_FOR_PLUGINS -> FirPluginAnnotationsResolveProcessor(session, scopeSession)
FirResolvePhase.CLASS_GENERATION -> FirDummyTransformerBasedProcessor(session, scopeSession) // TODO: remove
FirResolvePhase.IMPORTS -> FirImportResolveProcessor(session, scopeSession)
FirResolvePhase.SUPER_TYPES -> FirSupertypeResolverProcessor(session, scopeSession)
FirResolvePhase.SEALED_CLASS_INHERITORS -> FirIdeSealedHierarchyProcessor(session, scopeSession)
FirResolvePhase.TYPES -> FirTypeResolveProcessor(session, scopeSession)
FirResolvePhase.ARGUMENTS_OF_PLUGIN_ANNOTATIONS -> FirAnnotationArgumentsResolveProcessor(session, scopeSession)
FirResolvePhase.EXTENSION_STATUS_UPDATE -> FirTransformerBasedExtensionStatusProcessor(session, scopeSession)
FirResolvePhase.STATUS -> FirStatusResolveProcessor(session, scopeSession)
FirResolvePhase.CONTRACTS -> FirContractResolveProcessor(session, scopeSession)
FirResolvePhase.NEW_MEMBERS_GENERATION -> FirDummyTransformerBasedProcessor(session, scopeSession) // TODO: remove
FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE -> FirImplicitTypeBodyResolveProcessor(session, scopeSession)
FirResolvePhase.BODY_RESOLVE -> FirBodyResolveProcessor(session, scopeSession)
}
}
\ No newline at end of file
class ClassAnotherModuleInheritorA: SealedClass()
class ClassAnotherModuleInheritorB: SealedClass()
class InterfaceAnotherModuleInheritorA: SealedInterface
class InterfaceAnotherModuleInheritorB: SealedInterface
\ No newline at end of file
ClassSameFileInheritorA
ClassSameFileInheritorB
ClassSameFileInheritorC
ClassSamePackageInheritorA
ClassSamePackageInheritorB
InterfaceSameFileInheritorA
InterfaceSameFileInheritorB
InterfaceSameFileInheritorC
InterfaceSamePackageInheritorA
InterfaceSamePackageInheritorB
NonSealedClass.NestedSealedInheritorA
NonSealedClass.NestedSealedInheritorB
SealedClass.NestedInheritorA
SealedClass.NestedInheritorA.NestedNestedInheritorA
SealedClass.NestedInheritorA.NestedNestedInheritorB
SealedInterface.NestedInheritorA
SealedInterface.NestedInheritorA.NestedNestedInheritorA
SealedInterface.NestedInheritorA.NestedNestedInheritorB
\ No newline at end of file
class ClassSamePackageInheritorA: SealedClass()
class ClassSamePackageInheritorB: SealedClass()
class InterfaceSamePackageInheritorA: SealedInterface
class InterfaceSamePackageInheritorB: SealedInterface
package anotherpackage
class ClassAnotherPackageInheritorA: SealedClass()
class ClassAnotherPackageInheritorB: SealedClass()
class InterfaceAnotherPackageInheritorA: SealedInterface
class InterfaceAnotherPackageInheritorB: SealedInterface
\ No newline at end of file
sealed class SealedClass { // (1): top level sealed class
class NestedInheritorA: SealedClass() {
class NestedNestedInheritorA: SealedClass()
object NestedNestedInheritorB: SealedClass()
}
}
class ClassSameFileInheritorA: SealedClass()
class ClassSameFileInheritorB: SealedClass()
object ClassSameFileInheritorC: SealedClass()
sealed interface SealedInterface { // (2): top level sealed interface
class NestedInheritorA: SealedInterface {
interface NestedNestedInheritorA: SealedInterface
object NestedNestedInheritorB: SealedInterface
}
}
class InterfaceSameFileInheritorA: SealedInterface
class InterfaceSameFileInheritorB: SealedInterface
object InterfaceSameFileInheritorC: SealedInterface
class NonSealedClass {
sealed class NestedSealedClass // (3): nested sealed class
sealed interface NestedSealedInterface // (4): nested sealed interface
class NestedSealedInheritorA: NestedSealedClass()
class NestedSealedInheritorB: NestedSealedInterface
}
\ No newline at end of file
{
"modules" : [
{ "name": "main", "dependsOn": ["anotherModule"] },
{ "name": "anotherModule"}
],
"fileToResolve": { "module": "main", "file": "main.kt" }
}
\ No newline at end of file
......@@ -9,8 +9,10 @@ import com.google.gson.JsonElement
import com.google.gson.JsonObject
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.psi.PsiManager
import org.jetbrains.kotlin.executeOnPooledThreadInReadAction
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFir
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFirOfType
import org.jetbrains.kotlin.idea.fir.low.level.api.api.getResolveState
import org.jetbrains.kotlin.idea.jsonUtils.getString
import org.jetbrains.kotlin.idea.stubs.AbstractMultiModuleTest
......@@ -47,8 +49,9 @@ abstract class AbstractFirMultiModuleLazyResolveTest : AbstractMultiModuleTest()
val fails = testStructure.fails
try {
val fir = ktFileToAnalyse.getOrBuildFir(resolveState)
KotlinTestUtils.assertEqualsToFile(File("$path/expected.txt"), fir.render())
val fir = executeOnPooledThreadInReadAction { ktFileToAnalyse.getOrBuildFirOfType<FirFile>(resolveState) }
?: throw AssertionError("Can't build FirFile from ${ktFileToAnalyse.virtualFilePath}")
checkFirFile(fir, path)
} catch (e: Throwable) {
if (!fails) throw e
return
......@@ -57,6 +60,10 @@ abstract class AbstractFirMultiModuleLazyResolveTest : AbstractMultiModuleTest()
throw AssertionError("Looks like test is passing, please remove `\"fails\": true` from structure.json")
}
}
protected open fun checkFirFile(firFile: FirFile, path: String) {
KotlinTestUtils.assertEqualsToFile(File("$path/expected.txt"), firFile.render())
}
}
private data class FileToResolve(val moduleName: String, val relativeFilePath: String) {
......
......@@ -11,16 +11,17 @@ import com.intellij.psi.PsiFile
import com.intellij.psi.PsiManager
import com.intellij.psi.search.FileTypeIndex
import org.jetbrains.kotlin.fir.FirRenderer
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.builder.RawFirBuilder
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.dependenciesWithoutSelf
import org.jetbrains.kotlin.fir.java.*
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.firProvider
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirProviderImpl
import org.jetbrains.kotlin.fir.resolve.transformers.FirTransformerBasedResolveProcessor
import org.jetbrains.kotlin.fir.resolve.transformers.createAllTransformerBasedResolveProcessors
import org.jetbrains.kotlin.fir.resolve.transformers.*
import org.jetbrains.kotlin.fir.session.FirSessionFactory
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.idea.caches.project.IdeaModuleInfo
......@@ -155,5 +156,15 @@ abstract class AbstractFirMultiModuleResolveTest : AbstractMultiModuleTest() {
// KotlinTestUtils.assertEqualsToFile(File("$dirPath/extraDump.java.txt"), javaFirDump)
// }
}
private fun createAllTransformerBasedResolveProcessors(
session: FirSession,
scopeSession: ScopeSession? = null,
pluginPhasesEnabled: Boolean = false,
): List<FirTransformerBasedResolveProcessor> {
return createAllResolveProcessors(scopeSession, pluginPhasesEnabled) {
createTransformerBasedProcessorByPhase(session, it)
}
}
}
/*
* Copyright 2010-2020 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.fir.low.level.api
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.util.KtTestUtil
import org.jetbrains.kotlin.types.typeUtil.closure
import org.jetbrains.kotlin.utils.addToStdlib.flatMapToNullable
import java.io.File
/**
* The idea behind this test is to check that [FirIdeSealedHierarchyProcessor] finds all direct inheritors of sealed classes and interfaces.
* We use the fact that [SealedClassInheritorsKt#getSealedInheritors] property gets its value thanks to the class activity.
*
* Inheritors are collected for every sealed declaration of the 'fileToResolve' (see test data 'structure.json'). Resulting collection is
* compared with 'expected.txt'.
*/
abstract class AbstractFirSealedInheritorsTest : AbstractFirMultiModuleLazyResolveTest() {
override fun getTestDataPath(): String =
"${KtTestUtil.getHomeDirectory()}/idea/idea-frontend-fir/idea-fir-low-level-api/testdata/resolveSealed/"
override fun checkFirFile(firFile: FirFile, path: String) {
val allClasses = firFile.listNestedClasses().closure { it.listNestedClasses() }
val inheritorNames = allClasses.flatMap { it.sealedInheritors ?: emptyList() }.map { it.asString() }.sorted()
KotlinTestUtils.assertEqualsToFile(File("$path/expected.txt"), inheritorNames.joinToString("\n"))
}
}
private fun FirDeclaration.listNestedClasses(): List<FirRegularClass> {
return when (this) {
is FirFile -> declarations.filterIsInstance<FirRegularClass>()
is FirRegularClass -> declarations.filterIsInstance<FirRegularClass>()
else -> emptyList()
}
}
\ No newline at end of file
/*
* Copyright 2010-2021 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.fir.low.level.api;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/resolveSealed")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class FirSealedInheritorsTestGenerated extends AbstractFirSealedInheritorsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInResolveSealed() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/resolveSealed"), Pattern.compile("^([^\\.]+)$"), null, false);
}
@TestMetadata("directInheritors")
public void testDirectInheritors() throws Exception {
runTest("idea/idea-frontend-fir/idea-fir-low-level-api/testdata/resolveSealed/directInheritors/");
}
}
......@@ -42,7 +42,7 @@ internal class KtFirTypeProvider(
override fun buildSelfClassType(symbol: KtClassOrObjectSymbol): KtType {
require(symbol is KtFirClassOrObjectSymbol)
val type = symbol.firRef.withFir(FirResolvePhase.TYPES) { firClass ->
val type = symbol.firRef.withFir(FirResolvePhase.SUPER_TYPES) { firClass ->
ConeClassLikeTypeImpl(
firClass.symbol.toLookupTag(),
firClass.typeParameters.map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), isNullable = false) }.toTypedArray(),
......
......@@ -5,11 +5,14 @@
package org.jetbrains.kotlin.idea.util
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiJavaFile
import com.intellij.psi.impl.source.tree.LeafPsiElement
import com.intellij.psi.util.parentOfType
import com.intellij.psi.util.parentsOfType
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.cfg.containingDeclarationForPseudocode
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
......@@ -45,3 +48,15 @@ fun KtClassOrObject.classIdIfNonLocal(): ClassId? {
return ClassId(packageName, FqName(classesNames.joinToString(separator = ".")), /*local=*/false)
}
fun PsiClass.classIdIfNonLocal(): ClassId? {
if (this is KtLightClass) {
return this.kotlinOrigin?.classIdIfNonLocal()
}
val packageName = (containingFile as? PsiJavaFile)?.packageName ?: return null
val packageFqName = FqName(packageName)
val classesNames = parentsOfType<KtDeclaration>().map { it.name }.toList().asReversed()
if (classesNames.any { it == null }) return null
return ClassId(packageFqName, FqName(classesNames.joinToString(separator = ".")), false)
}
......@@ -262,7 +262,7 @@ The Kotlin FIR plugin provides language support in IntelliJ IDEA and Android Stu
<definitionsScopedSearch implementation="org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinDefinitionsSearcher"/>
<methodReferencesSearch implementation="org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinOverridingMethodReferenceSearcher"/>
<methodReferencesSearch implementation="org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinPropertyAccessorsReferenceSearcher"/>
<!-- <directClassInheritorsSearch implementation="org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinDirectInheritorsSearcher"/>-->
<directClassInheritorsSearch implementation="org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinDirectInheritorsSearcher"/>
<!-- <overridingMethodsSearch implementation="org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinOverridingMethodsWithGenericsSearcher"/>-->
<!-- <annotatedElementsSearch implementation="org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinAnnotatedElementsSearcher"/>-->
<!-- <classesWithAnnotatedMembersSearch implementation="org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinClassesWithAnnotatedMembersSearcher"/>-->
......
// FIR_IGNORE
// PSI_ELEMENT: com.intellij.psi.PsiMethod
// OPTIONS: usages
public class J {
......
// FIR_IGNORE
// PSI_ELEMENT: com.intellij.psi.PsiMethod
// OPTIONS: usages
public class J {
......
// FIR_IGNORE
// PSI_ELEMENT: com.intellij.psi.PsiClass
// OPTIONS: derivedClasses
public class <caret>A {
......
// FIR_IGNORE
// PSI_ELEMENT: com.intellij.psi.PsiClass
// OPTIONS: derivedClasses
public class <caret>A {
......
// FIR_IGNORE
// PSI_ELEMENT: com.intellij.psi.PsiClass
// OPTIONS: derivedClasses
public class <caret>A {
......
// FIR_COMPARISON
// PSI_ELEMENT: com.intellij.psi.PsiClass
// OPTIONS: derivedInterfaces
public interface <caret>A {
......
// FIR_IGNORE
// PSI_ELEMENT: com.intellij.psi.PsiClass
// OPTIONS: implementingClasses
public interface <caret>A {
......
// FIR_COMPARISON
// PSI_ELEMENT: com.intellij.psi.PsiClass
// OPTIONS: implementingClasses
public interface <caret>A {
......
// FIR_IGNORE
// PSI_ELEMENT: com.intellij.psi.PsiClass
// OPTIONS: implementingClasses
public interface <caret>A {
......
// FIR_COMPARISON
// PSI_ELEMENT: com.intellij.psi.PsiClass
// OPTIONS: implementingClasses
public interface <caret>A {
......
// FIR_COMPARISON
// PSI_ELEMENT: com.intellij.psi.PsiClass
// OPTIONS: implementingClasses
public interface <caret>A {
......
// FIR_COMPARISON
// PSI_ELEMENT: com.intellij.psi.PsiClass
// OPTIONS: implementingClasses
public interface <caret>A {
......
// FIR_COMPARISON
// PSI_ELEMENT: com.intellij.psi.PsiClass
// OPTIONS: derivedInterfaces
public interface <caret>A {
......
// FIR_COMPARISON
// PSI_ELEMENT: com.intellij.psi.PsiClass
// OPTIONS: implementingClasses
public interface <caret>A {
......
// FIR_COMPARISON
// PSI_ELEMENT: com.intellij.psi.PsiMethod
// OPTIONS: overrides
public class A {
......
[JKMethodOverrides.0.java] Unclassified usage 11 public void foo() {
[JKMethodOverrides.0.java] Unclassified usage 12 public void foo() {
[JKMethodOverrides.1.kt] Unclassified usage 14 public override fun foo() {
[JKMethodOverrides.1.kt] Unclassified usage 2 public override fun foo() {
[JKMethodOverrides.1.kt] Unclassified usage 8 public override fun foo() {
// FIR_COMPARISON
// PSI_ELEMENT: org.jetbrains.kotlin.psi.KtClass
// OPTIONS: derivedClasses
interface <caret>X {
......
[javaDerivedClassUsages2.0.kt] Unclassified usage 11 open class C: Y {
[javaDerivedClassUsages2.0.kt] Unclassified usage 7 open class A: X {
[javaDerivedClassUsages2.0.kt] Unclassified usage 12 open class C: Y {
[javaDerivedClassUsages2.0.kt] Unclassified usage 8 open class A: X {
[javaDerivedClassUsages2.1.java] Unclassified usage 1 class B extends A {
// FIR_COMPARISON
// PSI_ELEMENT: org.jetbrains.kotlin.psi.KtClass
// OPTIONS: derivedInterfaces
interface X {
......
[javaDerivedInterfaceUsages1.0.kt] Unclassified usage 15 interface Z: A {
[javaDerivedInterfaceUsages1.0.kt] Unclassified usage 16 interface Z: A {
[javaDerivedInterfaceUsages1.1.java] Unclassified usage 9 interface U extends Z {
// FIR_COMPARISON
// PSI_ELEMENT: org.jetbrains.kotlin.psi.KtClass
// OPTIONS: derivedInterfaces
interface <caret>X {
......
[javaDerivedInterfaceUsages2.0.kt] Unclassified usage 15 interface Z: A {
[javaDerivedInterfaceUsages2.0.kt] Unclassified usage 16 interface Z: A {
[javaDerivedInterfaceUsages2.1.java] Unclassified usage 5 interface Y extends X {
[javaDerivedInterfaceUsages2.1.java] Unclassified usage 9 interface U extends Z {
// FIR_IGNORE
// PSI_ELEMENT: org.jetbrains.kotlin.psi.KtClass
// OPTIONS: derivedClasses
open class <caret>A {
......
// FIR_COMPARISON
// PSI_ELEMENT: org.jetbrains.kotlin.psi.KtClass
// OPTIONS: derivedClasses
interface X {
......
// FIR_COMPARISON
// PSI_ELEMENT: org.jetbrains.kotlin.psi.KtClass
// OPTIONS: derivedClasses
interface X {
......
// FIR_COMPARISON
// PSI_ELEMENT: org.jetbrains.kotlin.psi.KtClass
// OPTIONS: derivedClasses
open class <caret>A {
......
// FIR_COMPARISON
// PSI_ELEMENT: org.jetbrains.kotlin.psi.KtClass
// OPTIONS: derivedClasses
interface X {
......
// FIR_COMPARISON
// PSI_ELEMENT: org.jetbrains.kotlin.psi.KtClass
// OPTIONS: derivedClasses
open class <caret>A {
......
// FIR_COMPARISON
// PSI_ELEMENT: org.jetbrains.kotlin.psi.KtClass
// OPTIONS: derivedInterfaces
interface X {
......
// FIR_COMPARISON
// PSI_ELEMENT: org.jetbrains.kotlin.psi.KtClass
// OPTIONS: derivedClasses
open class <caret>A {
......
// FIR_COMPARISON
// PSI_ELEMENT: org.jetbrains.kotlin.psi.KtClass
// OPTIONS: derivedInterfaces
interface X {
......
// FIR_IGNORE
// PSI_ELEMENT: org.jetbrains.kotlin.psi.KtClass
// OPTIONS: derivedClasses
fun foo() {
......
Unclassified usage 11 val c = object: A() {}
Unclassified usage 13 val d = object: T {}
Unclassified usage 6 val b = object: A() {}
Unclassified usage 12 val c = object: A() {}
Unclassified usage 14 val d = object: T {}
Unclassified usage 7 val b = object: A() {}
\ No newline at end of file
// FIR_COMPARISON
// PSI_ELEMENT: org.jetbrains.kotlin.psi.KtClass
// OPTIONS: derivedClasses
fun foo() {
......
Unclassified usage 11 class C: A()
Unclassified usage 13 class D: T
Unclassified usage 6 class B: A()
Unclassified usage 12 class C: A()
Unclassified usage 14 class D: T
Unclassified usage 7 class B: A()
\ No newline at end of file
// FIR_COMPARISON
// PSI_ELEMENT: org.jetbrains.kotlin.psi.KtClass
// OPTIONS: derivedClasses
fun foo() {
......
Unclassified usage 11 object C: A()
Unclassified usage 13 object D: T
Unclassified usage 6 object B: A()
Unclassified usage 12 object C: A()
Unclassified usage 14 object D: T
Unclassified usage 7 object B: A()
\ No newline at end of file
// FIR_COMPARISON
// PSI_ELEMENT: org.jetbrains.kotlin.psi.KtClass
// OPTIONS: derivedInterfaces
fun foo() {
......
Unclassified usage 6 interface T: A
Unclassified usage 9 interface U: T
Unclassified usage 10 interface U: T
Unclassified usage 7 interface T: A
\ No newline at end of file
// FIR_IGNORE
// PSI_ELEMENT: org.jetbrains.kotlin.psi.KtClass
// OPTIONS: derivedClasses
interface <caret>X {
......
[kotlinTraitDerivedAnonymousObjects.0.kt] Unclassified usage 7 open class A: X {
[kotlinTraitDerivedAnonymousObjects.0.kt] Unclassified usage 8 open class A: X {
[kotlinTraitDerivedAnonymousObjects.1.kt] Unclassified usage 12 val x = object : X {
[kotlinTraitDerivedAnonymousObjects.1.kt] Unclassified usage 9 doSomething(object : A() {}, object: X {})
[kotlinTraitDerivedAnonymousObjects.1.kt] Unclassified usage 9 doSomething(object : A() {}, object: X {})
[kotlinTraitDerivedAnonymousObjects.1.kt] Unclassified usage 9 doSomething(object : A() {}, object: X {})
\ No newline at end of file
// FIR_COMPARISON
// PSI_ELEMENT: org.jetbrains.kotlin.psi.KtClass
// OPTIONS: derivedClasses
interface <caret>X {
......
[kotlinTraitDerivedClasses.0.kt] Unclassified usage 7 open class A: X {
[kotlinTraitDerivedClasses.0.kt] Unclassified usage 8 open class A: X {
[kotlinTraitDerivedClasses.1.kt] Unclassified usage 3 open class B: A() {
[kotlinTraitDerivedClasses.1.kt] Unclassified usage 7 open class C: Y {
// FIR_COMPARISON
// PSI_ELEMENT: org.jetbrains.kotlin.psi.KtClass
// OPTIONS: derivedClasses
interface <caret>X {
......
[kotlinTraitDerivedInnerClasses.0.kt] Unclassified usage 7 open class A: X {
[kotlinTraitDerivedInnerClasses.0.kt] Unclassified usage 8 open class A: X {
[kotlinTraitDerivedInnerClasses.1.kt] Unclassified usage 4 open class B: A() {
[kotlinTraitDerivedInnerClasses.1.kt] Unclassified usage 8 open class C: Y {
// FIR_COMPARISON
// PSI_ELEMENT: org.jetbrains.kotlin.psi.KtClass
// OPTIONS: derivedClasses
interface <caret>X {
......
[kotlinTraitDerivedInnerObjects.0.kt] Unclassified usage 7 open class A: X {
[kotlinTraitDerivedInnerObjects.0.kt] Unclassified usage 8 open class A: X {
[kotlinTraitDerivedInnerObjects.1.kt] Unclassified usage 4 object O1: A() {
[kotlinTraitDerivedInnerObjects.1.kt] Unclassified usage 9 object O2: X {
// FIR_COMPARISON
// PSI_ELEMENT: org.jetbrains.kotlin.psi.KtClass
// OPTIONS: derivedClasses
interface <caret>X {
......
[kotlinTraitDerivedLocalClasses.0.kt] Unclassified usage 7 open class A: X {
[kotlinTraitDerivedLocalClasses.0.kt] Unclassified usage 8 open class A: X {
[kotlinTraitDerivedLocalClasses.1.kt] Unclassified usage 5 open class B: A() {
[kotlinTraitDerivedLocalClasses.1.kt] Unclassified usage 9 open class C: Y {
// FIR_COMPARISON
// PSI_ELEMENT: org.jetbrains.kotlin.psi.KtClass
// OPTIONS: derivedClasses
interface <caret>X {
......
[kotlinTraitDerivedLocalObjects.0.kt] Unclassified usage 7 open class A: X {
[kotlinTraitDerivedLocalObjects.0.kt] Unclassified usage 8 open class A: X {
[kotlinTraitDerivedLocalObjects.1.kt] Unclassified usage 10 object O2: X {
[kotlinTraitDerivedLocalObjects.1.kt] Unclassified usage 5 object O1: A() {
// FIR_COMPARISON
// PSI_ELEMENT: org.jetbrains.kotlin.psi.KtClass
// OPTIONS: derivedInterfaces
interface <caret>X {
......
// FIR_COMPARISON
// PSI_ELEMENT: org.jetbrains.kotlin.psi.KtClass
// OPTIONS: derivedClasses
interface <caret>X {
......
[kotlinTraitDerivedObjects.0.kt] Unclassified usage 7 open class A: X {
[kotlinTraitDerivedObjects.0.kt] Unclassified usage 8 open class A: X {
[kotlinTraitDerivedObjects.1.kt] Unclassified usage 3 object O1: A() {
[kotlinTraitDerivedObjects.1.kt] Unclassified usage 7 object O2: X {
// FIR_COMPARISON
// PSI_ELEMENT: org.jetbrains.kotlin.psi.KtClass
// OPTIONS: derivedInterfaces
interface <caret>X {
......
[kotlinTraitDerivedTraits.0.kt] Unclassified usage 11 interface Y: X {
[kotlinTraitDerivedTraits.0.kt] Unclassified usage 12 interface Y: X {
[kotlinTraitDerivedTraits.1.kt] Unclassified usage 11 interface Z: A {
[kotlinTraitDerivedTraits.1.kt] Unclassified usage 15 interface U: Z {
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册