[FIR] Add type-related diagnostics for the backing field
This commit is contained in:
committed by
TeamCityServer
parent
d2124e1ec6
commit
d4d43b9907
+4
@@ -873,6 +873,10 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
|||||||
parameter<ConeKotlinType>("actualType")
|
parameter<ConeKotlinType>("actualType")
|
||||||
}
|
}
|
||||||
val ACCESSOR_FOR_DELEGATED_PROPERTY by error<KtPropertyAccessor>()
|
val ACCESSOR_FOR_DELEGATED_PROPERTY by error<KtPropertyAccessor>()
|
||||||
|
val PROPERTY_INITIALIZER_WITH_EXPLICIT_FIELD_DECLARATION by error<KtExpression>()
|
||||||
|
val PROPERTY_FIELD_DECLARATION_MISSING_INITIALIZER by error<KtBackingField>()
|
||||||
|
val PROPERTY_MUST_HAVE_GETTER by error<KtProperty>()
|
||||||
|
val PROPERTY_MUST_HAVE_SETTER by error<KtProperty>()
|
||||||
val ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS by error<KtModifierListOwner>(PositioningStrategy.ABSTRACT_MODIFIER)
|
val ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS by error<KtModifierListOwner>(PositioningStrategy.ABSTRACT_MODIFIER)
|
||||||
val LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING by warning<KtProperty>(PositioningStrategy.TYPE_PARAMETERS_LIST)
|
val LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING by warning<KtProperty>(PositioningStrategy.TYPE_PARAMETERS_LIST)
|
||||||
val LOCAL_VARIABLE_WITH_TYPE_PARAMETERS by error<KtProperty>(PositioningStrategy.TYPE_PARAMETERS_LIST)
|
val LOCAL_VARIABLE_WITH_TYPE_PARAMETERS by error<KtProperty>(PositioningStrategy.TYPE_PARAMETERS_LIST)
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
||||||
import org.jetbrains.kotlin.psi.KtAnonymousInitializer
|
import org.jetbrains.kotlin.psi.KtAnonymousInitializer
|
||||||
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
|
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
|
||||||
|
import org.jetbrains.kotlin.psi.KtBackingField
|
||||||
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
||||||
import org.jetbrains.kotlin.psi.KtBinaryExpressionWithTypeRHS
|
import org.jetbrains.kotlin.psi.KtBinaryExpressionWithTypeRHS
|
||||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||||
@@ -479,6 +480,10 @@ object FirErrors {
|
|||||||
val WRONG_SETTER_RETURN_TYPE by error0<KtTypeReference>()
|
val WRONG_SETTER_RETURN_TYPE by error0<KtTypeReference>()
|
||||||
val WRONG_GETTER_RETURN_TYPE by error2<KtTypeReference, ConeKotlinType, ConeKotlinType>()
|
val WRONG_GETTER_RETURN_TYPE by error2<KtTypeReference, ConeKotlinType, ConeKotlinType>()
|
||||||
val ACCESSOR_FOR_DELEGATED_PROPERTY by error0<KtPropertyAccessor>()
|
val ACCESSOR_FOR_DELEGATED_PROPERTY by error0<KtPropertyAccessor>()
|
||||||
|
val PROPERTY_INITIALIZER_WITH_EXPLICIT_FIELD_DECLARATION by error0<KtExpression>()
|
||||||
|
val PROPERTY_FIELD_DECLARATION_MISSING_INITIALIZER by error0<KtBackingField>()
|
||||||
|
val PROPERTY_MUST_HAVE_GETTER by error0<KtProperty>()
|
||||||
|
val PROPERTY_MUST_HAVE_SETTER by error0<KtProperty>()
|
||||||
val ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS by error0<KtModifierListOwner>(SourceElementPositioningStrategies.ABSTRACT_MODIFIER)
|
val ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS by error0<KtModifierListOwner>(SourceElementPositioningStrategies.ABSTRACT_MODIFIER)
|
||||||
val LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING by warning0<KtProperty>(SourceElementPositioningStrategies.TYPE_PARAMETERS_LIST)
|
val LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING by warning0<KtProperty>(SourceElementPositioningStrategies.TYPE_PARAMETERS_LIST)
|
||||||
val LOCAL_VARIABLE_WITH_TYPE_PARAMETERS by error0<KtProperty>(SourceElementPositioningStrategies.TYPE_PARAMETERS_LIST)
|
val LOCAL_VARIABLE_WITH_TYPE_PARAMETERS by error0<KtProperty>(SourceElementPositioningStrategies.TYPE_PARAMETERS_LIST)
|
||||||
|
|||||||
+1
@@ -54,6 +54,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
|||||||
FirPropertyTypeParametersChecker,
|
FirPropertyTypeParametersChecker,
|
||||||
FirInitializerTypeMismatchChecker,
|
FirInitializerTypeMismatchChecker,
|
||||||
FirDelegatedPropertyChecker,
|
FirDelegatedPropertyChecker,
|
||||||
|
FirPropertyFieldTypeChecker,
|
||||||
FirInlinePropertyChecker,
|
FirInlinePropertyChecker,
|
||||||
FirPropertyFromParameterChecker,
|
FirPropertyFromParameterChecker,
|
||||||
FirLocalVariableTypeParametersSyntaxChecker,
|
FirLocalVariableTypeParametersSyntaxChecker,
|
||||||
|
|||||||
+9
-1
@@ -162,7 +162,15 @@ internal fun checkPropertyInitializer(
|
|||||||
else -> {
|
else -> {
|
||||||
val propertySource = property.source ?: return
|
val propertySource = property.source ?: return
|
||||||
val isExternal = property.isEffectivelyExternal(containingClass, context)
|
val isExternal = property.isEffectivelyExternal(containingClass, context)
|
||||||
if (backingFieldRequired && !inInterface && !property.isLateInit && !isExpect && !isInitialized && !isExternal) {
|
if (
|
||||||
|
backingFieldRequired &&
|
||||||
|
!inInterface &&
|
||||||
|
!property.isLateInit &&
|
||||||
|
!isExpect &&
|
||||||
|
!isInitialized &&
|
||||||
|
!isExternal &&
|
||||||
|
property.backingField == null
|
||||||
|
) {
|
||||||
if (property.receiverTypeRef != null && !property.hasAccessorImplementation) {
|
if (property.receiverTypeRef != null && !property.hasAccessorImplementation) {
|
||||||
reporter.reportOn(propertySource, FirErrors.EXTENSION_PROPERTY_MUST_HAVE_ACCESSORS_OR_BE_ABSTRACT, context)
|
reporter.reportOn(propertySource, FirErrors.EXTENSION_PROPERTY_MUST_HAVE_ACCESSORS_OR_BE_ABSTRACT, context)
|
||||||
} else if (reachable) { // TODO: can be suppressed not to report diagnostics about no body
|
} else if (reachable) { // TODO: can be suppressed not to report diagnostics about no body
|
||||||
|
|||||||
+71
@@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 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.analysis.checkers.declaration
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirErrorExpression
|
||||||
|
import org.jetbrains.kotlin.fir.typeContext
|
||||||
|
import org.jetbrains.kotlin.fir.types.isSubtypeOf
|
||||||
|
|
||||||
|
object FirPropertyFieldTypeChecker : FirPropertyChecker() {
|
||||||
|
override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
val backingField = declaration.backingField ?: return
|
||||||
|
|
||||||
|
val typeCheckerContext = context.session.typeContext.newBaseTypeCheckerContext(
|
||||||
|
errorTypesEqualToAnything = false,
|
||||||
|
stubTypesEqualToAnything = false
|
||||||
|
)
|
||||||
|
|
||||||
|
if (declaration.initializer != null) {
|
||||||
|
reporter.reportOn(declaration.initializer?.source, FirErrors.PROPERTY_INITIALIZER_WITH_EXPLICIT_FIELD_DECLARATION, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (backingField.initializer is FirErrorExpression) {
|
||||||
|
reporter.reportOn(backingField.source, FirErrors.PROPERTY_FIELD_DECLARATION_MISSING_INITIALIZER, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (backingField.isSubtypeOf(declaration, typeCheckerContext)) {
|
||||||
|
checkAsPropertyNotSubtype(declaration, context, reporter)
|
||||||
|
} else if (declaration.isSubtypeOf(backingField, typeCheckerContext)) {
|
||||||
|
checkAsFieldNotSubtype(declaration, context, reporter)
|
||||||
|
} else {
|
||||||
|
checkAsIndependentTypes(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkAsPropertyNotSubtype(
|
||||||
|
property: FirProperty,
|
||||||
|
context: CheckerContext,
|
||||||
|
reporter: DiagnosticReporter
|
||||||
|
) {
|
||||||
|
if (property.isVar && property.setter == null) {
|
||||||
|
reporter.reportOn(property.source, FirErrors.PROPERTY_MUST_HAVE_SETTER, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkAsFieldNotSubtype(
|
||||||
|
property: FirProperty,
|
||||||
|
context: CheckerContext,
|
||||||
|
reporter: DiagnosticReporter
|
||||||
|
) {
|
||||||
|
if (property.getter == null) {
|
||||||
|
reporter.reportOn(property.source, FirErrors.PROPERTY_MUST_HAVE_GETTER, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkAsIndependentTypes(
|
||||||
|
property: FirProperty,
|
||||||
|
context: CheckerContext,
|
||||||
|
reporter: DiagnosticReporter
|
||||||
|
) {
|
||||||
|
checkAsPropertyNotSubtype(property, context, reporter)
|
||||||
|
checkAsFieldNotSubtype(property, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
+20
@@ -333,8 +333,12 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PRIVATE_SETTER_FO
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_AS_OPERATOR
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_AS_OPERATOR
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_FIELD_DECLARATION_MISSING_INITIALIZER
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_INITIALIZER_IN_INTERFACE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_INITIALIZER_IN_INTERFACE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_INITIALIZER_NO_BACKING_FIELD
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_INITIALIZER_NO_BACKING_FIELD
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_INITIALIZER_WITH_EXPLICIT_FIELD_DECLARATION
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_MUST_HAVE_GETTER
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_MUST_HAVE_SETTER
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_TYPE_MISMATCH_BY_DELEGATION
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_TYPE_MISMATCH_BY_DELEGATION
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_TYPE_MISMATCH_ON_INHERITANCE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_TYPE_MISMATCH_ON_INHERITANCE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_TYPE_MISMATCH_ON_OVERRIDE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PROPERTY_TYPE_MISMATCH_ON_OVERRIDE
|
||||||
@@ -1267,6 +1271,22 @@ class FirDefaultErrorMessages {
|
|||||||
RENDER_TYPE
|
RENDER_TYPE
|
||||||
)
|
)
|
||||||
map.put(ACCESSOR_FOR_DELEGATED_PROPERTY, "Delegated property cannot have accessors with non-default implementations")
|
map.put(ACCESSOR_FOR_DELEGATED_PROPERTY, "Delegated property cannot have accessors with non-default implementations")
|
||||||
|
map.put(
|
||||||
|
PROPERTY_INITIALIZER_WITH_EXPLICIT_FIELD_DECLARATION,
|
||||||
|
"Property initializers are not allowed for properties with an explicit backing field declaration"
|
||||||
|
)
|
||||||
|
map.put(
|
||||||
|
PROPERTY_FIELD_DECLARATION_MISSING_INITIALIZER,
|
||||||
|
"Property backing field declaration must have an initializer"
|
||||||
|
)
|
||||||
|
map.put(
|
||||||
|
PROPERTY_MUST_HAVE_GETTER,
|
||||||
|
"This property needs a custom getter, because it's type is not a supertype of the backing field's type"
|
||||||
|
)
|
||||||
|
map.put(
|
||||||
|
PROPERTY_MUST_HAVE_SETTER,
|
||||||
|
"This property needs a custom setter, because it's type is not a subtype of the backing field's type"
|
||||||
|
)
|
||||||
map.put(ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS, "This property cannot be declared abstract")
|
map.put(ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS, "This property cannot be declared abstract")
|
||||||
map.put(LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING, "Type parameters for local variables are deprecated")
|
map.put(LOCAL_VARIABLE_WITH_TYPE_PARAMETERS_WARNING, "Type parameters for local variables are deprecated")
|
||||||
map.put(LOCAL_VARIABLE_WITH_TYPE_PARAMETERS, "Local variables are not allowed to have type parameters")
|
map.put(LOCAL_VARIABLE_WITH_TYPE_PARAMETERS, "Local variables are not allowed to have type parameters")
|
||||||
|
|||||||
+2
-2
@@ -524,7 +524,7 @@ class ControlFlowGraphBuilder {
|
|||||||
// ----------------------------------- Property -----------------------------------
|
// ----------------------------------- Property -----------------------------------
|
||||||
|
|
||||||
fun enterProperty(property: FirProperty): PropertyInitializerEnterNode? {
|
fun enterProperty(property: FirProperty): PropertyInitializerEnterNode? {
|
||||||
if (property.initializer == null && property.delegate == null) return null
|
if (property.initializer == null && property.delegate == null && property.backingField == null) return null
|
||||||
|
|
||||||
val graph = ControlFlowGraph(property, "val ${property.name}", ControlFlowGraph.Kind.PropertyInitializer)
|
val graph = ControlFlowGraph(property, "val ${property.name}", ControlFlowGraph.Kind.PropertyInitializer)
|
||||||
pushGraph(graph, Mode.PropertyInitializer)
|
pushGraph(graph, Mode.PropertyInitializer)
|
||||||
@@ -542,7 +542,7 @@ class ControlFlowGraphBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun exitProperty(property: FirProperty): Pair<PropertyInitializerExitNode, ControlFlowGraph>? {
|
fun exitProperty(property: FirProperty): Pair<PropertyInitializerExitNode, ControlFlowGraph>? {
|
||||||
if (property.initializer == null && property.delegate == null) return null
|
if (property.initializer == null && property.delegate == null && property.backingField == null) return null
|
||||||
val exitNode = exitTargetsForTry.pop() as PropertyInitializerExitNode
|
val exitNode = exitTargetsForTry.pop() as PropertyInitializerExitNode
|
||||||
popAndAddEdge(exitNode)
|
popAndAddEdge(exitNode)
|
||||||
val graph = popGraph()
|
val graph = popGraph()
|
||||||
|
|||||||
+1
@@ -110,6 +110,7 @@ open class FirTypeResolveTransformer(
|
|||||||
.transformReceiverTypeRef(this, data)
|
.transformReceiverTypeRef(this, data)
|
||||||
.transformGetter(this, data)
|
.transformGetter(this, data)
|
||||||
.transformSetter(this, data)
|
.transformSetter(this, data)
|
||||||
|
.transformBackingField(this, data)
|
||||||
.transformAnnotations(this, data)
|
.transformAnnotations(this, data)
|
||||||
if (property.isFromVararg == true) {
|
if (property.isFromVararg == true) {
|
||||||
property.transformTypeToArrayType()
|
property.transformTypeToArrayType()
|
||||||
|
|||||||
+7
@@ -266,6 +266,13 @@ open class FirBodyResolveTransformer(
|
|||||||
return declarationsTransformer.transformProperty(property, data)
|
return declarationsTransformer.transformProperty(property, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun transformBackingField(
|
||||||
|
backingField: FirBackingField,
|
||||||
|
data: ResolutionMode
|
||||||
|
): FirStatement {
|
||||||
|
return declarationsTransformer.transformBackingField(backingField, data)
|
||||||
|
}
|
||||||
|
|
||||||
override fun transformField(field: FirField, data: ResolutionMode): FirField {
|
override fun transformField(field: FirField, data: ResolutionMode): FirField {
|
||||||
return declarationsTransformer.transformField(field, data)
|
return declarationsTransformer.transformField(field, data)
|
||||||
}
|
}
|
||||||
|
|||||||
+68
-22
@@ -121,6 +121,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
|||||||
property.transformStatus(this, property.resolveStatus().mode())
|
property.transformStatus(this, property.resolveStatus().mode())
|
||||||
property.getter?.let { it.transformStatus(this, it.resolveStatus(containingProperty = property).mode()) }
|
property.getter?.let { it.transformStatus(this, it.resolveStatus(containingProperty = property).mode()) }
|
||||||
property.setter?.let { it.transformStatus(this, it.resolveStatus(containingProperty = property).mode()) }
|
property.setter?.let { it.transformStatus(this, it.resolveStatus(containingProperty = property).mode()) }
|
||||||
|
property.backingField?.let { it.transformStatus(this, it.resolveStatus(containingProperty = property).mode()) }
|
||||||
return transformLocalVariable(property)
|
return transformLocalVariable(property)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,9 +138,10 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
|||||||
val initializerIsAlreadyResolved = bodyResolveState >= FirPropertyBodyResolveState.INITIALIZER_RESOLVED
|
val initializerIsAlreadyResolved = bodyResolveState >= FirPropertyBodyResolveState.INITIALIZER_RESOLVED
|
||||||
context.withProperty(property) {
|
context.withProperty(property) {
|
||||||
context.forPropertyInitializer {
|
context.forPropertyInitializer {
|
||||||
|
property.transformBackingField(transformer, ResolutionMode.ContextDependent)
|
||||||
property.transformDelegate(transformer, ResolutionMode.ContextDependentDelegate)
|
property.transformDelegate(transformer, ResolutionMode.ContextDependentDelegate)
|
||||||
if (!initializerIsAlreadyResolved) {
|
if (!initializerIsAlreadyResolved) {
|
||||||
property.transformChildrenWithoutAccessors(returnTypeRef)
|
property.transformChildrenWithoutComponents(returnTypeRef)
|
||||||
property.replaceBodyResolveState(FirPropertyBodyResolveState.INITIALIZER_RESOLVED)
|
property.replaceBodyResolveState(FirPropertyBodyResolveState.INITIALIZER_RESOLVED)
|
||||||
}
|
}
|
||||||
if (property.initializer != null) {
|
if (property.initializer != null) {
|
||||||
@@ -301,7 +303,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
|||||||
return variable
|
return variable
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun FirProperty.transformChildrenWithoutAccessors(returnTypeRef: FirTypeRef): FirProperty {
|
private fun FirProperty.transformChildrenWithoutComponents(returnTypeRef: FirTypeRef): FirProperty {
|
||||||
val data = withExpectedType(returnTypeRef)
|
val data = withExpectedType(returnTypeRef)
|
||||||
return transformReturnTypeRef(transformer, data)
|
return transformReturnTypeRef(transformer, data)
|
||||||
.transformInitializer(transformer, data)
|
.transformInitializer(transformer, data)
|
||||||
@@ -817,6 +819,46 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun transformBackingField(
|
||||||
|
backingField: FirBackingField,
|
||||||
|
data: ResolutionMode,
|
||||||
|
): FirStatement {
|
||||||
|
if (backingField.returnTypeRef is FirErrorTypeRef) {
|
||||||
|
return backingField
|
||||||
|
}
|
||||||
|
backingField.transformInitializer(
|
||||||
|
transformer,
|
||||||
|
withExpectedType(backingField.returnTypeRef)
|
||||||
|
)
|
||||||
|
if (backingField.returnTypeRef !is FirImplicitTypeRef) {
|
||||||
|
return backingField
|
||||||
|
}
|
||||||
|
val resultType = backingField.initializer
|
||||||
|
?.unwrapSmartcastExpression()?.typeRef
|
||||||
|
?: return backingField.transformReturnTypeRef(
|
||||||
|
transformer,
|
||||||
|
withExpectedType(
|
||||||
|
buildErrorTypeRef {
|
||||||
|
diagnostic = ConeSimpleDiagnostic(
|
||||||
|
"Cannot infer variable type without an initializer",
|
||||||
|
DiagnosticKind.InferenceError,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
)
|
||||||
|
val expectedType = resultType.toExpectedTypeRef()
|
||||||
|
return backingField.transformReturnTypeRef(
|
||||||
|
transformer,
|
||||||
|
withExpectedType(
|
||||||
|
expectedType.approximatedIfNeededOrSelf(
|
||||||
|
inferenceComponents.approximator,
|
||||||
|
backingField.visibilityForApproximation(),
|
||||||
|
inferenceComponents.session.typeContext,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private fun storeVariableReturnType(variable: FirVariable) {
|
private fun storeVariableReturnType(variable: FirVariable) {
|
||||||
val initializer = variable.initializer
|
val initializer = variable.initializer
|
||||||
if (variable.returnTypeRef is FirImplicitTypeRef) {
|
if (variable.returnTypeRef is FirImplicitTypeRef) {
|
||||||
@@ -829,26 +871,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
|||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
if (resultType != null) {
|
if (resultType != null) {
|
||||||
val expectedType = when (resultType) {
|
val expectedType = resultType.toExpectedTypeRef()
|
||||||
is FirImplicitTypeRef -> buildErrorTypeRef {
|
|
||||||
diagnostic = ConeSimpleDiagnostic("No result type for initializer", DiagnosticKind.InferenceError)
|
|
||||||
}
|
|
||||||
is FirErrorTypeRef -> buildErrorTypeRef {
|
|
||||||
diagnostic = resultType.diagnostic
|
|
||||||
resultType.source?.fakeElement(FirFakeSourceElementKind.ImplicitTypeRef)?.let {
|
|
||||||
source = it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
buildResolvedTypeRef {
|
|
||||||
type = resultType.coneType
|
|
||||||
annotations.addAll(resultType.annotations)
|
|
||||||
resultType.source?.fakeElement(FirFakeSourceElementKind.PropertyFromParameter)?.let {
|
|
||||||
source = it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
variable.transformReturnTypeRef(
|
variable.transformReturnTypeRef(
|
||||||
transformer,
|
transformer,
|
||||||
withExpectedType(
|
withExpectedType(
|
||||||
@@ -876,6 +899,29 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun FirTypeRef.toExpectedTypeRef(): FirResolvedTypeRef {
|
||||||
|
return when (this) {
|
||||||
|
is FirImplicitTypeRef -> buildErrorTypeRef {
|
||||||
|
diagnostic = ConeSimpleDiagnostic("No result type for initializer", DiagnosticKind.InferenceError)
|
||||||
|
}
|
||||||
|
is FirErrorTypeRef -> buildErrorTypeRef {
|
||||||
|
diagnostic = this@toExpectedTypeRef.diagnostic
|
||||||
|
this@toExpectedTypeRef.source?.fakeElement(FirFakeSourceElementKind.ImplicitTypeRef)?.let {
|
||||||
|
source = it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
buildResolvedTypeRef {
|
||||||
|
type = this@toExpectedTypeRef.coneType
|
||||||
|
annotations.addAll(this@toExpectedTypeRef.annotations)
|
||||||
|
this@toExpectedTypeRef.source?.fakeElement(FirFakeSourceElementKind.PropertyFromParameter)?.let {
|
||||||
|
source = it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private object ImplicitToErrorTypeTransformer : FirTransformer<Any?>() {
|
private object ImplicitToErrorTypeTransformer : FirTransformer<Any?>() {
|
||||||
override fun <E : FirElement> transformElement(element: E, data: Any?): E {
|
override fun <E : FirElement> transformElement(element: E, data: Any?): E {
|
||||||
return element
|
return element
|
||||||
|
|||||||
+1
@@ -47,6 +47,7 @@ val FirProperty.hasBackingField: Boolean
|
|||||||
get() {
|
get() {
|
||||||
if (isAbstract) return false
|
if (isAbstract) return false
|
||||||
if (delegate != null) return false
|
if (delegate != null) return false
|
||||||
|
if (backingField != null) return true
|
||||||
when (origin) {
|
when (origin) {
|
||||||
FirDeclarationOrigin.SubstitutionOverride -> return false
|
FirDeclarationOrigin.SubstitutionOverride -> return false
|
||||||
FirDeclarationOrigin.IntersectionOverride -> return false
|
FirDeclarationOrigin.IntersectionOverride -> return false
|
||||||
|
|||||||
+25
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.fir.psi
|
|||||||
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
||||||
import org.jetbrains.kotlin.psi.KtAnonymousInitializer
|
import org.jetbrains.kotlin.psi.KtAnonymousInitializer
|
||||||
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
|
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
|
||||||
|
import org.jetbrains.kotlin.psi.KtBackingField
|
||||||
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
||||||
import org.jetbrains.kotlin.psi.KtBinaryExpressionWithTypeRHS
|
import org.jetbrains.kotlin.psi.KtBinaryExpressionWithTypeRHS
|
||||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||||
@@ -2405,6 +2406,30 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(FirErrors.PROPERTY_INITIALIZER_WITH_EXPLICIT_FIELD_DECLARATION) { firDiagnostic ->
|
||||||
|
PropertyInitializerWithExplicitFieldDeclarationImpl(
|
||||||
|
firDiagnostic as FirPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
add(FirErrors.PROPERTY_FIELD_DECLARATION_MISSING_INITIALIZER) { firDiagnostic ->
|
||||||
|
PropertyFieldDeclarationMissingInitializerImpl(
|
||||||
|
firDiagnostic as FirPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
add(FirErrors.PROPERTY_MUST_HAVE_GETTER) { firDiagnostic ->
|
||||||
|
PropertyMustHaveGetterImpl(
|
||||||
|
firDiagnostic as FirPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
add(FirErrors.PROPERTY_MUST_HAVE_SETTER) { firDiagnostic ->
|
||||||
|
PropertyMustHaveSetterImpl(
|
||||||
|
firDiagnostic as FirPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
add(FirErrors.ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS) { firDiagnostic ->
|
add(FirErrors.ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS) { firDiagnostic ->
|
||||||
AbstractPropertyInPrimaryConstructorParametersImpl(
|
AbstractPropertyInPrimaryConstructorParametersImpl(
|
||||||
firDiagnostic as FirPsiDiagnostic,
|
firDiagnostic as FirPsiDiagnostic,
|
||||||
|
|||||||
+17
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
||||||
import org.jetbrains.kotlin.psi.KtAnonymousInitializer
|
import org.jetbrains.kotlin.psi.KtAnonymousInitializer
|
||||||
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
|
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
|
||||||
|
import org.jetbrains.kotlin.psi.KtBackingField
|
||||||
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
||||||
import org.jetbrains.kotlin.psi.KtBinaryExpressionWithTypeRHS
|
import org.jetbrains.kotlin.psi.KtBinaryExpressionWithTypeRHS
|
||||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||||
@@ -1702,6 +1703,22 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
override val diagnosticClass get() = AccessorForDelegatedProperty::class
|
override val diagnosticClass get() = AccessorForDelegatedProperty::class
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class PropertyInitializerWithExplicitFieldDeclaration : KtFirDiagnostic<KtExpression>() {
|
||||||
|
override val diagnosticClass get() = PropertyInitializerWithExplicitFieldDeclaration::class
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class PropertyFieldDeclarationMissingInitializer : KtFirDiagnostic<KtBackingField>() {
|
||||||
|
override val diagnosticClass get() = PropertyFieldDeclarationMissingInitializer::class
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class PropertyMustHaveGetter : KtFirDiagnostic<KtProperty>() {
|
||||||
|
override val diagnosticClass get() = PropertyMustHaveGetter::class
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class PropertyMustHaveSetter : KtFirDiagnostic<KtProperty>() {
|
||||||
|
override val diagnosticClass get() = PropertyMustHaveSetter::class
|
||||||
|
}
|
||||||
|
|
||||||
abstract class AbstractPropertyInPrimaryConstructorParameters : KtFirDiagnostic<KtModifierListOwner>() {
|
abstract class AbstractPropertyInPrimaryConstructorParameters : KtFirDiagnostic<KtModifierListOwner>() {
|
||||||
override val diagnosticClass get() = AbstractPropertyInPrimaryConstructorParameters::class
|
override val diagnosticClass get() = AbstractPropertyInPrimaryConstructorParameters::class
|
||||||
}
|
}
|
||||||
|
|||||||
+29
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
||||||
import org.jetbrains.kotlin.psi.KtAnonymousInitializer
|
import org.jetbrains.kotlin.psi.KtAnonymousInitializer
|
||||||
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
|
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
|
||||||
|
import org.jetbrains.kotlin.psi.KtBackingField
|
||||||
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
||||||
import org.jetbrains.kotlin.psi.KtBinaryExpressionWithTypeRHS
|
import org.jetbrains.kotlin.psi.KtBinaryExpressionWithTypeRHS
|
||||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||||
@@ -2738,6 +2739,34 @@ internal class AccessorForDelegatedPropertyImpl(
|
|||||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal class PropertyInitializerWithExplicitFieldDeclarationImpl(
|
||||||
|
firDiagnostic: FirPsiDiagnostic,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.PropertyInitializerWithExplicitFieldDeclaration(), KtAbstractFirDiagnostic<KtExpression> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class PropertyFieldDeclarationMissingInitializerImpl(
|
||||||
|
firDiagnostic: FirPsiDiagnostic,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.PropertyFieldDeclarationMissingInitializer(), KtAbstractFirDiagnostic<KtBackingField> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class PropertyMustHaveGetterImpl(
|
||||||
|
firDiagnostic: FirPsiDiagnostic,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.PropertyMustHaveGetter(), KtAbstractFirDiagnostic<KtProperty> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class PropertyMustHaveSetterImpl(
|
||||||
|
firDiagnostic: FirPsiDiagnostic,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.PropertyMustHaveSetter(), KtAbstractFirDiagnostic<KtProperty> {
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||||
|
}
|
||||||
|
|
||||||
internal class AbstractPropertyInPrimaryConstructorParametersImpl(
|
internal class AbstractPropertyInPrimaryConstructorParametersImpl(
|
||||||
firDiagnostic: FirPsiDiagnostic,
|
firDiagnostic: FirPsiDiagnostic,
|
||||||
override val token: ValidityToken,
|
override val token: ValidityToken,
|
||||||
|
|||||||
Reference in New Issue
Block a user