提交 82b8cc33 编写于 作者: M Mikhail Glukhikh

FIR: introduce INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER

上级 47d2a914
......@@ -22,7 +22,7 @@ abstract class K {
<!INCOMPATIBLE_MODIFIERS!>private<!> <!INCOMPATIBLE_MODIFIERS!>abstract<!> val i2: Int
}
private open class L : K()
private open <!INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER!>class L<!> : K()
private abstract class M : K()
class X {
......
......@@ -299,6 +299,14 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
parameter<FirClass<*>>("classOrObject")
parameter<FirCallableDeclaration<*>>("missingDeclaration")
}
val INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER by error<FirSourceElement, KtClassOrObject>(PositioningStrategy.DECLARATION_NAME) {
parameter<FirClass<*>>("classOrObject")
parameter<FirCallableDeclaration<*>>("invisibleDeclaration")
}
val INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER_WARNING by warning<FirSourceElement, KtClassOrObject>(PositioningStrategy.DECLARATION_NAME) {
parameter<FirClass<*>>("classOrObject")
parameter<FirCallableDeclaration<*>>("invisibleDeclaration")
}
val MANY_IMPL_MEMBER_NOT_IMPLEMENTED by error<FirSourceElement, KtClassOrObject>(PositioningStrategy.DECLARATION_NAME) {
parameter<FirClass<*>>("classOrObject")
parameter<FirCallableDeclaration<*>>("missingDeclaration")
......
......@@ -210,6 +210,8 @@ object FirErrors {
val OVERRIDING_FINAL_MEMBER by error2<FirSourceElement, KtNamedDeclaration, FirCallableDeclaration<*>, Name>(SourceElementPositioningStrategies.OVERRIDE_MODIFIER)
val ABSTRACT_MEMBER_NOT_IMPLEMENTED by error2<FirSourceElement, KtClassOrObject, FirClass<*>, FirCallableDeclaration<*>>(SourceElementPositioningStrategies.DECLARATION_NAME)
val ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED by error2<FirSourceElement, KtClassOrObject, FirClass<*>, FirCallableDeclaration<*>>(SourceElementPositioningStrategies.DECLARATION_NAME)
val INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER by error2<FirSourceElement, KtClassOrObject, FirClass<*>, FirCallableDeclaration<*>>(SourceElementPositioningStrategies.DECLARATION_NAME)
val INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER_WARNING by warning2<FirSourceElement, KtClassOrObject, FirClass<*>, FirCallableDeclaration<*>>(SourceElementPositioningStrategies.DECLARATION_NAME)
val MANY_IMPL_MEMBER_NOT_IMPLEMENTED by error2<FirSourceElement, KtClassOrObject, FirClass<*>, FirCallableDeclaration<*>>(SourceElementPositioningStrategies.DECLARATION_NAME)
val MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED by error2<FirSourceElement, KtClassOrObject, FirClass<*>, FirCallableDeclaration<*>>(SourceElementPositioningStrategies.DECLARATION_NAME)
val RETURN_TYPE_MISMATCH_ON_OVERRIDE by error2<FirSourceElement, KtNamedDeclaration, FirMemberDeclaration, FirMemberDeclaration>(SourceElementPositioningStrategies.DECLARATION_RETURN_TYPE)
......
......@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
......@@ -17,6 +18,7 @@ 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.*
import org.jetbrains.kotlin.fir.languageVersionSettings
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.types.coneType
......@@ -43,6 +45,7 @@ object FirNotImplementedOverrideChecker : FirClassChecker() {
)
val notImplementedSymbols = mutableListOf<FirCallableSymbol<*>>()
val invisibleSymbols = mutableListOf<FirCallableSymbol<*>>()
val classPackage = declaration.symbol.classId.packageFqName
fun FirCallableMemberDeclaration<*>.isInvisible(): Boolean {
......@@ -67,22 +70,25 @@ object FirNotImplementedOverrideChecker : FirClassChecker() {
classScope.processFunctionsByName(name) { namedFunctionSymbol ->
val simpleFunction = namedFunctionSymbol.fir
if (!simpleFunction.shouldBeImplemented()) return@processFunctionsByName
// TODO: private & package-private functions / properties require another diagnostic
// (INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER)
if (simpleFunction.isInvisible()) return@processFunctionsByName
if (declaration.isData && simpleFunction.matchesDataClassSyntheticMemberSignatures) return@processFunctionsByName
// TODO: suspend function overridden by a Java class in the middle is not properly regarded as an override
if (simpleFunction.isSuspend) return@processFunctionsByName
notImplementedSymbols += namedFunctionSymbol
if (simpleFunction.isInvisible()) {
invisibleSymbols += namedFunctionSymbol
} else {
notImplementedSymbols += namedFunctionSymbol
}
}
classScope.processPropertiesByName(name) { propertySymbol ->
val property = propertySymbol.fir as? FirProperty ?: return@processPropertiesByName
if (!property.shouldBeImplemented()) return@processPropertiesByName
if (property.isInvisible()) return@processPropertiesByName
notImplementedSymbols += propertySymbol
if (property.isInvisible()) {
invisibleSymbols += propertySymbol
} else {
notImplementedSymbols += propertySymbol
}
}
}
......@@ -94,6 +100,14 @@ object FirNotImplementedOverrideChecker : FirClassChecker() {
reporter.reportOn(source, FirErrors.ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED, declaration, notImplemented, context)
}
}
if (invisibleSymbols.isNotEmpty()) {
val invisible = invisibleSymbols.first().fir
if (context.session.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitInvisibleAbstractMethodsInSuperclasses)) {
reporter.reportOn(source, FirErrors.INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER, declaration, invisible, context)
} else {
reporter.reportOn(source, FirErrors.INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER_WARNING, declaration, invisible, context)
}
}
}
private fun FirCallableDeclaration<*>.isFromInterface(context: CheckerContext): Boolean =
......
// !LANGUAGE: +ProhibitInvisibleAbstractMethodsInSuperclasses
// FILE: base/Base.java
package base;
public abstract class Base {
public void foo() {
packagePrivateFoo();
}
/* package-private */ abstract void packagePrivateFoo();
}
// FILE: Impl.kt
package impl
import base.*
class Impl : Base()
fun foo() {
Impl().foo()
}
// FIR_IDENTICAL
// !LANGUAGE: +ProhibitInvisibleAbstractMethodsInSuperclasses
// FILE: base/Base.java
package base;
......
......@@ -27,9 +27,9 @@ package impl
import base.*
import intermediate.*
class ImplDirectFromBase : Base()
<!INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER!>class ImplDirectFromBase<!> : Base()
object ImplObjDirectFromBase : Base()
<!INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER!>object ImplObjDirectFromBase<!> : Base()
class ImplDirectFromBaseWithOverride : BaseWithOverride()
......@@ -37,7 +37,7 @@ class ImplDirectFromBaseWithOverrid : Base() {
override fun internalFoo(): String = ""
}
class ImplViaIntermediate : Intermediate()
<!INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER!>class ImplViaIntermediate<!> : Intermediate()
fun foo() {
ImplDirectFromBase().foo()
......
// !LANGUAGE: -ProhibitInvisibleAbstractMethodsInSuperclasses
// MODULE: base
// FILE: Base.kt
package base
abstract class Base {
fun foo(): String {
return internalFoo()
}
internal abstract fun internalFoo(): String
}
// MODULE: impl(base)
// FILE: Impl.kt
package impl
import base.*
class Impl : Base()
fun foo() {
Impl().foo()
}
// FIR_IDENTICAL
// !LANGUAGE: -ProhibitInvisibleAbstractMethodsInSuperclasses
// MODULE: base
// FILE: Base.kt
......
......@@ -26,7 +26,7 @@ import base.*
// TESTCASE NUMBER: 1
class Case1 : BaseJava() {}
<!INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER!>class Case1<!> : BaseJava() {}
fun case1() {
val v = Case1()
......@@ -38,7 +38,7 @@ fun case1() {
*/
abstract class AbstractClassCase2 : BaseJava() {}
class Case2 : AbstractClassCase2() {}
<!INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER!>class Case2<!> : AbstractClassCase2() {}
fun case2() {
val v = Case2()
......
......@@ -51,7 +51,7 @@ fun case2() {
// TESTCASE NUMBER: 3
class Case3 : BaseJava() {}
<!INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER!>class Case3<!> : BaseJava() {}
fun case3() {
val v = Case3()
......@@ -63,7 +63,7 @@ fun case3() {
*/
abstract class AbstractClassCase4 : BaseJava() {}
class Case4 : AbstractClassCase4() {}
<!INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER!>class Case4<!> : AbstractClassCase4() {}
fun case4() {
val v = Case4()
......
......@@ -59,7 +59,7 @@ fun case2() {
// TESTCASE NUMBER: 3
class Case3 : BaseKotlin() {}
<!INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER!>class Case3<!> : BaseKotlin() {}
fun case3() {
val v = Case3()
......@@ -73,7 +73,7 @@ fun case3() {
*/
abstract class AbstractClassCase4 : BaseKotlin() {}
class Case4 : AbstractClassCase4() {}
<!INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER!>class Case4<!> : AbstractClassCase4() {}
fun case4() {
val v = Case4()
......
......@@ -20,7 +20,7 @@ abstract class AbstractClassCase1() {
public abstract val pub1: String
}
class Case1 : AbstractClassCase1(){
<!INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER!>class Case1<!> : AbstractClassCase1(){
override fun prot() {}
override fun int() {
......
......@@ -896,6 +896,22 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER) { firDiagnostic ->
InvisibleAbstractMemberFromSuperImpl(
firSymbolBuilder.buildClassLikeSymbol(firDiagnostic.a),
firSymbolBuilder.buildCallableSymbol(firDiagnostic.b as FirCallableDeclaration),
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER_WARNING) { firDiagnostic ->
InvisibleAbstractMemberFromSuperWarningImpl(
firSymbolBuilder.buildClassLikeSymbol(firDiagnostic.a),
firSymbolBuilder.buildCallableSymbol(firDiagnostic.b as FirCallableDeclaration),
firDiagnostic as FirPsiDiagnostic<*>,
token,
)
}
add(FirErrors.MANY_IMPL_MEMBER_NOT_IMPLEMENTED) { firDiagnostic ->
ManyImplMemberNotImplementedImpl(
firSymbolBuilder.buildClassLikeSymbol(firDiagnostic.a),
......
......@@ -637,6 +637,18 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
abstract val missingDeclaration: KtCallableSymbol
}
abstract class InvisibleAbstractMemberFromSuper : KtFirDiagnostic<KtClassOrObject>() {
override val diagnosticClass get() = InvisibleAbstractMemberFromSuper::class
abstract val classOrObject: KtClassLikeSymbol
abstract val invisibleDeclaration: KtCallableSymbol
}
abstract class InvisibleAbstractMemberFromSuperWarning : KtFirDiagnostic<KtClassOrObject>() {
override val diagnosticClass get() = InvisibleAbstractMemberFromSuperWarning::class
abstract val classOrObject: KtClassLikeSymbol
abstract val invisibleDeclaration: KtCallableSymbol
}
abstract class ManyImplMemberNotImplemented : KtFirDiagnostic<KtClassOrObject>() {
override val diagnosticClass get() = ManyImplMemberNotImplemented::class
abstract val classOrObject: KtClassLikeSymbol
......
......@@ -1025,6 +1025,24 @@ internal class AbstractClassMemberNotImplementedImpl(
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class InvisibleAbstractMemberFromSuperImpl(
override val classOrObject: KtClassLikeSymbol,
override val invisibleDeclaration: KtCallableSymbol,
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.InvisibleAbstractMemberFromSuper(), KtAbstractFirDiagnostic<KtClassOrObject> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class InvisibleAbstractMemberFromSuperWarningImpl(
override val classOrObject: KtClassLikeSymbol,
override val invisibleDeclaration: KtCallableSymbol,
firDiagnostic: FirPsiDiagnostic<*>,
override val token: ValidityToken,
) : KtFirDiagnostic.InvisibleAbstractMemberFromSuperWarning(), KtAbstractFirDiagnostic<KtClassOrObject> {
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
}
internal class ManyImplMemberNotImplementedImpl(
override val classOrObject: KtClassLikeSymbol,
override val missingDeclaration: KtCallableSymbol,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册