[LL FIR] introduce NonLocalAnnotationVisitor
- Unified and optimized visitor instead of transformer with many redundant operations. - `LLFirAnnotationArgumentsTargetResolver` now has the correct state keeper for nested declarations – e.g., property accessors or value parameters. - `FirAllLazyAnnotationCalculatorVisitor` in tests now almost the same as in the production as now it uses the same visitor without recursive visiting ^KT-63606 Fixed ^KT-64000 Fixed ^KT-64579 Fixed
This commit is contained in:
committed by
Space Team
parent
410dbcb4cf
commit
f246d1c037
+22
-98
@@ -9,6 +9,7 @@ import com.intellij.psi.PsiElement
|
|||||||
import kotlinx.collections.immutable.PersistentList
|
import kotlinx.collections.immutable.PersistentList
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import kotlinx.collections.immutable.toPersistentList
|
import kotlinx.collections.immutable.toPersistentList
|
||||||
|
import org.jetbrains.annotations.TestOnly
|
||||||
import org.jetbrains.kotlin.KtFakeSourceElementKind
|
import org.jetbrains.kotlin.KtFakeSourceElementKind
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDesignation
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDesignation
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.withFirDesignationEntry
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.withFirDesignationEntry
|
||||||
@@ -30,7 +31,6 @@ import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
|
|||||||
import org.jetbrains.kotlin.fir.scopes.kotlinScopeProvider
|
import org.jetbrains.kotlin.fir.scopes.kotlinScopeProvider
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
|
||||||
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.builder.buildTypeProjectionWithVariance
|
import org.jetbrains.kotlin.fir.types.builder.buildTypeProjectionWithVariance
|
||||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||||
@@ -52,8 +52,9 @@ internal object FirLazyBodiesCalculator {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestOnly
|
||||||
fun calculateAllLazyExpressionsInFile(firFile: FirFile) {
|
fun calculateAllLazyExpressionsInFile(firFile: FirFile) {
|
||||||
firFile.transformSingle(FirAllLazyAnnotationCalculatorTransformer, firFile.moduleData.session)
|
firFile.accept(RecursiveLazyAnnotationCalculatorVisitor, firFile.moduleData.session)
|
||||||
firFile.transformSingle(FirAllLazyBodiesCalculatorTransformer, persistentListOf())
|
firFile.transformSingle(FirAllLazyBodiesCalculatorTransformer, persistentListOf())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,7 +63,7 @@ internal object FirLazyBodiesCalculator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun calculateAnnotations(firElement: FirElement, session: FirSession) {
|
fun calculateAnnotations(firElement: FirElement, session: FirSession) {
|
||||||
firElement.transformSingle(FirTargetLazyAnnotationCalculatorTransformer, session)
|
firElement.accept(LazyAnnotationCalculatorVisitor, session)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun calculateLazyArgumentsForAnnotation(annotationCall: FirAnnotationCall, session: FirSession): FirArgumentList {
|
fun calculateLazyArgumentsForAnnotation(annotationCall: FirAnnotationCall, session: FirSession): FirArgumentList {
|
||||||
@@ -624,108 +625,31 @@ private fun calculateLazyBodyForCodeFragment(designation: FirDesignation) {
|
|||||||
codeFragment.replaceBlock(newCodeFragment.block)
|
codeFragment.replaceBlock(newCodeFragment.block)
|
||||||
}
|
}
|
||||||
|
|
||||||
private object FirAllLazyAnnotationCalculatorTransformer : FirLazyAnnotationTransformer() {
|
/**
|
||||||
override fun <E : FirElement> transformElement(element: E, data: FirSession): E {
|
* This object is supposed to be used only for tests.
|
||||||
element.transformChildren(this, data)
|
*
|
||||||
return element
|
* @see LazyAnnotationCalculatorVisitor
|
||||||
|
*/
|
||||||
|
private object RecursiveLazyAnnotationCalculatorVisitor : RecursiveNonLocalAnnotationVisitor<FirSession>() {
|
||||||
|
override fun processAnnotation(annotation: FirAnnotation, data: FirSession) {
|
||||||
|
calculateAnnotationCallIfNeeded(annotation, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private object FirTargetLazyAnnotationCalculatorTransformer : FirLazyAnnotationTransformer() {
|
/**
|
||||||
override fun <E : FirElement> transformElement(element: E, data: FirSession): E {
|
* Calculates all non-local lazy annotations on a provided declaration.
|
||||||
element.transformChildren(this, data)
|
*/
|
||||||
return element
|
private object LazyAnnotationCalculatorVisitor : NonLocalAnnotationVisitor<FirSession>() {
|
||||||
}
|
override fun processAnnotation(annotation: FirAnnotation, data: FirSession) {
|
||||||
|
calculateAnnotationCallIfNeeded(annotation, data)
|
||||||
override fun transformRegularClass(regularClass: FirRegularClass, data: FirSession): FirStatement {
|
|
||||||
regularClass.transformAnnotations(this, data)
|
|
||||||
regularClass.transformTypeParameters(this, data)
|
|
||||||
regularClass.transformSuperTypeRefs(this, data)
|
|
||||||
regularClass.contextReceivers.forEach {
|
|
||||||
it.transformSingle(this, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
return regularClass
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun transformScript(script: FirScript, data: FirSession): FirScript {
|
|
||||||
script.transformAnnotations(this, data)
|
|
||||||
return script
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun transformBlock(block: FirBlock, data: FirSession): FirStatement {
|
|
||||||
// We shouldn't process blocks because there are no lazy annotations
|
|
||||||
return block
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun transformFile(file: FirFile, data: FirSession): FirFile {
|
|
||||||
file.transformAnnotationsContainer(this, data)
|
|
||||||
return file
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private abstract class FirLazyAnnotationTransformer : FirTransformer<FirSession>() {
|
private fun calculateAnnotationCallIfNeeded(annotation: FirAnnotation, session: FirSession) {
|
||||||
override fun <E : FirElement> transformElement(element: E, data: FirSession): E {
|
if (annotation !is FirAnnotationCall || !FirLazyBodiesCalculator.needCalculatingAnnotationCall(annotation)) return
|
||||||
element.transformChildren(this, data)
|
|
||||||
return element
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun transformErrorTypeRef(errorTypeRef: FirErrorTypeRef, data: FirSession): FirTypeRef {
|
val newArgumentList = FirLazyBodiesCalculator.calculateLazyArgumentsForAnnotation(annotation, session)
|
||||||
visitTypeAnnotations(errorTypeRef, data)
|
annotation.replaceArgumentList(newArgumentList)
|
||||||
return super.transformErrorTypeRef(errorTypeRef, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun transformResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef, data: FirSession): FirTypeRef {
|
|
||||||
visitTypeAnnotations(resolvedTypeRef, data)
|
|
||||||
return super.transformResolvedTypeRef(resolvedTypeRef, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun visitTypeAnnotations(resolvedTypeRef: FirResolvedTypeRef, data: FirSession) {
|
|
||||||
resolvedTypeRef.coneType.forEachType { coneType ->
|
|
||||||
for (typeArgumentAnnotation in coneType.customAnnotations) {
|
|
||||||
typeArgumentAnnotation.accept(this, data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun transformAnnotationCall(annotationCall: FirAnnotationCall, data: FirSession): FirStatement {
|
|
||||||
if (FirLazyBodiesCalculator.needCalculatingAnnotationCall(annotationCall)) {
|
|
||||||
val newArgumentList = FirLazyBodiesCalculator.calculateLazyArgumentsForAnnotation(annotationCall, data)
|
|
||||||
annotationCall.replaceArgumentList(newArgumentList)
|
|
||||||
}
|
|
||||||
|
|
||||||
super.transformAnnotationCall(annotationCall, data)
|
|
||||||
return annotationCall
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun transformErrorAnnotationCall(errorAnnotationCall: FirErrorAnnotationCall, data: FirSession): FirStatement {
|
|
||||||
transformAnnotationCall(errorAnnotationCall, data)
|
|
||||||
return errorAnnotationCall
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun transformExpression(expression: FirExpression, data: FirSession): FirStatement {
|
|
||||||
if (expression is FirLazyExpression) {
|
|
||||||
return expression
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.transformExpression(expression, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun transformBlock(block: FirBlock, data: FirSession): FirStatement {
|
|
||||||
if (block is FirLazyBlock) {
|
|
||||||
return block
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.transformBlock(block, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun transformDelegatedConstructorCall(delegatedConstructorCall: FirDelegatedConstructorCall, data: FirSession): FirStatement {
|
|
||||||
if (delegatedConstructorCall is FirLazyDelegatedConstructorCall) {
|
|
||||||
return delegatedConstructorCall
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.transformDelegatedConstructorCall(delegatedConstructorCall, data)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private object FirAllLazyBodiesCalculatorTransformer : FirLazyBodiesCalculatorTransformer() {
|
private object FirAllLazyBodiesCalculatorTransformer : FirLazyBodiesCalculatorTransformer() {
|
||||||
|
|||||||
+215
@@ -0,0 +1,215 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2024 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.analysis.low.level.api.fir.lazy.resolve
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||||
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
|
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||||
|
import org.jetbrains.kotlin.fir.FirFileAnnotationsContainer
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirAnonymousInitializer
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirBackingField
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirConstructor
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirContextReceiver
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirDanglingModifierList
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirEnumEntry
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirErrorPrimaryConstructor
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirErrorProperty
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirPropertyAccessor
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirReceiverParameter
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirScript
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirTypeAlias
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirTypeParameterRefsOwner
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirVariable
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirAnnotationArgumentMapping
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirArgumentList
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirErrorAnnotationCall
|
||||||
|
import org.jetbrains.kotlin.fir.types.FirErrorTypeRef
|
||||||
|
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||||
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
|
import org.jetbrains.kotlin.fir.types.customAnnotations
|
||||||
|
import org.jetbrains.kotlin.fir.types.forEachType
|
||||||
|
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visitor for annotations outside bodies.
|
||||||
|
* Such annotations are processed in [ANNOTATION_ARGUMENTS][org.jetbrains.kotlin.fir.declarations.FirResolvePhase.ANNOTATION_ARGUMENTS]
|
||||||
|
* phase.
|
||||||
|
*
|
||||||
|
* This visitor is not recursive and processes only the target declaration (without unrelated nested declarations).
|
||||||
|
* See [RecursiveNonLocalAnnotationVisitor] for the recursive visitor.
|
||||||
|
*
|
||||||
|
* @see processAnnotation
|
||||||
|
* @see RecursiveNonLocalAnnotationVisitor
|
||||||
|
*/
|
||||||
|
internal abstract class NonLocalAnnotationVisitor<T> : FirVisitor<Unit, T>() {
|
||||||
|
abstract fun processAnnotation(annotation: FirAnnotation, data: T)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Skip all [FirElementWithResolveState] without explicit override
|
||||||
|
*/
|
||||||
|
override fun visitElement(element: FirElement, data: T) {
|
||||||
|
if (element is FirElementWithResolveState) return
|
||||||
|
|
||||||
|
element.acceptChildren(this, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Skip argument list as the compiler do not support annotations inside annotation arguments
|
||||||
|
*/
|
||||||
|
override fun visitArgumentList(argumentList: FirArgumentList, data: T) {}
|
||||||
|
override fun visitAnnotationArgumentMapping(annotationArgumentMapping: FirAnnotationArgumentMapping, data: T) {}
|
||||||
|
|
||||||
|
override fun visitResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef, data: T) {
|
||||||
|
visitTypeAnnotations(resolvedTypeRef, data)
|
||||||
|
resolvedTypeRef.acceptChildren(this, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitErrorTypeRef(errorTypeRef: FirErrorTypeRef, data: T) {
|
||||||
|
visitResolvedTypeRef(errorTypeRef, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun visitTypeAnnotations(resolvedTypeRef: FirResolvedTypeRef, data: T) {
|
||||||
|
resolvedTypeRef.coneType.forEachType { coneType ->
|
||||||
|
for (typeArgumentAnnotation in coneType.customAnnotations) {
|
||||||
|
typeArgumentAnnotation.accept(this, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitAnnotation(annotation: FirAnnotation, data: T) {
|
||||||
|
processAnnotation(annotation, data)
|
||||||
|
annotation.acceptChildren(this, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitAnnotationCall(annotationCall: FirAnnotationCall, data: T) {
|
||||||
|
visitAnnotation(annotationCall, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitErrorAnnotationCall(errorAnnotationCall: FirErrorAnnotationCall, data: T) {
|
||||||
|
visitAnnotation(errorAnnotationCall, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitFileAnnotationsContainer(fileAnnotationsContainer: FirFileAnnotationsContainer, data: T) {
|
||||||
|
visitAnnotationContainer(fileAnnotationsContainer, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitDanglingModifierList(danglingModifierList: FirDanglingModifierList, data: T) {
|
||||||
|
visitAnnotationContainer(danglingModifierList, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitScript(script: FirScript, data: T) {
|
||||||
|
visitAnnotationContainer(script, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitAnonymousInitializer(anonymousInitializer: FirAnonymousInitializer, data: T) {
|
||||||
|
visitAnnotationContainer(anonymousInitializer, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitMemberDeclaration(memberDeclaration: FirMemberDeclaration, data: T) {
|
||||||
|
visitTypeParameterRefsOwner(memberDeclaration, data)
|
||||||
|
visitAnnotationContainer(memberDeclaration, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitTypeAlias(typeAlias: FirTypeAlias, data: T) {
|
||||||
|
visitMemberDeclaration(typeAlias, data)
|
||||||
|
typeAlias.expandedTypeRef.accept(this, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitRegularClass(regularClass: FirRegularClass, data: T) {
|
||||||
|
visitMemberDeclaration(regularClass, data)
|
||||||
|
visitContextReceivers(regularClass.contextReceivers, data)
|
||||||
|
regularClass.superTypeRefs.forEach { it.accept(this, data) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitCallableDeclaration(callableDeclaration: FirCallableDeclaration, data: T) {
|
||||||
|
visitMemberDeclaration(callableDeclaration, data)
|
||||||
|
visitContextReceivers(callableDeclaration.contextReceivers, data)
|
||||||
|
callableDeclaration.receiverParameter?.accept(this, data)
|
||||||
|
callableDeclaration.returnTypeRef.accept(this, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun visitContextReceivers(contextReceivers: List<FirContextReceiver>, data: T) {
|
||||||
|
contextReceivers.forEach { it.accept(this, data) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitAnnotationContainer(annotationContainer: FirAnnotationContainer, data: T) {
|
||||||
|
annotationContainer.annotations.forEach { it.accept(this, data) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitTypeParameterRefsOwner(typeParameterRefsOwner: FirTypeParameterRefsOwner, data: T) {
|
||||||
|
typeParameterRefsOwner.typeParameters.forEach { it.accept(this, data) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitReceiverParameter(receiverParameter: FirReceiverParameter, data: T) {
|
||||||
|
receiverParameter.acceptChildren(this, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitContextReceiver(contextReceiver: FirContextReceiver, data: T) {
|
||||||
|
contextReceiver.acceptChildren(this, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitTypeParameter(typeParameter: FirTypeParameter, data: T) {
|
||||||
|
typeParameter.acceptChildren(this, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitFunction(function: FirFunction, data: T) {
|
||||||
|
visitCallableDeclaration(function, data)
|
||||||
|
function.valueParameters.forEach { it.accept(this, data) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: T) {
|
||||||
|
visitFunction(simpleFunction, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitConstructor(constructor: FirConstructor, data: T) {
|
||||||
|
visitFunction(constructor, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitErrorPrimaryConstructor(errorPrimaryConstructor: FirErrorPrimaryConstructor, data: T) {
|
||||||
|
visitFunction(errorPrimaryConstructor, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitPropertyAccessor(propertyAccessor: FirPropertyAccessor, data: T) {
|
||||||
|
visitFunction(propertyAccessor, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitVariable(variable: FirVariable, data: T) {
|
||||||
|
visitCallableDeclaration(variable, data)
|
||||||
|
variable.getter?.accept(this, data)
|
||||||
|
variable.setter?.accept(this, data)
|
||||||
|
variable.backingField?.accept(this, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitEnumEntry(enumEntry: FirEnumEntry, data: T) {
|
||||||
|
visitVariable(enumEntry, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitProperty(property: FirProperty, data: T) {
|
||||||
|
visitVariable(property, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitErrorProperty(errorProperty: FirErrorProperty, data: T) {
|
||||||
|
visitVariable(errorProperty, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitValueParameter(valueParameter: FirValueParameter, data: T) {
|
||||||
|
visitVariable(valueParameter, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitBackingField(backingField: FirBackingField, data: T) {
|
||||||
|
visitVariable(backingField, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2024 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.analysis.low.level.api.fir.lazy.resolve
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.forEachDeclaration
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirScript
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In opposite to [NonLocalAnnotationVisitor] processes not only the target declaration,
|
||||||
|
* but also its nested declarations.
|
||||||
|
*
|
||||||
|
* @see NonLocalAnnotationVisitor
|
||||||
|
*/
|
||||||
|
internal abstract class RecursiveNonLocalAnnotationVisitor<T> : NonLocalAnnotationVisitor<T>() {
|
||||||
|
override fun visitFile(file: FirFile, data: T) {
|
||||||
|
super.visitFile(file, data)
|
||||||
|
|
||||||
|
file.annotationsContainer?.accept(this, data)
|
||||||
|
file.forEachDeclaration { it.accept(this, data) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitScript(script: FirScript, data: T) {
|
||||||
|
super.visitScript(script, data)
|
||||||
|
|
||||||
|
script.forEachDeclaration { it.accept(this, data) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitRegularClass(regularClass: FirRegularClass, data: T) {
|
||||||
|
super.visitRegularClass(regularClass, data)
|
||||||
|
|
||||||
|
regularClass.forEachDeclaration { it.accept(this, data) }
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
-16
@@ -8,8 +8,8 @@ package org.jetbrains.kotlin.analysis.low.level.api.fir.transformers
|
|||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirResolveTarget
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.targets.LLFirResolveTarget
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.throwUnexpectedFirElementError
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.throwUnexpectedFirElementError
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyBodiesCalculator
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.FirLazyBodiesCalculator
|
||||||
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.lazy.resolve.NonLocalAnnotationVisitor
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.llFirSession
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.sessions.llFirSession
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.AnnotationVisitorVoid
|
|
||||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkAnnotationsAreResolved
|
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.checkAnnotationsAreResolved
|
||||||
import org.jetbrains.kotlin.fir.*
|
import org.jetbrains.kotlin.fir.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
|||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
||||||
import org.jetbrains.kotlin.fir.types.FirTypeProjection
|
import org.jetbrains.kotlin.fir.types.FirTypeProjection
|
||||||
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
|
||||||
import org.jetbrains.kotlin.fir.visitors.transformSingle
|
import org.jetbrains.kotlin.fir.visitors.transformSingle
|
||||||
|
|
||||||
internal object LLFirAnnotationArgumentsLazyResolver : LLFirLazyResolver(FirResolvePhase.ANNOTATION_ARGUMENTS) {
|
internal object LLFirAnnotationArgumentsLazyResolver : LLFirLazyResolver(FirResolvePhase.ANNOTATION_ARGUMENTS) {
|
||||||
@@ -134,10 +133,10 @@ private class LLFirAnnotationArgumentsTargetResolver(resolveTarget: LLFirResolve
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class ForeignAnnotationsContext(val collection: MutableCollection<FirBasedSymbol<*>>, val currentSymbol: FirCallableSymbol<*>)
|
private class ForeignAnnotationsContext(val collection: MutableCollection<FirBasedSymbol<*>>, val currentSymbol: FirCallableSymbol<*>)
|
||||||
private object ForeignAnnotationsCollector : AnnotationVisitorVoid<ForeignAnnotationsContext>() {
|
private object ForeignAnnotationsCollector : NonLocalAnnotationVisitor<ForeignAnnotationsContext>() {
|
||||||
override fun visitAnnotation(annotation: FirAnnotation, data: ForeignAnnotationsContext) {}
|
override fun processAnnotation(annotation: FirAnnotation, data: ForeignAnnotationsContext) {
|
||||||
override fun visitAnnotationCall(annotationCall: FirAnnotationCall, data: ForeignAnnotationsContext) {
|
if (annotation !is FirAnnotationCall) return
|
||||||
val symbolToPostpone = annotationCall.containingDeclarationSymbol.symbolToPostponeIfCanBeResolvedOnDemand() ?: return
|
val symbolToPostpone = annotation.containingDeclarationSymbol.symbolToPostponeIfCanBeResolvedOnDemand() ?: return
|
||||||
if (symbolToPostpone != data.currentSymbol) {
|
if (symbolToPostpone != data.currentSymbol) {
|
||||||
data.collection += symbolToPostpone
|
data.collection += symbolToPostpone
|
||||||
}
|
}
|
||||||
@@ -242,19 +241,13 @@ internal object AnnotationArgumentsStateKeepers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val DECLARATION: StateKeeper<FirElementWithResolveState, FirSession> = stateKeeper { target, session ->
|
val DECLARATION: StateKeeper<FirElementWithResolveState, FirSession> = stateKeeper { target, session ->
|
||||||
val visitor = object : FirVisitorVoid() {
|
val visitor = object : NonLocalAnnotationVisitor<Unit>() {
|
||||||
override fun visitElement(element: FirElement) {
|
override fun processAnnotation(annotation: FirAnnotation, data: Unit) {
|
||||||
when (element) {
|
entity(annotation, ANNOTATION, session)
|
||||||
is FirDeclaration -> if (element !== target) return // Avoid nested declarations
|
|
||||||
is FirAnnotation -> entity(element, ANNOTATION, session)
|
|
||||||
is FirStatement -> return
|
|
||||||
}
|
|
||||||
|
|
||||||
element.acceptChildren(this)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
target.accept(visitor)
|
target.accept(visitor, Unit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-32
@@ -7,6 +7,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.analysis.low.level.api.fir.lazy.resolve.NonLocalAnnotationVisitor
|
||||||
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
import org.jetbrains.kotlin.fir.FirAnnotationContainer
|
||||||
import org.jetbrains.kotlin.fir.FirElement
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
import org.jetbrains.kotlin.fir.FirElementWithResolveState
|
||||||
@@ -28,12 +29,8 @@ import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
|||||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.FirTypeProjectionWithVariance
|
import org.jetbrains.kotlin.fir.types.FirTypeProjectionWithVariance
|
||||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||||
import org.jetbrains.kotlin.fir.types.coneType
|
|
||||||
import org.jetbrains.kotlin.fir.types.customAnnotations
|
|
||||||
import org.jetbrains.kotlin.fir.types.forEachType
|
|
||||||
import org.jetbrains.kotlin.fir.utils.exceptions.withFirEntry
|
import org.jetbrains.kotlin.fir.utils.exceptions.withFirEntry
|
||||||
import org.jetbrains.kotlin.fir.utils.exceptions.withFirSymbolEntry
|
import org.jetbrains.kotlin.fir.utils.exceptions.withFirSymbolEntry
|
||||||
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
|
||||||
import org.jetbrains.kotlin.utils.exceptions.ExceptionAttachmentBuilder
|
import org.jetbrains.kotlin.utils.exceptions.ExceptionAttachmentBuilder
|
||||||
import org.jetbrains.kotlin.utils.exceptions.checkWithAttachment
|
import org.jetbrains.kotlin.utils.exceptions.checkWithAttachment
|
||||||
import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment
|
import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment
|
||||||
@@ -248,36 +245,10 @@ internal fun FirAbstractBodyResolveTransformerDispatcher.checkAnnotationCallIsRe
|
|||||||
checkAnnotationIsResolved(annotationCall, annotationContainer)
|
checkAnnotationIsResolved(annotationCall, annotationContainer)
|
||||||
}
|
}
|
||||||
|
|
||||||
private object AnnotationChecker : AnnotationVisitorVoid<FirAnnotationContainer>() {
|
private object AnnotationChecker : NonLocalAnnotationVisitor<FirAnnotationContainer>() {
|
||||||
override fun visitAnnotation(annotation: FirAnnotation, data: FirAnnotationContainer) {
|
override fun processAnnotation(annotation: FirAnnotation, data: FirAnnotationContainer) {
|
||||||
checkAnnotationIsResolved(annotation, data)
|
checkAnnotationIsResolved(annotation, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitAnnotationCall(annotationCall: FirAnnotationCall, data: FirAnnotationContainer) {
|
|
||||||
checkAnnotationIsResolved(annotationCall, data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This visitor is responsible for visiting all annotations recursively
|
|
||||||
*/
|
|
||||||
internal abstract class AnnotationVisitorVoid<T> : FirVisitor<Unit, T>() {
|
|
||||||
abstract override fun visitAnnotation(annotation: FirAnnotation, data: T)
|
|
||||||
abstract override fun visitAnnotationCall(annotationCall: FirAnnotationCall, data: T)
|
|
||||||
|
|
||||||
override fun visitResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef, data: T) {
|
|
||||||
resolvedTypeRef.acceptChildren(this, data)
|
|
||||||
|
|
||||||
resolvedTypeRef.coneType.forEachType {
|
|
||||||
it.type.attributes.customAnnotations.forEach { typeArgumentAnnotation ->
|
|
||||||
typeArgumentAnnotation.accept(this, data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitElement(element: FirElement, data: T) {
|
|
||||||
element.acceptChildren(this, data)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun checkAnnotationsAreResolved(annotationContainer: FirAnnotationContainer) {
|
internal fun checkAnnotationsAreResolved(annotationContainer: FirAnnotationContainer) {
|
||||||
|
|||||||
Reference in New Issue
Block a user