[FIR] Add FirDelegateUsesExtensionPropertyTypeParameterChecker
This commit is contained in:
committed by
TeamCityServer
parent
f97e666608
commit
dbfe3524ce
+12
@@ -2471,6 +2471,18 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(FirErrors.DELEGATE_USES_EXTENSION_PROPERTY_TYPE_PARAMETER) { firDiagnostic ->
|
||||||
|
DelegateUsesExtensionPropertyTypeParameterImpl(
|
||||||
|
firDiagnostic as FirPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
add(FirErrors.DELEGATE_USES_EXTENSION_PROPERTY_TYPE_PARAMETER_WARNING) { firDiagnostic ->
|
||||||
|
DelegateUsesExtensionPropertyTypeParameterWarningImpl(
|
||||||
|
firDiagnostic as FirPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
add(FirErrors.INITIALIZER_TYPE_MISMATCH) { firDiagnostic ->
|
add(FirErrors.INITIALIZER_TYPE_MISMATCH) { firDiagnostic ->
|
||||||
InitializerTypeMismatchImpl(
|
InitializerTypeMismatchImpl(
|
||||||
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
|
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
|
||||||
|
|||||||
+8
@@ -1749,6 +1749,14 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
abstract val actualType: KtType
|
abstract val actualType: KtType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class DelegateUsesExtensionPropertyTypeParameter : KtFirDiagnostic<KtProperty>() {
|
||||||
|
override val diagnosticClass get() = DelegateUsesExtensionPropertyTypeParameter::class
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class DelegateUsesExtensionPropertyTypeParameterWarning : KtFirDiagnostic<KtProperty>() {
|
||||||
|
override val diagnosticClass get() = DelegateUsesExtensionPropertyTypeParameterWarning::class
|
||||||
|
}
|
||||||
|
|
||||||
abstract class InitializerTypeMismatch : KtFirDiagnostic<KtProperty>() {
|
abstract class InitializerTypeMismatch : KtFirDiagnostic<KtProperty>() {
|
||||||
override val diagnosticClass get() = InitializerTypeMismatch::class
|
override val diagnosticClass get() = InitializerTypeMismatch::class
|
||||||
abstract val expectedType: KtType
|
abstract val expectedType: KtType
|
||||||
|
|||||||
+10
@@ -2103,6 +2103,16 @@ internal class WrongSetterParameterTypeImpl(
|
|||||||
override val token: ValidityToken,
|
override val token: ValidityToken,
|
||||||
) : KtFirDiagnostic.WrongSetterParameterType(), KtAbstractFirDiagnostic<KtTypeReference>
|
) : KtFirDiagnostic.WrongSetterParameterType(), KtAbstractFirDiagnostic<KtTypeReference>
|
||||||
|
|
||||||
|
internal class DelegateUsesExtensionPropertyTypeParameterImpl(
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.DelegateUsesExtensionPropertyTypeParameter(), KtAbstractFirDiagnostic<KtProperty>
|
||||||
|
|
||||||
|
internal class DelegateUsesExtensionPropertyTypeParameterWarningImpl(
|
||||||
|
override val firDiagnostic: FirPsiDiagnostic,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.DelegateUsesExtensionPropertyTypeParameterWarning(), KtAbstractFirDiagnostic<KtProperty>
|
||||||
|
|
||||||
internal class InitializerTypeMismatchImpl(
|
internal class InitializerTypeMismatchImpl(
|
||||||
override val expectedType: KtType,
|
override val expectedType: KtType,
|
||||||
override val actualType: KtType,
|
override val actualType: KtType,
|
||||||
|
|||||||
+2
@@ -891,6 +891,8 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
|||||||
parameter<ConeKotlinType>("expectedType")
|
parameter<ConeKotlinType>("expectedType")
|
||||||
parameter<ConeKotlinType>("actualType")
|
parameter<ConeKotlinType>("actualType")
|
||||||
}
|
}
|
||||||
|
val DELEGATE_USES_EXTENSION_PROPERTY_TYPE_PARAMETER by error<KtProperty>(PositioningStrategy.PROPERTY_DELEGATE)
|
||||||
|
val DELEGATE_USES_EXTENSION_PROPERTY_TYPE_PARAMETER_WARNING by warning<KtProperty>(PositioningStrategy.PROPERTY_DELEGATE)
|
||||||
val INITIALIZER_TYPE_MISMATCH by error<KtProperty>(PositioningStrategy.PROPERTY_INITIALIZER) {
|
val INITIALIZER_TYPE_MISMATCH by error<KtProperty>(PositioningStrategy.PROPERTY_INITIALIZER) {
|
||||||
parameter<ConeKotlinType>("expectedType")
|
parameter<ConeKotlinType>("expectedType")
|
||||||
parameter<ConeKotlinType>("actualType")
|
parameter<ConeKotlinType>("actualType")
|
||||||
|
|||||||
@@ -487,6 +487,8 @@ object FirErrors {
|
|||||||
val CONST_VAL_WITHOUT_INITIALIZER by error0<KtProperty>(SourceElementPositioningStrategies.CONST_MODIFIER)
|
val CONST_VAL_WITHOUT_INITIALIZER by error0<KtProperty>(SourceElementPositioningStrategies.CONST_MODIFIER)
|
||||||
val CONST_VAL_WITH_NON_CONST_INITIALIZER by error0<KtExpression>()
|
val CONST_VAL_WITH_NON_CONST_INITIALIZER by error0<KtExpression>()
|
||||||
val WRONG_SETTER_PARAMETER_TYPE by error2<KtTypeReference, ConeKotlinType, ConeKotlinType>()
|
val WRONG_SETTER_PARAMETER_TYPE by error2<KtTypeReference, ConeKotlinType, ConeKotlinType>()
|
||||||
|
val DELEGATE_USES_EXTENSION_PROPERTY_TYPE_PARAMETER by error0<KtProperty>(SourceElementPositioningStrategies.PROPERTY_DELEGATE)
|
||||||
|
val DELEGATE_USES_EXTENSION_PROPERTY_TYPE_PARAMETER_WARNING by warning0<KtProperty>(SourceElementPositioningStrategies.PROPERTY_DELEGATE)
|
||||||
val INITIALIZER_TYPE_MISMATCH by error3<KtProperty, ConeKotlinType, ConeKotlinType, Boolean>(SourceElementPositioningStrategies.PROPERTY_INITIALIZER)
|
val INITIALIZER_TYPE_MISMATCH by error3<KtProperty, ConeKotlinType, ConeKotlinType, Boolean>(SourceElementPositioningStrategies.PROPERTY_INITIALIZER)
|
||||||
val GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY by error0<KtModifierListOwner>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
|
val GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY by error0<KtModifierListOwner>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
|
||||||
val SETTER_VISIBILITY_INCONSISTENT_WITH_PROPERTY_VISIBILITY by error0<KtModifierListOwner>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
|
val SETTER_VISIBILITY_INCONSISTENT_WITH_PROPERTY_VISIBILITY by error0<KtModifierListOwner>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
|
||||||
|
|||||||
+1
@@ -60,6 +60,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
|||||||
FirInlinePropertyChecker,
|
FirInlinePropertyChecker,
|
||||||
FirPropertyFromParameterChecker,
|
FirPropertyFromParameterChecker,
|
||||||
FirLocalVariableTypeParametersSyntaxChecker,
|
FirLocalVariableTypeParametersSyntaxChecker,
|
||||||
|
FirDelegateUsesExtensionPropertyTypeParameterChecker,
|
||||||
)
|
)
|
||||||
|
|
||||||
override val backingFieldCheckers: Set<FirBackingFieldChecker>
|
override val backingFieldCheckers: Set<FirBackingFieldChecker>
|
||||||
|
|||||||
+66
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticFactory0
|
||||||
|
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.FirFunctionCall
|
||||||
|
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
|
object FirDelegateUsesExtensionPropertyTypeParameterChecker : FirPropertyChecker() {
|
||||||
|
override fun check(declaration: FirProperty, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
val delegate = declaration.delegate.safeAs<FirFunctionCall>() ?: return
|
||||||
|
val parameters = declaration.typeParameters.mapTo(hashSetOf()) { it.symbol }
|
||||||
|
|
||||||
|
val shouldReportError = delegate.typeRef.coneType.containsTypeParameterFrom(parameters, delegate, context, reporter)
|
||||||
|
|
||||||
|
if (shouldReportError) {
|
||||||
|
val diagnostic = getProperDiagnostic(context)
|
||||||
|
reporter.reportOn(declaration.source, diagnostic, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getProperDiagnostic(context: CheckerContext): FirDiagnosticFactory0 {
|
||||||
|
val reportAsError = context.session.languageVersionSettings.supportsFeature(
|
||||||
|
LanguageFeature.ForbidUsingExtensionPropertyTypeParameterInDelegate
|
||||||
|
)
|
||||||
|
|
||||||
|
return if (reportAsError) {
|
||||||
|
FirErrors.DELEGATE_USES_EXTENSION_PROPERTY_TYPE_PARAMETER
|
||||||
|
} else {
|
||||||
|
FirErrors.DELEGATE_USES_EXTENSION_PROPERTY_TYPE_PARAMETER_WARNING
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ConeKotlinType.containsTypeParameterFrom(
|
||||||
|
parameters: HashSet<FirTypeParameterSymbol>,
|
||||||
|
delegate: FirFunctionCall,
|
||||||
|
context: CheckerContext,
|
||||||
|
reporter: DiagnosticReporter,
|
||||||
|
): Boolean {
|
||||||
|
for (it in typeArguments) {
|
||||||
|
val theType = it.type ?: continue
|
||||||
|
val symbol = theType.toSymbol(context.session)
|
||||||
|
|
||||||
|
if (
|
||||||
|
symbol in parameters ||
|
||||||
|
theType.containsTypeParameterFrom(parameters, delegate, context, reporter)
|
||||||
|
) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
-22
@@ -1,22 +0,0 @@
|
|||||||
// !LANGUAGE: +ForbidUsingExtensionPropertyTypeParameterInDelegate
|
|
||||||
|
|
||||||
class Delegate<T : Any> {
|
|
||||||
private var v: T? = null
|
|
||||||
operator fun getValue(thisRef: Any?, kp: Any?): T = v!!
|
|
||||||
operator fun setValue(thisRef: Any?, kp: Any?, newValue: T) { v = newValue }
|
|
||||||
}
|
|
||||||
|
|
||||||
var <T : Any> List<T>.foo by Delegate<T>()
|
|
||||||
|
|
||||||
class Wrapper<T>(val v: T? = null)
|
|
||||||
|
|
||||||
operator fun <T> Wrapper<T>.getValue(thisRef: Any?, kp: Any?): T = v!!
|
|
||||||
|
|
||||||
val <T : Any> List<T>.bar by Wrapper<T>()
|
|
||||||
|
|
||||||
fun useString(s: String) {}
|
|
||||||
|
|
||||||
fun main(listInt: List<Int>, listStr: List<String>) {
|
|
||||||
listInt.foo = 42
|
|
||||||
useString(listStr.foo) // CCE
|
|
||||||
}
|
|
||||||
Vendored
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// !LANGUAGE: +ForbidUsingExtensionPropertyTypeParameterInDelegate
|
// !LANGUAGE: +ForbidUsingExtensionPropertyTypeParameterInDelegate
|
||||||
|
|
||||||
class Delegate<T : Any> {
|
class Delegate<T : Any> {
|
||||||
|
|||||||
-22
@@ -1,22 +0,0 @@
|
|||||||
// !LANGUAGE: -ForbidUsingExtensionPropertyTypeParameterInDelegate
|
|
||||||
|
|
||||||
class Delegate<T : Any> {
|
|
||||||
private var v: T? = null
|
|
||||||
operator fun getValue(thisRef: Any?, kp: Any?): T = v!!
|
|
||||||
operator fun setValue(thisRef: Any?, kp: Any?, newValue: T) { v = newValue }
|
|
||||||
}
|
|
||||||
|
|
||||||
var <T : Any> List<T>.foo by Delegate<T>()
|
|
||||||
|
|
||||||
class Wrapper<T>(val v: T? = null)
|
|
||||||
|
|
||||||
operator fun <T> Wrapper<T>.getValue(thisRef: Any?, kp: Any?): T = v!!
|
|
||||||
|
|
||||||
val <T : Any> List<T>.bar by Wrapper<T>()
|
|
||||||
|
|
||||||
fun useString(s: String) {}
|
|
||||||
|
|
||||||
fun main(listInt: List<Int>, listStr: List<String>) {
|
|
||||||
listInt.foo = 42
|
|
||||||
useString(listStr.foo) // CCE
|
|
||||||
}
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// !LANGUAGE: -ForbidUsingExtensionPropertyTypeParameterInDelegate
|
// !LANGUAGE: -ForbidUsingExtensionPropertyTypeParameterInDelegate
|
||||||
|
|
||||||
class Delegate<T : Any> {
|
class Delegate<T : Any> {
|
||||||
|
|||||||
Reference in New Issue
Block a user