[FIR] Check rest OUTER_CLASS_ARGUMENTS_REQUIRED diagnostics on checkers stage
Add FirOuterClassArgumentsRequiredChecker
This commit is contained in:
committed by
TeamCityServer
parent
0fc8be4d60
commit
28a6928873
+1
@@ -88,6 +88,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
||||
FirFunInterfaceDeclarationChecker,
|
||||
FirNestedClassChecker,
|
||||
FirInlineClassDeclarationChecker,
|
||||
FirOuterClassArgumentsRequiredChecker
|
||||
)
|
||||
|
||||
override val constructorCheckers: Set<FirConstructorChecker>
|
||||
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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.declaration
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.findClosest
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.extractArgumentTypeRefAndSource
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirTypeParameterRef
|
||||
import org.jetbrains.kotlin.fir.declarations.FirTypedDeclaration
|
||||
import org.jetbrains.kotlin.fir.resolve.getClassThatContainsTypeParameter
|
||||
import org.jetbrains.kotlin.fir.resolve.isValidTypeParameter
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.toTypeProjections
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
|
||||
object FirOuterClassArgumentsRequiredChecker : FirRegularClassChecker() {
|
||||
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
for (superTypeRef in declaration.superTypeRefs) {
|
||||
checkOuterClassArgumentsRequired(superTypeRef, declaration, context, reporter)
|
||||
}
|
||||
|
||||
for (subDecl in declaration.declarations) {
|
||||
if (subDecl is FirTypedDeclaration) {
|
||||
checkOuterClassArgumentsRequired(subDecl.returnTypeRef, declaration, context, reporter)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkOuterClassArgumentsRequired(
|
||||
typeRef: FirTypeRef,
|
||||
declaration: FirRegularClass?,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter
|
||||
) {
|
||||
val type: ConeKotlinType
|
||||
|
||||
if (typeRef is FirResolvedTypeRef) {
|
||||
if (typeRef is FirErrorTypeRef) {
|
||||
return
|
||||
}
|
||||
|
||||
type = typeRef.type
|
||||
val delegatedTypeRef = typeRef.delegatedTypeRef
|
||||
|
||||
if (delegatedTypeRef is FirUserTypeRef) {
|
||||
|
||||
if (type is ConeClassLikeType) {
|
||||
val symbol = type.lookupTag.toSymbol(context.session)
|
||||
|
||||
if (symbol is FirRegularClassSymbol) {
|
||||
var problemTypeParameter: FirTypeParameterRef? = null
|
||||
val typeArguments = delegatedTypeRef.qualifier.toTypeProjections()
|
||||
val argumentsFromOuterClassesAndParentsCount = symbol.fir.typeParameters.drop(typeArguments.size).sumOf {
|
||||
val result = if (isValidTypeParameter(it, declaration, context.session)) {
|
||||
1
|
||||
} else {
|
||||
if (problemTypeParameter == null) {
|
||||
problemTypeParameter = it
|
||||
}
|
||||
0
|
||||
}
|
||||
return@sumOf result
|
||||
}
|
||||
val finalTypeArgumentsCount = typeArguments.size + argumentsFromOuterClassesAndParentsCount
|
||||
|
||||
if (finalTypeArgumentsCount != symbol.fir.typeParameters.size) {
|
||||
val source = typeRef.source
|
||||
if (problemTypeParameter != null) {
|
||||
var outerClass: FirRegularClass? = null
|
||||
context.findClosest<FirRegularClass> {
|
||||
outerClass = getClassThatContainsTypeParameter(it, problemTypeParameter!!)
|
||||
return@findClosest outerClass != null
|
||||
}
|
||||
if (outerClass != null) {
|
||||
reporter.reportOn(source, FirErrors.OUTER_CLASS_ARGUMENTS_REQUIRED, outerClass!!, context)
|
||||
}
|
||||
} else {
|
||||
reporter.reportOn(
|
||||
source,
|
||||
FirErrors.WRONG_NUMBER_OF_TYPE_ARGUMENTS,
|
||||
symbol.fir.typeParameters.size - argumentsFromOuterClassesAndParentsCount,
|
||||
symbol,
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (typeRef is ConeKotlinType) {
|
||||
type = typeRef
|
||||
} else {
|
||||
return
|
||||
}
|
||||
|
||||
for (index in type.typeArguments.indices) {
|
||||
val firTypeRefSource = extractArgumentTypeRefAndSource(typeRef, index) ?: continue
|
||||
firTypeRefSource.typeRef?.let { checkOuterClassArgumentsRequired(it, declaration, context, reporter) }
|
||||
}
|
||||
}
|
||||
Vendored
-7
@@ -1,7 +0,0 @@
|
||||
interface Inv<X>
|
||||
class Outer<E> {
|
||||
inner class Inner
|
||||
|
||||
class Nested : Inv<Inner>
|
||||
object Obj : Inv<Inner>
|
||||
}
|
||||
Vendored
+3
@@ -1,7 +1,10 @@
|
||||
// FIR_IDENTICAL
|
||||
interface Inv<X>
|
||||
class Outer<E> {
|
||||
inner class Inner
|
||||
|
||||
class Nested : Inv<<!OUTER_CLASS_ARGUMENTS_REQUIRED!>Inner<!>>
|
||||
inner class Inner2 : Inv<Inner> // no error
|
||||
object Obj : Inv<<!OUTER_CLASS_ARGUMENTS_REQUIRED!>Inner<!>>
|
||||
}
|
||||
|
||||
|
||||
Vendored
+8
@@ -19,6 +19,13 @@ public final class Outer</*0*/ E> {
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final inner class Inner2 /*captured type parameters: /*0*/ E*/ : Inv<Outer<E>.Inner> {
|
||||
public constructor Inner2()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class Nested : Inv<[ERROR : Inner]> {
|
||||
public constructor Nested()
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
@@ -33,3 +40,4 @@ public final class Outer</*0*/ E> {
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user