[FIR] Support several super-related diagnostics
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
class A {
|
||||
fun f() {}
|
||||
}
|
||||
|
||||
class B : A {
|
||||
fun g() {
|
||||
<!NOT_A_SUPERTYPE!>super<String><!>.<!UNRESOLVED_REFERENCE!>f<!>()
|
||||
super<A>.f()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
FILE: notASupertype.kt
|
||||
public final class A : R|kotlin/Any| {
|
||||
public constructor(): R|A| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final fun f(): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
}
|
||||
public final class B : R|A| {
|
||||
public constructor(): R|B| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final fun g(): R|kotlin/Unit| {
|
||||
super<R|kotlin/String|>.<Unresolved name: f>#()
|
||||
super<R|A|>.R|/A.f|()
|
||||
}
|
||||
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
fun String.f() {
|
||||
<!NO_SUPERTYPE, NO_SUPERTYPE, SUPER_NOT_AVAILABLE!>super@f<!>.<!UNRESOLVED_REFERENCE!>compareTo<!>("")
|
||||
<!NO_SUPERTYPE, NO_SUPERTYPE, SUPER_NOT_AVAILABLE!>super<!>.<!UNRESOLVED_REFERENCE!>compareTo<!>("")
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
<!NO_SUPERTYPE, NO_SUPERTYPE, SUPER_NOT_AVAILABLE!>super<!>
|
||||
<!NO_SUPERTYPE, NO_SUPERTYPE, SUPER_NOT_AVAILABLE!>super<!>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
<!SUPER_NOT_AVAILABLE!>super<Nothing><!>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
}
|
||||
|
||||
class A {
|
||||
fun act() {
|
||||
<!UNRESOLVED_REFERENCE!>println<!>("Test")
|
||||
}
|
||||
|
||||
fun String.fact() {
|
||||
<!UNRESOLVED_REFERENCE!>println<!>("Fest")
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
FILE: superNotAvailable.kt
|
||||
public final fun R|kotlin/String|.f(): R|kotlin/Unit| {
|
||||
super<<ERROR TYPE REF: No super type>>.<Unresolved name: compareTo>#(String())
|
||||
super<<ERROR TYPE REF: No super type>>.<Unresolved name: compareTo>#(String())
|
||||
}
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
super<<ERROR TYPE REF: No super type>>
|
||||
super<<ERROR TYPE REF: No super type>>.<Unresolved name: foo>#()
|
||||
super<R|kotlin/Nothing|>.<Unresolved name: foo>#()
|
||||
}
|
||||
public final class A : R|kotlin/Any| {
|
||||
public constructor(): R|A| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final fun act(): R|kotlin/Unit| {
|
||||
<Unresolved name: println>#(String(Test))
|
||||
}
|
||||
|
||||
public final fun R|kotlin/String|.fact(): R|kotlin/Unit| {
|
||||
<Unresolved name: println>#(String(Fest))
|
||||
}
|
||||
|
||||
}
|
||||
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
open class A {
|
||||
open fun foo() {}
|
||||
}
|
||||
|
||||
interface ATrait : A {
|
||||
override fun foo() {
|
||||
<!SUPERCLASS_NOT_ACCESSIBLE_FROM_INTERFACE!>super<A><!>.foo()
|
||||
}
|
||||
}
|
||||
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
FILE: superclassNotAccessibleFromInterface.kt
|
||||
public open class A : R|kotlin/Any| {
|
||||
public constructor(): R|A| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public open fun foo(): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
}
|
||||
public abstract interface ATrait : R|A| {
|
||||
public open override fun foo(): R|kotlin/Unit| {
|
||||
super<R|A|>.R|/A.foo|()
|
||||
}
|
||||
|
||||
}
|
||||
Generated
+15
@@ -750,6 +750,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/infixFunctions.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("notASupertype.kt")
|
||||
public void testNotASupertype() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/notASupertype.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("redundantModifier.kt")
|
||||
public void testRedundantModifier() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/redundantModifier.kt");
|
||||
@@ -764,6 +769,16 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
|
||||
public void testSuperIsNotAnExpression() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/superIsNotAnExpression.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("superNotAvailable.kt")
|
||||
public void testSuperNotAvailable() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/superNotAvailable.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("superclassNotAccessibleFromInterface.kt")
|
||||
public void testSuperclassNotAccessibleFromInterface() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/superclassNotAccessibleFromInterface.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/expresssions")
|
||||
|
||||
+15
@@ -750,6 +750,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/infixFunctions.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("notASupertype.kt")
|
||||
public void testNotASupertype() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/notASupertype.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("redundantModifier.kt")
|
||||
public void testRedundantModifier() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/redundantModifier.kt");
|
||||
@@ -764,6 +769,16 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
public void testSuperIsNotAnExpression() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/superIsNotAnExpression.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("superNotAvailable.kt")
|
||||
public void testSuperNotAvailable() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/superNotAvailable.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("superclassNotAccessibleFromInterface.kt")
|
||||
public void testSuperclassNotAccessibleFromInterface() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/superclassNotAccessibleFromInterface.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/expresssions")
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.firClassLike
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
/**
|
||||
* Returns true if this is a superclass of other.
|
||||
*/
|
||||
fun FirClass<*>.isSuperclassOf(other: FirClass<*>): Boolean {
|
||||
/**
|
||||
* Hides additional parameters.
|
||||
*/
|
||||
fun FirClass<*>.isSuperclassOf(other: FirClass<*>, exclude: MutableSet<FirClass<*>>): Boolean {
|
||||
for (it in other.superTypeRefs) {
|
||||
val that = it.firClassLike(session) as? FirClass<*>
|
||||
?: continue
|
||||
|
||||
if (that in exclude) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (that.classKind == ClassKind.CLASS) {
|
||||
if (that == this) {
|
||||
return true
|
||||
}
|
||||
|
||||
exclude.add(that)
|
||||
return this.isSuperclassOf(that, exclude)
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
return isSuperclassOf(other, mutableSetOf())
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this is a superclass of other.
|
||||
*/
|
||||
fun FirClass<*>.isSupertypeOf(other: FirClass<*>): Boolean {
|
||||
/**
|
||||
* Hides additional parameters.
|
||||
*/
|
||||
fun FirClass<*>.isSupertypeOf(other: FirClass<*>, exclude: MutableSet<FirClass<*>>): Boolean {
|
||||
for (it in other.superTypeRefs) {
|
||||
val that = it.firClassLike(session) as? FirClass<*>
|
||||
?: continue
|
||||
|
||||
if (that in exclude) {
|
||||
continue
|
||||
}
|
||||
|
||||
exclude.add(that)
|
||||
|
||||
if (that == this) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (this.isSupertypeOf(that, exclude)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
return isSupertypeOf(other, mutableSetOf())
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the FirRegularClass associated with this
|
||||
* or null of something goes wrong.
|
||||
*/
|
||||
fun ConeClassLikeType.toRegularClass(session: FirSession): FirRegularClass? {
|
||||
return lookupTag.toSymbol(session).safeAs<FirRegularClassSymbol>()?.fir
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the FirRegularClass associated with this
|
||||
* or null of something goes wrong.
|
||||
*/
|
||||
fun ConeKotlinType.toRegularClass(session: FirSession): FirRegularClass? {
|
||||
return safeAs<ConeClassLikeType>()?.toRegularClass(session)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the FirRegularClass associated with this
|
||||
* or null of something goes wrong.
|
||||
*/
|
||||
fun FirTypeRef.toRegularClass(session: FirSession): FirRegularClass? {
|
||||
return safeAs<FirResolvedTypeRef>()?.type?.toRegularClass(session)
|
||||
}
|
||||
+10
-2
@@ -9,6 +9,14 @@ import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
|
||||
object CallCheckers {
|
||||
val EXPRESSIONS: List<FirExpressionChecker<FirExpression>> = listOf()
|
||||
val QUALIFIED_ACCESS: List<FirQualifiedAccessChecker> = listOf<FirQualifiedAccessChecker>() + EXPRESSIONS
|
||||
val FUNCTION_CALLS: List<FirFunctionCallChecker> = listOf<FirFunctionCallChecker>() + QUALIFIED_ACCESS
|
||||
|
||||
val QUALIFIED_ACCESS: List<FirQualifiedAccessChecker> = listOf(
|
||||
FirSuperNotAvailableChecker,
|
||||
FirNotASupertypeChecker,
|
||||
FirSuperclassNotAccessibleFromInterfaceChecker
|
||||
) + EXPRESSIONS
|
||||
|
||||
val FUNCTION_CALLS: List<FirFunctionCallChecker> = listOf<FirFunctionCallChecker>(
|
||||
|
||||
) + QUALIFIED_ACCESS
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.call
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.isSupertypeOf
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClass
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.declarations.FirAnonymousObject
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
object FirNotASupertypeChecker : FirQualifiedAccessChecker() {
|
||||
override fun check(functionCall: FirQualifiedAccessExpression, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val surrounding = context.findClosestClass() ?: return
|
||||
|
||||
val targetClass = functionCall.calleeReference.safeAs<FirSuperReference>()
|
||||
?.superTypeRef
|
||||
?.toRegularClass(context.session)
|
||||
?: return
|
||||
|
||||
if (!targetClass.isSupertypeOf(surrounding)) {
|
||||
reporter.report(functionCall.source)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the closest to the end of context.containingDeclarations
|
||||
* item like FirRegularClass or FirAnonymousObject
|
||||
* or null if no such item could be found.
|
||||
*/
|
||||
private fun CheckerContext.findClosestClass(): FirClass<*>? {
|
||||
for (it in containingDeclarations.reversed()) {
|
||||
if (
|
||||
it is FirRegularClass ||
|
||||
it is FirAnonymousObject
|
||||
) {
|
||||
return it as FirClass<*>
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private fun DiagnosticReporter.report(source: FirSourceElement?) {
|
||||
source?.let {
|
||||
report(FirErrors.NOT_A_SUPERTYPE.on(it))
|
||||
}
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.call
|
||||
|
||||
import org.jetbrains.kotlin.KtNodeTypes.*
|
||||
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.FirErrors
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
|
||||
object FirSuperNotAvailableChecker : FirQualifiedAccessChecker() {
|
||||
override fun check(functionCall: FirQualifiedAccessExpression, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (functionCall.source?.elementType == SUPER_EXPRESSION) {
|
||||
val isInsideClass = context.containingDeclarations.any {
|
||||
it.source?.elementType == CLASS || it.source?.elementType == OBJECT_LITERAL
|
||||
}
|
||||
|
||||
if (!isInsideClass) {
|
||||
reporter.report(functionCall.source)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun DiagnosticReporter.report(source: FirSourceElement?) {
|
||||
source?.let {
|
||||
report(FirErrors.SUPER_NOT_AVAILABLE.on(it))
|
||||
}
|
||||
}
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.call
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.isSuperclassOf
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
object FirSuperclassNotAccessibleFromInterfaceChecker : FirQualifiedAccessChecker() {
|
||||
override fun check(functionCall: FirQualifiedAccessExpression, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val closestClass = context.findClosest<FirRegularClass>() ?: return
|
||||
|
||||
if (closestClass.classKind == ClassKind.INTERFACE) {
|
||||
val origin = getClassLikeDeclaration(functionCall, context)
|
||||
?.symbol.safeAs<FirRegularClassSymbol>()
|
||||
?.fir
|
||||
?: return
|
||||
|
||||
if (origin.source != null && origin.isSuperclassOf(closestClass)) {
|
||||
reporter.report(functionCall.explicitReceiver?.source)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ClassLikeDeclaration where the function has been defined
|
||||
* or null if no proper declaration has been found.
|
||||
*/
|
||||
private fun getClassLikeDeclaration(functionCall: FirQualifiedAccessExpression, context: CheckerContext): FirClassLikeDeclaration<*>? {
|
||||
val classId = functionCall.calleeReference.safeAs<FirResolvedNamedReference>()
|
||||
?.resolvedSymbol.safeAs<FirNamedFunctionSymbol>()
|
||||
?.callableId
|
||||
?.classId
|
||||
?: return null
|
||||
|
||||
if (!classId.isLocal) {
|
||||
return context.session.firSymbolProvider.getClassLikeSymbolByFqName(classId)?.fir
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private fun DiagnosticReporter.report(source: FirSourceElement?) {
|
||||
source?.let {
|
||||
report(FirErrors.SUPERCLASS_NOT_ACCESSIBLE_FROM_INTERFACE.on(it))
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
-6
@@ -7,36 +7,58 @@ package org.jetbrains.kotlin.fir.analysis.checkers.context
|
||||
|
||||
import kotlinx.collections.immutable.PersistentList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.resolve.ImplicitReceiverStack
|
||||
import org.jetbrains.kotlin.fir.resolve.SessionHolder
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ImplicitReceiverValue
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
abstract class CheckerContext {
|
||||
abstract val implicitReceiverStack: ImplicitReceiverStack
|
||||
abstract val containingDeclarations: List<FirDeclaration>
|
||||
abstract val sessionHolder: SessionHolder
|
||||
|
||||
val session: FirSession
|
||||
get() = sessionHolder.session
|
||||
|
||||
/**
|
||||
* Returns the closest to the end of context.containingDeclarations
|
||||
* T instance or null if no such item could be found.
|
||||
*/
|
||||
inline fun <reified T : FirDeclaration> findClosest(): T? {
|
||||
for (it in containingDeclarations.reversed()) {
|
||||
return it as? T ?: continue
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
class PersistentCheckerContext(
|
||||
override val implicitReceiverStack: PersistentImplicitReceiverStack,
|
||||
override val containingDeclarations: PersistentList<FirDeclaration>
|
||||
override val implicitReceiverStack: PersistentImplicitReceiverStack = PersistentImplicitReceiverStack(),
|
||||
override val containingDeclarations: PersistentList<FirDeclaration> = persistentListOf(),
|
||||
override val sessionHolder: SessionHolder
|
||||
) : CheckerContext() {
|
||||
constructor() : this(
|
||||
constructor(sessionHolder: SessionHolder) : this(
|
||||
PersistentImplicitReceiverStack(),
|
||||
persistentListOf()
|
||||
persistentListOf(),
|
||||
sessionHolder
|
||||
)
|
||||
|
||||
fun addImplicitReceiver(name: Name?, value: ImplicitReceiverValue<*>): PersistentCheckerContext {
|
||||
return PersistentCheckerContext(
|
||||
implicitReceiverStack.add(name, value),
|
||||
containingDeclarations
|
||||
containingDeclarations,
|
||||
sessionHolder
|
||||
)
|
||||
}
|
||||
|
||||
fun addDeclaration(declaration: FirDeclaration): PersistentCheckerContext {
|
||||
return PersistentCheckerContext(
|
||||
implicitReceiverStack,
|
||||
containingDeclarations.add(declaration)
|
||||
containingDeclarations.add(declaration),
|
||||
sessionHolder
|
||||
)
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -48,7 +48,8 @@ abstract class AbstractDiagnosticCollector(
|
||||
private var componentsInitialized = false
|
||||
private val visitor = Visitor()
|
||||
|
||||
private var context = PersistentCheckerContext()
|
||||
@Suppress("LeakingThis")
|
||||
private var context = PersistentCheckerContext(this)
|
||||
|
||||
fun initializeComponents(vararg components: AbstractDiagnosticCollectorComponent) {
|
||||
if (componentsInitialized) {
|
||||
|
||||
+4
@@ -57,6 +57,10 @@ class DeclarationCheckersDiagnosticComponent(collector: AbstractDiagnosticCollec
|
||||
runCheck { DeclarationCheckers.DECLARATIONS.check(enumEntry, data, it) }
|
||||
}
|
||||
|
||||
override fun visitAnonymousObject(anonymousObject: FirAnonymousObject, data: CheckerContext) {
|
||||
runCheck { DeclarationCheckers.DECLARATIONS.check(anonymousObject, data, it) }
|
||||
}
|
||||
|
||||
private fun <D : FirDeclaration> List<FirDeclarationChecker<D>>.check(
|
||||
declaration: D,
|
||||
context: CheckerContext,
|
||||
|
||||
@@ -37,6 +37,9 @@ object FirErrors {
|
||||
val VARIABLE_EXPECTED by error0<FirSourceElement, PsiElement>()
|
||||
val RETURN_NOT_ALLOWED by error0<FirSourceElement, PsiElement>()
|
||||
val SUPER_IS_NOT_AN_EXPRESSION by error0<FirSourceElement, PsiElement>()
|
||||
val SUPER_NOT_AVAILABLE by error0<FirSourceElement, PsiElement>()
|
||||
val NOT_A_SUPERTYPE by error0<FirSourceElement, PsiElement>()
|
||||
val SUPERCLASS_NOT_ACCESSIBLE_FROM_INTERFACE by error0<FirSourceElement, PsiElement>()
|
||||
|
||||
val INAPPLICABLE_INFIX_MODIFIER by existing<FirSourceElement, PsiElement, String>(Errors.INAPPLICABLE_INFIX_MODIFIER)
|
||||
val CONSTRUCTOR_IN_OBJECT by existing<FirSourceElement, KtDeclaration>(Errors.CONSTRUCTOR_IN_OBJECT)
|
||||
|
||||
@@ -19,10 +19,10 @@ class A<E>() : C(), T {
|
||||
super<C>@A.bar()
|
||||
super<E>.<!UNRESOLVED_REFERENCE!>bar<!>()
|
||||
super<E>@A.<!UNRESOLVED_REFERENCE!>bar<!>()
|
||||
super<Int>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
<!NOT_A_SUPERTYPE!>super<Int><!>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
super<<!SYNTAX!><!>>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
super<() -> Unit>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
super<Unit>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
<!NOT_A_SUPERTYPE!>super<() -> Unit><!>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
<!NOT_A_SUPERTYPE!>super<Unit><!>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
super<T>@B.foo()
|
||||
super<C>@B.bar()
|
||||
}
|
||||
@@ -30,11 +30,11 @@ class A<E>() : C(), T {
|
||||
inner class B : T {
|
||||
fun test() {
|
||||
super<T>.foo();
|
||||
super<C>.bar()
|
||||
super<C>@A.bar()
|
||||
<!NOT_A_SUPERTYPE!>super<C><!>.bar()
|
||||
<!NOT_A_SUPERTYPE!>super<C>@A<!>.bar()
|
||||
super<T>@A.foo()
|
||||
super<T>@B.foo()
|
||||
super<C>@B.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
<!NOT_A_SUPERTYPE!>super<C>@B<!>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
super.foo()
|
||||
super
|
||||
super<T>
|
||||
|
||||
+1
-1
@@ -5,6 +5,6 @@ open class A {
|
||||
interface ATrait : A {
|
||||
|
||||
override fun foo() {
|
||||
super<A>.foo()
|
||||
<!SUPERCLASS_NOT_ACCESSIBLE_FROM_INTERFACE!>super<A><!>.foo()
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
fun String.f() {
|
||||
<!NO_SUPERTYPE, NO_SUPERTYPE!>super@f<!>.<!UNRESOLVED_REFERENCE!>compareTo<!>("")
|
||||
<!NO_SUPERTYPE, NO_SUPERTYPE!>super<!>.<!UNRESOLVED_REFERENCE!>compareTo<!>("")
|
||||
<!NO_SUPERTYPE, NO_SUPERTYPE, SUPER_NOT_AVAILABLE!>super@f<!>.<!UNRESOLVED_REFERENCE!>compareTo<!>("")
|
||||
<!NO_SUPERTYPE, NO_SUPERTYPE, SUPER_NOT_AVAILABLE!>super<!>.<!UNRESOLVED_REFERENCE!>compareTo<!>("")
|
||||
}
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
fun foo() {
|
||||
<!NO_SUPERTYPE, NO_SUPERTYPE!>super<!>
|
||||
<!NO_SUPERTYPE, NO_SUPERTYPE!>super<!>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
super<Nothing>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
<!NO_SUPERTYPE, NO_SUPERTYPE, SUPER_NOT_AVAILABLE!>super<!>
|
||||
<!NO_SUPERTYPE, NO_SUPERTYPE, SUPER_NOT_AVAILABLE!>super<!>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
<!SUPER_NOT_AVAILABLE!>super<Nothing><!>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
}
|
||||
+4
-4
@@ -1,11 +1,11 @@
|
||||
fun any(a : Any) {}
|
||||
|
||||
fun notAnExpression() {
|
||||
any(<!NO_SUPERTYPE, NO_SUPERTYPE!>super<!>) // not an expression
|
||||
if (<!NO_SUPERTYPE, NO_SUPERTYPE!>super<!>) {} else {} // not an expression
|
||||
val x = <!NO_SUPERTYPE, NO_SUPERTYPE, NO_SUPERTYPE!>super<!> // not an expression
|
||||
any(<!NO_SUPERTYPE, NO_SUPERTYPE, SUPER_NOT_AVAILABLE!>super<!>) // not an expression
|
||||
if (<!NO_SUPERTYPE, NO_SUPERTYPE, SUPER_NOT_AVAILABLE!>super<!>) {} else {} // not an expression
|
||||
val x = <!NO_SUPERTYPE, NO_SUPERTYPE, NO_SUPERTYPE, SUPER_NOT_AVAILABLE!>super<!> // not an expression
|
||||
when (1) {
|
||||
<!NO_SUPERTYPE, NO_SUPERTYPE!>super<!> -> 1 // not an expression
|
||||
<!NO_SUPERTYPE, NO_SUPERTYPE, SUPER_NOT_AVAILABLE!>super<!> -> 1 // not an expression
|
||||
else -> {}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -20,7 +20,7 @@ class TestSuperForBase : B() {
|
||||
typealias MyBase = B
|
||||
|
||||
override fun foo() {
|
||||
super<Base>.foo()
|
||||
<!NOT_A_SUPERTYPE!>super<Base><!>.foo()
|
||||
super<B>.foo()
|
||||
super<MyBase>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
super<U>.foo()
|
||||
@@ -32,7 +32,7 @@ class TestSuperForGenericBase<T> : GB<T>() {
|
||||
typealias MyBaseInt = GB<Int>
|
||||
|
||||
override fun foo() {
|
||||
super<GenericBase>.foo()
|
||||
<!NOT_A_SUPERTYPE!>super<GenericBase><!>.foo()
|
||||
super<GB>.foo()
|
||||
super<MyBase>.<!UNRESOLVED_REFERENCE!>foo<!>()
|
||||
super<MyBaseInt>.<!UNRESOLVED_REFERENCE!>foo<!>() // Type arguments don't matter here
|
||||
|
||||
Reference in New Issue
Block a user