Split property use-site targets during FIR building

This commit is contained in:
Mikhail Glukhikh
2021-10-06 15:36:52 +03:00
committed by teamcityserver
parent 2a9a1dbb86
commit 7243d30869
26 changed files with 227 additions and 138 deletions
@@ -36,13 +36,8 @@ KtFirKotlinPropertySymbol:
KtFirKotlinPropertySymbol:
annotatedType: [] kotlin/Int
annotationClassIds: [
kotlin/Deprecated
]
annotations: [
kotlin/Deprecated(message = don't use getter of i2)
psi: KtAnnotationEntry
]
annotationClassIds: []
annotations: []
callableIdIfNonLocal: /i2
dispatchType: null
getter: KtFirPropertyGetterSymbol(<getter>)
@@ -72,13 +67,8 @@ KtFirKotlinPropertySymbol:
KtFirKotlinPropertySymbol:
annotatedType: [] kotlin/Int
annotationClassIds: [
kotlin/Deprecated
]
annotations: [
kotlin/Deprecated(message = don't use getter of i3)
psi: KtAnnotationEntry
]
annotationClassIds: []
annotations: []
callableIdIfNonLocal: /i3
dispatchType: null
getter: KtFirPropertyGetterSymbol(<getter>)
@@ -108,16 +98,8 @@ KtFirKotlinPropertySymbol:
KtFirKotlinPropertySymbol:
annotatedType: [] kotlin/Int
annotationClassIds: [
kotlin/Deprecated
kotlin/Deprecated
]
annotations: [
kotlin/Deprecated(message = don't use getter of i4)
psi: KtAnnotationEntry
kotlin/Deprecated(message = don't use getter of i4)
psi: KtAnnotationEntry
]
annotationClassIds: []
annotations: []
callableIdIfNonLocal: /i4
dispatchType: null
getter: KtFirPropertyGetterSymbol(<getter>)
@@ -1,15 +1,7 @@
KtFirKotlinPropertySymbol:
annotatedType: [] kotlin/Int
annotationClassIds: [
kotlin/jvm/JvmName
kotlin/jvm/JvmName
]
annotations: [
kotlin/jvm/JvmName(name = getMyI)
psi: KtAnnotationEntry
kotlin/jvm/JvmName(name = setMyI)
psi: KtAnnotationEntry
]
annotationClassIds: []
annotations: []
callableIdIfNonLocal: /Foo.i
dispatchType: Foo
getter: KtFirPropertyGetterSymbol(<getter>)
@@ -93,7 +93,9 @@ internal open class FirElementsRecorder : FirVisitor<Unit, MutableMap<KtElement,
private fun cacheElement(element: FirElement, cache: MutableMap<KtElement, FirElement>) {
val psi = element.source
?.takeIf {
it.kind == FirFakeSourceElementKind.ReferenceInAtomicQualifiedAccess || it is FirRealPsiSourceElement
it is FirRealPsiSourceElement ||
it.kind == FirFakeSourceElementKind.ReferenceInAtomicQualifiedAccess ||
it.kind == FirFakeSourceElementKind.FromUseSiteTarget
}.psi as? KtElement
?: return
cache(psi, element, cache)
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirDeclarationDesignation
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier
@@ -98,14 +99,16 @@ internal class RawFirNonLocalDeclarationBuilder private constructor(
override fun convertValueParameter(
valueParameter: KtParameter,
defaultTypeRef: FirTypeRef?,
valueParameterDeclaration: ValueParameterDeclaration
valueParameterDeclaration: ValueParameterDeclaration,
additionalAnnotations: List<FirAnnotation>
): FirValueParameter {
val replacementParameter = replacementApplier?.tryReplace(valueParameter) ?: valueParameter
check(replacementParameter is KtParameter)
return super.convertValueParameter(
valueParameter = replacementParameter,
defaultTypeRef = defaultTypeRef,
valueParameterDeclaration = valueParameterDeclaration
valueParameterDeclaration = valueParameterDeclaration,
additionalAnnotations = additionalAnnotations
)
}
}
@@ -6,12 +6,12 @@ FILE: test.kt
}
public final data class KotlinResult : R|kotlin/Any| {
@R|KotlinMessage|() public constructor(@PROPERTY_GETTER:R|KotlinMessage|() @R|KotlinMessage|() message: R|kotlin/String| = String()): R|KotlinResult| {
@R|KotlinMessage|() public constructor(@R|KotlinMessage|() message: R|kotlin/String| = String()): R|KotlinResult| {
super<R|kotlin/Any|>()
}
@PROPERTY_GETTER:R|KotlinMessage|() @R|KotlinMessage|() public final val message: R|kotlin/String| = R|<local>/message|
public get(): R|kotlin/String|
@R|KotlinMessage|() public final val message: R|kotlin/String| = R|<local>/message|
@PROPERTY_GETTER:R|KotlinMessage|() public get(): R|kotlin/String|
public final operator fun component1(): R|kotlin/String|
@@ -28,8 +28,8 @@ FILE: test.kt
super<R|kotlin/Any|>()
}
@PROPERTY_GETTER:R|kotlin/jvm/JvmName|(name = String(getInstance)) public open val INSTANCE: R|kotlin/String|
public get(): R|kotlin/String| {
public open val INSTANCE: R|kotlin/String|
@PROPERTY_GETTER:R|kotlin/jvm/JvmName|(name = String(getInstance)) public get(): R|kotlin/String| {
^ String(Omega)
}
@@ -2,11 +2,11 @@
@Target(AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER, AnnotationTarget.CONSTRUCTOR)
annotation class KotlinMessage
data class KotlinResult @KotlinMessage constructor(@get:KotlinMessage <!REPEATED_ANNOTATION!>@KotlinMessage<!> val message: String = "")
data class KotlinResult @KotlinMessage constructor(@get:KotlinMessage @KotlinMessage val message: String = "")
open class Some {
companion object {
<!INAPPLICABLE_JVM_NAME!>@get:JvmName("getInstance")<!>
@get:JvmName("getInstance")
<!NON_FINAL_MEMBER_IN_OBJECT!>open<!> val INSTANCE: String
get() = "Omega"
}
@@ -113,7 +113,7 @@ fun checkRepeatedAnnotation(
) {
val duplicated = useSiteTarget in existingTargetsForAnnotation
|| existingTargetsForAnnotation.any { (it == null) != (useSiteTarget == null) }
if (duplicated && !annotation.isRepeatable(context.session) && annotation.source?.kind !is FirFakeSourceElementKind) {
if (duplicated && !annotation.isRepeatable(context.session)) {
reporter.reportOn(annotation.source, FirErrors.REPEATED_ANNOTATION, context)
}
}
@@ -77,10 +77,6 @@ object FirAnnotationChecker : FirAnnotatedDeclarationChecker() {
context: CheckerContext,
reporter: DiagnosticReporter
) {
if (declaration is FirValueParameter && declaration.source?.hasValOrVar() == true) {
// This will be checked later as property
return
}
val actualTargets = getActualTargetList(declaration)
val applicableTargets = annotation.getAllowedAnnotationTargets(context.session)
val useSiteTarget = annotation.useSiteTarget
@@ -114,6 +110,7 @@ object FirAnnotationChecker : FirAnnotatedDeclarationChecker() {
context
)
} else {
if (declaration is FirProperty && declaration.source?.kind == FirFakeSourceElementKind.PropertyFromParameter) return
reporter.reportOn(
annotation.source,
FirErrors.WRONG_ANNOTATION_TARGET,
@@ -130,6 +127,7 @@ object FirAnnotationChecker : FirAnnotatedDeclarationChecker() {
context: CheckerContext,
reporter: DiagnosticReporter
) {
if (annotation.source?.kind == FirFakeSourceElementKind.FromUseSiteTarget) return
when (target) {
AnnotationUseSiteTarget.PROPERTY,
AnnotationUseSiteTarget.PROPERTY_GETTER -> {
@@ -156,7 +154,9 @@ object FirAnnotationChecker : FirAnnotatedDeclarationChecker() {
annotated is FirValueParameter -> {
val container = context.containingDeclarations.lastOrNull()
if (container is FirConstructor && container.isPrimary) {
reporter.reportOn(annotation.source, FirErrors.REDUNDANT_ANNOTATION_TARGET, target.renderName, context)
if (annotated.source?.hasValOrVar() != true) {
reporter.reportOn(annotation.source, FirErrors.REDUNDANT_ANNOTATION_TARGET, target.renderName, context)
}
} else {
reporter.reportOn(annotation.source, FirErrors.INAPPLICABLE_PARAM_TARGET, context)
}
@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.fir.analysis.checkers.expression
import org.jetbrains.kotlin.config.AnalysisFlags
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.analysis.checkers.*
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
@@ -63,18 +62,15 @@ object FirOptInUsageBaseChecker {
private fun FirAnnotatedDeclaration.loadExperimentalitiesFromAnnotationTo(
session: FirSession,
result: MutableCollection<Experimentality>,
fromSetter: Boolean = false
result: MutableCollection<Experimentality>
) {
for (annotation in annotations) {
val annotationType = annotation.annotationTypeRef.coneTypeSafe<ConeClassLikeType>()
if (annotation.useSiteTarget != AnnotationUseSiteTarget.PROPERTY_SETTER || fromSetter) {
result.addIfNotNull(
annotationType?.lookupTag?.toFirRegularClassSymbol(
session
)?.loadExperimentalityForMarkerAnnotation()
)
}
result.addIfNotNull(
annotationType?.lookupTag?.toFirRegularClassSymbol(
session
)?.loadExperimentalityForMarkerAnnotation()
)
}
}
@@ -157,7 +153,7 @@ object FirOptInUsageBaseChecker {
parentClassSymbol?.loadExperimentalities(context, result, visited, fromSetter = false, dispatchReceiverType = null)
}
fir.loadExperimentalitiesFromAnnotationTo(session, result, fromSetter)
fir.loadExperimentalitiesFromAnnotationTo(session, result)
if (fir is FirTypeAlias) {
fir.expandedTypeRef.coneType.addExperimentalities(context, result, visited)
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.lightTree.converter
import com.intellij.lang.LighterASTNode
import com.intellij.psi.TokenType
import com.intellij.util.diff.FlyweightCapableTreeStructure
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.KtNodeTypes.*
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.builtins.StandardNames.DEFAULT_VALUE_PARAMETER
@@ -16,6 +17,7 @@ import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.*
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.builder.*
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
@@ -56,11 +58,9 @@ class DeclarationsConverter(
session: FirSession,
private val baseScopeProvider: FirScopeProvider,
tree: FlyweightCapableTreeStructure<LighterASTNode>,
offset: Int = 0,
@set:PrivateForInline override var offset: Int = 0,
context: Context<LighterASTNode> = Context()
) : BaseConverter(session, tree, context) {
@set:PrivateForInline
override var offset: Int = offset
@OptIn(PrivateForInline::class)
inline fun <R> withOffset(newOffset: Int, block: () -> R): R {
@@ -99,7 +99,7 @@ class DeclarationsConverter(
IMPORT_LIST -> importList += convertImportDirectives(it)
CLASS -> firDeclarationList += convertClass(it)
FUN -> firDeclarationList += convertFunctionDeclaration(it) as FirDeclaration
PROPERTY -> firDeclarationList += convertPropertyDeclaration(it)
KtNodeTypes.PROPERTY -> firDeclarationList += convertPropertyDeclaration(it)
TYPEALIAS -> firDeclarationList += convertTypeAlias(it)
OBJECT_DECLARATION -> firDeclarationList += convertClass(it)
SCRIPT -> {
@@ -132,7 +132,7 @@ class DeclarationsConverter(
when (node.tokenType) {
CLASS, OBJECT_DECLARATION -> container += convertClass(node) as FirStatement
FUN -> container += convertFunctionDeclaration(node)
PROPERTY -> container += convertPropertyDeclaration(node) as FirStatement
KtNodeTypes.PROPERTY -> container += convertPropertyDeclaration(node) as FirStatement
DESTRUCTURING_DECLARATION -> container += convertDestructingDeclaration(node).toFirDestructingDeclaration(baseModuleData)
TYPEALIAS -> container += convertTypeAlias(node) as FirStatement
CLASS_INITIALIZER -> container += convertAnonymousInitializer(node) as FirStatement
@@ -299,7 +299,7 @@ class DeclarationsConverter(
/**
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseAnnotationOrList
*/
fun convertAnnotation(annotationNode: LighterASTNode): List<FirAnnotation> {
fun convertAnnotation(annotationNode: LighterASTNode): List<FirAnnotationCall> {
var annotationTarget: AnnotationUseSiteTarget? = null
return annotationNode.forEachChildrenReturnList { node, container ->
when (node.tokenType) {
@@ -316,15 +316,15 @@ class DeclarationsConverter(
lateinit var annotationTarget: AnnotationUseSiteTarget
annotationUseSiteTarget.forEachChildren {
when (it.tokenType) {
FIELD_KEYWORD -> annotationTarget = AnnotationUseSiteTarget.FIELD
FILE_KEYWORD -> annotationTarget = AnnotationUseSiteTarget.FILE
FIELD_KEYWORD -> annotationTarget = FIELD
FILE_KEYWORD -> annotationTarget = FILE
PROPERTY_KEYWORD -> annotationTarget = AnnotationUseSiteTarget.PROPERTY
GET_KEYWORD -> annotationTarget = AnnotationUseSiteTarget.PROPERTY_GETTER
SET_KEYWORD -> annotationTarget = AnnotationUseSiteTarget.PROPERTY_SETTER
RECEIVER_KEYWORD -> annotationTarget = AnnotationUseSiteTarget.RECEIVER
PARAM_KEYWORD -> annotationTarget = AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER
SETPARAM_KEYWORD -> annotationTarget = AnnotationUseSiteTarget.SETTER_PARAMETER
DELEGATE_KEYWORD -> annotationTarget = AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD
GET_KEYWORD -> annotationTarget = PROPERTY_GETTER
SET_KEYWORD -> annotationTarget = PROPERTY_SETTER
RECEIVER_KEYWORD -> annotationTarget = RECEIVER
PARAM_KEYWORD -> annotationTarget = CONSTRUCTOR_PARAMETER
SETPARAM_KEYWORD -> annotationTarget = SETTER_PARAMETER
DELEGATE_KEYWORD -> annotationTarget = PROPERTY_DELEGATE_FIELD
}
}
@@ -338,7 +338,7 @@ class DeclarationsConverter(
fun convertAnnotationEntry(
unescapedAnnotation: LighterASTNode,
defaultAnnotationUseSiteTarget: AnnotationUseSiteTarget? = null
): FirAnnotation {
): FirAnnotationCall {
var annotationUseSiteTarget: AnnotationUseSiteTarget? = null
lateinit var constructorCalleePair: Pair<FirTypeRef, List<FirExpression>>
unescapedAnnotation.forEachChildren {
@@ -766,7 +766,7 @@ class DeclarationsConverter(
ENUM_ENTRY -> container += convertEnumEntry(node, classWrapper)
CLASS -> container += convertClass(node)
FUN -> container += convertFunctionDeclaration(node) as FirDeclaration
PROPERTY -> container += convertPropertyDeclaration(node, classWrapper)
KtNodeTypes.PROPERTY -> container += convertPropertyDeclaration(node, classWrapper)
TYPEALIAS -> container += convertTypeAlias(node)
OBJECT_DECLARATION -> container += convertClass(node)
CLASS_INITIALIZER -> container += convertAnonymousInitializer(node) //anonymousInitializer
@@ -797,7 +797,7 @@ class DeclarationsConverter(
primaryConstructor?.forEachChildren {
when (it.tokenType) {
MODIFIER_LIST -> modifiers = convertModifierList(it)
VALUE_PARAMETER_LIST -> valueParameters += convertValueParameters(it)
VALUE_PARAMETER_LIST -> valueParameters += convertValueParameters(it, ValueParameterDeclaration.PRIMARY_CONSTRUCTOR)
}
}
@@ -1150,6 +1150,7 @@ class DeclarationsConverter(
symbol,
).also {
it.status = defaultAccessorStatus()
it.annotations += modifiers.annotations.filterUseSiteTarget(PROPERTY_GETTER)
it.initContainingClassAttr()
}
// NOTE: We still need the setter even for a val property so we can report errors (e.g., VAL_WITH_SETTER).
@@ -1160,9 +1161,12 @@ class DeclarationsConverter(
moduleData,
FirDeclarationOrigin.Source,
returnType.copyWithNewSourceKind(FirFakeSourceElementKind.DefaultAccessor),
propertyVisibility, symbol,
propertyVisibility,
symbol,
parameterAnnotations = modifiers.annotations.filterUseSiteTarget(SETTER_PARAMETER)
).also {
it.status = defaultAccessorStatus()
it.annotations += modifiers.annotations.filterUseSiteTarget(PROPERTY_SETTER)
it.initContainingClassAttr()
}
} else null
@@ -1190,7 +1194,10 @@ class DeclarationsConverter(
)
}
}
annotations += modifiers.annotations
annotations += if (isLocal) modifiers.annotations else modifiers.annotations.filter {
it.useSiteTarget != PROPERTY_GETTER &&
(!isVar || it.useSiteTarget != SETTER_PARAMETER && it.useSiteTarget != PROPERTY_SETTER)
}
}.also {
fillDanglingConstraintsTo(firTypeParameters, typeConstraints, it)
}
@@ -1287,7 +1294,9 @@ class DeclarationsConverter(
SET_KEYWORD -> isGetter = false
MODIFIER_LIST -> modifiers = convertModifierList(it)
TYPE_REFERENCE -> returnType = convertType(it)
VALUE_PARAMETER_LIST -> firValueParameters = convertSetterParameter(it, propertyTypeRefToUse)
VALUE_PARAMETER_LIST -> firValueParameters = convertSetterParameter(
it, propertyTypeRefToUse, propertyModifiers.annotations.filterUseSiteTarget(SETTER_PARAMETER)
)
CONTRACT_EFFECT_LIST -> outerContractDescription = obtainContractDescription(it)
BLOCK -> block = it
else -> if (it.isExpression()) expression = it
@@ -1305,6 +1314,10 @@ class DeclarationsConverter(
isExternal = propertyModifiers.hasExternal() || modifiers.hasExternal()
}
val sourceElement = getterOrSetter.toFirSourceElement()
val accessorAdditionalAnnotations = propertyModifiers.annotations.filterUseSiteTarget(
if (isGetter) PROPERTY_GETTER
else PROPERTY_SETTER
)
if (block == null && expression == null) {
return FirDefaultPropertyAccessor
.createGetterOrSetter(
@@ -1318,6 +1331,7 @@ class DeclarationsConverter(
)
.also { accessor ->
accessor.annotations += modifiers.annotations
accessor.annotations += accessorAdditionalAnnotations
accessor.status = status
accessor.initContainingClassAttr()
}
@@ -1333,6 +1347,7 @@ class DeclarationsConverter(
this.status = status
context.firFunctionTargets += target
annotations += modifiers.annotations
annotations += accessorAdditionalAnnotations
if (!isGetter) {
valueParameters += firValueParameters
@@ -1398,7 +1413,7 @@ class DeclarationsConverter(
} else {
FirDefaultPropertyBackingField(
moduleData = baseModuleData,
annotations = modifiers.annotations,
annotations = mutableListOf(),
returnTypeRef = propertyReturnType.copyWithNewSourceKind(FirFakeSourceElementKind.DefaultAccessor),
isVar = isVar,
propertySymbol = propertySymbol,
@@ -1420,7 +1435,7 @@ class DeclarationsConverter(
}
}
private fun obtainContractDescription(rawContractDescription: LighterASTNode): FirContractDescription? =
private fun obtainContractDescription(rawContractDescription: LighterASTNode): FirContractDescription =
buildRawContractDescription {
source = rawContractDescription.toFirSourceElement()
extractRawEffects(rawContractDescription, rawEffects)
@@ -1452,7 +1467,11 @@ class DeclarationsConverter(
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parsePropertyGetterOrSetter
* @see org.jetbrains.kotlin.fir.builder.RawFirBuilder.Visitor.toFirValueParameter
*/
private fun convertSetterParameter(setterParameter: LighterASTNode, propertyTypeRef: FirTypeRef): FirValueParameter {
private fun convertSetterParameter(
setterParameter: LighterASTNode,
propertyTypeRef: FirTypeRef,
additionalAnnotations: List<FirAnnotation>
): FirValueParameter {
var modifiers = Modifier()
lateinit var firValueParameter: FirValueParameter
setterParameter.forEachChildren {
@@ -1473,7 +1492,8 @@ class DeclarationsConverter(
isCrossinline = modifiers.hasCrossinline() || firValueParameter.isCrossinline
isNoinline = modifiers.hasNoinline() || firValueParameter.isNoinline
isVararg = modifiers.hasVararg() || firValueParameter.isVararg
annotations += modifiers.annotations + firValueParameter.annotations
annotations += firValueParameter.annotations
annotations += additionalAnnotations
}
}
@@ -2081,11 +2101,12 @@ class DeclarationsConverter(
*/
fun convertValueParameters(
valueParameters: LighterASTNode,
valueParameterDeclaration: ValueParameterDeclaration = ValueParameterDeclaration.OTHER
valueParameterDeclaration: ValueParameterDeclaration = ValueParameterDeclaration.OTHER,
additionalAnnotations: List<FirAnnotation> = emptyList()
): List<ValueParameter> {
return valueParameters.forEachChildrenReturnList { node, container ->
when (node.tokenType) {
VALUE_PARAMETER -> container += convertValueParameter(node, valueParameterDeclaration)
VALUE_PARAMETER -> container += convertValueParameter(node, valueParameterDeclaration, additionalAnnotations)
}
}
}
@@ -2095,7 +2116,8 @@ class DeclarationsConverter(
*/
fun convertValueParameter(
valueParameter: LighterASTNode,
valueParameterDeclaration: ValueParameterDeclaration = ValueParameterDeclaration.OTHER
valueParameterDeclaration: ValueParameterDeclaration = ValueParameterDeclaration.OTHER,
additionalAnnotations: List<FirAnnotation> = emptyList()
): ValueParameter {
var modifiers = Modifier()
var isVal = false
@@ -2128,7 +2150,14 @@ class DeclarationsConverter(
isCrossinline = modifiers.hasCrossinline()
isNoinline = modifiers.hasNoinline()
isVararg = modifiers.hasVararg()
annotations += modifiers.annotations
val isFromPrimaryConstructor = valueParameterDeclaration == ValueParameterDeclaration.PRIMARY_CONSTRUCTOR
annotations += modifiers.annotations.filter {
!isFromPrimaryConstructor || it.useSiteTarget == null ||
it.useSiteTarget == CONSTRUCTOR_PARAMETER ||
it.useSiteTarget == RECEIVER ||
it.useSiteTarget == FILE
}
annotations += additionalAnnotations
}
return ValueParameter(isVal, isVar, modifiers, firValueParameter, destructuringDeclaration)
}
@@ -5,8 +5,10 @@
package org.jetbrains.kotlin.fir.lightTree.fir
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.builder.Context
import org.jetbrains.kotlin.fir.builder.filterUseSiteTarget
import org.jetbrains.kotlin.fir.builder.initContainingClassAttr
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.buildProperty
@@ -77,7 +79,11 @@ class ValueParameter(
isConst = modifiers.hasConst()
isLateInit = false
}
annotations += this@ValueParameter.firValueParameter.annotations
annotations += modifiers.annotations.filter {
it.useSiteTarget == null || it.useSiteTarget == AnnotationUseSiteTarget.PROPERTY ||
it.useSiteTarget == AnnotationUseSiteTarget.FIELD ||
it.useSiteTarget == AnnotationUseSiteTarget.PROPERTY_DELEGATE_FIELD
}
val defaultAccessorSource = propertySource?.fakeElement(FirFakeSourceElementKind.DefaultAccessor)
getter = FirDefaultPropertyGetter(
defaultAccessorSource,
@@ -86,7 +92,10 @@ class ValueParameter(
type.copyWithNewSourceKind(FirFakeSourceElementKind.DefaultAccessor),
modifiers.getVisibility(),
symbol,
).also { it.initContainingClassAttr(context) }
).also {
it.initContainingClassAttr(context)
it.annotations += modifiers.annotations.filterUseSiteTarget(AnnotationUseSiteTarget.PROPERTY_GETTER)
}
setter = if (this.isVar) FirDefaultPropertySetter(
defaultAccessorSource,
moduleData,
@@ -94,7 +103,11 @@ class ValueParameter(
type.copyWithNewSourceKind(FirFakeSourceElementKind.DefaultAccessor),
modifiers.getVisibility(),
symbol,
).also { it.initContainingClassAttr(context) } else null
parameterAnnotations = modifiers.annotations.filterUseSiteTarget(AnnotationUseSiteTarget.SETTER_PARAMETER)
).also {
it.initContainingClassAttr(context)
it.annotations += modifiers.annotations.filterUseSiteTarget(AnnotationUseSiteTarget.PROPERTY_SETTER)
} else null
}.apply {
if (firValueParameter.isVararg) {
this.isFromVararg = true
@@ -9,12 +9,12 @@ import com.intellij.lang.LighterASTNode
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.types.Variance
open class Modifier(var modifiers: Long = ModifierFlag.NONE.value) {
val annotations: MutableList<FirAnnotation> = mutableListOf()
val annotations: MutableList<FirAnnotationCall> = mutableListOf()
fun addModifier(modifier: LighterASTNode, isInClass: Boolean = false) {
when (val tokenType = modifier.tokenType) {
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.*
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
import org.jetbrains.kotlin.fir.contracts.builder.buildRawContractDescription
@@ -44,7 +45,6 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.*
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
import org.jetbrains.kotlin.types.ConstantValueKind
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.expressions.OperatorConventions
import org.jetbrains.kotlin.util.OperatorNameConventions
@@ -183,8 +183,9 @@ open class RawFirBuilder(
open fun convertValueParameter(
valueParameter: KtParameter,
defaultTypeRef: FirTypeRef? = null,
valueParameterDeclaration: ValueParameterDeclaration = ValueParameterDeclaration.OTHER
): FirValueParameter = valueParameter.toFirValueParameter(defaultTypeRef, valueParameterDeclaration)
valueParameterDeclaration: ValueParameterDeclaration = ValueParameterDeclaration.OTHER,
additionalAnnotations: List<FirAnnotation> = emptyList()
): FirValueParameter = valueParameter.toFirValueParameter(defaultTypeRef, valueParameterDeclaration, additionalAnnotations)
private fun KtTypeReference?.toFirOrImplicitType(): FirTypeRef =
convertSafe() ?: buildImplicitTypeRef {
@@ -365,6 +366,8 @@ open class RawFirBuilder(
propertyTypeRef: FirTypeRef,
propertySymbol: FirPropertySymbol,
isGetter: Boolean,
accessorAnnotationsFromProperty: List<FirAnnotation>,
parameterAnnotationsFromProperty: List<FirAnnotation>,
): FirPropertyAccessor? {
val accessorVisibility =
if (this?.visibility != null && this.visibility != Visibilities.Unknown) this.visibility else property.visibility
@@ -395,8 +398,11 @@ open class RawFirBuilder(
this.isGetter = isGetter
this.status = status
extractAnnotationsTo(this)
annotations += accessorAnnotationsFromProperty
this@RawFirBuilder.context.firFunctionTargets += accessorTarget
extractValueParametersTo(this, propertyTypeRefToUse)
extractValueParametersTo(
this, ValueParameterDeclaration.OTHER, propertyTypeRefToUse, parameterAnnotationsFromProperty
)
if (!isGetter && valueParameters.isEmpty()) {
valueParameters += buildDefaultSetterValueParameter {
this.source = source.fakeElement(FirFakeSourceElementKind.DefaultAccessor)
@@ -404,6 +410,7 @@ open class RawFirBuilder(
origin = FirDeclarationOrigin.Source
returnTypeRef = propertyTypeRefToUse
symbol = FirValueParameterSymbol(DEFAULT_VALUE_PARAMETER)
annotations += parameterAnnotationsFromProperty
}
}
symbol = FirPropertyAccessorSymbol()
@@ -433,12 +440,14 @@ open class RawFirBuilder(
propertyTypeRefToUse,
accessorVisibility,
propertySymbol,
isGetter
isGetter,
parameterAnnotations = parameterAnnotationsFromProperty
)
.also {
if (this != null) {
it.extractAnnotationsFrom(this)
}
it.annotations += accessorAnnotationsFromProperty
it.status = status
it.initContainingClassAttr()
}
@@ -512,8 +521,9 @@ open class RawFirBuilder(
}
private fun KtParameter.toFirValueParameter(
defaultTypeRef: FirTypeRef? = null,
valueParameterDeclaration: ValueParameterDeclaration = ValueParameterDeclaration.OTHER
defaultTypeRef: FirTypeRef?,
valueParameterDeclaration: ValueParameterDeclaration,
additionalAnnotations: List<FirAnnotation>
): FirValueParameter {
val name = convertValueParameterName(nameAsSafeName, nameIdentifier?.node?.text, valueParameterDeclaration)
return buildValueParameter {
@@ -533,7 +543,18 @@ open class RawFirBuilder(
isCrossinline = hasModifier(CROSSINLINE_KEYWORD)
isNoinline = hasModifier(NOINLINE_KEYWORD)
isVararg = isVarArg
extractAnnotationsTo(this)
val isFromPrimaryConstructor = valueParameterDeclaration == ValueParameterDeclaration.PRIMARY_CONSTRUCTOR
for (annotationEntry in annotationEntries) {
annotationEntry.convert<FirAnnotation>().takeIf {
!isFromPrimaryConstructor || it.useSiteTarget == null ||
it.useSiteTarget == CONSTRUCTOR_PARAMETER ||
it.useSiteTarget == RECEIVER ||
it.useSiteTarget == FILE
}?.let {
this.annotations += it
}
}
annotations += additionalAnnotations
}
}
@@ -549,6 +570,10 @@ open class RawFirBuilder(
}
val propertySource = toFirSourceElement(FirFakeSourceElementKind.PropertyFromParameter)
val propertyName = nameAsSafeName
val parameterAnnotations = mutableListOf<FirAnnotationCall>()
for (annotationEntry in annotationEntries) {
parameterAnnotations += annotationEntry.convert<FirAnnotationCall>()
}
return buildProperty {
source = propertySource
moduleData = baseModuleData
@@ -576,7 +601,10 @@ open class RawFirBuilder(
type.copyWithNewSourceKind(FirFakeSourceElementKind.DefaultAccessor),
visibility,
symbol,
).also { it.initContainingClassAttr() }
).also { getter ->
getter.initContainingClassAttr()
getter.annotations += parameterAnnotations.filterUseSiteTarget(PROPERTY_GETTER)
}
setter = if (isMutable) FirDefaultPropertySetter(
defaultAccessorSource,
baseModuleData,
@@ -584,8 +612,16 @@ open class RawFirBuilder(
type.copyWithNewSourceKind(FirFakeSourceElementKind.DefaultAccessor),
visibility,
symbol,
).also { it.initContainingClassAttr() } else null
extractAnnotationsTo(this)
parameterAnnotations = parameterAnnotations.filterUseSiteTarget(SETTER_PARAMETER)
).also { setter ->
setter.initContainingClassAttr()
setter.annotations += parameterAnnotations.filterUseSiteTarget(PROPERTY_SETTER)
} else null
annotations += parameterAnnotations.filter {
it.useSiteTarget == null || it.useSiteTarget == PROPERTY ||
it.useSiteTarget == FIELD ||
it.useSiteTarget == PROPERTY_DELEGATE_FIELD
}
dispatchReceiverType = currentDispatchReceiverType()
}.apply {
@@ -678,10 +714,14 @@ open class RawFirBuilder(
private fun KtDeclarationWithBody.extractValueParametersTo(
container: FirFunctionBuilder,
valueParameterDeclaration: ValueParameterDeclaration,
defaultTypeRef: FirTypeRef? = null,
additionalAnnotations: List<FirAnnotation> = emptyList(),
) {
for (valueParameter in valueParameters) {
container.valueParameters += convertValueParameter(valueParameter, defaultTypeRef)
container.valueParameters += convertValueParameter(
valueParameter, defaultTypeRef, valueParameterDeclaration, additionalAnnotations = additionalAnnotations
)
}
}
@@ -852,7 +892,7 @@ open class RawFirBuilder(
delegatedConstructor = firDelegatedCall
typeParameters += constructorTypeParametersFromConstructedClass(ownerTypeParameters)
this@toFirConstructor?.extractAnnotationsTo(this)
this@toFirConstructor?.extractValueParametersTo(this)
this@toFirConstructor?.extractValueParametersTo(this, ValueParameterDeclaration.PRIMARY_CONSTRUCTOR)
this.body = body
}.apply {
containingClassForStaticMemberAttr = currentDispatchReceiverType()!!.lookupTag
@@ -1401,7 +1441,7 @@ open class RawFirBuilder(
this@RawFirBuilder.context.firFunctionTargets += target
extractAnnotationsTo(this)
typeParameters += constructorTypeParametersFromConstructedClass(ownerTypeParameters)
extractValueParametersTo(this)
extractValueParametersTo(this, ValueParameterDeclaration.OTHER)
val (body, _) = buildFirBody()
@@ -1478,6 +1518,10 @@ open class RawFirBuilder(
initializer = propertyInitializer
val propertyAnnotations = mutableListOf<FirAnnotationCall>()
for (annotationEntry in annotationEntries) {
propertyAnnotations += annotationEntry.convert<FirAnnotationCall>()
}
if (this@toFirProperty.isLocal) {
isLocal = true
symbol = FirPropertySymbol(propertyName)
@@ -1529,13 +1573,17 @@ open class RawFirBuilder(
this@toFirProperty,
propertyType,
propertySymbol = symbol,
isGetter = true
isGetter = true,
accessorAnnotationsFromProperty = propertyAnnotations.filterUseSiteTarget(PROPERTY_GETTER),
parameterAnnotationsFromProperty = emptyList()
)
setter = this@toFirProperty.setter.toFirPropertyAccessor(
this@toFirProperty,
propertyType,
propertySymbol = symbol,
isGetter = false
isGetter = false,
accessorAnnotationsFromProperty = propertyAnnotations.filterUseSiteTarget(PROPERTY_SETTER),
parameterAnnotationsFromProperty = propertyAnnotations.filterUseSiteTarget(SETTER_PARAMETER)
)
status = FirDeclarationStatusImpl(visibility, modality).apply {
@@ -1575,7 +1623,10 @@ open class RawFirBuilder(
}
}
}
extractAnnotationsTo(this)
annotations += if (isLocal) propertyAnnotations else propertyAnnotations.filter {
it.useSiteTarget != PROPERTY_GETTER &&
(!isVar || it.useSiteTarget != SETTER_PARAMETER && it.useSiteTarget != PROPERTY_SETTER)
}
}.also {
if (!isLocal) {
fillDanglingConstraintsTo(it)
@@ -1261,6 +1261,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
enum class ValueParameterDeclaration {
OTHER,
LAMBDA,
CATCH
CATCH,
PRIMARY_CONSTRUCTOR,
}
}
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.builder
import com.intellij.psi.tree.IElementType
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.contracts.FirContractDescription
import org.jetbrains.kotlin.fir.contracts.builder.buildLegacyRawContractDescription
@@ -474,6 +475,7 @@ fun <T> FirPropertyBuilder.generateAccessorsByDelegate(
}
if (isVar && (setter == null || setter is FirDefaultPropertyAccessor)) {
val annotations = setter?.annotations
val parameterAnnotations = setter?.valueParameters?.firstOrNull()?.annotations
setter = buildPropertyAccessor {
this.source = fakeSource
this.moduleData = moduleData
@@ -493,6 +495,9 @@ fun <T> FirPropertyBuilder.generateAccessorsByDelegate(
isCrossinline = false
isNoinline = false
isVararg = false
if (parameterAnnotations != null) {
this.annotations.addAll(parameterAnnotations)
}
}
valueParameters += parameter
symbol = FirPropertyAccessorSymbol()
@@ -580,6 +585,19 @@ fun FirQualifiedAccess.wrapWithSafeCall(receiver: FirExpression, source: FirSour
}
}
fun List<FirAnnotationCall>.filterUseSiteTarget(target: AnnotationUseSiteTarget): List<FirAnnotationCall> =
mapNotNull {
if (it.useSiteTarget != target) null
else buildAnnotationCall {
source = it.source?.fakeElement(FirFakeSourceElementKind.FromUseSiteTarget)
useSiteTarget = it.useSiteTarget
annotationTypeRef = it.annotationTypeRef
argumentList = it.argumentList
calleeReference = it.calleeReference
argumentMapping = it.argumentMapping
}
}
fun <T> FirCallableDeclaration.initContainingClassAttr(context: Context<T>) {
containingClassForStaticMemberAttr = currentDispatchReceiverType(context)?.lookupTag ?: return
}
@@ -69,8 +69,12 @@ fun getDeprecationsFromAccessors(
currentVersion: ApiVersion
): DeprecationsPerUseSite {
val perUseSite = buildMap<AnnotationUseSiteTarget, DeprecationInfo> {
setter?.getDeprecationInfos(currentVersion)?.all?.let { put(AnnotationUseSiteTarget.PROPERTY_SETTER, it) }
getter?.getDeprecationInfos(currentVersion)?.all?.let { put(AnnotationUseSiteTarget.PROPERTY_GETTER, it) }
val setterDeprecations = setter?.getDeprecationInfos(currentVersion)
setterDeprecations?.all?.let { put(AnnotationUseSiteTarget.PROPERTY_SETTER, it) }
setterDeprecations?.bySpecificSite?.let { putAll(it) }
val getterDeprecations = getter?.getDeprecationInfos(currentVersion)
getterDeprecations?.all?.let { put(AnnotationUseSiteTarget.PROPERTY_GETTER, it) }
getterDeprecations?.bySpecificSite?.let { putAll(it) }
}
return if (perUseSite.isEmpty()) EmptyDeprecationsPerUseSite else DeprecationsPerUseSite(null, perUseSite)
}
@@ -180,6 +180,9 @@ sealed class FirFakeSourceElementKind : FirSourceElementKind() {
// for the implicit field storing the delegated object for class delegation
// with a fake source that refers to the KtExpression that creates the delegate
object ClassDelegationField : FirFakeSourceElementKind()
// for annotation moved to another element due to annotation use-site target
object FromUseSiteTarget : FirFakeSourceElementKind()
}
sealed class FirSourceElement {
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.contracts.impl.FirEmptyContractDescription
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.buildDefaultSetterValueParameter
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.expressions.FirBlock
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertyAccessorSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
@@ -72,12 +73,16 @@ abstract class FirDefaultPropertyAccessor(
propertyTypeRef: FirTypeRef,
visibility: Visibility,
propertySymbol: FirPropertySymbol,
isGetter: Boolean
isGetter: Boolean,
parameterAnnotations: List<FirAnnotation> = emptyList(),
): FirDefaultPropertyAccessor {
return if (isGetter) {
FirDefaultPropertyGetter(source, moduleData, origin, propertyTypeRef, visibility, propertySymbol, Modality.FINAL)
} else {
FirDefaultPropertySetter(source, moduleData, origin, propertyTypeRef, visibility, propertySymbol, Modality.FINAL)
FirDefaultPropertySetter(
source, moduleData, origin, propertyTypeRef, visibility, propertySymbol, Modality.FINAL,
parameterAnnotations = parameterAnnotations
)
}
}
}
@@ -116,7 +121,8 @@ class FirDefaultPropertySetter(
propertySymbol: FirPropertySymbol,
modality: Modality = Modality.FINAL,
effectiveVisibility: EffectiveVisibility? = null,
symbol: FirPropertyAccessorSymbol = FirPropertyAccessorSymbol()
symbol: FirPropertyAccessorSymbol = FirPropertyAccessorSymbol(),
parameterAnnotations: List<FirAnnotation> = emptyList(),
) : FirDefaultPropertyAccessor(
source,
moduleData,
@@ -129,6 +135,7 @@ class FirDefaultPropertySetter(
this@builder.origin = origin
this@builder.returnTypeRef = propertyTypeRef
this@builder.symbol = FirValueParameterSymbol(Name.special("<default-setter-parameter>"))
this@builder.annotations += parameterAnnotations
}
),
propertySymbol,
@@ -1,5 +1,5 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
// !LANGUAGE: +ProhibitRepeatedUseSiteTargetAnnotations
// !LANGUAGE: -ProhibitRepeatedUseSiteTargetAnnotations
// Ann is not repeatable
annotation class Ann(val x: Int)
@@ -17,6 +17,6 @@ var c = " "
set(@Ann(20) x) {}
<!REPEATED_ANNOTATION!>@get:Ann(10)<!>
<!REPEATED_ANNOTATION, REPEATED_ANNOTATION!>@get:Ann(20)<!>
<!REPEATED_ANNOTATION!>@get:Ann(20)<!>
val d: String
@Ann(30) <!REPEATED_ANNOTATION!>@Ann(40)<!> get() = "foo"
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER
// !LANGUAGE: -ProhibitRepeatedUseSiteTargetAnnotations
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER
// !LANGUAGE: +ProhibitRepeatedUseSiteTargetAnnotations
@@ -46,12 +46,12 @@ annotation class fieldOrPropAnn
annotation class getSetAndParamAnn
public class B(<!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@param:fieldOrPropAnn<!> @fieldOrPropAnn val x: Int,
@property:fieldOrPropAnn <!REPEATED_ANNOTATION, REPEATED_ANNOTATION!>@fieldOrPropAnn<!> val y: Int) {
@property:fieldOrPropAnn <!REPEATED_ANNOTATION!>@fieldOrPropAnn<!> val y: Int) {
@fieldOrPropAnn @field:fieldOrPropAnn
val z: Int = 42
<!WRONG_ANNOTATION_TARGET!>@getSetAndParamAnn<!>
<!REPEATED_ANNOTATION!>@setparam:getSetAndParamAnn<!>
@setparam:getSetAndParamAnn
var w: Int
@getSetAndParamAnn <!REPEATED_ANNOTATION!>@get:getSetAndParamAnn<!> get() = 0
// See KT-15470: fake INAPPLICABLE_TARGET_ON_PROPERTY
@@ -1,13 +0,0 @@
interface Test {
<!JVM_STATIC_NOT_IN_OBJECT_OR_COMPANION!>@get:JvmStatic
val a: Int<!>
@get:JvmName("1")
val b: Int
@get:Synchronized
val c: Int
<!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@get:JvmOverloads<!>
val d: Int
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
interface Test {
<!JVM_STATIC_NOT_IN_OBJECT_OR_COMPANION!>@get:JvmStatic
val a: Int<!>
@@ -89,7 +89,7 @@ class D: AB() {
}
interface Intf {
@get:JvmName("getBar") // no error in IDE
@set:JvmName("setBar") // no error in IDE
<!INAPPLICABLE_JVM_NAME!>@get:JvmName("getBar")<!> // no error in IDE
<!INAPPLICABLE_JVM_NAME!>@set:JvmName("setBar")<!> // no error in IDE
var foo: Int
}
@@ -19,6 +19,6 @@ var z: Int = 44
fun user(): Int {
<!OPT_IN_USAGE_ERROR!>x<!> = 10
<!OPT_IN_USAGE_ERROR!>y<!> = 5
<!OPT_IN_USAGE_ERROR!>x<!> = 15
<!OPT_IN_USAGE_ERROR!>z<!> = 15
return x + <!OPT_IN_USAGE_ERROR!>y<!> + z
}