[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
@@ -154,7 +154,7 @@ object FirOptInUsageBaseChecker {
fir.loadCallableSpecificExperimentalities(this, context, visited, fromSetter, dispatchReceiverType, result)
is FirClassLikeDeclaration ->
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)
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.*
import org.jetbrains.kotlin.fir.declarations.impl.*
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.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
@@ -97,6 +98,7 @@ class DeclarationsConverter(
var fileAnnotationContainer: FirFileAnnotationsContainer? = null
val importList = mutableListOf<FirImport>()
val firDeclarationList = mutableListOf<FirDeclaration>()
val modifierList = mutableListOf<LighterASTNode>()
context.packageFqName = FqName.ROOT
var packageDirective: FirPackageDirective? = null
file.forEachChildren { child ->
@@ -116,9 +118,14 @@ class DeclarationsConverter(
SCRIPT -> {
// TODO: scripts aren't supported yet
}
MODIFIER_LIST -> modifierList += child
}
}
modifierList.forEach {
firDeclarationList += buildErrorTopLevelDeclarationForDanglingModifierList(it)
}
return buildFile {
symbol = fileSymbol
source = file.toFirSourceElement()
@@ -839,7 +846,8 @@ class DeclarationsConverter(
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseEnumClassBody
*/
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")
when (node.tokenType) {
ENUM_ENTRY -> container += convertEnumEntry(node, classWrapper)
@@ -850,8 +858,22 @@ class DeclarationsConverter(
OBJECT_DECLARATION -> container += convertClass(node)
CLASS_INITIALIZER -> container += convertAnonymousInitializer(node) //anonymousInitializer
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");
}
@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")
public void testDelegates() throws Exception {
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.tree.IElementType
import com.intellij.util.AstLoadingFilter
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.*
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.builtins.StandardNames.BACKING_FIELD
@@ -1057,6 +1058,10 @@ open class RawFirBuilder(
else -> declaration.convert()
}
}
for (danglingModifierList in PsiTreeUtil.getChildrenOfTypeAsList(file, KtModifierList::class.java)) {
declarations += buildErrorTopLevelDeclarationForDanglingModifierList(danglingModifierList)
}
}
}
@@ -1269,7 +1274,14 @@ open class RawFirBuilder(
classOrObject,
this,
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()
)
}
for (danglingModifier in PsiTreeUtil.getChildrenOfTypeAsList(objectDeclaration.body, KtModifierList::class.java)) {
declarations += buildErrorTopLevelDeclarationForDanglingModifierList(danglingModifier).apply {
containingClassAttr = currentDispatchReceiverType()?.lookupTag
}
}
}.also {
it.delegateFieldsMap = delegatedFieldsMap
}
@@ -2730,6 +2748,17 @@ open class RawFirBuilder(
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");
}
@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")
public void testDelegates() throws Exception {
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");
}
@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")
public void testDelegates() throws Exception {
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.isCompanion
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
import org.jetbrains.kotlin.fir.diagnostics.ConeDestructuringDeclarationsOnTopLevel
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.diagnostics.*
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.*
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.declarations.FirErrorFunction
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.FirQualifiedErrorAccessExpression
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.declarations.FirErrorFunction
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.FirQualifiedErrorAccessExpression
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.declarations.FirErrorFunction
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.FirQualifiedErrorAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression
@@ -514,6 +515,10 @@ abstract class FirTransformer<in D> : FirVisitor<FirElement, D>() {
return transformElement(errorProperty, data)
}
open fun transformDanglingModifierList(danglingModifierList: FirDanglingModifierList, data: D): FirDanglingModifierList {
return transformElement(danglingModifierList, data)
}
open fun transformQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression, data: D): FirStatement {
return transformElement(qualifiedAccessExpression, data)
}
@@ -1086,6 +1091,10 @@ abstract class FirTransformer<in D> : FirVisitor<FirElement, D>() {
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 {
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.declarations.FirErrorFunction
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.FirQualifiedErrorAccessExpression
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 visitDanglingModifierList(danglingModifierList: FirDanglingModifierList, data: D): R = visitElement(danglingModifierList, data)
open fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression, data: D): R = visitElement(qualifiedAccessExpression, 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.declarations.FirErrorFunction
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.FirQualifiedErrorAccessExpression
import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression
@@ -513,6 +514,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
visitElement(errorProperty)
}
open fun visitDanglingModifierList(danglingModifierList: FirDanglingModifierList) {
visitElement(danglingModifierList)
}
open fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression) {
visitElement(qualifiedAccessExpression)
}
@@ -1085,6 +1090,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
visitErrorProperty(errorProperty)
}
final override fun visitDanglingModifierList(danglingModifierList: FirDanglingModifierList, data: Nothing?) {
visitDanglingModifierList(danglingModifierList)
}
final override fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression, data: Nothing?) {
visitQualifiedAccessExpression(qualifiedAccessExpression)
}
@@ -37,9 +37,13 @@ fun FirCallableDeclaration.containingClassLookupTag(): ConeClassLikeLookupTag? =
fun FirRegularClass.containingClassForLocal(): ConeClassLikeLookupTag? =
if (isLocal) containingClassForLocalAttr else null
fun FirDanglingModifierList.containingClass(): ConeClassLikeLookupTag? =
containingClassAttr
private object ContainingClassKey : FirDeclarationDataKey()
var FirCallableDeclaration.containingClassForStaticMemberAttr: 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()
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"
}
object ConeDanglingModifierOnTopLevel : ConeDiagnostic {
override val reason: String
get() = "Top level declaration expected"
}
enum class DiagnosticKind {
Syntax,
ExpressionExpected,
@@ -387,6 +387,11 @@ class FirRenderer(
bodyRenderer?.renderBody(anonymousInitializer.body)
}
override fun visitDanglingModifierList(danglingModifierList: FirDanglingModifierList) {
annotationRenderer?.render(danglingModifierList)
print("<DANGLING MODIFIER: ${danglingModifierList.diagnostic.reason}>")
}
override fun visitBlock(block: FirBlock) {
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 errorFunction by element(Declaration, function, diagnosticHolder)
val errorProperty by element(Declaration, variable, diagnosticHolder)
val danglingModifierList by element(Declaration, declaration, diagnosticHolder)
val qualifiedAccessExpression by element(Expression, expression, qualifiedAccess)
val qualifiedErrorAccessExpression by element(Expression, expression, diagnosticHolder)
val propertyAccessExpression by element(Expression, qualifiedAccessExpression)
@@ -43,6 +43,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
}
impl(anonymousObject)
impl(danglingModifierList)
noImpl(anonymousObjectExpression)
impl(typeAlias)
@@ -456,6 +456,10 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
+field("dispatchReceiverType", coneSimpleKotlinTypeType, nullable = true)
}
danglingModifierList.configure {
+symbol("FirDanglingModifierSymbol")
}
file.configure {
+field("annotationsContainer", fileAnnotationsContainer).withTransform()
+field("packageDirective", packageDirective)
@@ -57,6 +57,9 @@ sealed class KtFakeSourceElementKind : KtSourceElementKind() {
// with a fake sources which refers to the target expression
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
// with a fake sources which refers to the return target
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 Ann2
interface I {}
class C {
fun foo() {
class Local {
@@ -9,6 +10,12 @@ class C {
@Ann2(<!TOO_MANY_ARGUMENTS!>1<!>)
@<!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<!>
@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 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");
}
@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 {
@@ -75,6 +75,18 @@ public class PsiVisualizerForRawFirDataGenerated extends AbstractPsiVisualizerTe
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 {