FIR: introduce not implemented checker
This commit is contained in:
+1
-1
@@ -16,7 +16,7 @@ abstract class A : C() {
|
||||
}
|
||||
}
|
||||
|
||||
class B : A() {
|
||||
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>class B<!> : A() {
|
||||
override fun f() {
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ public class LightMember<D> : Member<D>, Light() {
|
||||
override fun getName(): String = "Light"
|
||||
}
|
||||
|
||||
public class LightClassWrapper : Light(), Klass {
|
||||
public <!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class LightClassWrapper<!> : Light(), Klass {
|
||||
fun test() = typeParameters.single()
|
||||
}
|
||||
|
||||
|
||||
+17
@@ -291,6 +291,23 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
|
||||
parameter<Name>("containingClassName")
|
||||
}
|
||||
|
||||
val ABSTRACT_MEMBER_NOT_IMPLEMENTED by error<FirSourceElement, KtClassOrObject>(PositioningStrategy.DECLARATION_NAME) {
|
||||
parameter<FirClass<*>>("classOrObject")
|
||||
parameter<FirCallableDeclaration<*>>("missingDeclaration")
|
||||
}
|
||||
val ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED by error<FirSourceElement, KtClassOrObject>(PositioningStrategy.DECLARATION_NAME) {
|
||||
parameter<FirClass<*>>("classOrObject")
|
||||
parameter<FirCallableDeclaration<*>>("missingDeclaration")
|
||||
}
|
||||
val MANY_IMPL_MEMBER_NOT_IMPLEMENTED by error<FirSourceElement, KtClassOrObject>(PositioningStrategy.DECLARATION_NAME) {
|
||||
parameter<FirClass<*>>("classOrObject")
|
||||
parameter<FirCallableDeclaration<*>>("missingDeclaration")
|
||||
}
|
||||
val MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED by error<FirSourceElement, KtClassOrObject>(PositioningStrategy.DECLARATION_NAME) {
|
||||
parameter<FirClass<*>>("classOrObject")
|
||||
parameter<FirCallableDeclaration<*>>("missingDeclaration")
|
||||
}
|
||||
|
||||
val RETURN_TYPE_MISMATCH_ON_OVERRIDE by error<FirSourceElement, KtNamedDeclaration>(PositioningStrategy.DECLARATION_RETURN_TYPE) {
|
||||
parameter<FirMemberDeclaration>("function")
|
||||
parameter<FirMemberDeclaration>("superFunction")
|
||||
|
||||
@@ -208,6 +208,10 @@ object FirErrors {
|
||||
val CANNOT_WEAKEN_ACCESS_PRIVILEGE by error3<FirSourceElement, KtModifierListOwner, Visibility, FirCallableDeclaration<*>, Name>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
|
||||
val CANNOT_CHANGE_ACCESS_PRIVILEGE by error3<FirSourceElement, KtModifierListOwner, Visibility, FirCallableDeclaration<*>, Name>(SourceElementPositioningStrategies.VISIBILITY_MODIFIER)
|
||||
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 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)
|
||||
val PROPERTY_TYPE_MISMATCH_ON_OVERRIDE by error2<FirSourceElement, KtNamedDeclaration, FirMemberDeclaration, FirMemberDeclaration>(SourceElementPositioningStrategies.DECLARATION_RETURN_TYPE)
|
||||
val VAR_TYPE_MISMATCH_ON_OVERRIDE by error2<FirSourceElement, KtNamedDeclaration, FirMemberDeclaration, FirMemberDeclaration>(SourceElementPositioningStrategies.DECLARATION_RETURN_TYPE)
|
||||
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* 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.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.fir.HASHCODE_NAME
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClass
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.modality
|
||||
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.scopes.unsubstitutedScope
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.fir.types.isNullableAny
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
object FirNotImplementedOverrideChecker : FirClassChecker() {
|
||||
|
||||
override fun check(declaration: FirClass<*>, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
// TODO: kt4763Property: reporting on `object` literal causes invalid error in test...FirDiagnosticHandler
|
||||
if (declaration !is FirRegularClass) return
|
||||
|
||||
val source = declaration.source ?: return
|
||||
if (source.kind is FirFakeSourceElementKind) return
|
||||
val modality = declaration.modality()
|
||||
if (modality == Modality.ABSTRACT || modality == Modality.SEALED) return
|
||||
if (declaration.isExpect) return
|
||||
val classKind = declaration.classKind
|
||||
// TODO: we should check enum entries (probably as anonymous objects, see above)
|
||||
if (classKind == ClassKind.ANNOTATION_CLASS || classKind == ClassKind.ENUM_CLASS) return
|
||||
|
||||
val classScope = declaration.unsubstitutedScope(
|
||||
context.session, context.sessionHolder.scopeSession, withForcedTypeCalculator = false
|
||||
)
|
||||
|
||||
val notImplementedSymbols = mutableListOf<FirCallableSymbol<*>>()
|
||||
val classPackage = declaration.symbol.classId.packageFqName
|
||||
|
||||
fun FirCallableMemberDeclaration<*>.isInvisible(): Boolean {
|
||||
if (visibility == Visibilities.Private ||
|
||||
!visibility.visibleFromPackage(classPackage, symbol.callableId.packageName)
|
||||
) return true
|
||||
if (visibility == Visibilities.Internal &&
|
||||
session !== declaration.session
|
||||
) return true
|
||||
return false
|
||||
}
|
||||
|
||||
fun FirCallableMemberDeclaration<*>.shouldBeImplemented(): Boolean {
|
||||
if (!isAbstract) return false
|
||||
val containingClass = getContainingClass(context)
|
||||
if (containingClass === declaration) return false
|
||||
if (containingClass is FirRegularClass && containingClass.isExpect) return false
|
||||
return true
|
||||
}
|
||||
|
||||
for (name in classScope.getCallableNames()) {
|
||||
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
|
||||
}
|
||||
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 (notImplementedSymbols.isNotEmpty()) {
|
||||
val notImplemented = notImplementedSymbols.first().fir
|
||||
if (notImplemented.isFromInterface(context)) {
|
||||
reporter.reportOn(source, FirErrors.ABSTRACT_MEMBER_NOT_IMPLEMENTED, declaration, notImplemented, context)
|
||||
} else {
|
||||
reporter.reportOn(source, FirErrors.ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED, declaration, notImplemented, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirCallableDeclaration<*>.isFromInterface(context: CheckerContext): Boolean =
|
||||
(getContainingClass(context) as? FirRegularClass)?.isInterface == true
|
||||
|
||||
private val FirSimpleFunction.matchesDataClassSyntheticMemberSignatures: Boolean
|
||||
get() = (this.name == OperatorNameConventions.EQUALS && matchesEqualsSignature) ||
|
||||
(this.name == HASHCODE_NAME && matchesHashCodeSignature) ||
|
||||
(this.name == OperatorNameConventions.TO_STRING && matchesToStringSignature)
|
||||
|
||||
// NB: we intentionally do not check return types
|
||||
private val FirSimpleFunction.matchesEqualsSignature: Boolean
|
||||
get() = valueParameters.size == 1 && valueParameters[0].returnTypeRef.coneType.isNullableAny
|
||||
|
||||
private val FirSimpleFunction.matchesHashCodeSignature: Boolean
|
||||
get() = valueParameters.isEmpty()
|
||||
|
||||
private val FirSimpleFunction.matchesToStringSignature: Boolean
|
||||
get() = valueParameters.isEmpty()
|
||||
}
|
||||
+29
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.FQ_N
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.NAME
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.NULLABLE_STRING
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.PROPERTY_NAME
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_CLASS_OR_OBJECT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.RENDER_TYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.SYMBOL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.SYMBOLS
|
||||
@@ -21,9 +22,11 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.TO_S
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.VISIBILITY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.WHEN_MISSING_CASES
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSENCE_OF_PRIMARY_CONSTRUCTOR_FOR_INLINE_CLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_DELEGATED_PROPERTY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_FUNCTION_WITH_BODY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_MEMBER_NOT_IMPLEMENTED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_PROPERTY_WITH_GETTER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_PROPERTY_WITH_INITIALIZER
|
||||
@@ -117,6 +120,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.LOCAL_ANNOTATION_
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.LOCAL_INTERFACE_NOT_ALLOWED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.LOCAL_OBJECT_NOT_ALLOWED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MANY_COMPANION_OBJECTS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MANY_IMPL_MEMBER_NOT_IMPLEMENTED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MISSING_VAL_ON_ANNOTATION_PARAMETER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTIPLE_VARARG_PARAMETERS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MUST_BE_INITIALIZED
|
||||
@@ -455,6 +459,31 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
|
||||
TO_STRING
|
||||
)
|
||||
|
||||
map.put(
|
||||
ABSTRACT_MEMBER_NOT_IMPLEMENTED,
|
||||
"{0} is not abstract and does not implement abstract member {1}",
|
||||
RENDER_CLASS_OR_OBJECT,
|
||||
FQ_NAMES_IN_TYPES
|
||||
)
|
||||
map.put(
|
||||
ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED,
|
||||
"{0} is not abstract and does not implement abstract base class member {1}",
|
||||
RENDER_CLASS_OR_OBJECT,
|
||||
FQ_NAMES_IN_TYPES
|
||||
)
|
||||
map.put(
|
||||
MANY_IMPL_MEMBER_NOT_IMPLEMENTED,
|
||||
"{0} must override {1} because it inherits many implementations of it",
|
||||
RENDER_CLASS_OR_OBJECT,
|
||||
FQ_NAMES_IN_TYPES
|
||||
)
|
||||
map.put(
|
||||
MANY_IMPL_MEMBER_NOT_IMPLEMENTED,
|
||||
"{0} must override {1} because it inherits multiple interface methods of it",
|
||||
RENDER_CLASS_OR_OBJECT,
|
||||
FQ_NAMES_IN_TYPES
|
||||
)
|
||||
|
||||
map.put(
|
||||
RETURN_TYPE_MISMATCH_ON_OVERRIDE,
|
||||
"Return type of ''{0}'' is not a subtype of the return type of the overridden member ''{1}''",
|
||||
|
||||
+6
@@ -77,6 +77,12 @@ object FirDiagnosticRenderers {
|
||||
name.asString()
|
||||
}
|
||||
|
||||
val RENDER_CLASS_OR_OBJECT = Renderer { firClass: FirClass<*> ->
|
||||
val name = firClass.classId.relativeClassName.asString()
|
||||
val classOrObject = if (firClass is FirRegularClass) "Class" else "Object"
|
||||
"$classOrObject $name"
|
||||
}
|
||||
|
||||
val RENDER_TYPE = Renderer { t: ConeKotlinType ->
|
||||
// TODO: need a way to tune granuality, e.g., without parameter names in functional types.
|
||||
t.render()
|
||||
|
||||
+1
@@ -40,6 +40,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
||||
|
||||
override val classCheckers: Set<FirClassChecker> = setOf(
|
||||
FirOverrideChecker,
|
||||
FirNotImplementedOverrideChecker,
|
||||
FirThrowableSubclassChecker,
|
||||
FirOpenMemberChecker,
|
||||
)
|
||||
|
||||
+2
-2
@@ -23,8 +23,8 @@ abstract class D {
|
||||
abstract val d: @An Int
|
||||
}
|
||||
|
||||
class E : D(), A
|
||||
class F : A
|
||||
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>class E<!> : D(), A
|
||||
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class F<!> : A
|
||||
|
||||
@An
|
||||
interface G {
|
||||
|
||||
@@ -12,9 +12,9 @@ fun foo() {
|
||||
x.foo()
|
||||
}
|
||||
|
||||
object Rr : SomeTrait {}
|
||||
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>object Rr<!> : SomeTrait {}
|
||||
|
||||
class C : SomeTrait {}
|
||||
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class C<!> : SomeTrait {}
|
||||
|
||||
fun foo2() {
|
||||
val r = object : Runnable {} //no error
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
//KT-559 Forbid abstract method call through super
|
||||
|
||||
package kt559
|
||||
|
||||
abstract class A {
|
||||
abstract val i : Int
|
||||
|
||||
abstract fun foo() : Int
|
||||
|
||||
fun fff() {}
|
||||
}
|
||||
|
||||
abstract class D(): A() {
|
||||
override val i : Int = 34
|
||||
}
|
||||
|
||||
class C() : D() {
|
||||
fun test() {
|
||||
super.i
|
||||
}
|
||||
}
|
||||
|
||||
class B() : A() {
|
||||
override fun foo(): Int {
|
||||
super.<!ABSTRACT_SUPER_CALL!>i<!>
|
||||
|
||||
super.fff() //everything is ok
|
||||
return super.<!ABSTRACT_SUPER_CALL!>foo<!>()
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
//KT-559 Forbid abstract method call through super
|
||||
|
||||
package kt559
|
||||
|
||||
+2
-2
@@ -5,11 +5,11 @@ interface T {
|
||||
val v : Int
|
||||
}
|
||||
|
||||
open class Br(t : T) : T {
|
||||
open <!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class Br<!>(t : T) : T {
|
||||
|
||||
}
|
||||
|
||||
class Br3(t : T) : Br(t) {
|
||||
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class Br3<!>(t : T) : Br(t) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -108,7 +108,7 @@ public class A extends AImpl implements List<String> {
|
||||
}
|
||||
|
||||
// FILE: X.kt
|
||||
class X : A()
|
||||
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>class X<!> : A()
|
||||
|
||||
fun main() {
|
||||
val x = X()
|
||||
|
||||
Vendored
+1
-1
@@ -95,7 +95,7 @@ public class A extends AImpl implements List<String> {
|
||||
}
|
||||
|
||||
// FILE: X.kt
|
||||
class X : A()
|
||||
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>class X<!> : A()
|
||||
|
||||
fun main() {
|
||||
val x = X()
|
||||
|
||||
@@ -11,7 +11,7 @@ public abstract class B implements A {
|
||||
|
||||
// FILE: C.kt
|
||||
|
||||
class C : B()
|
||||
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class C<!> : B()
|
||||
|
||||
fun main() {
|
||||
C().a
|
||||
|
||||
@@ -24,7 +24,7 @@ abstract class C {
|
||||
}
|
||||
}
|
||||
|
||||
object D : C() {
|
||||
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>object D<!> : C() {
|
||||
<!INCOMPATIBLE_MODIFIERS!>override<!> <!INCOMPATIBLE_MODIFIERS!>const<!> val x: Int = 9
|
||||
|
||||
const val inObject = 10
|
||||
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
// !LANGUAGE: +MultiPlatformProjects
|
||||
// MODULE: m1-common
|
||||
// FILE: common.kt
|
||||
|
||||
interface Foo {
|
||||
fun foo()
|
||||
}
|
||||
|
||||
expect class ImplicitFoo : Foo
|
||||
|
||||
expect class ExplicitFoo : Foo {
|
||||
override fun foo()
|
||||
}
|
||||
|
||||
expect class ImplicitFooCheck : Foo
|
||||
|
||||
// MODULE: m2-jvm(m1-common)
|
||||
// FILE: jvm.kt
|
||||
|
||||
actual class ImplicitFoo : Foo {
|
||||
override fun foo() {}
|
||||
}
|
||||
|
||||
actual class ExplicitFoo : Foo {
|
||||
actual override fun foo() {}
|
||||
}
|
||||
|
||||
actual class ImplicitFooCheck : Foo
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// !LANGUAGE: +MultiPlatformProjects
|
||||
// MODULE: m1-common
|
||||
// FILE: common.kt
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
abstract class A {
|
||||
abstract fun foo(): Int
|
||||
}
|
||||
|
||||
class B() : A() {
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
abstract class A {
|
||||
abstract fun foo(): Int
|
||||
}
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
abstract class A {
|
||||
abstract val i: Int
|
||||
}
|
||||
|
||||
class B() : A() {
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
abstract class A {
|
||||
abstract val i: Int
|
||||
}
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
abstract class A {
|
||||
abstract var i: Int
|
||||
}
|
||||
|
||||
class B() : A() {
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
abstract class A {
|
||||
abstract var i: Int
|
||||
}
|
||||
|
||||
@@ -21,21 +21,21 @@ open class MyClass() : MyTrait, MyAbstractClass() {
|
||||
|
||||
class MyChildClass() : MyClass() {}
|
||||
|
||||
class MyIllegalClass : MyTrait, MyAbstractClass() {}
|
||||
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class MyIllegalClass<!> : MyTrait, MyAbstractClass() {}
|
||||
|
||||
class MyIllegalClass2() : MyTrait, MyAbstractClass() {
|
||||
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>class MyIllegalClass2<!>() : MyTrait, MyAbstractClass() {
|
||||
override fun foo() {}
|
||||
override val pr : Unit = Unit
|
||||
override val prr : Unit = Unit
|
||||
}
|
||||
|
||||
class MyIllegalClass3() : MyTrait, MyAbstractClass() {
|
||||
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class MyIllegalClass3<!>() : MyTrait, MyAbstractClass() {
|
||||
override fun bar() {}
|
||||
override val pr : Unit = Unit
|
||||
override val prr : Unit = Unit
|
||||
}
|
||||
|
||||
class MyIllegalClass4() : MyTrait, MyAbstractClass() {
|
||||
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>class MyIllegalClass4<!>() : MyTrait, MyAbstractClass() {
|
||||
fun foo() {}
|
||||
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!>val pr : Unit<!>
|
||||
override fun other() {}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
abstract class A {
|
||||
abstract override fun toString(): String
|
||||
}
|
||||
|
||||
interface B
|
||||
|
||||
abstract class C : A(), B
|
||||
|
||||
class Test : C()
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
abstract class A {
|
||||
abstract override fun toString(): String
|
||||
}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
interface A {
|
||||
fun test() {
|
||||
}
|
||||
}
|
||||
|
||||
interface B : A {
|
||||
override fun test()
|
||||
}
|
||||
|
||||
interface C : A
|
||||
|
||||
interface D : C, B
|
||||
|
||||
class K : D
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
interface A {
|
||||
fun test() {
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
interface Runnable {
|
||||
fun run()
|
||||
}
|
||||
|
||||
class C {
|
||||
fun f() {
|
||||
class MyRunnable(): Runnable {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
interface Runnable {
|
||||
fun run()
|
||||
}
|
||||
|
||||
@@ -6,6 +6,6 @@ open class Q {
|
||||
val x: Int = 42
|
||||
}
|
||||
|
||||
class R : P, Q()
|
||||
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class R<!> : P, Q()
|
||||
|
||||
val s: Q = object : Q(), P {}
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ abstract class A2 {
|
||||
abstract fun foo()
|
||||
}
|
||||
|
||||
class B2 : A2()
|
||||
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>class B2<!> : A2()
|
||||
class C2 : B2() {
|
||||
override fun foo() {}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ class E : D(), B {
|
||||
override fun bar(x: CharSequence?, y: List<*>?): String = ""
|
||||
}
|
||||
|
||||
class E2 : B {
|
||||
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class E2<!> : B {
|
||||
override fun foo(x: Any, y: List<String?>): String = ""
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,6 @@ class E1 : C.D(), B {
|
||||
override fun foo(x: Any, y: Fun<Any?>) {}
|
||||
}
|
||||
|
||||
class E2 : B {
|
||||
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class E2<!> : B {
|
||||
override fun foo(x: Any, y: Fun<String?>) {}
|
||||
}
|
||||
|
||||
+4
-4
@@ -14,20 +14,20 @@ public interface B {
|
||||
|
||||
// FILE: C.kt
|
||||
|
||||
class C1 : A, B {
|
||||
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class C1<!> : A, B {
|
||||
override fun foo(x: String) {}
|
||||
}
|
||||
|
||||
class C2 : A, B {
|
||||
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class C2<!> : A, B {
|
||||
override fun foo(x: String?) {}
|
||||
}
|
||||
|
||||
interface I : A, B
|
||||
|
||||
class C3 : I {
|
||||
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class C3<!> : I {
|
||||
override fun foo(x: String) {}
|
||||
}
|
||||
|
||||
class C4 : I {
|
||||
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class C4<!> : I {
|
||||
override fun foo(x: String?) {}
|
||||
}
|
||||
@@ -57,7 +57,7 @@ interface I {
|
||||
fun foo2()
|
||||
}
|
||||
|
||||
class X : I {
|
||||
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class X<!> : I {
|
||||
override fun foo1() {
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -10,5 +10,5 @@ class BasicRecord(val x: String)
|
||||
data class BasicDataRecord(val x: String)
|
||||
|
||||
@JvmRecord
|
||||
class BasicRecordWithSuperClass(val x: String) : Record()
|
||||
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>class BasicRecordWithSuperClass<!>(val x: String) : Record()
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -2,4 +2,4 @@
|
||||
|
||||
import kotlin.reflect.*
|
||||
|
||||
class A: KSuspendFunction0<Unit> {}
|
||||
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class A<!>: KSuspendFunction0<Unit> {}
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ interface C : A {
|
||||
}
|
||||
}
|
||||
|
||||
class D : J {
|
||||
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class D<!> : J {
|
||||
suspend override fun foo() {
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -67,7 +67,7 @@ fun case3() {
|
||||
ImplBaseCase3()
|
||||
}
|
||||
|
||||
class ImplBaseCase3() : Base() {
|
||||
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>class ImplBaseCase3<!>() : Base() {
|
||||
override var b: Any
|
||||
get() = TODO()
|
||||
set(value) {}
|
||||
@@ -95,7 +95,7 @@ fun case4() {
|
||||
ImplBaseCase4()
|
||||
}
|
||||
|
||||
class ImplBaseCase4() : Base() {
|
||||
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>class ImplBaseCase4<!>() : Base() {
|
||||
override var b: Any
|
||||
get() = TODO()
|
||||
set(value) {}
|
||||
|
||||
+3
-3
@@ -26,7 +26,7 @@ class Case2Outer {
|
||||
}
|
||||
|
||||
inner
|
||||
class A() : Case2Base() {
|
||||
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>class A<!>() : Case2Base() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,7 @@ fun case3() {
|
||||
object : CaseOuter.CaseBase() {}.outerFoo()
|
||||
}
|
||||
|
||||
class B() : CaseOuter.CaseBase() {}
|
||||
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>class B<!>() : CaseOuter.CaseBase() {}
|
||||
|
||||
sealed class CaseOuter {
|
||||
val v = "v"
|
||||
@@ -46,6 +46,6 @@ sealed class CaseOuter {
|
||||
abstract fun foo(): String
|
||||
}
|
||||
|
||||
class A() : CaseBase() {
|
||||
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>class A<!>() : CaseBase() {
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ class Case2(override val a: String, override var b: <!VAR_TYPE_MISMATCH_ON_OVERR
|
||||
*/
|
||||
|
||||
class Case3 {
|
||||
class ImplBase1 : MainClass.Base1() {}
|
||||
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>class ImplBase1<!> : MainClass.Base1() {}
|
||||
}
|
||||
|
||||
class MainClass {
|
||||
|
||||
+4
-4
@@ -30,7 +30,7 @@ class Case1 {
|
||||
|
||||
inner
|
||||
|
||||
class ImplBase2_1 : ImplBase2() {
|
||||
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>class ImplBase2_1<!> : ImplBase2() {
|
||||
override var b: CharSequence = ""
|
||||
override fun boo(x: Int) {}
|
||||
}
|
||||
@@ -80,7 +80,7 @@ abstract class BaseCase3{
|
||||
* NOTE: abstract class implements kotlin interface
|
||||
*/
|
||||
|
||||
class Case4(a: String) : BaseCase4(a) {}
|
||||
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class Case4<!>(a: String) : BaseCase4(a) {}
|
||||
|
||||
interface InterfaceCase4 {
|
||||
fun foo(): String
|
||||
@@ -97,7 +97,7 @@ abstract class BaseCase4(val a: String) : InterfaceCase4 {}
|
||||
* NOTE: abstract class implements java interface
|
||||
*/
|
||||
|
||||
class Case5(a: String) : BaseCase5(a) {}
|
||||
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>class Case5<!>(a: String) : BaseCase5(a) {}
|
||||
|
||||
abstract class BaseCase5(val a: String) : java.util.Deque<String> {}
|
||||
|
||||
@@ -106,6 +106,6 @@ abstract class BaseCase5(val a: String) : java.util.Deque<String> {}
|
||||
* NOTE: abstract class implements java abstract class
|
||||
*/
|
||||
|
||||
class Case6(a: String) : BaseCase6(a) {}
|
||||
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>class Case6<!>(a: String) : BaseCase6(a) {}
|
||||
|
||||
abstract class BaseCase6(val a: String) : java.util.AbstractCollection<String>() {}
|
||||
|
||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.descriptors.java
|
||||
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
object JavaVisibilities {
|
||||
object PackageVisibility : Visibility("package", isPublicAPI = false) {
|
||||
@@ -32,6 +33,10 @@ object JavaVisibilities {
|
||||
override fun customEffectiveVisibility(): EffectiveVisibility? {
|
||||
return EffectiveVisibility.PackagePrivate
|
||||
}
|
||||
|
||||
override fun visibleFromPackage(fromPackage: FqName, myPackage: FqName): Boolean {
|
||||
return fromPackage == myPackage
|
||||
}
|
||||
}
|
||||
|
||||
object ProtectedStaticVisibility : Visibility("protected_static", isPublicAPI = true) {
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.descriptors
|
||||
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
abstract class Visibility protected constructor(
|
||||
val name: String,
|
||||
val isPublicAPI: Boolean
|
||||
@@ -27,4 +29,6 @@ abstract class Visibility protected constructor(
|
||||
|
||||
// Should be overloaded in Java visibilities
|
||||
open fun customEffectiveVisibility(): EffectiveVisibility? = null
|
||||
|
||||
open fun visibleFromPackage(fromPackage: FqName, myPackage: FqName): Boolean = true
|
||||
}
|
||||
|
||||
+32
@@ -880,6 +880,38 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.ABSTRACT_MEMBER_NOT_IMPLEMENTED) { firDiagnostic ->
|
||||
AbstractMemberNotImplementedImpl(
|
||||
firSymbolBuilder.buildClassLikeSymbol(firDiagnostic.a),
|
||||
firSymbolBuilder.buildCallableSymbol(firDiagnostic.b as FirCallableDeclaration),
|
||||
firDiagnostic as FirPsiDiagnostic<*>,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED) { firDiagnostic ->
|
||||
AbstractClassMemberNotImplementedImpl(
|
||||
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),
|
||||
firSymbolBuilder.buildCallableSymbol(firDiagnostic.b as FirCallableDeclaration),
|
||||
firDiagnostic as FirPsiDiagnostic<*>,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED) { firDiagnostic ->
|
||||
ManyInterfacesMemberNotImplementedImpl(
|
||||
firSymbolBuilder.buildClassLikeSymbol(firDiagnostic.a),
|
||||
firSymbolBuilder.buildCallableSymbol(firDiagnostic.b as FirCallableDeclaration),
|
||||
firDiagnostic as FirPsiDiagnostic<*>,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.RETURN_TYPE_MISMATCH_ON_OVERRIDE) { firDiagnostic ->
|
||||
ReturnTypeMismatchOnOverrideImpl(
|
||||
firSymbolBuilder.buildSymbol(firDiagnostic.a as FirDeclaration),
|
||||
|
||||
+24
@@ -625,6 +625,30 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
abstract val containingClassName: Name
|
||||
}
|
||||
|
||||
abstract class AbstractMemberNotImplemented : KtFirDiagnostic<KtClassOrObject>() {
|
||||
override val diagnosticClass get() = AbstractMemberNotImplemented::class
|
||||
abstract val classOrObject: KtClassLikeSymbol
|
||||
abstract val missingDeclaration: KtCallableSymbol
|
||||
}
|
||||
|
||||
abstract class AbstractClassMemberNotImplemented : KtFirDiagnostic<KtClassOrObject>() {
|
||||
override val diagnosticClass get() = AbstractClassMemberNotImplemented::class
|
||||
abstract val classOrObject: KtClassLikeSymbol
|
||||
abstract val missingDeclaration: KtCallableSymbol
|
||||
}
|
||||
|
||||
abstract class ManyImplMemberNotImplemented : KtFirDiagnostic<KtClassOrObject>() {
|
||||
override val diagnosticClass get() = ManyImplMemberNotImplemented::class
|
||||
abstract val classOrObject: KtClassLikeSymbol
|
||||
abstract val missingDeclaration: KtCallableSymbol
|
||||
}
|
||||
|
||||
abstract class ManyInterfacesMemberNotImplemented : KtFirDiagnostic<KtClassOrObject>() {
|
||||
override val diagnosticClass get() = ManyInterfacesMemberNotImplemented::class
|
||||
abstract val classOrObject: KtClassLikeSymbol
|
||||
abstract val missingDeclaration: KtCallableSymbol
|
||||
}
|
||||
|
||||
abstract class ReturnTypeMismatchOnOverride : KtFirDiagnostic<KtNamedDeclaration>() {
|
||||
override val diagnosticClass get() = ReturnTypeMismatchOnOverride::class
|
||||
abstract val function: KtSymbol
|
||||
|
||||
+36
@@ -1007,6 +1007,42 @@ internal class OverridingFinalMemberImpl(
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class AbstractMemberNotImplementedImpl(
|
||||
override val classOrObject: KtClassLikeSymbol,
|
||||
override val missingDeclaration: KtCallableSymbol,
|
||||
firDiagnostic: FirPsiDiagnostic<*>,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.AbstractMemberNotImplemented(), KtAbstractFirDiagnostic<KtClassOrObject> {
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class AbstractClassMemberNotImplementedImpl(
|
||||
override val classOrObject: KtClassLikeSymbol,
|
||||
override val missingDeclaration: KtCallableSymbol,
|
||||
firDiagnostic: FirPsiDiagnostic<*>,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.AbstractClassMemberNotImplemented(), KtAbstractFirDiagnostic<KtClassOrObject> {
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ManyImplMemberNotImplementedImpl(
|
||||
override val classOrObject: KtClassLikeSymbol,
|
||||
override val missingDeclaration: KtCallableSymbol,
|
||||
firDiagnostic: FirPsiDiagnostic<*>,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.ManyImplMemberNotImplemented(), KtAbstractFirDiagnostic<KtClassOrObject> {
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ManyInterfacesMemberNotImplementedImpl(
|
||||
override val classOrObject: KtClassLikeSymbol,
|
||||
override val missingDeclaration: KtCallableSymbol,
|
||||
firDiagnostic: FirPsiDiagnostic<*>,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.ManyInterfacesMemberNotImplemented(), KtAbstractFirDiagnostic<KtClassOrObject> {
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ReturnTypeMismatchOnOverrideImpl(
|
||||
override val function: KtSymbol,
|
||||
override val superFunction: KtSymbol,
|
||||
|
||||
Reference in New Issue
Block a user