[FIR] Implement OUTER_CLASS_ARGUMENTS_REQUIRED diagnostics
This commit is contained in:
committed by
TeamCityServer
parent
f7ed2f813d
commit
0fc8be4d60
+3
@@ -452,6 +452,9 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
parameter<Int>("expectedCount")
|
||||
parameter<FirClassLikeSymbol<*>>("classifier")
|
||||
}
|
||||
val OUTER_CLASS_ARGUMENTS_REQUIRED by error<PsiElement>() {
|
||||
parameter<FirRegularClass>("outer")
|
||||
}
|
||||
val TYPE_PARAMETERS_IN_OBJECT by error<PsiElement>()
|
||||
val ILLEGAL_PROJECTION_USAGE by error<PsiElement>()
|
||||
val TYPE_PARAMETERS_IN_ENUM by error<PsiElement>()
|
||||
|
||||
@@ -297,6 +297,7 @@ object FirErrors {
|
||||
val TYPE_ARGUMENTS_NOT_ALLOWED by error0<PsiElement>()
|
||||
val WRONG_NUMBER_OF_TYPE_ARGUMENTS by error2<PsiElement, Int, FirClassLikeSymbol<*>>()
|
||||
val NO_TYPE_ARGUMENTS_ON_RHS by error2<PsiElement, Int, FirClassLikeSymbol<*>>()
|
||||
val OUTER_CLASS_ARGUMENTS_REQUIRED by error1<PsiElement, FirRegularClass>()
|
||||
val TYPE_PARAMETERS_IN_OBJECT by error0<PsiElement>()
|
||||
val ILLEGAL_PROJECTION_USAGE by error0<PsiElement>()
|
||||
val TYPE_PARAMETERS_IN_ENUM by error0<PsiElement>()
|
||||
|
||||
+7
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.FUNC
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.NOT_RENDERED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.NULLABLE_STRING
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_CLASS_OR_OBJECT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_CLASS_OR_OBJECT_NAME
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_COLLECTION_OF_TYPES
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_TYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.SYMBOL
|
||||
@@ -255,6 +256,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NULLABLE_TYPE_OF_
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ONLY_ONE_CLASS_BOUND_ALLOWED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPERATOR_RENAMED_ON_IMPORT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OTHER_ERROR
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OUTER_CLASS_ARGUMENTS_REQUIRED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OVERLOAD_RESOLUTION_AMBIGUITY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OVERRIDING_FINAL_MEMBER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.PACKAGE_CANNOT_BE_IMPORTED
|
||||
@@ -717,6 +719,11 @@ class FirDefaultErrorMessages {
|
||||
null,
|
||||
SYMBOL
|
||||
)
|
||||
map.put(
|
||||
OUTER_CLASS_ARGUMENTS_REQUIRED,
|
||||
"Type arguments should be specified for an outer {0}. Use full class name to specify them",
|
||||
RENDER_CLASS_OR_OBJECT_NAME
|
||||
)
|
||||
map.put(TYPE_PARAMETERS_IN_OBJECT, "Type parameters are not allowed for objects")
|
||||
// map.put(ILLEGAL_PROJECTION_USAGE, ...) // &
|
||||
map.put(TYPE_PARAMETERS_IN_ENUM, "Enum class cannot have type parameters")
|
||||
|
||||
+21
-1
@@ -12,8 +12,9 @@ import org.jetbrains.kotlin.diagnostics.rendering.Renderer
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirRenderer
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.classId
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.isLocalClassOrAnonymousObject
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
@@ -79,6 +80,25 @@ object FirDiagnosticRenderers {
|
||||
"$classOrObject $name"
|
||||
}
|
||||
|
||||
val RENDER_CLASS_OR_OBJECT_NAME = Renderer { firClassLike: FirClassLikeDeclaration ->
|
||||
val name = firClassLike.classId.relativeClassName.shortName().asString()
|
||||
val prefix = when (firClassLike) {
|
||||
is FirTypeAlias -> "typealias"
|
||||
is FirRegularClass -> {
|
||||
when {
|
||||
firClassLike.isCompanion -> "companion object"
|
||||
firClassLike.isInterface -> "interface"
|
||||
firClassLike.isEnumClass -> "enum class"
|
||||
firClassLike.isFromEnumClass -> "enum entry"
|
||||
firClassLike.isLocalClassOrAnonymousObject() -> "object"
|
||||
else -> "class"
|
||||
}
|
||||
}
|
||||
else -> AssertionError("Unexpected class: $firClassLike")
|
||||
}
|
||||
"$prefix '$name'"
|
||||
}
|
||||
|
||||
val RENDER_TYPE = Renderer { t: ConeKotlinType ->
|
||||
// TODO: need a way to tune granuality, e.g., without parameter names in functional types.
|
||||
t.render()
|
||||
|
||||
+2
@@ -69,6 +69,8 @@ private fun ConeDiagnostic.toFirDiagnostic(
|
||||
is ConeIllegalAnnotationError -> FirErrors.NOT_AN_ANNOTATION_CLASS.createOn(source, this.name.asString())
|
||||
is ConeWrongNumberOfTypeArgumentsError ->
|
||||
FirErrors.WRONG_NUMBER_OF_TYPE_ARGUMENTS.createOn(qualifiedAccessSource ?: source, this.desiredCount, this.type)
|
||||
is ConeOuterClassArgumentsRequired ->
|
||||
FirErrors.OUTER_CLASS_ARGUMENTS_REQUIRED.createOn(qualifiedAccessSource ?: source, this.type)
|
||||
is ConeNoTypeArgumentsOnRhsError ->
|
||||
FirErrors.NO_TYPE_ARGUMENTS_ON_RHS.createOn(qualifiedAccessSource ?: source, this.desiredCount, this.type)
|
||||
is ConeSimpleDiagnostic -> when (source.kind) {
|
||||
|
||||
@@ -6,10 +6,11 @@
|
||||
package org.jetbrains.kotlin.fir.resolve
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSessionComponent
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.ScopeClassDeclaration
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
|
||||
abstract class FirTypeResolver : FirSessionComponent {
|
||||
abstract fun resolveType(typeRef: FirTypeRef, scope: FirScope, areBareTypesAllowed: Boolean): ConeKotlinType
|
||||
abstract fun resolveType(typeRef: FirTypeRef, scopeClassDeclaration: ScopeClassDeclaration, areBareTypesAllowed: Boolean): ConeKotlinType
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirOuterClassTypeParameterRef
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
||||
@@ -447,3 +448,44 @@ fun FirFunction.getAsForbiddenNamedArgumentsTarget(session: FirSession): Forbidd
|
||||
// org.jetbrains.kotlin.fir.serialization.FirElementSerializer.functionProto
|
||||
// org.jetbrains.kotlin.fir.serialization.FirElementSerializer.constructorProto
|
||||
fun FirFunction.getHasStableParameterNames(session: FirSession): Boolean = getAsForbiddenNamedArgumentsTarget(session) == null
|
||||
|
||||
fun isValidTypeParameter(typeParameter: FirTypeParameterRef, classDeclaration: FirRegularClass?, session: FirSession): Boolean {
|
||||
if (typeParameter !is FirOuterClassTypeParameterRef || classDeclaration == null) {
|
||||
return true
|
||||
}
|
||||
|
||||
fun containsTypeParameter(currentClassDeclaration: FirRegularClass): Boolean {
|
||||
val result = currentClassDeclaration.typeParameters.any { it.symbol == typeParameter.symbol }
|
||||
if (result) {
|
||||
return true
|
||||
}
|
||||
|
||||
for (superTypeRef in currentClassDeclaration.superTypeRefs) {
|
||||
val superClassFir = superTypeRef.firClassLike(session)
|
||||
if (superClassFir == null || superClassFir is FirRegularClass && containsTypeParameter(superClassFir)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
return containsTypeParameter(classDeclaration)
|
||||
}
|
||||
|
||||
fun getClassThatContainsTypeParameter(klass: FirRegularClass, typeParameter: FirTypeParameterRef): FirRegularClass? {
|
||||
if (klass.typeParameters.any { param -> param.symbol == typeParameter.symbol }) {
|
||||
return klass
|
||||
}
|
||||
|
||||
for (declaration in klass.declarations) {
|
||||
if (declaration is FirRegularClass) {
|
||||
val result = getClassThatContainsTypeParameter(declaration, typeParameter)
|
||||
if (result != null) {
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
+7
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.resolve.diagnostics
|
||||
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.Candidate
|
||||
@@ -113,6 +114,12 @@ class ConeNoTypeArgumentsOnRhsError(
|
||||
override val reason: String get() = "No type arguments on RHS"
|
||||
}
|
||||
|
||||
class ConeOuterClassArgumentsRequired(
|
||||
val type: FirRegularClass,
|
||||
) : ConeDiagnostic() {
|
||||
override val reason: String = "Type arguments should be specified for an outer class"
|
||||
}
|
||||
|
||||
class ConeInstanceAccessBeforeSuperCall(val target: String) : ConeDiagnostic() {
|
||||
override val reason: String get() = "Cannot access ''${target}'' before superclass constructor has been called"
|
||||
}
|
||||
|
||||
+42
-20
@@ -8,15 +8,17 @@ package org.jetbrains.kotlin.fir.resolve.providers.impl
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.ThreadSafeMutableState
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirTypeParameterRef
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeUnexpectedTypeArgumentsError
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeOuterClassArgumentsRequired
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedQualifierError
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnsupportedDynamicType
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeWrongNumberOfTypeArgumentsError
|
||||
import org.jetbrains.kotlin.fir.resolve.getSymbolByLookupTag
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.ScopeClassDeclaration
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
@@ -46,7 +48,7 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
|
||||
|
||||
private fun resolveToSymbol(
|
||||
typeRef: FirTypeRef,
|
||||
scope: FirScope
|
||||
scopeClassDeclaration: ScopeClassDeclaration
|
||||
): Pair<FirClassifierSymbol<*>?, ConeSubstitutor?> {
|
||||
return when (typeRef) {
|
||||
is FirResolvedTypeRef -> {
|
||||
@@ -58,7 +60,7 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
|
||||
val qualifierResolver = session.qualifierResolver
|
||||
var resolvedSymbol: FirClassifierSymbol<*>? = null
|
||||
var substitutor: ConeSubstitutor? = null
|
||||
scope.processClassifiersByNameWithSubstitution(typeRef.qualifier.first().name) { symbol, substitutorFromScope ->
|
||||
scopeClassDeclaration.scope.processClassifiersByNameWithSubstitution(typeRef.qualifier.first().name) { symbol, substitutorFromScope ->
|
||||
if (resolvedSymbol != null) return@processClassifiersByNameWithSubstitution
|
||||
resolvedSymbol = when (symbol) {
|
||||
is FirClassLikeSymbol<*> -> {
|
||||
@@ -94,7 +96,8 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
|
||||
typeRef: FirUserTypeRef,
|
||||
symbol: FirClassifierSymbol<*>?,
|
||||
substitutor: ConeSubstitutor?,
|
||||
areBareTypesAllowed: Boolean
|
||||
areBareTypesAllowed: Boolean,
|
||||
scopeClassDeclaration: ScopeClassDeclaration
|
||||
): ConeKotlinType {
|
||||
if (symbol == null) {
|
||||
return ConeKotlinErrorType(ConeUnresolvedQualifierError(typeRef.render()))
|
||||
@@ -117,24 +120,43 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
|
||||
return ConeClassErrorType(ConeWrongNumberOfTypeArgumentsError(symbol.fir.typeParameters.size, symbol))
|
||||
} else {
|
||||
val substitutor = substitutor ?: ConeSubstitutor.Empty
|
||||
var problemTypeParameter: FirTypeParameterRef? = null
|
||||
val classDeclarations = scopeClassDeclaration.classDeclarations
|
||||
val argumentsFromOuterClassesAndParents = symbol.fir.typeParameters.drop(typeArguments.size).mapNotNull {
|
||||
val type = ConeTypeParameterTypeImpl(ConeTypeParameterLookupTag(it.symbol), isNullable = false)
|
||||
// we should report ConeSimpleDiagnostic(..., WrongNumberOfTypeArguments)
|
||||
// but genericArgumentNumberMismatch.kt test fails with
|
||||
// index out of bounds exception for start offset of
|
||||
// the source
|
||||
substitutor.substituteOrNull(type)
|
||||
|
||||
if (isValidTypeParameter(it, classDeclarations.lastOrNull(), session)) {
|
||||
val type = ConeTypeParameterTypeImpl(ConeTypeParameterLookupTag(it.symbol), isNullable = false)
|
||||
// we should report ConeSimpleDiagnostic(..., WrongNumberOfTypeArguments)
|
||||
// but genericArgumentNumberMismatch.kt test fails with
|
||||
// index out of bounds exception for start offset of
|
||||
// the source
|
||||
substitutor.substituteOrNull(type)
|
||||
} else {
|
||||
if (problemTypeParameter == null) {
|
||||
problemTypeParameter = it
|
||||
}
|
||||
null
|
||||
}
|
||||
}.toTypedArray<ConeTypeProjection>()
|
||||
typeArguments += argumentsFromOuterClassesAndParents
|
||||
|
||||
if (typeArguments.size != symbol.fir.typeParameters.size) {
|
||||
return ConeClassErrorType(
|
||||
ConeWrongNumberOfTypeArgumentsError(
|
||||
desiredCount = symbol.fir.typeParameters.size - argumentsFromOuterClassesAndParents.size,
|
||||
type = symbol
|
||||
if (problemTypeParameter != null) {
|
||||
var outerClass: FirRegularClass? = null
|
||||
classDeclarations.forEach {
|
||||
getClassThatContainsTypeParameter(it, problemTypeParameter!!)?.let { result ->
|
||||
outerClass = result
|
||||
return@forEach
|
||||
}
|
||||
}
|
||||
return ConeClassErrorType(ConeOuterClassArgumentsRequired(outerClass!!))
|
||||
} else {
|
||||
return ConeClassErrorType(
|
||||
ConeWrongNumberOfTypeArgumentsError(
|
||||
desiredCount = symbol.fir.typeParameters.size - argumentsFromOuterClassesAndParents.size,
|
||||
type = symbol
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -174,14 +196,14 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
|
||||
|
||||
override fun resolveType(
|
||||
typeRef: FirTypeRef,
|
||||
scope: FirScope,
|
||||
scopeClassDeclaration: ScopeClassDeclaration,
|
||||
areBareTypesAllowed: Boolean
|
||||
): ConeKotlinType {
|
||||
return when (typeRef) {
|
||||
is FirResolvedTypeRef -> typeRef.type
|
||||
is FirUserTypeRef -> {
|
||||
val (symbol, substitutor) = resolveToSymbol(typeRef, scope)
|
||||
resolveUserType(typeRef, symbol, substitutor, areBareTypesAllowed)
|
||||
val (symbol, substitutor) = resolveToSymbol(typeRef, scopeClassDeclaration)
|
||||
resolveUserType(typeRef, symbol, substitutor, areBareTypesAllowed, scopeClassDeclaration)
|
||||
}
|
||||
is FirFunctionTypeRef -> createFunctionalType(typeRef)
|
||||
is FirDynamicTypeRef -> ConeKotlinErrorType(ConeUnsupportedDynamicType())
|
||||
|
||||
+8
@@ -30,6 +30,7 @@ abstract class FirAbstractTreeTransformerWithSuperTypes(
|
||||
protected val scopeSession: ScopeSession
|
||||
) : FirAbstractTreeTransformer<Any?>(phase) {
|
||||
protected val scopes = mutableListOf<FirScope>()
|
||||
protected val classDeclarations = mutableListOf<FirRegularClass>()
|
||||
protected val towerScope = FirCompositeScope(scopes.asReversed())
|
||||
|
||||
protected open fun needReplacePhase(firDeclaration: FirDeclaration): Boolean = transformerPhase > firDeclaration.resolvePhase
|
||||
@@ -45,6 +46,13 @@ abstract class FirAbstractTreeTransformerWithSuperTypes(
|
||||
return result
|
||||
}
|
||||
|
||||
protected inline fun <T> withClassDeclarationCleanup(declaration: FirRegularClass, crossinline l: () -> T): T {
|
||||
classDeclarations.add(declaration)
|
||||
val result = l()
|
||||
classDeclarations.removeAt(classDeclarations.lastIndex)
|
||||
return result
|
||||
}
|
||||
|
||||
protected fun resolveNestedClassesSupertypes(
|
||||
firClass: FirClass,
|
||||
data: Any?
|
||||
|
||||
+7
-7
@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
class FirSpecificTypeResolverTransformer(
|
||||
override val session: FirSession,
|
||||
private val errorTypeAsResolved: Boolean = true
|
||||
) : FirAbstractTreeTransformer<FirScope>(phase = FirResolvePhase.SUPER_TYPES) {
|
||||
) : FirAbstractTreeTransformer<ScopeClassDeclaration>(phase = FirResolvePhase.SUPER_TYPES) {
|
||||
private val typeResolver = session.typeResolver
|
||||
|
||||
@set:PrivateForInline
|
||||
@@ -53,8 +53,8 @@ class FirSpecificTypeResolverTransformer(
|
||||
}
|
||||
|
||||
@OptIn(PrivateForInline::class)
|
||||
override fun transformTypeRef(typeRef: FirTypeRef, data: FirScope): FirResolvedTypeRef {
|
||||
session.lookupTracker?.recordTypeLookup(typeRef, data.scopeOwnerLookupNames, currentFile?.source)
|
||||
override fun transformTypeRef(typeRef: FirTypeRef, data: ScopeClassDeclaration): FirResolvedTypeRef {
|
||||
session.lookupTracker?.recordTypeLookup(typeRef, data.scope.scopeOwnerLookupNames, currentFile?.source)
|
||||
typeRef.transformChildren(this, data)
|
||||
return transformType(typeRef, typeResolver.resolveType(typeRef, data, areBareTypesAllowed))
|
||||
}
|
||||
@@ -62,10 +62,10 @@ class FirSpecificTypeResolverTransformer(
|
||||
@OptIn(PrivateForInline::class)
|
||||
override fun transformFunctionTypeRef(
|
||||
functionTypeRef: FirFunctionTypeRef,
|
||||
data: FirScope
|
||||
data: ScopeClassDeclaration
|
||||
): FirResolvedTypeRef {
|
||||
functionTypeRef.transformChildren(this, data)
|
||||
session.lookupTracker?.recordTypeLookup(functionTypeRef, data.scopeOwnerLookupNames, currentFile?.source)
|
||||
session.lookupTracker?.recordTypeLookup(functionTypeRef, data.scope.scopeOwnerLookupNames, currentFile?.source)
|
||||
val resolvedType = typeResolver.resolveType(functionTypeRef, data, areBareTypesAllowed).takeIfAcceptable()
|
||||
return if (resolvedType != null && resolvedType !is ConeClassErrorType) {
|
||||
buildResolvedTypeRef {
|
||||
@@ -118,11 +118,11 @@ class FirSpecificTypeResolverTransformer(
|
||||
!errorTypeAsResolved && it is ConeClassErrorType
|
||||
}
|
||||
|
||||
override fun transformResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef, data: FirScope): FirTypeRef {
|
||||
override fun transformResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef, data: ScopeClassDeclaration): FirTypeRef {
|
||||
return resolvedTypeRef
|
||||
}
|
||||
|
||||
override fun transformImplicitTypeRef(implicitTypeRef: FirImplicitTypeRef, data: FirScope): FirTypeRef {
|
||||
override fun transformImplicitTypeRef(implicitTypeRef: FirImplicitTypeRef, data: ScopeClassDeclaration): FirTypeRef {
|
||||
return implicitTypeRef
|
||||
}
|
||||
}
|
||||
|
||||
+8
-5
@@ -215,6 +215,7 @@ open class FirSupertypeResolverVisitor(
|
||||
private val firProviderInterceptor: FirProviderInterceptor? = null,
|
||||
) : FirDefaultVisitor<Unit, Any?>() {
|
||||
private val supertypeGenerationExtensions = session.extensionService.supertypeGenerators
|
||||
private val classDeclarations = mutableListOf<FirRegularClass>()
|
||||
|
||||
private fun getFirClassifierContainerFileIfAny(symbol: FirClassLikeSymbol<*>): FirFile? =
|
||||
if (firProviderInterceptor != null) firProviderInterceptor.getFirClassifierContainerFileIfAny(symbol)
|
||||
@@ -291,7 +292,7 @@ open class FirSupertypeResolverVisitor(
|
||||
|
||||
private fun resolveSpecificClassLikeSupertypes(
|
||||
classLikeDeclaration: FirClassLikeDeclaration,
|
||||
resolveSuperTypeRefs: (FirTransformer<FirScope>, FirScope) -> List<FirResolvedTypeRef>
|
||||
resolveSuperTypeRefs: (FirTransformer<ScopeClassDeclaration>, ScopeClassDeclaration) -> List<FirResolvedTypeRef>
|
||||
): List<FirTypeRef> {
|
||||
when (val status = supertypeComputationSession.getSupertypesComputationStatus(classLikeDeclaration)) {
|
||||
is SupertypeComputationStatus.Computed -> return status.supertypeRefs
|
||||
@@ -308,7 +309,7 @@ open class FirSupertypeResolverVisitor(
|
||||
val scopes = prepareScopes(classLikeDeclaration)
|
||||
|
||||
val transformer = FirSpecificTypeResolverTransformer(session)
|
||||
val resolvedTypesRefs = resolveSuperTypeRefs(transformer, FirCompositeScope(scopes))
|
||||
val resolvedTypesRefs = resolveSuperTypeRefs(transformer, ScopeClassDeclaration(FirCompositeScope(scopes), classDeclarations))
|
||||
|
||||
supertypeComputationSession.storeSupertypes(classLikeDeclaration, resolvedTypesRefs)
|
||||
return resolvedTypesRefs
|
||||
@@ -319,8 +320,10 @@ open class FirSupertypeResolverVisitor(
|
||||
}
|
||||
|
||||
override fun visitRegularClass(regularClass: FirRegularClass, data: Any?) {
|
||||
classDeclarations.add(regularClass)
|
||||
resolveSpecificClassLikeSupertypes(regularClass, regularClass.superTypeRefs)
|
||||
visitDeclarationContent(regularClass, null)
|
||||
classDeclarations.removeAt(classDeclarations.lastIndex)
|
||||
}
|
||||
|
||||
override fun visitAnonymousObject(anonymousObject: FirAnonymousObject, data: Any?) {
|
||||
@@ -332,12 +335,12 @@ open class FirSupertypeResolverVisitor(
|
||||
classLikeDeclaration: FirClassLikeDeclaration,
|
||||
supertypeRefs: List<FirTypeRef>
|
||||
): List<FirTypeRef> {
|
||||
return resolveSpecificClassLikeSupertypes(classLikeDeclaration) { transformer, scope ->
|
||||
return resolveSpecificClassLikeSupertypes(classLikeDeclaration) { transformer, scopeDeclaration ->
|
||||
if (!classLikeDeclaration.isLocalClassOrAnonymousObject()) {
|
||||
session.lookupTracker?.let {
|
||||
val fileSource = getFirClassifierContainerFileIfAny(classLikeDeclaration.symbol)?.source
|
||||
for (supertypeRef in supertypeRefs) {
|
||||
it.recordTypeLookup(supertypeRef, scope.scopeOwnerLookupNames, fileSource)
|
||||
it.recordTypeLookup(supertypeRef, scopeDeclaration.scope.scopeOwnerLookupNames, fileSource)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -348,7 +351,7 @@ open class FirSupertypeResolverVisitor(
|
||||
So we create a copy of supertypeRefs to avoid it
|
||||
*/
|
||||
supertypeRefs.createCopy().mapTo(mutableListOf()) {
|
||||
val superTypeRef = transformer.transformTypeRef(it, scope)
|
||||
val superTypeRef = transformer.transformTypeRef(it, scopeDeclaration)
|
||||
val typeParameterType = superTypeRef.coneTypeSafe<ConeTypeParameterType>()
|
||||
when {
|
||||
typeParameterType != null ->
|
||||
|
||||
+15
-8
@@ -64,15 +64,17 @@ open class FirTypeResolveTransformer(
|
||||
}
|
||||
|
||||
override fun transformRegularClass(regularClass: FirRegularClass, data: Any?): FirStatement {
|
||||
withScopeCleanup {
|
||||
regularClass.addTypeParametersScope()
|
||||
regularClass.typeParameters.forEach {
|
||||
it.accept(this, data)
|
||||
return withClassDeclarationCleanup(regularClass) {
|
||||
withScopeCleanup {
|
||||
regularClass.addTypeParametersScope()
|
||||
regularClass.typeParameters.forEach {
|
||||
it.accept(this, data)
|
||||
}
|
||||
unboundCyclesInTypeParametersSupertypes(regularClass)
|
||||
}
|
||||
unboundCyclesInTypeParametersSupertypes(regularClass)
|
||||
}
|
||||
|
||||
return resolveNestedClassesSupertypes(regularClass, data)
|
||||
resolveNestedClassesSupertypes(regularClass, data)
|
||||
}
|
||||
}
|
||||
|
||||
override fun transformAnonymousObject(anonymousObject: FirAnonymousObject, data: Any?): FirStatement {
|
||||
@@ -185,7 +187,12 @@ open class FirTypeResolveTransformer(
|
||||
}
|
||||
|
||||
override fun transformTypeRef(typeRef: FirTypeRef, data: Any?): FirResolvedTypeRef {
|
||||
return typeResolverTransformer.withFile(currentFile) { typeRef.transform(typeResolverTransformer, towerScope) }
|
||||
return typeResolverTransformer.withFile(currentFile) {
|
||||
typeRef.transform(
|
||||
typeResolverTransformer,
|
||||
ScopeClassDeclaration(towerScope, classDeclarations)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun transformValueParameter(valueParameter: FirValueParameter, data: Any?): FirStatement {
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* 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.resolve.transformers
|
||||
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
|
||||
data class ScopeClassDeclaration(val scope: FirScope, val classDeclarations: List<FirRegularClass>) {
|
||||
}
|
||||
+7
-2
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.resolve.dfa.DataFlowAnalyzerContext
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirProviderInterceptor
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculatorForFullBodyResolve
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.ScopeClassDeclaration
|
||||
import org.jetbrains.kotlin.fir.scopes.FirCompositeScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.createCurrentScopeList
|
||||
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
||||
@@ -46,6 +47,7 @@ open class FirBodyResolveTransformer(
|
||||
internal open val expressionsTransformer = FirExpressionsResolveTransformer(this)
|
||||
protected open val declarationsTransformer = FirDeclarationsResolveTransformer(this)
|
||||
private val controlFlowStatementsTransformer = FirControlFlowStatementsResolveTransformer(this)
|
||||
private val classDeclarations = mutableListOf<FirRegularClass>()
|
||||
|
||||
override fun transformFile(file: FirFile, data: ResolutionMode): FirFile {
|
||||
checkSessionConsistency(file)
|
||||
@@ -68,7 +70,7 @@ open class FirBodyResolveTransformer(
|
||||
typeRef
|
||||
} else {
|
||||
typeResolverTransformer.withFile(context.file) {
|
||||
transformTypeRef(typeRef, FirCompositeScope(components.createCurrentScopeList()))
|
||||
transformTypeRef(typeRef, ScopeClassDeclaration(FirCompositeScope(components.createCurrentScopeList()), classDeclarations))
|
||||
}
|
||||
}
|
||||
return resolvedTypeRef.transformAnnotations(this, data)
|
||||
@@ -261,7 +263,10 @@ open class FirBodyResolveTransformer(
|
||||
}
|
||||
|
||||
override fun transformRegularClass(regularClass: FirRegularClass, data: ResolutionMode): FirStatement {
|
||||
return declarationsTransformer.transformRegularClass(regularClass, data)
|
||||
classDeclarations.add(regularClass)
|
||||
val result = declarationsTransformer.transformRegularClass(regularClass, data)
|
||||
classDeclarations.removeAt(classDeclarations.lastIndex)
|
||||
return result
|
||||
}
|
||||
|
||||
override fun transformAnonymousObject(
|
||||
|
||||
+7
-6
@@ -21,10 +21,7 @@ import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||
import org.jetbrains.kotlin.fir.extensions.*
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.fqName
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirAbstractPhaseTransformer
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirImportResolveTransformer
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirSpecificTypeResolverTransformer
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.FirTransformerBasedResolveProcessor
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
class FirPluginAnnotationsResolveProcessor(session: FirSession, scopeSession: ScopeSession) : FirTransformerBasedResolveProcessor(session, scopeSession) {
|
||||
@@ -93,6 +90,7 @@ private class FirAnnotationResolveTransformer(
|
||||
)
|
||||
|
||||
private var owners: PersistentList<FirAnnotatedDeclaration> = persistentListOf()
|
||||
protected val classDeclarations = mutableListOf<FirRegularClass>()
|
||||
|
||||
override fun beforeChildren(declaration: FirAnnotatedDeclaration): PersistentList<FirAnnotatedDeclaration> {
|
||||
val current = owners
|
||||
@@ -109,14 +107,15 @@ private class FirAnnotationResolveTransformer(
|
||||
annotationCall: FirAnnotationCall,
|
||||
data: Multimap<AnnotationFqn, FirRegularClass>
|
||||
): FirStatement {
|
||||
return annotationCall.transformAnnotationTypeRef(typeResolverTransformer, scope)
|
||||
return annotationCall.transformAnnotationTypeRef(typeResolverTransformer, ScopeClassDeclaration(scope, listOf()))
|
||||
}
|
||||
|
||||
override fun transformRegularClass(
|
||||
regularClass: FirRegularClass,
|
||||
data: Multimap<AnnotationFqn, FirRegularClass>
|
||||
): FirStatement {
|
||||
return super.transformRegularClass(regularClass, data).also {
|
||||
classDeclarations.add(regularClass)
|
||||
val result = super.transformRegularClass(regularClass, data).also {
|
||||
if (regularClass.classKind == ClassKind.ANNOTATION_CLASS && metaAnnotations.isNotEmpty()) {
|
||||
val annotations = regularClass.annotations.mapNotNull { it.fqName(session) }
|
||||
for (annotation in annotations.filter { it in metaAnnotations }) {
|
||||
@@ -124,6 +123,8 @@ private class FirAnnotationResolveTransformer(
|
||||
}
|
||||
}
|
||||
}
|
||||
classDeclarations.removeAt(classDeclarations.lastIndex)
|
||||
return result
|
||||
}
|
||||
|
||||
override fun transformAnnotatedDeclaration(
|
||||
|
||||
+2
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.fir.declarations.builder
|
||||
|
||||
import kotlin.contracts.*
|
||||
import org.jetbrains.kotlin.fir.FirImplementationDetail
|
||||
import org.jetbrains.kotlin.fir.FirPureAbstractElement
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.builder.FirBuilderDsl
|
||||
@@ -24,6 +25,7 @@ class FirOuterClassTypeParameterRefBuilder {
|
||||
var source: FirSourceElement? = null
|
||||
lateinit var symbol: FirTypeParameterSymbol
|
||||
|
||||
@OptIn(FirImplementationDetail::class)
|
||||
fun build(): FirTypeParameterRef {
|
||||
return FirOuterClassTypeParameterRef(
|
||||
source,
|
||||
|
||||
+2
-1
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.declarations.impl
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirImplementationDetail
|
||||
import org.jetbrains.kotlin.fir.FirPureAbstractElement
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.declarations.FirTypeParameterRef
|
||||
@@ -16,7 +17,7 @@ import org.jetbrains.kotlin.fir.visitors.*
|
||||
* DO NOT MODIFY IT MANUALLY
|
||||
*/
|
||||
|
||||
internal class FirOuterClassTypeParameterRef(
|
||||
class FirOuterClassTypeParameterRef @FirImplementationDetail constructor(
|
||||
override val source: FirSourceElement?,
|
||||
override val symbol: FirTypeParameterSymbol,
|
||||
) : FirPureAbstractElement(), FirTypeParameterRef {
|
||||
|
||||
+3
-1
@@ -25,7 +25,9 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
defaultTrue("isPrimary", withGetter = true)
|
||||
}
|
||||
|
||||
impl(typeParameterRef, "FirOuterClassTypeParameterRef")
|
||||
impl(typeParameterRef, "FirOuterClassTypeParameterRef") {
|
||||
publicImplementation()
|
||||
}
|
||||
impl(typeParameterRef, "FirConstructedClassTypeParameterRef")
|
||||
|
||||
noImpl(declarationStatus)
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ class Outer<E> {
|
||||
}
|
||||
|
||||
class Nested {
|
||||
fun bar(x: Inner) {}
|
||||
fun bar(x: <!OUTER_CLASS_ARGUMENTS_REQUIRED!>Inner<!>) {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -11,13 +11,13 @@ class A<T> {
|
||||
}
|
||||
|
||||
class Nested {
|
||||
val x: B<String>? = null
|
||||
val y: B<String>.C<String>? = null
|
||||
val z: B<String>.D? = null
|
||||
val x: <!OUTER_CLASS_ARGUMENTS_REQUIRED("class 'A'")!>B<String>?<!> = null
|
||||
val y: <!OUTER_CLASS_ARGUMENTS_REQUIRED("class 'A'")!>B<String>.C<String>?<!> = null
|
||||
val z: <!OUTER_CLASS_ARGUMENTS_REQUIRED("class 'A'")!>B<String>.D?<!> = null
|
||||
|
||||
val c: <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>C<Int>?<!> = null
|
||||
val d: <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>D?<!> = null
|
||||
val c: <!OUTER_CLASS_ARGUMENTS_REQUIRED("class 'B'")!>C<Int>?<!> = null
|
||||
val d: <!OUTER_CLASS_ARGUMENTS_REQUIRED("class 'B'")!>D?<!> = null
|
||||
|
||||
val innerMost: <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>Innermost<String>?<!> = null
|
||||
val innerMost: <!OUTER_CLASS_ARGUMENTS_REQUIRED("class 'B'")!>Innermost<String>?<!> = null
|
||||
}
|
||||
}
|
||||
|
||||
+7
@@ -1349,6 +1349,13 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.OUTER_CLASS_ARGUMENTS_REQUIRED) { firDiagnostic ->
|
||||
OuterClassArgumentsRequiredImpl(
|
||||
firSymbolBuilder.classifierBuilder.buildClassLikeSymbol(firDiagnostic.a) as KtNamedClassOrObjectSymbol,
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.TYPE_PARAMETERS_IN_OBJECT) { firDiagnostic ->
|
||||
TypeParametersInObjectImpl(
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
|
||||
+5
@@ -956,6 +956,11 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
abstract val classifier: KtClassLikeSymbol
|
||||
}
|
||||
|
||||
abstract class OuterClassArgumentsRequired : KtFirDiagnostic<PsiElement>() {
|
||||
override val diagnosticClass get() = OuterClassArgumentsRequired::class
|
||||
abstract val outer: KtNamedClassOrObjectSymbol
|
||||
}
|
||||
|
||||
abstract class TypeParametersInObject : KtFirDiagnostic<PsiElement>() {
|
||||
override val diagnosticClass get() = TypeParametersInObject::class
|
||||
}
|
||||
|
||||
+8
@@ -1536,6 +1536,14 @@ internal class NoTypeArgumentsOnRhsImpl(
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class OuterClassArgumentsRequiredImpl(
|
||||
override val outer: KtNamedClassOrObjectSymbol,
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.OuterClassArgumentsRequired(), KtAbstractFirDiagnostic<PsiElement> {
|
||||
override val firDiagnostic: FirPsiDiagnostic by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class TypeParametersInObjectImpl(
|
||||
firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
|
||||
Reference in New Issue
Block a user