FIR: report ABSTRACT_*_NOT_IMPLEMENTED on appropriate intersections
This commit is contained in:
+2
-2
@@ -6,8 +6,8 @@ public interface MyList<E> extends java.util.List<E>, I {}
|
|||||||
fun <R> elemAndList(r: R, t: MutableList<R>): R = TODO()
|
fun <R> elemAndList(r: R, t: MutableList<R>): R = TODO()
|
||||||
|
|
||||||
interface I
|
interface I
|
||||||
class A : Comparable<A>, I
|
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class A<!> : Comparable<A>, I
|
||||||
class B : Comparable<B>, I
|
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class B<!> : Comparable<B>, I
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
elemAndList(A(), list(B()))
|
elemAndList(A(), list(B()))
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ interface Message<M : Message<M>> {
|
|||||||
fun <T> ext(e: Ext<M, T>): T
|
fun <T> ext(e: Ext<M, T>): T
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyMessage : Message<MyMessage>
|
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class MyMessage<!> : Message<MyMessage>
|
||||||
class MyExt : Ext<MyMessage, String>
|
class MyExt : Ext<MyMessage, String>
|
||||||
|
|
||||||
fun <M : Message<M>, T> Message<M>.extF(e: Ext<M, T>): T = ext(e)
|
fun <M : Message<M>, T> Message<M>.extF(e: Ext<M, T>): T = ext(e)
|
||||||
|
|||||||
+3
-6
@@ -9,8 +9,7 @@ import org.jetbrains.kotlin.config.LanguageFeature
|
|||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
import org.jetbrains.kotlin.fir.*
|
||||||
import org.jetbrains.kotlin.fir.HASHCODE_NAME
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClass
|
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClass
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.modality
|
import org.jetbrains.kotlin.fir.analysis.checkers.modality
|
||||||
@@ -25,9 +24,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MANY_IMPL_MEMBER_
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OVERRIDING_FINAL_MEMBER_BY_DELEGATION
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OVERRIDING_FINAL_MEMBER_BY_DELEGATION
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.containingClass
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionCallableSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionCallableSymbol
|
||||||
@@ -69,7 +66,7 @@ object FirNotImplementedOverrideChecker : FirClassChecker() {
|
|||||||
fun FirCallableMemberDeclaration<*>.shouldBeImplemented(): Boolean {
|
fun FirCallableMemberDeclaration<*>.shouldBeImplemented(): Boolean {
|
||||||
if (!isAbstract) return false
|
if (!isAbstract) return false
|
||||||
val containingClass = getContainingClass(context)
|
val containingClass = getContainingClass(context)
|
||||||
if (containingClass === declaration) return false
|
if (containingClass === declaration && origin == FirDeclarationOrigin.Source) return false
|
||||||
if (containingClass is FirRegularClass && containingClass.isExpect) return false
|
if (containingClass is FirRegularClass && containingClass.isExpect) return false
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -121,7 +118,7 @@ object FirNotImplementedOverrideChecker : FirClassChecker() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (notImplementedSymbols.isNotEmpty()) {
|
if (notImplementedSymbols.isNotEmpty()) {
|
||||||
val notImplemented = notImplementedSymbols.first().fir
|
val notImplemented = notImplementedSymbols.first().unwrapFakeOverrides().fir
|
||||||
if (notImplemented.isFromInterfaceOrEnum(context)) {
|
if (notImplemented.isFromInterfaceOrEnum(context)) {
|
||||||
reporter.reportOn(source, ABSTRACT_MEMBER_NOT_IMPLEMENTED, declaration, notImplemented, context)
|
reporter.reportOn(source, ABSTRACT_MEMBER_NOT_IMPLEMENTED, declaration, notImplemented, context)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ interface G<T> {
|
|||||||
fun foo(t : T) : T
|
fun foo(t : T) : T
|
||||||
}
|
}
|
||||||
|
|
||||||
class GC() : G<Int> {
|
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class GC<!>() : G<Int> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ abstract class A<T> {
|
|||||||
public abstract fun bar(x: T)
|
public abstract fun bar(x: T)
|
||||||
|
|
||||||
public inner abstract class B<S> : A<B<S>>() {
|
public inner abstract class B<S> : A<B<S>>() {
|
||||||
public inner class C<U> : <!UNRESOLVED_REFERENCE!>B<C<U>><!>()
|
public inner <!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>class C<!><U> : <!UNRESOLVED_REFERENCE!>B<C<U>><!>()
|
||||||
{
|
{
|
||||||
// Here B<C<U>> means A<A<A<T>.B<S>>.B<A<T>.B<S>.C<U>>>.B<A<A<T>.B<S>>.B<A<T>.B<S>.C<U>>.C<U>>
|
// Here B<C<U>> means A<A<A<T>.B<S>>.B<A<T>.B<S>.C<U>>>.B<A<A<T>.B<S>>.B<A<T>.B<S>.C<U>>.C<U>>
|
||||||
// while for being a correct override it should be A<A<T>.B<S>>.B<A<T>.B<S>.C<U>>
|
// while for being a correct override it should be A<A<T>.B<S>>.B<A<T>.B<S>.C<U>>
|
||||||
|
|||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
package typeReferenceError
|
package typeReferenceError
|
||||||
|
|
||||||
class Pair<<!SYNTAX!><!>:<!UNRESOLVED_REFERENCE!>(val c: <!SYNTAX!><!SYNTAX!><!>fun<!><!SYNTAX!><!> <!UNRESOLVED_REFERENCE!>main<!><!>()
|
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class Pair<!><<!SYNTAX!><!>:<!UNRESOLVED_REFERENCE!>(val c: <!SYNTAX!><!SYNTAX!><!>fun<!><!SYNTAX!><!> <!UNRESOLVED_REFERENCE!>main<!><!>()
|
||||||
|
|||||||
Vendored
+1
-1
@@ -108,7 +108,7 @@ public class A extends AImpl implements List<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FILE: X.kt
|
// FILE: X.kt
|
||||||
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>class X<!> : A()
|
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class X<!> : A()
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
val x = X()
|
val x = X()
|
||||||
|
|||||||
Vendored
+1
-1
@@ -95,7 +95,7 @@ public class A extends AImpl implements List<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FILE: X.kt
|
// FILE: X.kt
|
||||||
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>class X<!> : A()
|
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class X<!> : A()
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
val x = X()
|
val x = X()
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
interface ILeft {
|
|
||||||
fun foo()
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IRight {
|
|
||||||
fun foo()
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IDerived : ILeft, IRight
|
|
||||||
|
|
||||||
class CDerived : ILeft, IRight
|
|
||||||
|
|
||||||
abstract class ADerived : ILeft, IRight
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
interface ILeft {
|
interface ILeft {
|
||||||
fun foo()
|
fun foo()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
package extendFunctionClass
|
|
||||||
|
|
||||||
class A : Function1<Int, Int> {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class B : Function1<Int, Int> {
|
|
||||||
override fun invoke(p1 : Int) = p1
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
package extendFunctionClass
|
package extendFunctionClass
|
||||||
|
|
||||||
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class A<!> : Function1<Int, Int> {
|
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class A<!> : Function1<Int, Int> {
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
interface A {
|
|
||||||
fun foo() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface B : A {
|
|
||||||
abstract override fun foo()
|
|
||||||
}
|
|
||||||
|
|
||||||
interface C {
|
|
||||||
abstract fun foo()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fake override Z#foo should be abstract
|
|
||||||
class Z : B, C
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
interface A {
|
interface A {
|
||||||
fun foo() {}
|
fun foo() {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
interface A {
|
|
||||||
fun foo() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface B : A {
|
|
||||||
abstract override fun foo()
|
|
||||||
}
|
|
||||||
|
|
||||||
interface C : A {
|
|
||||||
abstract override fun foo()
|
|
||||||
}
|
|
||||||
|
|
||||||
interface D : A
|
|
||||||
|
|
||||||
// Fake override Z#foo should be abstract
|
|
||||||
class Z : B, C, D
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
interface A {
|
interface A {
|
||||||
fun foo() {}
|
fun foo() {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,15 +40,15 @@ abstract class MyAbstractClass1 : MyTrait<Int>, MyAbstractClass<String>() {
|
|||||||
override fun bar(t: String) = t
|
override fun bar(t: String) = t
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyIllegalGenericClass1<T> : MyTrait<T>, MyAbstractClass<T>() {}
|
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class MyIllegalGenericClass1<!><T> : MyTrait<T>, MyAbstractClass<T>() {}
|
||||||
class MyIllegalGenericClass2<T, R>(r : R) : MyTrait<T>, MyAbstractClass<R>() {
|
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class MyIllegalGenericClass2<!><T, R>(r : R) : MyTrait<T>, MyAbstractClass<R>() {
|
||||||
override fun foo(r: R) = r
|
override fun foo(r: R) = r
|
||||||
override val <T> pr : R = r
|
override val <T> pr : R = r
|
||||||
}
|
}
|
||||||
class MyIllegalClass1 : MyTrait<Int>, MyAbstractClass<String>() {}
|
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class MyIllegalClass1<!> : MyTrait<Int>, MyAbstractClass<String>() {}
|
||||||
abstract class MyLegalAbstractClass1 : MyTrait<Int>, MyAbstractClass<String>() {}
|
abstract class MyLegalAbstractClass1 : MyTrait<Int>, MyAbstractClass<String>() {}
|
||||||
|
|
||||||
class MyIllegalClass2<T>(t : T) : MyTrait<Int>, MyAbstractClass<Int>() {
|
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class MyIllegalClass2<!><T>(t : T) : MyTrait<Int>, MyAbstractClass<Int>() {
|
||||||
fun foo(t: T) = t
|
fun foo(t: T) = t
|
||||||
fun bar(t: T) = t
|
fun bar(t: T) = t
|
||||||
val <R> pr : T = t
|
val <R> pr : T = t
|
||||||
|
|||||||
Vendored
+2
-2
@@ -6,5 +6,5 @@ interface Y {
|
|||||||
fun foo(a : Int = 1)
|
fun foo(a : Int = 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
class Z1 : X, Y {} // BUG
|
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class Z1<!> : X, Y {} // BUG
|
||||||
object Z1O : X, Y {} // BUG
|
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>object Z1O<!> : X, Y {} // BUG
|
||||||
|
|||||||
-17
@@ -1,17 +0,0 @@
|
|||||||
package test
|
|
||||||
|
|
||||||
interface A {
|
|
||||||
val a: String
|
|
||||||
}
|
|
||||||
|
|
||||||
interface B {
|
|
||||||
val a: String
|
|
||||||
}
|
|
||||||
|
|
||||||
open class C {
|
|
||||||
private val a: String = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
class Subject : C(), A, B {
|
|
||||||
val c = a
|
|
||||||
}
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
package test
|
package test
|
||||||
|
|
||||||
interface A {
|
interface A {
|
||||||
|
|||||||
-11
@@ -1,11 +0,0 @@
|
|||||||
// http://youtrack.jetbrains.com/issue/KT-1996
|
|
||||||
|
|
||||||
interface Foo {
|
|
||||||
fun foo(): Unit
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Bar {
|
|
||||||
fun foo(): Unit
|
|
||||||
}
|
|
||||||
|
|
||||||
class Baz : Foo, Bar
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// http://youtrack.jetbrains.com/issue/KT-1996
|
// http://youtrack.jetbrains.com/issue/KT-1996
|
||||||
|
|
||||||
interface Foo {
|
interface Foo {
|
||||||
|
|||||||
Vendored
+1
-1
@@ -19,7 +19,7 @@ interface IDerived : ILeft, IRight {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Error: ILeft::copy and IRight::copy have unrelated return types
|
// Error: ILeft::copy and IRight::copy have unrelated return types
|
||||||
class CDerivedInvalid1 : ILeft, IRight
|
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class CDerivedInvalid1<!> : ILeft, IRight
|
||||||
|
|
||||||
// Error: CLeft::copy and IRight::copy have unrelated return types
|
// Error: CLeft::copy and IRight::copy have unrelated return types
|
||||||
class CDerivedInvalid2 : CLeft(), IRight
|
class CDerivedInvalid2 : CLeft(), IRight
|
||||||
|
|||||||
Vendored
+1
-1
@@ -9,7 +9,7 @@ fun test() {
|
|||||||
<!INAPPLICABLE_CANDIDATE!>a<!> {}
|
<!INAPPLICABLE_CANDIDATE!>a<!> {}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Ext : String.() -> Unit {
|
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class Ext<!> : String.() -> Unit {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun test2() {
|
fun test2() {
|
||||||
|
|||||||
+1
-1
@@ -97,7 +97,7 @@ abstract class BaseCase4(val a: String) : InterfaceCase4 {}
|
|||||||
* NOTE: abstract class implements java interface
|
* NOTE: abstract class implements java interface
|
||||||
*/
|
*/
|
||||||
|
|
||||||
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>class Case5<!>(a: String) : BaseCase5(a) {}
|
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class Case5<!>(a: String) : BaseCase5(a) {}
|
||||||
|
|
||||||
abstract class BaseCase5(val a: String) : java.util.Deque<String> {}
|
abstract class BaseCase5(val a: String) : java.util.Deque<String> {}
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -23,13 +23,13 @@
|
|||||||
override fun bar(t: String) = t
|
override fun bar(t: String) = t
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyIllegalGenericClass1<T> : MyTrait<T>, MyAbstractClass<T>() {}
|
<error descr="[ABSTRACT_MEMBER_NOT_IMPLEMENTED] Class MyIllegalGenericClass1 is not abstract and does not implement abstract member foo">class MyIllegalGenericClass1</error><T> : MyTrait<T>, MyAbstractClass<T>() {}
|
||||||
class MyIllegalGenericClass2<T, R> : MyTrait<T>, MyAbstractClass<R>() {
|
<error descr="[ABSTRACT_MEMBER_NOT_IMPLEMENTED] Class MyIllegalGenericClass2 is not abstract and does not implement abstract member foo">class MyIllegalGenericClass2</error><T, R> : MyTrait<T>, MyAbstractClass<R>() {
|
||||||
override fun foo(r: R) = r
|
override fun foo(r: R) = r
|
||||||
}
|
}
|
||||||
class MyIllegalClass1 : MyTrait<Int>, MyAbstractClass<String>() {}
|
<error descr="[ABSTRACT_MEMBER_NOT_IMPLEMENTED] Class MyIllegalClass1 is not abstract and does not implement abstract member foo">class MyIllegalClass1</error> : MyTrait<Int>, MyAbstractClass<String>() {}
|
||||||
|
|
||||||
class MyIllegalClass2<T> : MyTrait<Int>, MyAbstractClass<Int>() {
|
<error descr="[ABSTRACT_MEMBER_NOT_IMPLEMENTED] Class MyIllegalClass2 is not abstract and does not implement abstract member foo">class MyIllegalClass2</error><T> : MyTrait<Int>, MyAbstractClass<Int>() {
|
||||||
fun foo(t: T) = t
|
fun foo(t: T) = t
|
||||||
fun bar(t: T) = t
|
fun bar(t: T) = t
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user