diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KaFe10SymbolProvider.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KaFe10SymbolProvider.kt index 6aa7f576c97c8..a02ed95c15fe0 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KaFe10SymbolProvider.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KaFe10SymbolProvider.kt @@ -35,13 +35,13 @@ internal class KaFe10SymbolProvider( } override val KtFile.symbol: KaFileSymbol - get() = withValidityAssertion { KaFe10FileSymbol(this, this@KaFe10SymbolProvider.analysisContext) } + get() = createPsiBasedSymbolWithValidityAssertion { KaFe10FileSymbol(this, this@KaFe10SymbolProvider.analysisContext) } override val KtScript.symbol: KaScriptSymbol - get() = withValidityAssertion { KaFe10PsiScriptSymbol(this, analysisContext) } + get() = createPsiBasedSymbolWithValidityAssertion { KaFe10PsiScriptSymbol(this, analysisContext) } override val KtParameter.symbol: KaVariableSymbol - get() = withValidityAssertion { + get() = createPsiBasedSymbolWithValidityAssertion { when { isFunctionTypeParameter -> error("Function type parameters are not supported in getParameterSymbol()") isLoopParameter -> KaFe10PsiLoopParameterLocalVariableSymbol(this, analysisContext) @@ -50,8 +50,8 @@ internal class KaFe10SymbolProvider( } override val KtNamedFunction.symbol: KaFunctionSymbol - get() = withValidityAssertion { - return if (hasBody() && (funKeyword == null || nameIdentifier == null)) { + get() = createPsiBasedSymbolWithValidityAssertion { + if (hasBody() && (funKeyword == null || nameIdentifier == null)) { KaFe10PsiAnonymousFunctionSymbol(this, analysisContext) } else { KaFe10PsiNamedFunctionSymbol(this, analysisContext) @@ -59,23 +59,23 @@ internal class KaFe10SymbolProvider( } override val KtConstructor<*>.symbol: KaConstructorSymbol - get() = withValidityAssertion { KaFe10PsiConstructorSymbol(this, analysisContext) } + get() = createPsiBasedSymbolWithValidityAssertion { KaFe10PsiConstructorSymbol(this, analysisContext) } override val KtTypeParameter.symbol: KaTypeParameterSymbol - get() = withValidityAssertion { KaFe10PsiTypeParameterSymbol(this, analysisContext) } + get() = createPsiBasedSymbolWithValidityAssertion { KaFe10PsiTypeParameterSymbol(this, analysisContext) } override val KtTypeAlias.symbol: KaTypeAliasSymbol - get() = withValidityAssertion { KaFe10PsiTypeAliasSymbol(this, analysisContext) } + get() = createPsiBasedSymbolWithValidityAssertion { KaFe10PsiTypeAliasSymbol(this, analysisContext) } override val KtEnumEntry.symbol: KaEnumEntrySymbol - get() = withValidityAssertion { KaFe10PsiEnumEntrySymbol(this, analysisContext) } + get() = createPsiBasedSymbolWithValidityAssertion { KaFe10PsiEnumEntrySymbol(this, analysisContext) } override val KtFunctionLiteral.symbol: KaAnonymousFunctionSymbol - get() = withValidityAssertion { KaFe10PsiLiteralAnonymousFunctionSymbol(this, analysisContext) } + get() = createPsiBasedSymbolWithValidityAssertion { KaFe10PsiLiteralAnonymousFunctionSymbol(this, analysisContext) } override val KtProperty.symbol: KaVariableSymbol - get() = withValidityAssertion { - return if (isLocal) { + get() = createPsiBasedSymbolWithValidityAssertion { + if (isLocal) { KaFe10PsiLocalVariableSymbol(this, analysisContext) } else { KaFe10PsiKotlinPropertySymbol(this, analysisContext) @@ -83,10 +83,10 @@ internal class KaFe10SymbolProvider( } override val KtObjectLiteralExpression.symbol: KaAnonymousObjectSymbol - get() = withValidityAssertion { KaFe10PsiAnonymousObjectSymbol(objectDeclaration, analysisContext) } + get() = createPsiBasedSymbolWithValidityAssertion { KaFe10PsiAnonymousObjectSymbol(objectDeclaration, analysisContext) } override val KtObjectDeclaration.symbol: KaClassSymbol - get() = withValidityAssertion { + get() = createPsiBasedSymbolWithValidityAssertion { if (isObjectLiteral()) KaFe10PsiAnonymousObjectSymbol(this, analysisContext) else @@ -94,7 +94,7 @@ internal class KaFe10SymbolProvider( } override val KtClassOrObject.classSymbol: KaClassSymbol? - get() = withValidityAssertion { + get() = createPsiBasedSymbolWithValidityAssertion { when (this) { is KtEnumEntry -> null is KtObjectDeclaration -> symbol @@ -103,17 +103,17 @@ internal class KaFe10SymbolProvider( } override val KtClassOrObject.namedClassSymbol: KaNamedClassSymbol? - get() = withValidityAssertion { + get() = createPsiBasedSymbolWithValidityAssertion { if (this is KtEnumEntry || nameIdentifier == null) { return null } - return KaFe10PsiNamedClassSymbol(this, analysisContext) + KaFe10PsiNamedClassSymbol(this, analysisContext) } override val KtPropertyAccessor.symbol: KaPropertyAccessorSymbol - get() = withValidityAssertion { - return if (isGetter) { + get() = createPsiBasedSymbolWithValidityAssertion { + if (isGetter) { KaFe10PsiPropertyGetterSymbol(this, analysisContext) } else { KaFe10PsiPropertySetterSymbol(this, analysisContext) @@ -121,22 +121,22 @@ internal class KaFe10SymbolProvider( } override val KtClassInitializer.symbol: KaClassInitializerSymbol - get() = withValidityAssertion { KaFe10PsiClassInitializerSymbol(this, analysisContext) } + get() = createPsiBasedSymbolWithValidityAssertion { KaFe10PsiClassInitializerSymbol(this, analysisContext) } override val KtDestructuringDeclarationEntry.symbol: KaVariableSymbol - get() = withValidityAssertion { KaFe10PsiLocalVariableSymbol(this, analysisContext) } + get() = createPsiBasedSymbolWithValidityAssertion { KaFe10PsiLocalVariableSymbol(this, analysisContext) } override val KtDestructuringDeclaration.symbol: KaDestructuringDeclarationSymbol - get() = withValidityAssertion { KaFe10PsiDestructuringDeclarationSymbol(this, analysisSession) } + get() = createPsiBasedSymbolWithValidityAssertion { KaFe10PsiDestructuringDeclarationSymbol(this, analysisSession) } override fun findClass(classId: ClassId): KaClassSymbol? = withValidityAssertion { val descriptor = analysisContext.resolveSession.moduleDescriptor.findClassAcrossModuleDependencies(classId) ?: return null - return descriptor.toKaClassSymbol(analysisContext) + descriptor.toKaClassSymbol(analysisContext) } override fun findTypeAlias(classId: ClassId): KaTypeAliasSymbol? = withValidityAssertion { val descriptor = analysisContext.resolveSession.moduleDescriptor.findTypeAliasAcrossModuleDependencies(classId) ?: return null - return descriptor.toKtClassifierSymbol(analysisContext) as? KaTypeAliasSymbol + descriptor.toKtClassifierSymbol(analysisContext) as? KaTypeAliasSymbol } override fun findClassLike(classId: ClassId): KaClassLikeSymbol? = withValidityAssertion { @@ -146,7 +146,7 @@ internal class KaFe10SymbolProvider( override fun findTopLevelCallables(packageFqName: FqName, name: Name): Sequence = withValidityAssertion { val packageViewDescriptor = analysisContext.resolveSession.moduleDescriptor.getPackage(packageFqName) - return packageViewDescriptor.memberScope.getContributedDescriptors(DescriptorKindFilter.ALL, nameFilter = { it == name }) + packageViewDescriptor.memberScope.getContributedDescriptors(DescriptorKindFilter.ALL, nameFilter = { it == name }) .asSequence() .filter { it.name == name } .mapNotNull { it.toKtSymbol(analysisContext) as? KaCallableSymbol } @@ -154,6 +154,6 @@ internal class KaFe10SymbolProvider( override fun findPackage(fqName: FqName): KaPackageSymbol? = withValidityAssertion { if (analysisContext.resolveSession.packageFragmentProvider.isEmpty(fqName)) return null - return KaFe10PackageSymbol(fqName, analysisContext) + KaFe10PackageSymbol(fqName, analysisContext) } } \ No newline at end of file diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KaFirSymbolProvider.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KaFirSymbolProvider.kt index 4e31f743f4e6c..b11de7ba56218 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KaFirSymbolProvider.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/symbols/KaFirSymbolProvider.kt @@ -27,7 +27,7 @@ internal class KaFirSymbolProvider( private val firSymbolProvider: FirSymbolProvider, ) : KaBaseSymbolProvider(), KaFirSessionComponent { override val KtParameter.symbol: KaVariableSymbol - get() = withValidityAssertion { + get() = createPsiBasedSymbolWithValidityAssertion { when { isFunctionTypeParameter -> errorWithFirSpecificEntries( "Creating ${KaVariableSymbol::class.simpleName} for function type parameter is not possible. " + @@ -41,17 +41,17 @@ internal class KaFirSymbolProvider( } override val KtFile.symbol: KaFileSymbol - get() = withValidityAssertion { + get() = createPsiBasedSymbolWithValidityAssertion { KaFirFileSymbol(this, analysisSession) } override val KtScript.symbol: KaScriptSymbol - get() = withValidityAssertion { + get() = createPsiBasedSymbolWithValidityAssertion { KaFirScriptSymbol(this, analysisSession) } override val KtNamedFunction.symbol: KaFunctionSymbol - get() = withValidityAssertion { + get() = createPsiBasedSymbolWithValidityAssertion { if (isAnonymous) { KaFirAnonymousFunctionSymbol(this, analysisSession) } else { @@ -60,32 +60,32 @@ internal class KaFirSymbolProvider( } override val KtConstructor<*>.symbol: KaConstructorSymbol - get() = withValidityAssertion { + get() = createPsiBasedSymbolWithValidityAssertion { KaFirConstructorSymbol(this, analysisSession) } override val KtTypeParameter.symbol: KaTypeParameterSymbol - get() = withValidityAssertion { + get() = createPsiBasedSymbolWithValidityAssertion { KaFirTypeParameterSymbol(this, analysisSession) } override val KtTypeAlias.symbol: KaTypeAliasSymbol - get() = withValidityAssertion { + get() = createPsiBasedSymbolWithValidityAssertion { KaFirTypeAliasSymbol(this, analysisSession) } override val KtEnumEntry.symbol: KaEnumEntrySymbol - get() = withValidityAssertion { + get() = createPsiBasedSymbolWithValidityAssertion { KaFirEnumEntrySymbol(this, analysisSession) } override val KtFunctionLiteral.symbol: KaAnonymousFunctionSymbol - get() = withValidityAssertion { + get() = createPsiBasedSymbolWithValidityAssertion { KaFirAnonymousFunctionSymbol(this, analysisSession) } override val KtProperty.symbol: KaVariableSymbol - get() = withValidityAssertion { + get() = createPsiBasedSymbolWithValidityAssertion { if (isLocal) { KaFirLocalVariableSymbol(this, analysisSession) } else { @@ -94,12 +94,12 @@ internal class KaFirSymbolProvider( } override val KtObjectLiteralExpression.symbol: KaAnonymousObjectSymbol - get() = withValidityAssertion { + get() = createPsiBasedSymbolWithValidityAssertion { KaFirAnonymousObjectSymbol(objectDeclaration, analysisSession) } override val KtObjectDeclaration.symbol: KaClassSymbol - get() = withValidityAssertion { + get() = createPsiBasedSymbolWithValidityAssertion { if (isObjectLiteral()) { KaFirAnonymousObjectSymbol(this, analysisSession) } else { @@ -108,7 +108,7 @@ internal class KaFirSymbolProvider( } override val KtClassOrObject.classSymbol: KaClassSymbol? - get() = withValidityAssertion { + get() = createPsiBasedSymbolWithValidityAssertion { when (this) { is KtEnumEntry -> null is KtObjectDeclaration -> symbol @@ -117,7 +117,7 @@ internal class KaFirSymbolProvider( } override val KtClassOrObject.namedClassSymbol: KaNamedClassSymbol? - get() = withValidityAssertion { + get() = createPsiBasedSymbolWithValidityAssertion { if (this is KtEnumEntry || this.isObjectLiteral()) { return null } @@ -126,7 +126,7 @@ internal class KaFirSymbolProvider( } override val KtPropertyAccessor.symbol: KaPropertyAccessorSymbol - get() = withValidityAssertion { + get() = createPsiBasedSymbolWithValidityAssertion { if (isGetter) { KaFirPropertyGetterSymbol.create(this, analysisSession) } else { @@ -135,12 +135,12 @@ internal class KaFirSymbolProvider( } override val KtClassInitializer.symbol: KaClassInitializerSymbol - get() = withValidityAssertion { + get() = createPsiBasedSymbolWithValidityAssertion { KaFirClassInitializerSymbol(this, analysisSession) } override val KtDestructuringDeclarationEntry.symbol: KaVariableSymbol - get() = withValidityAssertion { + get() = createPsiBasedSymbolWithValidityAssertion { when (val parent = parent) { is KtDestructuringDeclaration -> { if (parent.parent?.parent is KtScript) { @@ -162,18 +162,18 @@ internal class KaFirSymbolProvider( } override val KtDestructuringDeclaration.symbol: KaDestructuringDeclarationSymbol - get() = withValidityAssertion { + get() = createPsiBasedSymbolWithValidityAssertion { KaFirDestructuringDeclarationSymbol(this, analysisSession) } override fun findClass(classId: ClassId): KaClassSymbol? = withValidityAssertion { val symbol = firSymbolProvider.getClassLikeSymbolByClassId(classId) as? FirRegularClassSymbol ?: return null - return firSymbolBuilder.classifierBuilder.buildNamedClassSymbol(symbol) + firSymbolBuilder.classifierBuilder.buildNamedClassSymbol(symbol) } override fun findTypeAlias(classId: ClassId): KaTypeAliasSymbol? = withValidityAssertion { val symbol = firSymbolProvider.getClassLikeSymbolByClassId(classId) as? FirTypeAliasSymbol ?: return null - return firSymbolBuilder.classifierBuilder.buildTypeAliasSymbol(symbol) + firSymbolBuilder.classifierBuilder.buildTypeAliasSymbol(symbol) } override fun findClassLike(classId: ClassId): KaClassLikeSymbol? { @@ -183,7 +183,7 @@ internal class KaFirSymbolProvider( override fun findTopLevelCallables(packageFqName: FqName, name: Name): Sequence = withValidityAssertion { val firs = firSymbolProvider.getTopLevelCallableSymbols(packageFqName, name) - return firs.asSequence().map { firSymbol -> + firs.asSequence().map { firSymbol -> firSymbolBuilder.buildSymbol(firSymbol) as KaCallableSymbol } } diff --git a/analysis/analysis-api-impl-base/resources/META-INF/analysis-api/analysis-api-impl-base.xml b/analysis/analysis-api-impl-base/resources/META-INF/analysis-api/analysis-api-impl-base.xml index c578888cbda0b..d9797821dfdbe 100644 --- a/analysis/analysis-api-impl-base/resources/META-INF/analysis-api/analysis-api-impl-base.xml +++ b/analysis/analysis-api-impl-base/resources/META-INF/analysis-api/analysis-api-impl-base.xml @@ -52,5 +52,12 @@ key="kotlin.decompiled.light.classes.check.inconsistency" restartRequired="false" /> + + \ No newline at end of file diff --git a/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/components/KaBaseSymbolProvider.kt b/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/components/KaBaseSymbolProvider.kt index dc19e1bb5461e..7b35b2e0836d5 100644 --- a/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/components/KaBaseSymbolProvider.kt +++ b/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/components/KaBaseSymbolProvider.kt @@ -5,28 +5,19 @@ package org.jetbrains.kotlin.analysis.api.impl.base.components +import com.intellij.openapi.util.registry.Registry +import com.intellij.psi.PsiElement import org.jetbrains.kotlin.analysis.api.KaImplementationDetail import org.jetbrains.kotlin.analysis.api.KaSession +import org.jetbrains.kotlin.analysis.api.getModule import org.jetbrains.kotlin.analysis.api.lifetime.withValidityAssertion import org.jetbrains.kotlin.analysis.api.symbols.KaDeclarationSymbol import org.jetbrains.kotlin.analysis.api.symbols.KaSymbolProvider -import org.jetbrains.kotlin.psi.KtClassInitializer -import org.jetbrains.kotlin.psi.KtClassOrObject -import org.jetbrains.kotlin.psi.KtConstructor -import org.jetbrains.kotlin.psi.KtDeclaration -import org.jetbrains.kotlin.psi.KtDestructuringDeclaration -import org.jetbrains.kotlin.psi.KtDestructuringDeclarationEntry -import org.jetbrains.kotlin.psi.KtEnumEntry -import org.jetbrains.kotlin.psi.KtFunctionLiteral -import org.jetbrains.kotlin.psi.KtNamedFunction -import org.jetbrains.kotlin.psi.KtObjectDeclaration -import org.jetbrains.kotlin.psi.KtParameter -import org.jetbrains.kotlin.psi.KtProperty -import org.jetbrains.kotlin.psi.KtPropertyAccessor -import org.jetbrains.kotlin.psi.KtScript -import org.jetbrains.kotlin.psi.KtScriptInitializer -import org.jetbrains.kotlin.psi.KtTypeAlias -import org.jetbrains.kotlin.psi.KtTypeParameter +import org.jetbrains.kotlin.analysis.api.utils.errors.withKaModuleEntry +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.utils.exceptions.KotlinIllegalArgumentExceptionWithAttachments +import org.jetbrains.kotlin.utils.exceptions.buildAttachment +import org.jetbrains.kotlin.utils.exceptions.withPsiEntry @KaImplementationDetail abstract class KaBaseSymbolProvider : KaSessionComponent(), KaSymbolProvider { @@ -52,4 +43,37 @@ abstract class KaBaseSymbolProvider : KaSessionComponent(), Ka else -> error("Cannot build symbol for ${this::class}") } } + + protected inline fun T.createPsiBasedSymbolWithValidityAssertion(builder: () -> R): R = withValidityAssertion { + with(analysisSession) { + if (!canBeAnalysed() && !Registry.`is`("kotlin.analysis.unrelatedSymbolCreation.allowed", false)) { + throw KaBaseIllegalPsiException(this, this@createPsiBasedSymbolWithValidityAssertion) + } + } + + builder() + } + + @KaImplementationDetail + class KaBaseIllegalPsiException(session: KaSession, psi: PsiElement) : KotlinIllegalArgumentExceptionWithAttachments( + "The element cannot be analyzed in the context of the current session.\n" + + "The call site should be adjusted according to ${KaSymbolProvider::class.simpleName} KDoc." + ) { + init { + with(session) { + buildAttachment("info.txt") { + withKaModuleEntry("useSiteModule", useSiteModule) + + val psiModule = getModule(psi) + withKaModuleEntry("psiModule", psiModule) + + runCatching { + withPsiEntry("psi", psi) + }.exceptionOrNull()?.let { + withEntry("psiException", it.stackTraceToString()) + } + } + } + } + } } diff --git a/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/symbols/AbstractSymbolTest.kt b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/symbols/AbstractSymbolTest.kt index acd2f55def26c..2eb0ef2d8a76a 100644 --- a/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/symbols/AbstractSymbolTest.kt +++ b/analysis/analysis-api-impl-base/tests/org/jetbrains/kotlin/analysis/api/impl/base/test/cases/symbols/AbstractSymbolTest.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.analysis.api.impl.base.test.cases.symbols import com.intellij.psi.PsiElement import org.jetbrains.kotlin.analysis.api.KaSession +import org.jetbrains.kotlin.analysis.api.impl.base.components.KaBaseSymbolProvider import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.symbols.SymbolTestDirectives.DO_NOT_CHECK_NON_PSI_SYMBOL_RESTORE import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.symbols.SymbolTestDirectives.DO_NOT_CHECK_NON_PSI_SYMBOL_RESTORE_K1 import org.jetbrains.kotlin.analysis.api.impl.base.test.cases.symbols.SymbolTestDirectives.DO_NOT_CHECK_NON_PSI_SYMBOL_RESTORE_K2 @@ -35,9 +36,11 @@ import org.jetbrains.kotlin.test.directives.model.RegisteredDirectives import org.jetbrains.kotlin.test.directives.model.SimpleDirectivesContainer import org.jetbrains.kotlin.test.services.TestServices import org.jetbrains.kotlin.test.services.assertions +import org.jetbrains.kotlin.test.services.moduleStructure import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.mapToSetOrEmpty import org.opentest4j.AssertionFailedError +import java.util.concurrent.ExecutionException import kotlin.reflect.full.* import kotlin.reflect.jvm.javaField import kotlin.test.fail @@ -63,8 +66,13 @@ abstract class AbstractSymbolTest : AbstractAnalysisApiBasedTest() { abstract fun KaSession.collectSymbols(ktFile: KtFile, testServices: TestServices): SymbolsData override fun doTestByMainFile(mainFile: KtFile, mainModule: KtTestModule, testServices: TestServices) { - doTestByMainFile(mainFile, mainModule, testServices, disablePsiBasedLogic = false) - doTestByMainFile(mainFile, mainModule, testServices, disablePsiBasedLogic = true) + testServices.moduleStructure.allDirectives.suppressIf( + suppressionDirective = SymbolTestDirectives.ILLEGAL_PSI, + filter = Throwable::isIllegalPsiException, + ) { + doTestByMainFile(mainFile, mainModule, testServices, disablePsiBasedLogic = false) + doTestByMainFile(mainFile, mainModule, testServices, disablePsiBasedLogic = true) + } } private fun doTestByMainFile( @@ -181,7 +189,9 @@ abstract class AbstractSymbolTest : AbstractAnalysisApiBasedTest() { } private fun KaSession.checkContainingFiles(symbols: List, mainFile: KtFile, testServices: TestServices) { - val allowedContainingFileSymbols = getAllowedContainingFiles(mainFile, testServices).mapToSetOrEmpty { it.symbol } + val allowedContainingFileSymbols = getAllowedContainingFiles(mainFile, testServices).mapToSetOrEmpty { + it.takeIf { it.canBeAnalysed() }?.symbol + } for (symbol in symbols) { if (symbol.origin != KaSymbolOrigin.SOURCE) continue @@ -373,6 +383,8 @@ object SymbolTestDirectives : SimpleDirectivesContainer() { val PRETTY_RENDERER_OPTION by enumDirective(description = "Explicit rendering mode") { PrettyRendererOption.valueOf(it) } val TARGET_FILE_NAME by stringDirective(description = "The name of the main file") + + val ILLEGAL_PSI by stringDirective(description = "Symbol should not be created for this PSI element") } enum class PrettyRendererOption(val transformation: (KaDeclarationRenderer) -> KaDeclarationRenderer) { @@ -511,3 +523,10 @@ private fun KaSymbol.dropBackingPsi() { // Drop backing PSI to trigger non-psi implementation field.set(this, null) } + +private val Throwable.isIllegalPsiException: Boolean + get() = when (this) { + is KaBaseSymbolProvider.KaBaseIllegalPsiException -> true + is ExecutionException -> cause?.isIllegalPsiException == true + else -> false + } diff --git a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/symbols/KaSymbolProvider.kt b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/symbols/KaSymbolProvider.kt index b724fa91c33d9..8ac7486985984 100644 --- a/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/symbols/KaSymbolProvider.kt +++ b/analysis/analysis-api/src/org/jetbrains/kotlin/analysis/api/symbols/KaSymbolProvider.kt @@ -10,6 +10,15 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* +/** + * Provides a mapping between a PSI element and the corresponding [KaSymbol]. + * + * **Note**: symbols can be created only for elements which are a part of the current [KaSession] + * ([KaAnalysisScopeProvider.canBeAnalysed][org.jetbrains.kotlin.analysis.api.components.KaAnalysisScopeProvider.canBeAnalysed] + * is **true** for them). + * + * @see org.jetbrains.kotlin.analysis.api.components.KaAnalysisScopeProvider + */ public interface KaSymbolProvider { public val KtDeclaration.symbol: KaDeclarationSymbol diff --git a/analysis/analysis-api/testData/symbols/symbolByPsi/classFromDependentModule.kt b/analysis/analysis-api/testData/symbols/symbolByPsi/classFromDependentModule.kt index 7f5f4413627e5..4610fc9f01a54 100644 --- a/analysis/analysis-api/testData/symbols/symbolByPsi/classFromDependentModule.kt +++ b/analysis/analysis-api/testData/symbols/symbolByPsi/classFromDependentModule.kt @@ -1,4 +1,4 @@ -// DO_NOT_CHECK_SYMBOL_RESTORE +// ILLEGAL_PSI // MODULE: dep // FILE: dependency.kt class Dep diff --git a/analysis/analysis-api/testData/symbols/symbolByPsi/classFromDependentModule.pretty.txt b/analysis/analysis-api/testData/symbols/symbolByPsi/classFromDependentModule.pretty.txt deleted file mode 100644 index e5cb7e0b9bb9b..0000000000000 --- a/analysis/analysis-api/testData/symbols/symbolByPsi/classFromDependentModule.pretty.txt +++ /dev/null @@ -1 +0,0 @@ -class MyClass diff --git a/analysis/analysis-api/testData/symbols/symbolByPsi/classFromDependentModule.txt b/analysis/analysis-api/testData/symbols/symbolByPsi/classFromDependentModule.txt deleted file mode 100644 index b48de669a6963..0000000000000 --- a/analysis/analysis-api/testData/symbols/symbolByPsi/classFromDependentModule.txt +++ /dev/null @@ -1,30 +0,0 @@ -KaNamedClassSymbol: - annotations: [] - classId: MyClass - classKind: CLASS - companionObject: null - compilerVisibility: Public - contextReceivers: [] - isActual: false - isData: false - isExpect: false - isExternal: false - isFun: false - isInline: false - isInner: false - location: TOP_LEVEL - modality: FINAL - name: MyClass - origin: SOURCE - superTypes: [ - KaUsualClassType: - annotations: [] - typeArguments: [] - type: kotlin/Any - ] - typeParameters: [] - visibility: PUBLIC - getContainingFileSymbol: KaFileSymbol(main.kt) - getContainingModule: KaSourceModule "Sources of main" - annotationApplicableTargets: null - deprecationStatus: null diff --git a/analysis/analysis-api/testData/symbols/symbolByPsi/functionFromDependentModule.kt b/analysis/analysis-api/testData/symbols/symbolByPsi/functionFromDependentModule.kt index a35fee6bec204..55faf2b731a87 100644 --- a/analysis/analysis-api/testData/symbols/symbolByPsi/functionFromDependentModule.kt +++ b/analysis/analysis-api/testData/symbols/symbolByPsi/functionFromDependentModule.kt @@ -1,4 +1,4 @@ -// DO_NOT_CHECK_SYMBOL_RESTORE +// ILLEGAL_PSI // MODULE: dep // FILE: dependency.kt class Dep diff --git a/analysis/analysis-api/testData/symbols/symbolByPsi/functionFromDependentModule.pretty.txt b/analysis/analysis-api/testData/symbols/symbolByPsi/functionFromDependentModule.pretty.txt deleted file mode 100644 index 15079b66c5a4b..0000000000000 --- a/analysis/analysis-api/testData/symbols/symbolByPsi/functionFromDependentModule.pretty.txt +++ /dev/null @@ -1 +0,0 @@ -fun main() diff --git a/analysis/analysis-api/testData/symbols/symbolByPsi/functionFromDependentModule.txt b/analysis/analysis-api/testData/symbols/symbolByPsi/functionFromDependentModule.txt deleted file mode 100644 index f962ed53af619..0000000000000 --- a/analysis/analysis-api/testData/symbols/symbolByPsi/functionFromDependentModule.txt +++ /dev/null @@ -1,35 +0,0 @@ -KaNamedFunctionSymbol: - annotations: [] - callableId: /main - compilerVisibility: Public - contextReceivers: [] - contractEffects: [] - hasStableParameterNames: true - isActual: false - isBuiltinFunctionInvoke: false - isExpect: false - isExtension: false - isExternal: false - isInfix: false - isInline: false - isOperator: false - isOverride: false - isStatic: false - isSuspend: false - isTailRec: false - location: TOP_LEVEL - modality: FINAL - name: main - origin: SOURCE - receiverParameter: null - returnType: KaUsualClassType: - annotations: [] - typeArguments: [] - type: kotlin/Unit - typeParameters: [] - valueParameters: [] - visibility: PUBLIC - getContainingFileSymbol: KaFileSymbol(main.kt) - getContainingJvmClassName: MainKt - getContainingModule: KaSourceModule "Sources of main" - deprecationStatus: null diff --git a/analysis/analysis-api/testData/symbols/symbolByPsi/propertyFromDependentModule.kt b/analysis/analysis-api/testData/symbols/symbolByPsi/propertyFromDependentModule.kt index 8fdb367b10e3a..1687be8a1c6c3 100644 --- a/analysis/analysis-api/testData/symbols/symbolByPsi/propertyFromDependentModule.kt +++ b/analysis/analysis-api/testData/symbols/symbolByPsi/propertyFromDependentModule.kt @@ -1,4 +1,4 @@ -// DO_NOT_CHECK_SYMBOL_RESTORE +// ILLEGAL_PSI // MODULE: dep // FILE: dependency.kt class Dep diff --git a/analysis/analysis-api/testData/symbols/symbolByPsi/propertyFromDependentModule.pretty.txt b/analysis/analysis-api/testData/symbols/symbolByPsi/propertyFromDependentModule.pretty.txt deleted file mode 100644 index 643630bcbdb3b..0000000000000 --- a/analysis/analysis-api/testData/symbols/symbolByPsi/propertyFromDependentModule.pretty.txt +++ /dev/null @@ -1 +0,0 @@ -val prop: kotlin.Int diff --git a/analysis/analysis-api/testData/symbols/symbolByPsi/propertyFromDependentModule.txt b/analysis/analysis-api/testData/symbols/symbolByPsi/propertyFromDependentModule.txt deleted file mode 100644 index f35ee9144aa45..0000000000000 --- a/analysis/analysis-api/testData/symbols/symbolByPsi/propertyFromDependentModule.txt +++ /dev/null @@ -1,90 +0,0 @@ -KaKotlinPropertySymbol: - annotations: [] - backingFieldSymbol: KaBackingFieldSymbol: - annotations: [] - callableId: null - compilerVisibility: Private - contextReceivers: [] - isActual: false - isExpect: false - isExtension: false - isVal: true - location: PROPERTY - modality: FINAL - name: field - origin: PROPERTY_BACKING_FIELD - owningProperty: KaKotlinPropertySymbol(/prop) - receiverParameter: null - returnType: KaUsualClassType: - annotations: [] - typeArguments: [] - type: kotlin/Int - visibility: PRIVATE - getContainingFileSymbol: KaFileSymbol(main.kt) - getContainingJvmClassName: MainKt - getContainingModule: KaSourceModule "Sources of main" - deprecationStatus: null - callableId: /prop - compilerVisibility: Public - contextReceivers: [] - getter: KaPropertyGetterSymbol: - annotations: [] - callableId: null - compilerVisibility: Public - contextReceivers: [] - hasBody: false - hasStableParameterNames: true - isActual: false - isDefault: true - isExpect: false - isExtension: false - isInline: false - isOverride: false - location: PROPERTY - modality: FINAL - origin: SOURCE - receiverParameter: null - returnType: KaUsualClassType: - annotations: [] - typeArguments: [] - type: kotlin/Int - valueParameters: [] - visibility: PUBLIC - getContainingFileSymbol: KaFileSymbol(main.kt) - getContainingJvmClassName: MainKt - getContainingModule: KaSourceModule "Sources of main" - deprecationStatus: null - hasBackingField: true - hasGetter: true - hasSetter: false - initializer: KtConstantInitializerValue(0) - isActual: false - isConst: false - isDelegatedProperty: false - isExpect: false - isExtension: false - isFromPrimaryConstructor: false - isLateInit: false - isOverride: false - isStatic: false - isVal: true - location: TOP_LEVEL - modality: FINAL - name: prop - origin: SOURCE - receiverParameter: null - returnType: KaUsualClassType: - annotations: [] - typeArguments: [] - type: kotlin/Int - setter: null - typeParameters: [] - visibility: PUBLIC - getContainingFileSymbol: KaFileSymbol(main.kt) - getContainingJvmClassName: MainKt - getContainingModule: KaSourceModule "Sources of main" - deprecationStatus: null - getterDeprecationStatus: null - javaGetterName: getProp - javaSetterName: null - setterDeprecationStatus: null diff --git a/analysis/analysis-test-framework/tests/org/jetbrains/kotlin/analysis/test/framework/base/AbstractAnalysisApiBasedTest.kt b/analysis/analysis-test-framework/tests/org/jetbrains/kotlin/analysis/test/framework/base/AbstractAnalysisApiBasedTest.kt index ffba74deb703e..38c456150c299 100644 --- a/analysis/analysis-test-framework/tests/org/jetbrains/kotlin/analysis/test/framework/base/AbstractAnalysisApiBasedTest.kt +++ b/analysis/analysis-test-framework/tests/org/jetbrains/kotlin/analysis/test/framework/base/AbstractAnalysisApiBasedTest.kt @@ -33,6 +33,7 @@ import org.jetbrains.kotlin.test.builders.testConfiguration import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives import org.jetbrains.kotlin.test.directives.model.Directive import org.jetbrains.kotlin.test.directives.model.RegisteredDirectives +import org.jetbrains.kotlin.test.directives.model.StringDirective import org.jetbrains.kotlin.test.directives.model.singleOrZeroValue import org.jetbrains.kotlin.test.model.DependencyKind import org.jetbrains.kotlin.test.model.FrontendKinds @@ -440,4 +441,24 @@ abstract class AbstractAnalysisApiBasedTest : TestWithDisposable() { tags = testInfo.tags ) } + + fun RegisteredDirectives.suppressIf(suppressionDirective: StringDirective, filter: (Throwable) -> Boolean, action: () -> Unit) { + val hasSuppressionDirective = suppressionDirective in this + var exception: Throwable? = null + try { + action() + } catch (e: Throwable) { + exception = e + } + + if (exception != null) { + if (!filter(exception) || !hasSuppressionDirective) { + throw exception + } + + return + } else if (hasSuppressionDirective) { + throw AssertionError("'${suppressionDirective.name}' directive present but no exception thrown. Please remove directive") + } + } } \ No newline at end of file