[FIR] Add FirDelegateUsesExtensionPropertyTypeParameterChecker

This commit is contained in:
Nikolay Lunyak
2021-09-29 15:20:52 +03:00
committed by TeamCityServer
parent f97e666608
commit dbfe3524ce
11 changed files with 103 additions and 44 deletions
@@ -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)
@@ -60,6 +60,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
FirInlinePropertyChecker,
FirPropertyFromParameterChecker,
FirLocalVariableTypeParametersSyntaxChecker,
FirDelegateUsesExtensionPropertyTypeParameterChecker,
)
override val backingFieldCheckers: Set<FirBackingFieldChecker>
@@ -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
}
}