[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 @Nested
@TestMetadata("analysis/analysis-api/testData/referenceResolve/delegatedPropertyAccessors") @TestMetadata("analysis/analysis-api/testData/referenceResolve/delegatedPropertyAccessors")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@@ -1609,6 +1643,12 @@ public class Fe10IdeNormalAnalysisSourceModuleReferenceResolveTestGenerated exte
runTest("analysis/analysis-api/testData/referenceResolve/withErrors/CoroutineSuspensionPoint.kt"); 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 @Test
@TestMetadata("DeprecatedHidden.kt") @TestMetadata("DeprecatedHidden.kt")
public void testDeprecatedHidden() throws Exception { 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 @Nested
@TestMetadata("analysis/analysis-api/testData/referenceResolve/delegatedPropertyAccessors") @TestMetadata("analysis/analysis-api/testData/referenceResolve/delegatedPropertyAccessors")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@@ -1609,6 +1643,12 @@ public class FirIdeDependentAnalysisSourceModuleReferenceResolveTestGenerated ex
runTest("analysis/analysis-api/testData/referenceResolve/withErrors/CoroutineSuspensionPoint.kt"); 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 @Test
@TestMetadata("DeprecatedHidden.kt") @TestMetadata("DeprecatedHidden.kt")
public void testDeprecatedHidden() throws Exception { 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 @Nested
@TestMetadata("analysis/analysis-api/testData/referenceResolve/delegatedPropertyAccessors") @TestMetadata("analysis/analysis-api/testData/referenceResolve/delegatedPropertyAccessors")
@TestDataPath("$PROJECT_ROOT") @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 @Nested
@TestMetadata("analysis/analysis-api/testData/referenceResolve/delegatedPropertyAccessors") @TestMetadata("analysis/analysis-api/testData/referenceResolve/delegatedPropertyAccessors")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@@ -1609,6 +1643,12 @@ public class FirIdeNormalAnalysisSourceModuleReferenceResolveTestGenerated exten
runTest("analysis/analysis-api/testData/referenceResolve/withErrors/CoroutineSuspensionPoint.kt"); 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 @Test
@TestMetadata("DeprecatedHidden.kt") @TestMetadata("DeprecatedHidden.kt")
public void testDeprecatedHidden() throws Exception { 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 @Nested
@TestMetadata("analysis/analysis-api/testData/referenceResolve/delegatedPropertyAccessors") @TestMetadata("analysis/analysis-api/testData/referenceResolve/delegatedPropertyAccessors")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@@ -1609,6 +1643,12 @@ public class FirStandaloneNormalAnalysisSourceModuleReferenceResolveTestGenerate
runTest("analysis/analysis-api/testData/referenceResolve/withErrors/CoroutineSuspensionPoint.kt"); 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 @Test
@TestMetadata("DeprecatedHidden.kt") @TestMetadata("DeprecatedHidden.kt")
public void testDeprecatedHidden() throws Exception { 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.*
import org.jetbrains.kotlin.fir.declarations.utils.classId import org.jetbrains.kotlin.fir.declarations.utils.classId
import org.jetbrains.kotlin.fir.declarations.utils.isLocal 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.java.javaSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.firProvider import org.jetbrains.kotlin.fir.resolve.providers.firProvider
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLookupTagWithFixedSymbol 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( class FirDesignationWithFile(
path: List<FirRegularClass>, 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.firProvider::getFirClassifierByFqName)
?: outerClassId?.let(target.moduleData.session.javaSymbolProvider::getClassLikeSymbolByClassId)?.fir ?: 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 else -> return null
} ?: return emptyList() } ?: return emptyList()
@@ -12,10 +12,8 @@ import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirElementWithResolvePhase import org.jetbrains.kotlin.fir.FirElementWithResolvePhase
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollectorVisitor
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration import org.jetbrains.kotlin.fir.containingClass
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.renderWithType import org.jetbrains.kotlin.fir.renderWithType
import org.jetbrains.kotlin.fir.resolve.SessionHolder import org.jetbrains.kotlin.fir.resolve.SessionHolder
@@ -61,6 +59,7 @@ internal object PersistenceContextCollector {
val isLocal = when (declaration) { val isLocal = when (declaration) {
is FirClassLikeDeclaration -> declaration.symbol.classId.isLocal is FirClassLikeDeclaration -> declaration.symbol.classId.isLocal
is FirCallableDeclaration -> declaration.symbol.callableId.isLocal is FirCallableDeclaration -> declaration.symbol.callableId.isLocal
is FirDanglingModifierList -> declaration.containingClass()?.classId?.isLocal == true
else -> error("Unsupported declaration ${declaration.renderWithType()}") else -> error("Unsupported declaration ${declaration.renderWithType()}")
} }
require(!isLocal) { require(!isLocal) {
@@ -6,12 +6,17 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure package org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure
import com.intellij.psi.PsiElement 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.LLFirModuleResolveComponents
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.DiagnosticCheckerFilter 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.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.low.level.api.fir.util.findSourceNonLocalFirDeclaration
import org.jetbrains.kotlin.analysis.utils.printer.getElementTextInContext import org.jetbrains.kotlin.analysis.utils.printer.getElementTextInContext
import org.jetbrains.kotlin.diagnostics.KtPsiDiagnostic 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.FirFile
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.resolve.providers.firProvider 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 firProvider = firFile.moduleData.session.firProvider
private val structureElements = ConcurrentHashMap<KtAnnotated, FileStructureElement>() private val structureElements = ConcurrentHashMap<KtElement, FileStructureElement>()
fun getStructureElementFor(element: 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) return getStructureElementForDeclaration(container)
} }
private fun getStructureElementForDeclaration(declaration: KtAnnotated): FileStructureElement { private fun getStructureElementForDeclaration(declaration: KtElement): FileStructureElement {
@Suppress("CANNOT_CHECK_FOR_ERASED") @Suppress("CANNOT_CHECK_FOR_ERASED")
val structureElement = structureElements.compute(declaration) { _, structureElement -> val structureElement = structureElements.compute(declaration) { _, structureElement ->
when { when {
@@ -91,6 +105,12 @@ internal class FileStructure private constructor(
dcl.acceptChildren(this) dcl.acceptChildren(this)
} }
} }
override fun visitModifierList(list: KtModifierList) {
if (list.parent == ktFile) {
structureElements += getStructureElementFor(list)
}
}
}) })
return structureElements return structureElements
@@ -112,8 +132,15 @@ internal class FileStructure private constructor(
) )
} }
private fun createStructureElement(container: KtAnnotated): FileStructureElement = when (container) { private fun createDanglingModifierListStructure(container: KtElement): FileStructureElement {
is KtFile -> { 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) val firFile = moduleComponents.firFileBuilder.buildRawFirFileWithCaching(ktFile)
moduleComponents.firModuleLazyDeclarationResolver.lazyResolve( moduleComponents.firModuleLazyDeclarationResolver.lazyResolve(
target = firFile.annotationsContainer, target = firFile.annotationsContainer,
@@ -123,7 +150,8 @@ internal class FileStructure private constructor(
RootStructureElement(firFile, container, moduleComponents) 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") 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( internal class RootStructureElement(
firFile: FirFile, 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.DesugaredPrefixNameReference ||
it.kind == KtFakeSourceElementKind.DesugaredPostfixNameReference || it.kind == KtFakeSourceElementKind.DesugaredPostfixNameReference ||
it.kind == KtFakeSourceElementKind.SmartCastExpression || it.kind == KtFakeSourceElementKind.SmartCastExpression ||
it.kind == KtFakeSourceElementKind.DanglingModifierList ||
it.isSourceForCompoundAccess(element) it.isSourceForCompoundAccess(element)
}.psi as? KtElement }.psi as? KtElement
?: return ?: 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.transformers.LLFirLazyTransformerExecutor
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkCanceled 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.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.low.level.api.fir.util.withFirEntry
import org.jetbrains.kotlin.analysis.utils.errors.rethrowExceptionWithDetails import org.jetbrains.kotlin.analysis.utils.errors.rethrowExceptionWithDetails
import org.jetbrains.kotlin.fir.FirElement 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.providers.firProvider
import org.jetbrains.kotlin.fir.resolve.transformers.FirImportResolveTransformer import org.jetbrains.kotlin.fir.resolve.transformers.FirImportResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirTowerDataContextCollector 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.KtClassBody
import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtEnumEntry import org.jetbrains.kotlin.psi.KtEnumEntry
@@ -224,7 +230,16 @@ internal class LLFirModuleLazyDeclarationResolver(val moduleComponents: LLFirMod
val designation: FirDesignationWithFile val designation: FirDesignationWithFile
val neededPhase: FirResolvePhase 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 designation = requestedDeclarationDesignation
neededPhase = toPhase neededPhase = toPhase
} else { } else {
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.analysis.low.level.api.fir.util 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.FirElementWithResolvePhase
import org.jetbrains.kotlin.fir.FirFileAnnotationsContainer import org.jetbrains.kotlin.fir.FirFileAnnotationsContainer
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
@@ -20,6 +21,7 @@ fun FirElementWithResolvePhase.getContainingFile(): FirFile? {
is FirValueParameter -> containingFunctionSymbol.fir.getContainingFile() is FirValueParameter -> containingFunctionSymbol.fir.getContainingFile()
is FirCallableDeclaration -> provider.getFirCallableContainerFile(symbol) is FirCallableDeclaration -> provider.getFirCallableContainerFile(symbol)
is FirClassLikeDeclaration -> provider.getFirClassifierContainerFile(symbol) is FirClassLikeDeclaration -> provider.getFirClassifierContainerFile(symbol)
is FirDanglingModifierList -> null
else -> errorWithFirSpecificEntries("Unsupported declaration ${this::class.java}", fir = this) else -> errorWithFirSpecificEntries("Unsupported declaration ${this::class.java}", fir = this)
} }
} }
@@ -28,7 +28,7 @@ internal fun KtDeclaration.findSourceNonLocalFirDeclaration(
): FirDeclaration { ): FirDeclaration {
//TODO test what way faster //TODO test what way faster
findSourceNonLocalFirDeclarationByProvider(firFileBuilder, provider, containerFirFile)?.let { return it } 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) errorWithFirSpecificEntries("No fir element was found for", psi = this)
} }
@@ -56,14 +56,15 @@ internal inline fun <reified F : FirDeclaration> KtDeclaration.findFirDeclaratio
return fir return fir
} }
private fun KtDeclaration.findSourceOfNonLocalFirDeclarationByTraversingWholeTree( internal fun KtElement.findSourceByTraversingWholeTree(
firFileBuilder: LLFirFileBuilder, firFileBuilder: LLFirFileBuilder,
containerFirFile: FirFile?, containerFirFile: FirFile?,
): FirDeclaration? { ): FirDeclaration? {
val firFile = containerFirFile ?: firFileBuilder.buildRawFirFileWithCaching(containingKtFile) 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 -> 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"); 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 @Test
@TestMetadata("delegates.kt") @TestMetadata("delegates.kt")
public void testDelegates() throws Exception { 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"); 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 @Test
@TestMetadata("fileAnnotation.kt") @TestMetadata("fileAnnotation.kt")
public void testFileAnnotation() throws Exception { public void testFileAnnotation() throws Exception {
@@ -572,6 +584,12 @@ public class GetOrBuildFirTestGenerated extends AbstractGetOrBuildFirTest {
public void testJavaClassLiteral() throws Exception { public void testJavaClassLiteral() throws Exception {
runTest("analysis/low-level-api-fir/testdata/getOrBuildFir/invalidCode/javaClassLiteral.kt"); 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 @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.api.getOrBuildFirFile
import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.BeforeElementDiagnosticCollectionHandler 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.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.FileStructureElement
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.NonReanalyzableDeclarationStructureElement import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.NonReanalyzableDeclarationStructureElement
import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.ReanalyzableStructureElement import org.jetbrains.kotlin.analysis.low.level.api.fir.file.structure.ReanalyzableStructureElement
@@ -62,6 +64,7 @@ abstract class AbstractFirContextCollectionTest : AbstractLowLevelApiSingleFileT
is NonReanalyzableDeclarationStructureElement -> fir is NonReanalyzableDeclarationStructureElement -> fir
is ReanalyzableStructureElement<*, *> -> firSymbol.fir is ReanalyzableStructureElement<*, *> -> firSymbol.fir
is RootStructureElement -> firFile 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"); 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 @Test
@TestMetadata("declarationsInPropertyInit.kt") @TestMetadata("declarationsInPropertyInit.kt")
public void testDeclarationsInPropertyInit() throws Exception { 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.PsiComment
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.PsiElementVisitor import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiErrorElement
import com.intellij.psi.impl.source.tree.LeafPsiElement 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.state.LLFirSourceResolveSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getFirResolveSession import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getFirResolveSession
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirResolvableModuleSession import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.LLFirResolvableModuleSession
@@ -32,7 +34,8 @@ abstract class AbstractFileStructureTest : AbstractLowLevelApiSingleFileTest() {
val comment = structureElement.createComment() val comment = structureElement.createComment()
when (ktDeclaration) { when (ktDeclaration) {
is KtClassOrObject -> { is KtClassOrObject -> {
val lBrace = ktDeclaration.body?.lBrace val body = ktDeclaration.body
val lBrace = body?.lBrace
if (lBrace != null) { if (lBrace != null) {
elementToComment[lBrace] = comment elementToComment[lBrace] = comment
} else { } 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 { val text = buildString {
ktFile.accept(object : PsiElementVisitor() { ktFile.accept(object : PsiElementVisitor() {
@@ -36,6 +36,18 @@ public class FileStructureTestGenerated extends AbstractFileStructureTest {
runTest("analysis/low-level-api-fir/testdata/fileStructure/classMemberProperty.kt"); 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 @Test
@TestMetadata("declarationsInPropertyInit.kt") @TestMetadata("declarationsInPropertyInit.kt")
public void testDeclarationsInPropertyInit() throws Exception { public void testDeclarationsInPropertyInit() throws Exception {
@@ -154,7 +154,7 @@ object FirOptInUsageBaseChecker {
fir.loadCallableSpecificExperimentalities(this, context, visited, fromSetter, dispatchReceiverType, result) fir.loadCallableSpecificExperimentalities(this, context, visited, fromSetter, dispatchReceiverType, result)
is FirClassLikeDeclaration -> is FirClassLikeDeclaration ->
fir.loadClassLikeSpecificExperimentalities(this, context, visited, result) fir.loadClassLikeSpecificExperimentalities(this, context, visited, result)
is FirAnonymousInitializer, is FirFile, is FirTypeParameter, is FirScript -> {} is FirAnonymousInitializer, is FirDanglingModifierList, is FirFile, is FirTypeParameter, is FirScript -> {}
} }
fir.loadExperimentalitiesFromAnnotationTo(session, result, fromSupertype) fir.loadExperimentalitiesFromAnnotationTo(session, result, fromSupertype)
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.* import org.jetbrains.kotlin.fir.declarations.builder.*
import org.jetbrains.kotlin.fir.declarations.impl.* import org.jetbrains.kotlin.fir.declarations.impl.*
import org.jetbrains.kotlin.fir.declarations.utils.* import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.diagnostics.ConeDanglingModifierOnTopLevel
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
@@ -97,6 +98,7 @@ class DeclarationsConverter(
var fileAnnotationContainer: FirFileAnnotationsContainer? = null var fileAnnotationContainer: FirFileAnnotationsContainer? = null
val importList = mutableListOf<FirImport>() val importList = mutableListOf<FirImport>()
val firDeclarationList = mutableListOf<FirDeclaration>() val firDeclarationList = mutableListOf<FirDeclaration>()
val modifierList = mutableListOf<LighterASTNode>()
context.packageFqName = FqName.ROOT context.packageFqName = FqName.ROOT
var packageDirective: FirPackageDirective? = null var packageDirective: FirPackageDirective? = null
file.forEachChildren { child -> file.forEachChildren { child ->
@@ -116,9 +118,14 @@ class DeclarationsConverter(
SCRIPT -> { SCRIPT -> {
// TODO: scripts aren't supported yet // TODO: scripts aren't supported yet
} }
MODIFIER_LIST -> modifierList += child
} }
} }
modifierList.forEach {
firDeclarationList += buildErrorTopLevelDeclarationForDanglingModifierList(it)
}
return buildFile { return buildFile {
symbol = fileSymbol symbol = fileSymbol
source = file.toFirSourceElement() source = file.toFirSourceElement()
@@ -839,7 +846,8 @@ class DeclarationsConverter(
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseEnumClassBody * @see org.jetbrains.kotlin.parsing.KotlinParsing.parseEnumClassBody
*/ */
private fun convertClassBody(classBody: LighterASTNode, classWrapper: ClassWrapper): List<FirDeclaration> { private fun convertClassBody(classBody: LighterASTNode, classWrapper: ClassWrapper): List<FirDeclaration> {
return classBody.forEachChildrenReturnList { node, container -> val modifierLists = mutableListOf<LighterASTNode>()
var firDeclarations = classBody.forEachChildrenReturnList { node, container ->
@Suppress("RemoveRedundantQualifierName") @Suppress("RemoveRedundantQualifierName")
when (node.tokenType) { when (node.tokenType) {
ENUM_ENTRY -> container += convertEnumEntry(node, classWrapper) ENUM_ENTRY -> container += convertEnumEntry(node, classWrapper)
@@ -850,8 +858,22 @@ class DeclarationsConverter(
OBJECT_DECLARATION -> container += convertClass(node) OBJECT_DECLARATION -> container += convertClass(node)
CLASS_INITIALIZER -> container += convertAnonymousInitializer(node) //anonymousInitializer CLASS_INITIALIZER -> container += convertAnonymousInitializer(node) //anonymousInitializer
SECONDARY_CONSTRUCTOR -> container += convertSecondaryConstructor(node, classWrapper) SECONDARY_CONSTRUCTOR -> container += convertSecondaryConstructor(node, classWrapper)
MODIFIER_LIST -> modifierLists += node
} }
} }
for (node in modifierLists) {
firDeclarations += buildErrorTopLevelDeclarationForDanglingModifierList(node)
}
return firDeclarations
}
private fun buildErrorTopLevelDeclarationForDanglingModifierList(node: LighterASTNode) = buildDanglingModifierList {
this.source = node.toFirSourceElement(KtFakeSourceElementKind.DanglingModifierList)
moduleData = baseModuleData
origin = FirDeclarationOrigin.Source
diagnostic = ConeDanglingModifierOnTopLevel
symbol = FirDanglingModifierSymbol()
annotations += convertModifierList(node).annotations
} }
/** /**
@@ -76,6 +76,16 @@ public class LightTree2FirConverterTestCaseGenerated extends AbstractLightTree2F
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/contextReceivers.kt"); runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/contextReceivers.kt");
} }
@TestMetadata("danglingAnnotationsClassLevel.kt")
public void testDanglingAnnotationsClassLevel() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/danglingAnnotationsClassLevel.kt");
}
@TestMetadata("danglingAnnotationsFileLevel.kt")
public void testDanglingAnnotationsFileLevel() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/danglingAnnotationsFileLevel.kt");
}
@TestMetadata("delegates.kt") @TestMetadata("delegates.kt")
public void testDelegates() throws Exception { public void testDelegates() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/delegates.kt"); runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/delegates.kt");
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.builder
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.tree.IElementType import com.intellij.psi.tree.IElementType
import com.intellij.util.AstLoadingFilter import com.intellij.util.AstLoadingFilter
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.* import org.jetbrains.kotlin.*
import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.builtins.StandardNames.BACKING_FIELD import org.jetbrains.kotlin.builtins.StandardNames.BACKING_FIELD
@@ -1057,6 +1058,10 @@ open class RawFirBuilder(
else -> declaration.convert() else -> declaration.convert()
} }
} }
for (danglingModifierList in PsiTreeUtil.getChildrenOfTypeAsList(file, KtModifierList::class.java)) {
declarations += buildErrorTopLevelDeclarationForDanglingModifierList(danglingModifierList)
}
} }
} }
@@ -1269,7 +1274,14 @@ open class RawFirBuilder(
classOrObject, classOrObject,
this, this,
typeParameters typeParameters
), )
)
}
for (danglingModifier in PsiTreeUtil.getChildrenOfTypeAsList(classOrObject.body, KtModifierList::class.java)) {
addDeclaration(
buildErrorTopLevelDeclarationForDanglingModifierList(danglingModifier).apply {
containingClassAttr = currentDispatchReceiverType()?.lookupTag
}
) )
} }
@@ -1361,6 +1373,12 @@ open class RawFirBuilder(
ownerTypeParameters = emptyList() ownerTypeParameters = emptyList()
) )
} }
for (danglingModifier in PsiTreeUtil.getChildrenOfTypeAsList(objectDeclaration.body, KtModifierList::class.java)) {
declarations += buildErrorTopLevelDeclarationForDanglingModifierList(danglingModifier).apply {
containingClassAttr = currentDispatchReceiverType()?.lookupTag
}
}
}.also { }.also {
it.delegateFieldsMap = delegatedFieldsMap it.delegateFieldsMap = delegatedFieldsMap
} }
@@ -2730,6 +2748,17 @@ open class RawFirBuilder(
this += typeArgument.convert<FirTypeProjection>() this += typeArgument.convert<FirTypeProjection>()
} }
} }
private fun buildErrorTopLevelDeclarationForDanglingModifierList(modifierList : KtModifierList) = buildDanglingModifierList {
this.source = modifierList.toFirSourceElement(KtFakeSourceElementKind.DanglingModifierList)
moduleData = baseModuleData
origin = FirDeclarationOrigin.Source
diagnostic = ConeDanglingModifierOnTopLevel
symbol = FirDanglingModifierSymbol()
for (annotationEntry in modifierList.getAnnotationEntries()) {
annotations += annotationEntry.convert<FirAnnotation>()
}
}
} }
} }
@@ -0,0 +1,22 @@
class A {
@Suppress("") @MustBeDocumented
}
class B {
@Suppress("") @MustBeDocumented
}
class Outer {
class Inner {
@Suppress("") @MustBeDocumented
}
fun withLocal() {
class Local {
@Suppress("") @MustBeDocumented
}
val r : I = object : I {
@Suppress("") @MustBeDocumented
}
}
}
interface I {}
@@ -0,0 +1,33 @@
FILE: danglingAnnotationsClassLevel.kt
public? final? class A : R|kotlin/Any| {
public? constructor(): R|A| {
super<R|kotlin/Any|>()
}
@Suppress(String()) @MustBeDocumented() <DANGLING MODIFIER: Top level declaration expected>
}
public? final? class B : R|kotlin/Any| {
public? constructor(): R|B| {
super<R|kotlin/Any|>()
}
@Suppress(String()) @MustBeDocumented() <DANGLING MODIFIER: Top level declaration expected>
}
public? final? class Outer : R|kotlin/Any| {
public? constructor(): R|Outer| {
super<R|kotlin/Any|>()
}
public? final? class Inner : R|kotlin/Any| {
public? constructor(): R|Outer.Inner| {
super<R|kotlin/Any|>()
}
@Suppress(String()) @MustBeDocumented() <DANGLING MODIFIER: Top level declaration expected>
}
public? final? fun withLocal(): R|kotlin/Unit| { LAZY_BLOCK }
}
public? final? interface I : R|kotlin/Any| {
}
@@ -0,0 +1,50 @@
FILE: danglingAnnotationsClassLevel.kt
public? final? class A : R|kotlin/Any| {
public? [ContainingClassKey=A] constructor(): R|A| {
super<R|kotlin/Any|>()
}
@Suppress(String()) @MustBeDocumented() <DANGLING MODIFIER: Top level declaration expected>
}
public? final? class B : R|kotlin/Any| {
public? [ContainingClassKey=B] constructor(): R|B| {
super<R|kotlin/Any|>()
}
@Suppress(String()) @MustBeDocumented() <DANGLING MODIFIER: Top level declaration expected>
}
public? final? class Outer : R|kotlin/Any| {
public? [ContainingClassKey=Outer] constructor(): R|Outer| {
super<R|kotlin/Any|>()
}
public? final? class Inner : R|kotlin/Any| {
public? [ContainingClassKey=Inner] constructor(): R|Outer.Inner| {
super<R|kotlin/Any|>()
}
@Suppress(String()) @MustBeDocumented() <DANGLING MODIFIER: Top level declaration expected>
}
public? final? fun withLocal(): R|kotlin/Unit| {
local final? [ContainingClassKey=Outer] class Local : R|kotlin/Any| {
public? [ContainingClassKey=Local] constructor(): R|Outer.Local| {
super<R|kotlin/Any|>()
}
@Suppress(String()) @MustBeDocumented() <DANGLING MODIFIER: Top level declaration expected>
}
lval r: I = object : I {
private [ContainingClassKey=<anonymous>] constructor(): R|<anonymous>| {
super<<implicit>>()
}
@Suppress(String()) @MustBeDocumented() <DANGLING MODIFIER: Top level declaration expected>
}
}
}
public? final? interface I : R|kotlin/Any| {
}
@@ -0,0 +1 @@
@Suppress("") @MustBeDocumented
@@ -0,0 +1,2 @@
FILE: danglingAnnotationsFileLevel.kt
@Suppress(String()) @MustBeDocumented() <DANGLING MODIFIER: Top level declaration expected>
@@ -0,0 +1,2 @@
FILE: danglingAnnotationsFileLevel.kt
@Suppress(String()) @MustBeDocumented() <DANGLING MODIFIER: Top level declaration expected>
@@ -76,6 +76,16 @@ public class RawFirBuilderLazyBodiesTestCaseGenerated extends AbstractRawFirBuil
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/contextReceivers.kt"); runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/contextReceivers.kt");
} }
@TestMetadata("danglingAnnotationsClassLevel.kt")
public void testDanglingAnnotationsClassLevel() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/danglingAnnotationsClassLevel.kt");
}
@TestMetadata("danglingAnnotationsFileLevel.kt")
public void testDanglingAnnotationsFileLevel() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/danglingAnnotationsFileLevel.kt");
}
@TestMetadata("delegates.kt") @TestMetadata("delegates.kt")
public void testDelegates() throws Exception { public void testDelegates() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/delegates.kt"); runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/delegates.kt");
@@ -76,6 +76,16 @@ public class RawFirBuilderTestCaseGenerated extends AbstractRawFirBuilderTestCas
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/contextReceivers.kt"); runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/contextReceivers.kt");
} }
@TestMetadata("danglingAnnotationsClassLevel.kt")
public void testDanglingAnnotationsClassLevel() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/danglingAnnotationsClassLevel.kt");
}
@TestMetadata("danglingAnnotationsFileLevel.kt")
public void testDanglingAnnotationsFileLevel() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/danglingAnnotationsFileLevel.kt");
}
@TestMetadata("delegates.kt") @TestMetadata("delegates.kt")
public void testDelegates() throws Exception { public void testDelegates() throws Exception {
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/delegates.kt"); runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/delegates.kt");
@@ -18,10 +18,7 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl
import org.jetbrains.kotlin.fir.declarations.utils.addDeclaration import org.jetbrains.kotlin.fir.declarations.utils.addDeclaration
import org.jetbrains.kotlin.fir.declarations.utils.isCompanion import org.jetbrains.kotlin.fir.declarations.utils.isCompanion
import org.jetbrains.kotlin.fir.declarations.utils.isLocal import org.jetbrains.kotlin.fir.declarations.utils.isLocal
import org.jetbrains.kotlin.fir.diagnostics.ConeDestructuringDeclarationsOnTopLevel import org.jetbrains.kotlin.fir.diagnostics.*
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.ConeUnderscoreIsReserved
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.* import org.jetbrains.kotlin.fir.expressions.builder.*
import org.jetbrains.kotlin.fir.references.FirReference import org.jetbrains.kotlin.fir.references.FirReference
@@ -0,0 +1,43 @@
/*
* Copyright 2010-2022 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.declarations
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.FirDiagnosticHolder
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.symbols.impl.FirDanglingModifierSymbol
import org.jetbrains.kotlin.fir.visitors.*
/*
* This file was generated automatically
* DO NOT MODIFY IT MANUALLY
*/
abstract class FirDanglingModifierList : FirDeclaration(), FirDiagnosticHolder {
abstract override val source: KtSourceElement?
abstract override val resolvePhase: FirResolvePhase
abstract override val annotations: List<FirAnnotation>
abstract override val moduleData: FirModuleData
abstract override val origin: FirDeclarationOrigin
abstract override val attributes: FirDeclarationAttributes
abstract override val diagnostic: ConeDiagnostic
abstract override val symbol: FirDanglingModifierSymbol
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitDanglingModifierList(this, data)
@Suppress("UNCHECKED_CAST")
override fun <E : FirElement, D> transform(transformer: FirTransformer<D>, data: D): E =
transformer.transformDanglingModifierList(this, data) as E
abstract override fun replaceResolvePhase(newResolvePhase: FirResolvePhase)
abstract override fun replaceAnnotations(newAnnotations: List<FirAnnotation>)
abstract override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirDanglingModifierList
}
@@ -0,0 +1,63 @@
/*
* Copyright 2010-2022 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.
*/
@file:Suppress("DuplicatedCode")
package org.jetbrains.kotlin.fir.declarations.builder
import kotlin.contracts.*
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.builder.FirAnnotationContainerBuilder
import org.jetbrains.kotlin.fir.builder.FirBuilderDsl
import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty
import org.jetbrains.kotlin.fir.declarations.FirDanglingModifierList
import org.jetbrains.kotlin.fir.declarations.FirDeclarationAttributes
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.impl.FirDanglingModifierListImpl
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.symbols.impl.FirDanglingModifierSymbol
import org.jetbrains.kotlin.fir.visitors.*
/*
* This file was generated automatically
* DO NOT MODIFY IT MANUALLY
*/
@FirBuilderDsl
class FirDanglingModifierListBuilder : FirAnnotationContainerBuilder {
override var source: KtSourceElement? = null
var resolvePhase: FirResolvePhase = FirResolvePhase.RAW_FIR
override val annotations: MutableList<FirAnnotation> = mutableListOf()
lateinit var moduleData: FirModuleData
lateinit var origin: FirDeclarationOrigin
var attributes: FirDeclarationAttributes = FirDeclarationAttributes()
lateinit var diagnostic: ConeDiagnostic
lateinit var symbol: FirDanglingModifierSymbol
override fun build(): FirDanglingModifierList {
return FirDanglingModifierListImpl(
source,
resolvePhase,
annotations.toMutableOrEmpty(),
moduleData,
origin,
attributes,
diagnostic,
symbol,
)
}
}
@OptIn(ExperimentalContracts::class)
inline fun buildDanglingModifierList(init: FirDanglingModifierListBuilder.() -> Unit): FirDanglingModifierList {
contract {
callsInPlace(init, kotlin.contracts.InvocationKind.EXACTLY_ONCE)
}
return FirDanglingModifierListBuilder().apply(init).build()
}
@@ -0,0 +1,64 @@
/*
* Copyright 2010-2022 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.
*/
@file:Suppress("DuplicatedCode")
package org.jetbrains.kotlin.fir.declarations.impl
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.declarations.FirDanglingModifierList
import org.jetbrains.kotlin.fir.declarations.FirDeclarationAttributes
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.symbols.impl.FirDanglingModifierSymbol
import org.jetbrains.kotlin.fir.visitors.*
import org.jetbrains.kotlin.fir.MutableOrEmptyList
import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty
/*
* This file was generated automatically
* DO NOT MODIFY IT MANUALLY
*/
internal class FirDanglingModifierListImpl(
override val source: KtSourceElement?,
@Volatile
override var resolvePhase: FirResolvePhase,
override var annotations: MutableOrEmptyList<FirAnnotation>,
override val moduleData: FirModuleData,
override val origin: FirDeclarationOrigin,
override val attributes: FirDeclarationAttributes,
override val diagnostic: ConeDiagnostic,
override val symbol: FirDanglingModifierSymbol,
) : FirDanglingModifierList() {
init {
symbol.bind(this)
}
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
annotations.forEach { it.accept(visitor, data) }
}
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirDanglingModifierListImpl {
transformAnnotations(transformer, data)
return this
}
override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirDanglingModifierListImpl {
annotations.transformInplace(transformer, data)
return this
}
override fun replaceResolvePhase(newResolvePhase: FirResolvePhase) {
resolvePhase = newResolvePhase
}
override fun replaceAnnotations(newAnnotations: List<FirAnnotation>) {
annotations = newAnnotations.toMutableOrEmpty()
}
}
@@ -95,6 +95,7 @@ import org.jetbrains.kotlin.fir.expressions.FirClassReferenceExpression
import org.jetbrains.kotlin.fir.expressions.FirErrorExpression import org.jetbrains.kotlin.fir.expressions.FirErrorExpression
import org.jetbrains.kotlin.fir.declarations.FirErrorFunction import org.jetbrains.kotlin.fir.declarations.FirErrorFunction
import org.jetbrains.kotlin.fir.declarations.FirErrorProperty import org.jetbrains.kotlin.fir.declarations.FirErrorProperty
import org.jetbrains.kotlin.fir.declarations.FirDanglingModifierList
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirQualifiedErrorAccessExpression import org.jetbrains.kotlin.fir.expressions.FirQualifiedErrorAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression
@@ -95,6 +95,7 @@ import org.jetbrains.kotlin.fir.expressions.FirClassReferenceExpression
import org.jetbrains.kotlin.fir.expressions.FirErrorExpression import org.jetbrains.kotlin.fir.expressions.FirErrorExpression
import org.jetbrains.kotlin.fir.declarations.FirErrorFunction import org.jetbrains.kotlin.fir.declarations.FirErrorFunction
import org.jetbrains.kotlin.fir.declarations.FirErrorProperty import org.jetbrains.kotlin.fir.declarations.FirErrorProperty
import org.jetbrains.kotlin.fir.declarations.FirDanglingModifierList
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirQualifiedErrorAccessExpression import org.jetbrains.kotlin.fir.expressions.FirQualifiedErrorAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression
@@ -95,6 +95,7 @@ import org.jetbrains.kotlin.fir.expressions.FirClassReferenceExpression
import org.jetbrains.kotlin.fir.expressions.FirErrorExpression import org.jetbrains.kotlin.fir.expressions.FirErrorExpression
import org.jetbrains.kotlin.fir.declarations.FirErrorFunction import org.jetbrains.kotlin.fir.declarations.FirErrorFunction
import org.jetbrains.kotlin.fir.declarations.FirErrorProperty import org.jetbrains.kotlin.fir.declarations.FirErrorProperty
import org.jetbrains.kotlin.fir.declarations.FirDanglingModifierList
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirQualifiedErrorAccessExpression import org.jetbrains.kotlin.fir.expressions.FirQualifiedErrorAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression
@@ -514,6 +515,10 @@ abstract class FirTransformer<in D> : FirVisitor<FirElement, D>() {
return transformElement(errorProperty, data) return transformElement(errorProperty, data)
} }
open fun transformDanglingModifierList(danglingModifierList: FirDanglingModifierList, data: D): FirDanglingModifierList {
return transformElement(danglingModifierList, data)
}
open fun transformQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression, data: D): FirStatement { open fun transformQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression, data: D): FirStatement {
return transformElement(qualifiedAccessExpression, data) return transformElement(qualifiedAccessExpression, data)
} }
@@ -1086,6 +1091,10 @@ abstract class FirTransformer<in D> : FirVisitor<FirElement, D>() {
return transformErrorProperty(errorProperty, data) return transformErrorProperty(errorProperty, data)
} }
final override fun visitDanglingModifierList(danglingModifierList: FirDanglingModifierList, data: D): FirDanglingModifierList {
return transformDanglingModifierList(danglingModifierList, data)
}
final override fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression, data: D): FirStatement { final override fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression, data: D): FirStatement {
return transformQualifiedAccessExpression(qualifiedAccessExpression, data) return transformQualifiedAccessExpression(qualifiedAccessExpression, data)
} }
@@ -95,6 +95,7 @@ import org.jetbrains.kotlin.fir.expressions.FirClassReferenceExpression
import org.jetbrains.kotlin.fir.expressions.FirErrorExpression import org.jetbrains.kotlin.fir.expressions.FirErrorExpression
import org.jetbrains.kotlin.fir.declarations.FirErrorFunction import org.jetbrains.kotlin.fir.declarations.FirErrorFunction
import org.jetbrains.kotlin.fir.declarations.FirErrorProperty import org.jetbrains.kotlin.fir.declarations.FirErrorProperty
import org.jetbrains.kotlin.fir.declarations.FirDanglingModifierList
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirQualifiedErrorAccessExpression import org.jetbrains.kotlin.fir.expressions.FirQualifiedErrorAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression
@@ -335,6 +336,8 @@ abstract class FirVisitor<out R, in D> {
open fun visitErrorProperty(errorProperty: FirErrorProperty, data: D): R = visitElement(errorProperty, data) open fun visitErrorProperty(errorProperty: FirErrorProperty, data: D): R = visitElement(errorProperty, data)
open fun visitDanglingModifierList(danglingModifierList: FirDanglingModifierList, data: D): R = visitElement(danglingModifierList, data)
open fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression, data: D): R = visitElement(qualifiedAccessExpression, data) open fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression, data: D): R = visitElement(qualifiedAccessExpression, data)
open fun visitQualifiedErrorAccessExpression(qualifiedErrorAccessExpression: FirQualifiedErrorAccessExpression, data: D): R = visitElement(qualifiedErrorAccessExpression, data) open fun visitQualifiedErrorAccessExpression(qualifiedErrorAccessExpression: FirQualifiedErrorAccessExpression, data: D): R = visitElement(qualifiedErrorAccessExpression, data)
@@ -95,6 +95,7 @@ import org.jetbrains.kotlin.fir.expressions.FirClassReferenceExpression
import org.jetbrains.kotlin.fir.expressions.FirErrorExpression import org.jetbrains.kotlin.fir.expressions.FirErrorExpression
import org.jetbrains.kotlin.fir.declarations.FirErrorFunction import org.jetbrains.kotlin.fir.declarations.FirErrorFunction
import org.jetbrains.kotlin.fir.declarations.FirErrorProperty import org.jetbrains.kotlin.fir.declarations.FirErrorProperty
import org.jetbrains.kotlin.fir.declarations.FirDanglingModifierList
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirQualifiedErrorAccessExpression import org.jetbrains.kotlin.fir.expressions.FirQualifiedErrorAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression
@@ -513,6 +514,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
visitElement(errorProperty) visitElement(errorProperty)
} }
open fun visitDanglingModifierList(danglingModifierList: FirDanglingModifierList) {
visitElement(danglingModifierList)
}
open fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression) { open fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression) {
visitElement(qualifiedAccessExpression) visitElement(qualifiedAccessExpression)
} }
@@ -1085,6 +1090,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
visitErrorProperty(errorProperty) visitErrorProperty(errorProperty)
} }
final override fun visitDanglingModifierList(danglingModifierList: FirDanglingModifierList, data: Nothing?) {
visitDanglingModifierList(danglingModifierList)
}
final override fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression, data: Nothing?) { final override fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression, data: Nothing?) {
visitQualifiedAccessExpression(qualifiedAccessExpression) visitQualifiedAccessExpression(qualifiedAccessExpression)
} }
@@ -37,9 +37,13 @@ fun FirCallableDeclaration.containingClassLookupTag(): ConeClassLikeLookupTag? =
fun FirRegularClass.containingClassForLocal(): ConeClassLikeLookupTag? = fun FirRegularClass.containingClassForLocal(): ConeClassLikeLookupTag? =
if (isLocal) containingClassForLocalAttr else null if (isLocal) containingClassForLocalAttr else null
fun FirDanglingModifierList.containingClass(): ConeClassLikeLookupTag? =
containingClassAttr
private object ContainingClassKey : FirDeclarationDataKey() private object ContainingClassKey : FirDeclarationDataKey()
var FirCallableDeclaration.containingClassForStaticMemberAttr: ConeClassLikeLookupTag? by FirDeclarationDataRegistry.data(ContainingClassKey) var FirCallableDeclaration.containingClassForStaticMemberAttr: ConeClassLikeLookupTag? by FirDeclarationDataRegistry.data(ContainingClassKey)
var FirRegularClass.containingClassForLocalAttr: ConeClassLikeLookupTag? by FirDeclarationDataRegistry.data(ContainingClassKey) var FirRegularClass.containingClassForLocalAttr: ConeClassLikeLookupTag? by FirDeclarationDataRegistry.data(ContainingClassKey)
var FirDanglingModifierList.containingClassAttr: ConeClassLikeLookupTag? by FirDeclarationDataRegistry.data(ContainingClassKey)
private object IsNewPlaceForBodyGeneration : FirDeclarationDataKey() private object IsNewPlaceForBodyGeneration : FirDeclarationDataKey()
var FirRegularClass.isNewPlaceForBodyGeneration: Boolean? by FirDeclarationDataRegistry.data(IsNewPlaceForBodyGeneration) var FirRegularClass.isNewPlaceForBodyGeneration: Boolean? by FirDeclarationDataRegistry.data(IsNewPlaceForBodyGeneration)
@@ -46,6 +46,11 @@ object ConeDestructuringDeclarationsOnTopLevel : ConeDiagnostic {
get() = "Destructuring declarations are only allowed for local variables/values" get() = "Destructuring declarations are only allowed for local variables/values"
} }
object ConeDanglingModifierOnTopLevel : ConeDiagnostic {
override val reason: String
get() = "Top level declaration expected"
}
enum class DiagnosticKind { enum class DiagnosticKind {
Syntax, Syntax,
ExpressionExpected, ExpressionExpected,
@@ -387,6 +387,11 @@ class FirRenderer(
bodyRenderer?.renderBody(anonymousInitializer.body) bodyRenderer?.renderBody(anonymousInitializer.body)
} }
override fun visitDanglingModifierList(danglingModifierList: FirDanglingModifierList) {
annotationRenderer?.render(danglingModifierList)
print("<DANGLING MODIFIER: ${danglingModifierList.diagnostic.reason}>")
}
override fun visitBlock(block: FirBlock) { override fun visitBlock(block: FirBlock) {
bodyRenderer?.renderBody(block) bodyRenderer?.renderBody(block)
} }
@@ -0,0 +1,13 @@
/*
* 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.fir.symbols.impl
import org.jetbrains.kotlin.fir.declarations.FirDanglingModifierList
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
class FirDanglingModifierSymbol : FirBasedSymbol<FirDanglingModifierList>() {
override fun toString(): String = "${this::class.simpleName}"
}
@@ -118,6 +118,7 @@ object FirTreeBuilder : AbstractFirTreeBuilder() {
val errorExpression by element(Expression, expression, diagnosticHolder) val errorExpression by element(Expression, expression, diagnosticHolder)
val errorFunction by element(Declaration, function, diagnosticHolder) val errorFunction by element(Declaration, function, diagnosticHolder)
val errorProperty by element(Declaration, variable, diagnosticHolder) val errorProperty by element(Declaration, variable, diagnosticHolder)
val danglingModifierList by element(Declaration, declaration, diagnosticHolder)
val qualifiedAccessExpression by element(Expression, expression, qualifiedAccess) val qualifiedAccessExpression by element(Expression, expression, qualifiedAccess)
val qualifiedErrorAccessExpression by element(Expression, expression, diagnosticHolder) val qualifiedErrorAccessExpression by element(Expression, expression, diagnosticHolder)
val propertyAccessExpression by element(Expression, qualifiedAccessExpression) val propertyAccessExpression by element(Expression, qualifiedAccessExpression)
@@ -43,6 +43,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
} }
impl(anonymousObject) impl(anonymousObject)
impl(danglingModifierList)
noImpl(anonymousObjectExpression) noImpl(anonymousObjectExpression)
impl(typeAlias) impl(typeAlias)
@@ -456,6 +456,10 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
+field("dispatchReceiverType", coneSimpleKotlinTypeType, nullable = true) +field("dispatchReceiverType", coneSimpleKotlinTypeType, nullable = true)
} }
danglingModifierList.configure {
+symbol("FirDanglingModifierSymbol")
}
file.configure { file.configure {
+field("annotationsContainer", fileAnnotationsContainer).withTransform() +field("annotationsContainer", fileAnnotationsContainer).withTransform()
+field("packageDirective", packageDirective) +field("packageDirective", packageDirective)
@@ -57,6 +57,9 @@ sealed class KtFakeSourceElementKind : KtSourceElementKind() {
// with a fake sources which refers to the target expression // with a fake sources which refers to the target expression
object GeneratedLambdaLabel : KtFakeSourceElementKind() object GeneratedLambdaLabel : KtFakeSourceElementKind()
// for error element which is created for dangling modifier lists
object DanglingModifierList : KtFakeSourceElementKind()
// for lambdas & functions with expression bodies the return statement is added // for lambdas & functions with expression bodies the return statement is added
// with a fake sources which refers to the return target // with a fake sources which refers to the return target
sealed class ImplicitReturn : KtFakeSourceElementKind() { sealed class ImplicitReturn : KtFakeSourceElementKind() {
@@ -1,22 +0,0 @@
annotation class Ann
annotation class Ann2
class C {
fun foo() {
class Local {
@Ann0
@Ann @Ann3
@Ann2(1)
@Ann4<!SYNTAX!><!>
}
}
@Ann0
@Ann @Ann3
@Ann2(1)
@Ann4<!SYNTAX!><!>
}
@Ann0
@Ann @Ann3
@Ann2(1)
@Ann4<!SYNTAX!><!>
@@ -1,6 +1,7 @@
// FIR_IDENTICAL
annotation class Ann annotation class Ann
annotation class Ann2 annotation class Ann2
interface I {}
class C { class C {
fun foo() { fun foo() {
class Local { class Local {
@@ -9,6 +10,12 @@ class C {
@Ann2(<!TOO_MANY_ARGUMENTS!>1<!>) @Ann2(<!TOO_MANY_ARGUMENTS!>1<!>)
@<!UNRESOLVED_REFERENCE!>Ann4<!><!SYNTAX!><!> @<!UNRESOLVED_REFERENCE!>Ann4<!><!SYNTAX!><!>
} }
val i = object : I {
@<!UNRESOLVED_REFERENCE!>Ann0<!>
@Ann @<!UNRESOLVED_REFERENCE!>Ann3<!>
@Ann2(<!TOO_MANY_ARGUMENTS!>1<!>)
@<!UNRESOLVED_REFERENCE!>Ann4<!><!SYNTAX!><!>
}
} }
@<!UNRESOLVED_REFERENCE!>Ann0<!> @<!UNRESOLVED_REFERENCE!>Ann0<!>
@Ann @<!UNRESOLVED_REFERENCE!>Ann3<!> @Ann @<!UNRESOLVED_REFERENCE!>Ann3<!>
@@ -21,3 +21,10 @@ public final class C {
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
} }
public interface I {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -75,6 +75,18 @@ public class FirVisualizerForRawFirDataGenerated extends AbstractFirVisualizerTe
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/contextReceivers.kt"); 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 @Test
@TestMetadata("delegates.kt") @TestMetadata("delegates.kt")
public void testDelegates() throws Exception { public void testDelegates() throws Exception {
@@ -75,6 +75,18 @@ public class PsiVisualizerForRawFirDataGenerated extends AbstractPsiVisualizerTe
runTest("compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/contextReceivers.kt"); 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 @Test
@TestMetadata("delegates.kt") @TestMetadata("delegates.kt")
public void testDelegates() throws Exception { public void testDelegates() throws Exception {