[compiler] introduce dedicated Fir declaration for dangling modifier lists (KTIJ-23008)

ensure fir annotations are included in FirDanglingModifierList and resolved,
dedicated DanglingTopLevelModifierListStructureElement exists for top
level lists only, class level lists are processed by containing structure
element
This commit is contained in:
Anna Kozlova
2022-11-18 18:12:58 +01:00
committed by teamcity
parent d788adcbb5
commit 15b1e429d7
70 changed files with 895 additions and 48 deletions
@@ -718,6 +718,40 @@ public class Fe10IdeNormalAnalysisSourceModuleReferenceResolveTestGenerated exte
}
}
@Nested
@TestMetadata("analysis/analysis-api/testData/referenceResolve/danglingAnnotations")
@TestDataPath("$PROJECT_ROOT")
public class DanglingAnnotations {
@Test
public void testAllFilesPresentInDanglingAnnotations() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/referenceResolve/danglingAnnotations"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@Test
@TestMetadata("DanglingAnnotationsResolvedAnonymous.kt")
public void testDanglingAnnotationsResolvedAnonymous() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedAnonymous.kt");
}
@Test
@TestMetadata("DanglingAnnotationsResolvedClass.kt")
public void testDanglingAnnotationsResolvedClass() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedClass.kt");
}
@Test
@TestMetadata("DanglingAnnotationsResolvedLocal.kt")
public void testDanglingAnnotationsResolvedLocal() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedLocal.kt");
}
@Test
@TestMetadata("DanglingAnnotationsResolvedTopLevel.kt")
public void testDanglingAnnotationsResolvedTopLevel() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedTopLevel.kt");
}
}
@Nested
@TestMetadata("analysis/analysis-api/testData/referenceResolve/delegatedPropertyAccessors")
@TestDataPath("$PROJECT_ROOT")
@@ -1609,6 +1643,12 @@ public class Fe10IdeNormalAnalysisSourceModuleReferenceResolveTestGenerated exte
runTest("analysis/analysis-api/testData/referenceResolve/withErrors/CoroutineSuspensionPoint.kt");
}
@Test
@TestMetadata("DanglingAnnotations.kt")
public void testDanglingAnnotations() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/withErrors/DanglingAnnotations.kt");
}
@Test
@TestMetadata("DeprecatedHidden.kt")
public void testDeprecatedHidden() throws Exception {
@@ -718,6 +718,40 @@ public class FirIdeDependentAnalysisSourceModuleReferenceResolveTestGenerated ex
}
}
@Nested
@TestMetadata("analysis/analysis-api/testData/referenceResolve/danglingAnnotations")
@TestDataPath("$PROJECT_ROOT")
public class DanglingAnnotations {
@Test
public void testAllFilesPresentInDanglingAnnotations() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/referenceResolve/danglingAnnotations"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@Test
@TestMetadata("DanglingAnnotationsResolvedAnonymous.kt")
public void testDanglingAnnotationsResolvedAnonymous() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedAnonymous.kt");
}
@Test
@TestMetadata("DanglingAnnotationsResolvedClass.kt")
public void testDanglingAnnotationsResolvedClass() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedClass.kt");
}
@Test
@TestMetadata("DanglingAnnotationsResolvedLocal.kt")
public void testDanglingAnnotationsResolvedLocal() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedLocal.kt");
}
@Test
@TestMetadata("DanglingAnnotationsResolvedTopLevel.kt")
public void testDanglingAnnotationsResolvedTopLevel() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedTopLevel.kt");
}
}
@Nested
@TestMetadata("analysis/analysis-api/testData/referenceResolve/delegatedPropertyAccessors")
@TestDataPath("$PROJECT_ROOT")
@@ -1609,6 +1643,12 @@ public class FirIdeDependentAnalysisSourceModuleReferenceResolveTestGenerated ex
runTest("analysis/analysis-api/testData/referenceResolve/withErrors/CoroutineSuspensionPoint.kt");
}
@Test
@TestMetadata("DanglingAnnotations.kt")
public void testDanglingAnnotations() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/withErrors/DanglingAnnotations.kt");
}
@Test
@TestMetadata("DeprecatedHidden.kt")
public void testDeprecatedHidden() throws Exception {
@@ -690,6 +690,40 @@ public class FirIdeNormalAnalysisLibrarySourceModuleReferenceResolveTestGenerate
}
}
@Nested
@TestMetadata("analysis/analysis-api/testData/referenceResolve/danglingAnnotations")
@TestDataPath("$PROJECT_ROOT")
public class DanglingAnnotations {
@Test
public void testAllFilesPresentInDanglingAnnotations() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/referenceResolve/danglingAnnotations"), Pattern.compile("^([^.]+)\\.kt$"), null, true, "withErrors");
}
@Test
@TestMetadata("DanglingAnnotationsResolvedAnonymous.kt")
public void testDanglingAnnotationsResolvedAnonymous() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedAnonymous.kt");
}
@Test
@TestMetadata("DanglingAnnotationsResolvedClass.kt")
public void testDanglingAnnotationsResolvedClass() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedClass.kt");
}
@Test
@TestMetadata("DanglingAnnotationsResolvedLocal.kt")
public void testDanglingAnnotationsResolvedLocal() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedLocal.kt");
}
@Test
@TestMetadata("DanglingAnnotationsResolvedTopLevel.kt")
public void testDanglingAnnotationsResolvedTopLevel() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedTopLevel.kt");
}
}
@Nested
@TestMetadata("analysis/analysis-api/testData/referenceResolve/delegatedPropertyAccessors")
@TestDataPath("$PROJECT_ROOT")
@@ -718,6 +718,40 @@ public class FirIdeNormalAnalysisSourceModuleReferenceResolveTestGenerated exten
}
}
@Nested
@TestMetadata("analysis/analysis-api/testData/referenceResolve/danglingAnnotations")
@TestDataPath("$PROJECT_ROOT")
public class DanglingAnnotations {
@Test
public void testAllFilesPresentInDanglingAnnotations() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/referenceResolve/danglingAnnotations"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@Test
@TestMetadata("DanglingAnnotationsResolvedAnonymous.kt")
public void testDanglingAnnotationsResolvedAnonymous() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedAnonymous.kt");
}
@Test
@TestMetadata("DanglingAnnotationsResolvedClass.kt")
public void testDanglingAnnotationsResolvedClass() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedClass.kt");
}
@Test
@TestMetadata("DanglingAnnotationsResolvedLocal.kt")
public void testDanglingAnnotationsResolvedLocal() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedLocal.kt");
}
@Test
@TestMetadata("DanglingAnnotationsResolvedTopLevel.kt")
public void testDanglingAnnotationsResolvedTopLevel() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedTopLevel.kt");
}
}
@Nested
@TestMetadata("analysis/analysis-api/testData/referenceResolve/delegatedPropertyAccessors")
@TestDataPath("$PROJECT_ROOT")
@@ -1609,6 +1643,12 @@ public class FirIdeNormalAnalysisSourceModuleReferenceResolveTestGenerated exten
runTest("analysis/analysis-api/testData/referenceResolve/withErrors/CoroutineSuspensionPoint.kt");
}
@Test
@TestMetadata("DanglingAnnotations.kt")
public void testDanglingAnnotations() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/withErrors/DanglingAnnotations.kt");
}
@Test
@TestMetadata("DeprecatedHidden.kt")
public void testDeprecatedHidden() throws Exception {
@@ -718,6 +718,40 @@ public class FirStandaloneNormalAnalysisSourceModuleReferenceResolveTestGenerate
}
}
@Nested
@TestMetadata("analysis/analysis-api/testData/referenceResolve/danglingAnnotations")
@TestDataPath("$PROJECT_ROOT")
public class DanglingAnnotations {
@Test
public void testAllFilesPresentInDanglingAnnotations() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/referenceResolve/danglingAnnotations"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@Test
@TestMetadata("DanglingAnnotationsResolvedAnonymous.kt")
public void testDanglingAnnotationsResolvedAnonymous() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedAnonymous.kt");
}
@Test
@TestMetadata("DanglingAnnotationsResolvedClass.kt")
public void testDanglingAnnotationsResolvedClass() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedClass.kt");
}
@Test
@TestMetadata("DanglingAnnotationsResolvedLocal.kt")
public void testDanglingAnnotationsResolvedLocal() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedLocal.kt");
}
@Test
@TestMetadata("DanglingAnnotationsResolvedTopLevel.kt")
public void testDanglingAnnotationsResolvedTopLevel() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/danglingAnnotations/DanglingAnnotationsResolvedTopLevel.kt");
}
}
@Nested
@TestMetadata("analysis/analysis-api/testData/referenceResolve/delegatedPropertyAccessors")
@TestDataPath("$PROJECT_ROOT")
@@ -1609,6 +1643,12 @@ public class FirStandaloneNormalAnalysisSourceModuleReferenceResolveTestGenerate
runTest("analysis/analysis-api/testData/referenceResolve/withErrors/CoroutineSuspensionPoint.kt");
}
@Test
@TestMetadata("DanglingAnnotations.kt")
public void testDanglingAnnotations() throws Exception {
runTest("analysis/analysis-api/testData/referenceResolve/withErrors/DanglingAnnotations.kt");
}
@Test
@TestMetadata("DeprecatedHidden.kt")
public void testDeprecatedHidden() throws Exception {
@@ -0,0 +1,10 @@
// COMPILATION_ERRORS
annotation class Ann0
interface I
class Foo {
fun foo() {
val i = object : I {
@<caret>Ann0 @Suppress
}
}
}
@@ -0,0 +1,2 @@
Resolved to:
0: (in Ann0) constructor()
@@ -0,0 +1,6 @@
// COMPILATION_ERRORS
annotation class Ann0
interface I
class Foo {
@<caret>Ann0 @Suppress
}
@@ -0,0 +1,2 @@
Resolved to:
0: (in Ann0) constructor()
@@ -0,0 +1,9 @@
// COMPILATION_ERRORS
annotation class Ann0
class Foo {
fun foo() {
class Local {
@<caret>Ann0 @Suppress
}
}
}
@@ -0,0 +1,2 @@
Resolved to:
0: (in Ann0) constructor()
@@ -0,0 +1,3 @@
// COMPILATION_ERRORS
annotation class Ann0
@<caret>Ann0 @Suppress
@@ -0,0 +1,2 @@
Resolved to:
0: (in Ann0) constructor()
@@ -0,0 +1,8 @@
// UNRESOLVED_REFERENCE
class Foo {
fun foo() {
class Local {
@<caret>Ann0
}
}
}
@@ -18,11 +18,15 @@ import org.jetbrains.kotlin.fir.containingClassLookupTag
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.classId
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
import org.jetbrains.kotlin.fir.diagnostics.ConeDestructuringDeclarationsOnTopLevel
import org.jetbrains.kotlin.fir.java.javaSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLookupTagWithFixedSymbol
import org.jetbrains.kotlin.analysis.utils.errors.buildErrorWithAttachment
import org.jetbrains.kotlin.analysis.utils.errors.checkWithAttachmentBuilder
import org.jetbrains.kotlin.fir.containingClass
import org.jetbrains.kotlin.fir.diagnostics.ConeDestructuringDeclarationsOnTopLevel
import org.jetbrains.kotlin.fir.java.javaSymbolProvider
class FirDesignationWithFile(
path: List<FirRegularClass>,
@@ -92,6 +96,11 @@ private fun collectDesignationPath(target: FirElementWithResolvePhase): List<Fir
outerClassId?.let(target.moduleData.session.firProvider::getFirClassifierByFqName)
?: outerClassId?.let(target.moduleData.session.javaSymbolProvider::getClassLikeSymbolByClassId)?.fir
}
is FirDanglingModifierList -> {
val klass = target.containingClass() ?: return emptyList()
if (klass.classId.isLocal) return null
klass.toFirRegularClassFromSameSession(target.moduleData.session)
}
else -> return null
} ?: return emptyList()
@@ -12,10 +12,8 @@ import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirElementWithResolvePhase
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.containingClass
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.renderWithType
import org.jetbrains.kotlin.fir.resolve.SessionHolder
@@ -61,6 +59,7 @@ internal object PersistenceContextCollector {
val isLocal = when (declaration) {
is FirClassLikeDeclaration -> declaration.symbol.classId.isLocal
is FirCallableDeclaration -> declaration.symbol.callableId.isLocal
is FirDanglingModifierList -> declaration.containingClass()?.classId?.isLocal == true
else -> error("Unsupported declaration ${declaration.renderWithType()}")
}
require(!isLocal) {
@@ -6,12 +6,17 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiErrorElement
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.analysis.low.level.api.fir.LLFirModuleResolveComponents
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter
import org.jetbrains.kotlin.analysis.low.level.api.fir.element.builder.getNonLocalContainingOrThisDeclaration
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.errorWithFirSpecificEntries
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.findSourceByTraversingWholeTree
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.findSourceNonLocalFirDeclaration
import org.jetbrains.kotlin.analysis.utils.printer.getElementTextInContext
import org.jetbrains.kotlin.diagnostics.KtPsiDiagnostic
import org.jetbrains.kotlin.fir.declarations.FirDanglingModifierList
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
@@ -36,14 +41,23 @@ internal class FileStructure private constructor(
private val firProvider = firFile.moduleData.session.firProvider
private val structureElements = ConcurrentHashMap<KtAnnotated, FileStructureElement>()
private val structureElements = ConcurrentHashMap<KtElement, FileStructureElement>()
fun getStructureElementFor(element: KtElement): FileStructureElement {
val container: KtAnnotated = element.getNonLocalContainingOrThisDeclaration() ?: element.containingKtFile
val declaration = element.getNonLocalContainingOrThisDeclaration()
val container: KtElement
if (declaration != null) {
container = declaration
} else {
val modifierList = PsiTreeUtil.getParentOfType(element, KtModifierList::class.java, false)
container = if (modifierList != null && modifierList.nextSibling is PsiErrorElement) {
modifierList
} else element.containingKtFile
}
return getStructureElementForDeclaration(container)
}
private fun getStructureElementForDeclaration(declaration: KtAnnotated): FileStructureElement {
private fun getStructureElementForDeclaration(declaration: KtElement): FileStructureElement {
@Suppress("CANNOT_CHECK_FOR_ERASED")
val structureElement = structureElements.compute(declaration) { _, structureElement ->
when {
@@ -91,6 +105,12 @@ internal class FileStructure private constructor(
dcl.acceptChildren(this)
}
}
override fun visitModifierList(list: KtModifierList) {
if (list.parent == ktFile) {
structureElements += getStructureElementFor(list)
}
}
})
return structureElements
@@ -112,8 +132,15 @@ internal class FileStructure private constructor(
)
}
private fun createStructureElement(container: KtAnnotated): FileStructureElement = when (container) {
is KtFile -> {
private fun createDanglingModifierListStructure(container: KtElement): FileStructureElement {
val firDanglingModifierList = container.findSourceByTraversingWholeTree(moduleComponents.firFileBuilder, firFile) as? FirDanglingModifierList
?: errorWithFirSpecificEntries("No dangling modifier found", psi = container)
firDanglingModifierList.lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE)
return DanglingTopLevelModifierListStructureElement(firFile, firDanglingModifierList, moduleComponents, container.containingKtFile)
}
private fun createStructureElement(container: KtElement): FileStructureElement = when {
container is KtFile -> {
val firFile = moduleComponents.firFileBuilder.buildRawFirFileWithCaching(ktFile)
moduleComponents.firModuleLazyDeclarationResolver.lazyResolve(
target = firFile.annotationsContainer,
@@ -123,7 +150,8 @@ internal class FileStructure private constructor(
RootStructureElement(firFile, container, moduleComponents)
}
is KtDeclaration -> createDeclarationStructure(container)
container is KtDeclaration -> createDeclarationStructure(container)
container is KtModifierList && container.nextSibling is PsiErrorElement -> createDanglingModifierListStructure(container)
else -> error("Invalid container $container")
}
}
@@ -226,6 +226,12 @@ internal class NonReanalyzableDeclarationStructureElement(
}
}
internal class DanglingTopLevelModifierListStructureElement(firFile: FirFile, val fir: FirDeclaration, moduleComponents: LLFirModuleResolveComponents, override val psi: KtAnnotated) :
FileStructureElement(firFile, moduleComponents) {
override val mappings = KtToFirMapping(fir, FirElementsRecorder())
override val diagnostics = FileStructureElementDiagnostics(firFile, SingleNonLocalDeclarationDiagnosticRetriever(fir), moduleComponents)
}
internal class RootStructureElement(
firFile: FirFile,
@@ -246,4 +252,4 @@ internal class RootStructureElement(
}
}
}
}
}
@@ -116,6 +116,7 @@ internal open class FirElementsRecorder : FirVisitor<Unit, MutableMap<KtElement,
it.kind == KtFakeSourceElementKind.DesugaredPrefixNameReference ||
it.kind == KtFakeSourceElementKind.DesugaredPostfixNameReference ||
it.kind == KtFakeSourceElementKind.SmartCastExpression ||
it.kind == KtFakeSourceElementKind.DanglingModifierList ||
it.isSourceForCompoundAccess(element)
}.psi as? KtElement
?: return
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LLFirFirProv
import org.jetbrains.kotlin.analysis.low.level.api.fir.transformers.LLFirLazyTransformerExecutor
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkCanceled
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.findSourceNonLocalFirDeclaration
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.ktDeclaration
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirEntry
import org.jetbrains.kotlin.analysis.utils.errors.rethrowExceptionWithDetails
import org.jetbrains.kotlin.fir.FirElement
@@ -29,6 +30,11 @@ import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
import org.jetbrains.kotlin.fir.resolve.transformers.FirImportResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector
import org.jetbrains.kotlin.analysis.utils.errors.buildErrorWithAttachment
import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.util.SourceCodeAnalysisException
import org.jetbrains.kotlin.util.shouldIjPlatformExceptionBeRethrown
import org.jetbrains.kotlin.psi.KtClassBody
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtEnumEntry
@@ -224,7 +230,16 @@ internal class LLFirModuleLazyDeclarationResolver(val moduleComponents: LLFirMod
val designation: FirDesignationWithFile
val neededPhase: FirResolvePhase
if (requestedDeclarationDesignation != null) {
if (target is FirDanglingModifierList) {
neededPhase = toPhase
val ktFile = target.psi?.containingFile as? KtFile
?: error("File for dangling modifier list cannot be null")
designation = FirDesignationWithFile(
emptyList(),
target,
moduleComponents.cache.getCachedFirFile(ktFile) ?: error("Fir file for dandling modifier list cannot be null")
)
} else if (requestedDeclarationDesignation != null) {
designation = requestedDeclarationDesignation
neededPhase = toPhase
} else {
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.util
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.FirElementWithResolvePhase
import org.jetbrains.kotlin.fir.FirFileAnnotationsContainer
import org.jetbrains.kotlin.fir.declarations.*
@@ -20,6 +21,7 @@ fun FirElementWithResolvePhase.getContainingFile(): FirFile? {
is FirValueParameter -> containingFunctionSymbol.fir.getContainingFile()
is FirCallableDeclaration -> provider.getFirCallableContainerFile(symbol)
is FirClassLikeDeclaration -> provider.getFirClassifierContainerFile(symbol)
is FirDanglingModifierList -> null
else -> errorWithFirSpecificEntries("Unsupported declaration ${this::class.java}", fir = this)
}
}
@@ -28,7 +28,7 @@ internal fun KtDeclaration.findSourceNonLocalFirDeclaration(
): FirDeclaration {
//TODO test what way faster
findSourceNonLocalFirDeclarationByProvider(firFileBuilder, provider, containerFirFile)?.let { return it }
findSourceOfNonLocalFirDeclarationByTraversingWholeTree(firFileBuilder, containerFirFile)?.let { return it }
findSourceByTraversingWholeTree(firFileBuilder, containerFirFile)?.let { return it }
errorWithFirSpecificEntries("No fir element was found for", psi = this)
}
@@ -56,14 +56,15 @@ internal inline fun <reified F : FirDeclaration> KtDeclaration.findFirDeclaratio
return fir
}
private fun KtDeclaration.findSourceOfNonLocalFirDeclarationByTraversingWholeTree(
internal fun KtElement.findSourceByTraversingWholeTree(
firFileBuilder: LLFirFileBuilder,
containerFirFile: FirFile?,
): FirDeclaration? {
val firFile = containerFirFile ?: firFileBuilder.buildRawFirFileWithCaching(containingKtFile)
val originalDeclaration = originalDeclaration
val originalDeclaration = (this as? KtDeclaration)?.originalDeclaration
val isDeclaration = this is KtDeclaration
return FirElementFinder.findElementIn(firFile, canGoInside = { it is FirRegularClass }) { firDeclaration ->
firDeclaration.psi == this || firDeclaration.psi == originalDeclaration
firDeclaration.psi == this || isDeclaration && firDeclaration.psi == originalDeclaration
}
}
@@ -0,0 +1,16 @@
class Foo {/* NonReanalyzableDeclarationStructureElement */
@Suppress("") @MustBeDocumented
}
class Bar {/* NonReanalyzableDeclarationStructureElement */
@Suppress("") @MustBeDocumented
}
class Outer {/* NonReanalyzableDeclarationStructureElement */
class Inner {/* NonReanalyzableDeclarationStructureElement */
@Suppress("") @MustBeDocumented
}
fun foo() {/* ReanalyzableFunctionStructureElement */
class Local {
@Suppress("") @MustBeDocumented
}
}
}
@@ -0,0 +1 @@
@Suppress("") @MustBeDocumented/* DanglingTopLevelModifierListStructureElement */
@@ -0,0 +1,3 @@
// WITH_STDLIB
// LOOK_UP_FOR_ELEMENT_OF_TYPE: org.jetbrains.kotlin.psi.KtAnnotationEntry
<expr>@Suppress("")</expr> @MustBeDocumented
@@ -0,0 +1,6 @@
KT element: KtAnnotationEntry
FIR element: FirAnnotationCallImpl
FIR source kind: KtRealSourceElementKind
FIR element rendered:
@R|kotlin/Suppress|(names = vararg(String()))
@@ -0,0 +1,5 @@
// WITH_STDLIB
// LOOK_UP_FOR_ELEMENT_OF_TYPE: org.jetbrains.kotlin.psi.KtAnnotationEntry
class F {
<expr>@Suppress("")</expr> @MustBeDocumented
}
@@ -0,0 +1,6 @@
KT element: KtAnnotationEntry
FIR element: FirAnnotationCallImpl
FIR source kind: KtRealSourceElementKind
FIR element rendered:
@R|kotlin/Suppress|(names = vararg(String()))
@@ -0,0 +1,5 @@
annotation class JsQualifier : kotlin.Annotation {
public constructor JsQualifier(<expr>value</expr>: kotlin.String)
public final val value: kotlin.String { get; }
}
@@ -0,0 +1,6 @@
KT element: KtDeclarationModifierList
FIR element: FirDanglingModifierListImpl
FIR source kind: DanglingModifierList
FIR element rendered:
<DANGLING MODIFIER: Top level declaration expected>
@@ -75,6 +75,18 @@ public class FirLazyBodiesCalculatorTestGenerated extends AbstractFirLazyBodiesC
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/contextReceivers.kt");
}
@Test
@TestMetadata("danglingAnnotationsClassLevel.kt")
public void testDanglingAnnotationsClassLevel() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/danglingAnnotationsClassLevel.kt");
}
@Test
@TestMetadata("danglingAnnotationsFileLevel.kt")
public void testDanglingAnnotationsFileLevel() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/danglingAnnotationsFileLevel.kt");
}
@Test
@TestMetadata("delegates.kt")
public void testDelegates() throws Exception {
@@ -69,6 +69,18 @@ public class GetOrBuildFirTestGenerated extends AbstractGetOrBuildFirTest {
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/annotations/annotationApplicationWithArgumentsOnCallSite.kt");
}
@Test
@TestMetadata("danglingAnnotation.kt")
public void testDanglingAnnotation() throws Exception {
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/annotations/danglingAnnotation.kt");
}
@Test
@TestMetadata("danglingAnnotationInClass.kt")
public void testDanglingAnnotationInClass() throws Exception {
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/annotations/danglingAnnotationInClass.kt");
}
@Test
@TestMetadata("fileAnnotation.kt")
public void testFileAnnotation() throws Exception {
@@ -572,6 +584,12 @@ public class GetOrBuildFirTestGenerated extends AbstractGetOrBuildFirTest {
public void testJavaClassLiteral() throws Exception {
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/invalidCode/javaClassLiteral.kt");
}
@Test
@TestMetadata("secondaryConstructor.kt")
public void testSecondaryConstructor() throws Exception {
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/invalidCode/secondaryConstructor.kt");
}
}
@Nested
@@ -17,6 +17,8 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getDiagnostics
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirFile
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.BeforeElementDiagnosticCollectionHandler
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.fir.PersistenceContextCollector
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.*
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.DanglingTopLevelModifierListStructureElement
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.FileStructureElement
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.NonReanalyzableDeclarationStructureElement
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.ReanalyzableStructureElement
@@ -62,6 +64,7 @@ abstract class AbstractFirContextCollectionTest : AbstractLowLevelApiSingleFileT
is NonReanalyzableDeclarationStructureElement -> fir
is ReanalyzableStructureElement<*, *> -> firSymbol.fir
is RootStructureElement -> firFile
is DanglingTopLevelModifierListStructureElement -> fir
}
@@ -36,6 +36,18 @@ public class FirContextCollectionTestGenerated extends AbstractFirContextCollect
runTest("analysis/low-level-api-fir/testdata/fileStructure/classMemberProperty.kt");
}
@Test
@TestMetadata("danglingAnnotationClassLevel.kt")
public void testDanglingAnnotationClassLevel() throws Exception {
runTest("analysis/low-level-api-fir/testdata/fileStructure/danglingAnnotationClassLevel.kt");
}
@Test
@TestMetadata("danglingAnnotationTopLevel.kt")
public void testDanglingAnnotationTopLevel() throws Exception {
runTest("analysis/low-level-api-fir/testdata/fileStructure/danglingAnnotationTopLevel.kt");
}
@Test
@TestMetadata("declarationsInPropertyInit.kt")
public void testDeclarationsInPropertyInit() throws Exception {
@@ -8,7 +8,9 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure
import com.intellij.psi.PsiComment
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiErrorElement
import com.intellij.psi.impl.source.tree.LeafPsiElement
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.analysis.low.level.api.fir.state.LLFirSourceResolveSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getFirResolveSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirResolvableModuleSession
@@ -32,7 +34,8 @@ abstract class AbstractFileStructureTest : AbstractLowLevelApiSingleFileTest() {
val comment = structureElement.createComment()
when (ktDeclaration) {
is KtClassOrObject -> {
val lBrace = ktDeclaration.body?.lBrace
val body = ktDeclaration.body
val lBrace = body?.lBrace
if (lBrace != null) {
elementToComment[lBrace] = comment
} else {
@@ -62,6 +65,13 @@ abstract class AbstractFileStructureTest : AbstractLowLevelApiSingleFileTest() {
}
}
PsiTreeUtil.getChildrenOfTypeAsList(ktFile, KtModifierList::class.java).forEach {
if (it.nextSibling is PsiErrorElement) {
val structureElement = declarationToStructureElement[ktFile] ?: return@forEach
val comment = structureElement.createComment()
elementToComment[it] = comment
}
}
val text = buildString {
ktFile.accept(object : PsiElementVisitor() {
@@ -36,6 +36,18 @@ public class FileStructureTestGenerated extends AbstractFileStructureTest {
runTest("analysis/low-level-api-fir/testdata/fileStructure/classMemberProperty.kt");
}
@Test
@TestMetadata("danglingAnnotationClassLevel.kt")
public void testDanglingAnnotationClassLevel() throws Exception {
runTest("analysis/low-level-api-fir/testdata/fileStructure/danglingAnnotationClassLevel.kt");
}
@Test
@TestMetadata("danglingAnnotationTopLevel.kt")
public void testDanglingAnnotationTopLevel() throws Exception {
runTest("analysis/low-level-api-fir/testdata/fileStructure/danglingAnnotationTopLevel.kt");
}
@Test
@TestMetadata("declarationsInPropertyInit.kt")
public void testDeclarationsInPropertyInit() throws Exception {