[FIR] Improve TYPE_PARAMETER_AS_REIFIED detecting, implement TYPE_PARAMETER_AS_REIFIED_ARRAY, TYPE_PARAMETER_AS_REIFIED_ARRAY_WARNING
This commit is contained in:
committed by
teamcityserver
parent
2333b1bcf6
commit
bade6cb611
+8
@@ -483,6 +483,14 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
parameter<FirTypeParameterSymbol>("typeParameter")
|
||||
}
|
||||
|
||||
val TYPE_PARAMETER_AS_REIFIED_ARRAY by error<PsiElement> {
|
||||
parameter<FirTypeParameterSymbol>("typeParameter")
|
||||
}
|
||||
|
||||
val TYPE_PARAMETER_AS_REIFIED_ARRAY_WARNING by warning<PsiElement> {
|
||||
parameter<FirTypeParameterSymbol>("typeParameter")
|
||||
}
|
||||
|
||||
val FINAL_UPPER_BOUND by warning<KtTypeReference> {
|
||||
parameter<ConeKotlinType>("type")
|
||||
}
|
||||
|
||||
@@ -319,6 +319,8 @@ object FirErrors {
|
||||
val INNER_CLASS_OF_GENERIC_THROWABLE_SUBCLASS by error0<KtClassOrObject>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val KCLASS_WITH_NULLABLE_TYPE_PARAMETER_IN_SIGNATURE by error1<KtNamedDeclaration, FirTypeParameterSymbol>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val TYPE_PARAMETER_AS_REIFIED by error1<PsiElement, FirTypeParameterSymbol>()
|
||||
val TYPE_PARAMETER_AS_REIFIED_ARRAY by error1<PsiElement, FirTypeParameterSymbol>()
|
||||
val TYPE_PARAMETER_AS_REIFIED_ARRAY_WARNING by warning1<PsiElement, FirTypeParameterSymbol>()
|
||||
val FINAL_UPPER_BOUND by warning1<KtTypeReference, ConeKotlinType>()
|
||||
val UPPER_BOUND_IS_EXTENSION_FUNCTION_TYPE by error0<KtTypeReference>()
|
||||
val BOUNDS_NOT_ALLOWED_IF_BOUNDED_BY_TYPE_PARAMETER by error0<KtElement>()
|
||||
|
||||
+2
-1
@@ -42,7 +42,8 @@ object CommonExpressionCheckers : ExpressionCheckers() {
|
||||
FirTypeParameterInQualifiedAccessChecker,
|
||||
FirSealedClassConstructorCallChecker,
|
||||
FirUninitializedEnumChecker,
|
||||
FirFunInterfaceConstructorReferenceChecker
|
||||
FirFunInterfaceConstructorReferenceChecker,
|
||||
FirTypeParameterAsReifiedChecker
|
||||
)
|
||||
|
||||
override val functionCallCheckers: Set<FirFunctionCallChecker>
|
||||
|
||||
@@ -601,24 +601,20 @@ fun extractArgumentTypeRefAndSource(typeRef: FirTypeRef?, index: Int): FirTypeRe
|
||||
if (typeRef is FirResolvedTypeRef) {
|
||||
val delegatedTypeRef = typeRef.delegatedTypeRef
|
||||
if (delegatedTypeRef is FirUserTypeRef) {
|
||||
var currentTypeArguments: List<FirTypeProjection>? = null
|
||||
var currentIndex = index
|
||||
val qualifier = delegatedTypeRef.qualifier
|
||||
|
||||
for (i in qualifier.size - 1 downTo 0) {
|
||||
val typeArguments = qualifier[i].typeArgumentList.typeArguments
|
||||
if (currentIndex < typeArguments.size) {
|
||||
currentTypeArguments = typeArguments
|
||||
break
|
||||
val typeArgument = typeArguments.elementAtOrNull(currentIndex)
|
||||
return if (typeArgument is FirTypeProjection)
|
||||
FirTypeRefSource((typeArgument as? FirTypeProjectionWithVariance)?.typeRef, typeArgument.source)
|
||||
else null
|
||||
} else {
|
||||
currentIndex -= typeArguments.size
|
||||
}
|
||||
}
|
||||
|
||||
val typeArgument = currentTypeArguments?.elementAtOrNull(currentIndex)
|
||||
if (typeArgument is FirTypeProjection) {
|
||||
return FirTypeRefSource((typeArgument as? FirTypeProjectionWithVariance)?.typeRef, typeArgument.source)
|
||||
}
|
||||
} else if (delegatedTypeRef is FirFunctionTypeRef) {
|
||||
val valueParameters = delegatedTypeRef.valueParameters
|
||||
if (index < valueParameters.size) {
|
||||
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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.expression
|
||||
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticFactory1
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
|
||||
object FirTypeParameterAsReifiedChecker : FirQualifiedAccessExpressionChecker() {
|
||||
override fun check(expression: FirQualifiedAccessExpression, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val calleReference = expression.calleeReference
|
||||
val typeArguments = expression.typeArguments
|
||||
val typeParameters = calleReference.toResolvedCallableSymbol()?.typeParameterSymbols ?: return
|
||||
|
||||
val count = minOf(typeArguments.size, typeParameters.size)
|
||||
for (index in 0 until count) {
|
||||
val typeArgumentProjection = typeArguments.elementAt(index)
|
||||
val source = typeArgumentProjection.source ?: calleReference.source
|
||||
val typeArgument = typeArgumentProjection.toConeTypeProjection().type
|
||||
val typeParameter = typeParameters[index]
|
||||
|
||||
if (source != null && (typeParameter.isTypeParameterOfKotlinArray())) {
|
||||
checkArgumentAndReport(typeArgument, source, false, context, reporter)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirTypeParameterSymbol.isTypeParameterOfKotlinArray(): Boolean {
|
||||
val containingDeclaration = containingDeclarationSymbol
|
||||
return isReified ||
|
||||
containingDeclaration is FirRegularClassSymbol && containingDeclaration.classId == StandardClassIds.Array
|
||||
}
|
||||
|
||||
private fun checkArgumentAndReport(
|
||||
typeArgument: ConeKotlinType?,
|
||||
source: FirSourceElement,
|
||||
isArray: Boolean,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter
|
||||
) {
|
||||
if (typeArgument?.classId == StandardClassIds.Array) {
|
||||
checkArgumentAndReport(typeArgument.typeArguments[0].type, source, true, context, reporter)
|
||||
return
|
||||
}
|
||||
|
||||
var factory: FirDiagnosticFactory1<FirTypeParameterSymbol>? = null
|
||||
|
||||
lateinit var symbol: FirTypeParameterSymbol
|
||||
if (typeArgument is ConeTypeParameterType) {
|
||||
factory = if (isArray) {
|
||||
if (context.session.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitNonReifiedArraysAsReifiedTypeArguments))
|
||||
FirErrors.TYPE_PARAMETER_AS_REIFIED_ARRAY else
|
||||
FirErrors.TYPE_PARAMETER_AS_REIFIED_ARRAY_WARNING
|
||||
} else {
|
||||
FirErrors.TYPE_PARAMETER_AS_REIFIED
|
||||
}
|
||||
symbol = typeArgument.toSymbol(context.session) as FirTypeParameterSymbol
|
||||
}
|
||||
|
||||
if (factory != null && !symbol.isReified) {
|
||||
reporter.reportOn(source, factory, symbol, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
@@ -41,6 +41,10 @@ class ExpressionCheckersDiagnosticComponent(
|
||||
checkers.allFunctionCallCheckers.check(functionCall, data, reporter)
|
||||
}
|
||||
|
||||
override fun visitImplicitInvokeCall(implicitInvokeCall: FirImplicitInvokeCall, data: CheckerContext) {
|
||||
checkers.allFunctionCallCheckers.check(implicitInvokeCall, data, reporter)
|
||||
}
|
||||
|
||||
override fun visitCallableReferenceAccess(callableReferenceAccess: FirCallableReferenceAccess, data: CheckerContext) {
|
||||
checkers.allCallableReferenceAccessCheckers.check(callableReferenceAccess, data, reporter)
|
||||
}
|
||||
|
||||
+12
@@ -365,6 +365,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETERS_I
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETERS_IN_OBJECT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETERS_NOT_ALLOWED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_AS_REIFIED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_AS_REIFIED_ARRAY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_AS_REIFIED_ARRAY_WARNING
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_IN_CATCH_CLAUSE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_IS_NOT_AN_EXPRESSION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER
|
||||
@@ -782,6 +784,16 @@ class FirDefaultErrorMessages {
|
||||
)
|
||||
|
||||
map.put(TYPE_PARAMETER_AS_REIFIED, "Cannot use ''{0}'' as reified type parameter. Use a class instead", SYMBOL)
|
||||
map.put(
|
||||
TYPE_PARAMETER_AS_REIFIED_ARRAY,
|
||||
"Cannot use ''{0}'' as reified type parameter, since the array type parameter is not reified.",
|
||||
SYMBOL
|
||||
)
|
||||
map.put(
|
||||
TYPE_PARAMETER_AS_REIFIED_ARRAY_WARNING,
|
||||
"Cannot use ''{0}'' as reified type parameter, since the array type parameter is not reified.",
|
||||
SYMBOL
|
||||
)
|
||||
map.put(
|
||||
FINAL_UPPER_BOUND,
|
||||
"''{0}'' is a final type, and thus a value of the type parameter is predetermined",
|
||||
|
||||
Reference in New Issue
Block a user