FIR: use Java 8 rules in not implemented checker
This commit is contained in:
+5
@@ -2789,6 +2789,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/problems/secondaryConstructorCfg.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("symbolsAndDescriptors.kt")
|
||||
public void testSymbolsAndDescriptors() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/problems/symbolsAndDescriptors.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("transform.kt")
|
||||
public void testTransform() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/problems/transform.kt");
|
||||
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
FILE: symbolsAndDescriptors.kt
|
||||
public final class IrClassSymbolImpl : R|IrBindableSymbolBase<kotlin/String>|, R|IrClassSymbol| {
|
||||
public constructor(descriptor: R|kotlin/String?| = Null(null)): R|IrClassSymbolImpl| {
|
||||
super<R|IrBindableSymbolBase<kotlin/String>|>(R|<local>/descriptor|)
|
||||
}
|
||||
|
||||
}
|
||||
public abstract interface IrClassSymbol : R|IrClassifierSymbol|, R|IrBindableSymbol<kotlin/String>| {
|
||||
}
|
||||
public abstract interface IrClassifierSymbol : R|IrSymbol|, R|TypeConstructorMarker| {
|
||||
public abstract override val descriptor: R|kotlin/CharSequence|
|
||||
public get(): R|kotlin/CharSequence|
|
||||
|
||||
}
|
||||
public abstract interface IrSymbol : R|kotlin/Any| {
|
||||
public abstract val descriptor: R|kotlin/Any|
|
||||
public get(): R|kotlin/Any|
|
||||
|
||||
}
|
||||
public abstract interface TypeConstructorMarker : R|kotlin/Any| {
|
||||
}
|
||||
public abstract interface IrBindableSymbol<out D : R|kotlin/Any|> : R|IrSymbol| {
|
||||
public abstract override val descriptor: R|D|
|
||||
public get(): R|D|
|
||||
|
||||
}
|
||||
public abstract class IrBindableSymbolBase<out D : R|kotlin/Any|> : R|IrBindableSymbol<D>|, R|IrSymbolBase<D>| {
|
||||
public constructor<out D : R|kotlin/Any|>(descriptor: R|D?|): R|IrBindableSymbolBase<D>| {
|
||||
super<R|IrSymbolBase<D>|>(R|<local>/descriptor|)
|
||||
}
|
||||
|
||||
}
|
||||
public abstract class IrSymbolBase<out D : R|kotlin/Any|> : R|IrSymbol| {
|
||||
public constructor<out D : R|kotlin/Any|>(_descriptor: R|D?|): R|IrSymbolBase<D>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
private final val _descriptor: R|D?| = R|<local>/_descriptor|
|
||||
private get(): R|D?|
|
||||
|
||||
public open override val descriptor: R|D|
|
||||
public get(): R|D| {
|
||||
^ this@R|/IrSymbolBase|.R|/IrSymbolBase._descriptor|!!
|
||||
}
|
||||
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
class IrClassSymbolImpl(descriptor: String? = null) :
|
||||
IrBindableSymbolBase<String>(descriptor),
|
||||
IrClassSymbol
|
||||
|
||||
interface IrClassSymbol : IrClassifierSymbol, IrBindableSymbol<String>
|
||||
|
||||
interface IrClassifierSymbol : IrSymbol, TypeConstructorMarker {
|
||||
override val descriptor: CharSequence
|
||||
}
|
||||
|
||||
interface IrSymbol {
|
||||
val descriptor: Any
|
||||
}
|
||||
|
||||
interface TypeConstructorMarker
|
||||
|
||||
interface IrBindableSymbol<out D : Any> : IrSymbol {
|
||||
override val descriptor: D
|
||||
}
|
||||
|
||||
abstract class IrBindableSymbolBase<out D : Any>(descriptor: D?) :
|
||||
IrBindableSymbol<D>, IrSymbolBase<D>(descriptor)
|
||||
|
||||
abstract class IrSymbolBase<out D : Any>(
|
||||
private val _descriptor: D?
|
||||
) : IrSymbol {
|
||||
override val descriptor: D
|
||||
get() = _descriptor!!
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
+6
@@ -3159,6 +3159,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/problems/secondaryConstructorCfg.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("symbolsAndDescriptors.kt")
|
||||
public void testSymbolsAndDescriptors() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/problems/symbolsAndDescriptors.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("transform.kt")
|
||||
public void testTransform() throws Exception {
|
||||
|
||||
+6
@@ -3159,6 +3159,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/problems/secondaryConstructorCfg.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("symbolsAndDescriptors.kt")
|
||||
public void testSymbolsAndDescriptors() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolve/problems/symbolsAndDescriptors.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("transform.kt")
|
||||
public void testTransform() throws Exception {
|
||||
|
||||
+53
-8
@@ -63,11 +63,58 @@ object FirNotImplementedOverrideChecker : FirClassChecker() {
|
||||
return false
|
||||
}
|
||||
|
||||
fun FirIntersectionCallableSymbol.subjectToManyNotImplemented(): Boolean {
|
||||
var nonAbstractCountInClass = 0
|
||||
var nonAbstractCountInInterface = 0
|
||||
var abstractCountInInterface = 0
|
||||
for (intersectionSymbol in intersections) {
|
||||
val intersection = intersectionSymbol.fir as FirCallableMemberDeclaration
|
||||
val containingClass = intersection.getContainingClass(context) as? FirRegularClass
|
||||
val hasInterfaceContainer = containingClass?.classKind == ClassKind.INTERFACE
|
||||
if (intersection.modality != Modality.ABSTRACT) {
|
||||
if (hasInterfaceContainer) {
|
||||
nonAbstractCountInInterface++
|
||||
} else {
|
||||
nonAbstractCountInClass++
|
||||
}
|
||||
} else if (hasInterfaceContainer) {
|
||||
abstractCountInInterface++
|
||||
}
|
||||
if (nonAbstractCountInClass + nonAbstractCountInInterface > 1) {
|
||||
return true
|
||||
}
|
||||
if (nonAbstractCountInInterface > 0 && abstractCountInInterface > 0) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun FirIntersectionCallableSymbol.shouldBeImplemented(): Boolean {
|
||||
// In Java 8, non-abstract intersection overrides having abstract symbol from base class
|
||||
// still should be implemented in current class (even when they have default interface implementation)
|
||||
if (intersections.none {
|
||||
val fir = (it.fir as FirCallableMemberDeclaration).unwrapFakeOverrides()
|
||||
fir.isAbstract && (fir.getContainingClass(context) as? FirRegularClass)?.classKind == ClassKind.CLASS
|
||||
}
|
||||
) return false
|
||||
// Exception from the rule above: interface implementation via delegation
|
||||
if (intersections.any {
|
||||
val fir = (it.fir as FirCallableMemberDeclaration)
|
||||
fir.origin == FirDeclarationOrigin.Delegated && !fir.isAbstract
|
||||
}
|
||||
) return false
|
||||
return true
|
||||
}
|
||||
|
||||
fun FirCallableMemberDeclaration<*>.shouldBeImplemented(): Boolean {
|
||||
if (!isAbstract) return false
|
||||
val containingClass = getContainingClass(context)
|
||||
if (containingClass === declaration && origin == FirDeclarationOrigin.Source) return false
|
||||
if (containingClass is FirRegularClass && containingClass.isExpect) return false
|
||||
if (!isAbstract) {
|
||||
val symbol = symbol as? FirIntersectionCallableSymbol ?: return false
|
||||
return symbol.shouldBeImplemented()
|
||||
}
|
||||
if (containingClass === declaration && origin == FirDeclarationOrigin.Source) return false
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -75,9 +122,8 @@ object FirNotImplementedOverrideChecker : FirClassChecker() {
|
||||
classScope.processFunctionsByName(name) { namedFunctionSymbol ->
|
||||
val simpleFunction = namedFunctionSymbol.fir
|
||||
if (namedFunctionSymbol is FirIntersectionOverrideFunctionSymbol) {
|
||||
if (namedFunctionSymbol.intersections.count {
|
||||
(it.fir as FirCallableMemberDeclaration).modality != Modality.ABSTRACT
|
||||
} > 1 && simpleFunction.getContainingClass(context) === declaration
|
||||
if (simpleFunction.getContainingClass(context) === declaration &&
|
||||
namedFunctionSymbol.subjectToManyNotImplemented()
|
||||
) {
|
||||
notImplementedIntersectionSymbols += namedFunctionSymbol
|
||||
return@processFunctionsByName
|
||||
@@ -99,9 +145,8 @@ object FirNotImplementedOverrideChecker : FirClassChecker() {
|
||||
classScope.processPropertiesByName(name) { propertySymbol ->
|
||||
val property = propertySymbol.fir as? FirProperty ?: return@processPropertiesByName
|
||||
if (propertySymbol is FirIntersectionOverridePropertySymbol) {
|
||||
if (propertySymbol.intersections.count {
|
||||
(it.fir as FirCallableMemberDeclaration).modality != Modality.ABSTRACT
|
||||
} > 1 && property.getContainingClass(context) === declaration
|
||||
if (property.getContainingClass(context) === declaration &&
|
||||
propertySymbol.subjectToManyNotImplemented()
|
||||
) {
|
||||
notImplementedIntersectionSymbols += propertySymbol
|
||||
return@processPropertiesByName
|
||||
|
||||
Reference in New Issue
Block a user