[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,
|
||||
)
|
||||
}
|
||||
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 ->
|
||||
InitializerTypeMismatchImpl(
|
||||
firSymbolBuilder.typeBuilder.buildKtType(firDiagnostic.a),
|
||||
|
||||
+8
@@ -1749,6 +1749,14 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
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>() {
|
||||
override val diagnosticClass get() = InitializerTypeMismatch::class
|
||||
abstract val expectedType: KtType
|
||||
|
||||
+10
@@ -2103,6 +2103,16 @@ internal class WrongSetterParameterTypeImpl(
|
||||
override val token: ValidityToken,
|
||||
) : 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(
|
||||
override val expectedType: KtType,
|
||||
override val actualType: KtType,
|
||||
|
||||
+2
@@ -891,6 +891,8 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
parameter<ConeKotlinType>("expectedType")
|
||||
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) {
|
||||
parameter<ConeKotlinType>("expectedType")
|
||||
parameter<ConeKotlinType>("actualType")
|
||||
|
||||
@@ -487,6 +487,8 @@ object FirErrors {
|
||||
val CONST_VAL_WITHOUT_INITIALIZER by error0<KtProperty>(SourceElementPositioningStrategies.CONST_MODIFIER)
|
||||
val CONST_VAL_WITH_NON_CONST_INITIALIZER by error0<KtExpression>()
|
||||
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 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)
|
||||
|
||||
+1
@@ -60,6 +60,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
||||
FirInlinePropertyChecker,
|
||||
FirPropertyFromParameterChecker,
|
||||
FirLocalVariableTypeParametersSyntaxChecker,
|
||||
FirDelegateUsesExtensionPropertyTypeParameterChecker,
|
||||
)
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
class Delegate<T : Any> {
|
||||
|
||||
Reference in New Issue
Block a user