Skip to content

Commit

Permalink
~~~
Browse files Browse the repository at this point in the history
  • Loading branch information
mglukhikh committed Mar 18, 2021
1 parent 9882e02 commit ff00017
Show file tree
Hide file tree
Showing 8 changed files with 72 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,23 @@ object FirNotImplementedOverrideChecker : FirClassChecker() {
if (source.kind is FirFakeSourceElementKind) return

val contributedMembers = collectCallableMembers(declaration, context)
val baseSymbolsForFakeOverrides = declaration.calcBaseSymbolsForFakeOverrides(
val trivialFakeOverrideStubs = declaration.computeFakeOverrideStubs(
contributedMembers, context.session, context.sessionHolder.scopeSession
).filter {
val fir = it.fir
if (it !is FirFakeOverrideStub.Trivial) return@filter false
val fir = it.baseSymbol.fir
fir is FirMemberDeclaration &&
fir.isAbstract &&
// TODO: FIR MPP support
(fir.getContainingClass(context) as? FirRegularClass)?.isExpect == false
}

if (baseSymbolsForFakeOverrides.isEmpty()) return
if (trivialFakeOverrideStubs.isEmpty()) return

// TODO: differentiate type-substituted declarations. Otherwise, they will be reported as MANY_IMPL_MEMBER_NOT_IMPLEMENTED
val sigToDeclarations = mutableMapOf<String, MutableList<FirCallableDeclaration<*>>>()
for (baseSymbolForFakeOverride in baseSymbolsForFakeOverrides) {
for (trivialFakeOverrideStub in trivialFakeOverrideStubs) {
val baseSymbolForFakeOverride = trivialFakeOverrideStub.baseSymbol
val sig = when (baseSymbolForFakeOverride) {
is FirNamedFunctionSymbol -> SignaturePresenter.represent(baseSymbolForFakeOverride.fir)
is FirPropertySymbol -> SignaturePresenter.represent(baseSymbolForFakeOverride.fir)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

package org.jetbrains.kotlin.fir.declarations

import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.resolve.ScopeSession
Expand All @@ -15,75 +14,89 @@ import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenProperties
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol

fun FirClass<*>.calcBaseSymbolsForFakeOverrides(
contributedDeclarations: Collection<FirDeclaration>,
sealed class FirFakeOverrideStub(val baseSymbols: List<FirCallableSymbol<*>>) {
class FromScope(
val symbol: FirCallableSymbol<*>,
baseSymbols: List<FirCallableSymbol<*>>
) : FirFakeOverrideStub(baseSymbols)

class Trivial(baseSymbol: FirCallableSymbol<*>) : FirFakeOverrideStub(listOf(baseSymbol))

val baseSymbol get() = baseSymbols.single()
}

private object FakeOverrideStubKey : FirDeclarationDataKey()

var FirClass<*>.fakeOverrideStubs: List<FirFakeOverrideStub>?
by FirDeclarationDataRegistry.data(FakeOverrideStubKey)

fun FirClass<*>.computeFakeOverrideStubs(
realDeclarations: Collection<FirDeclaration>,
session: FirSession,
scopeSession: ScopeSession,
): Collection<FirCallableSymbol<*>> {
baseSymbolsForFakeOverrides?.let { return it }
val result = mutableListOf<FirCallableSymbol<*>>()
): List<FirFakeOverrideStub> {
fakeOverrideStubs?.let { return it }
val result = mutableListOf<FirFakeOverrideStub>()
val classScope = unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = false)

fun checkFunctionSymbolAndAddToResult(originalSymbol: FirCallableSymbol<*>) {
this.computeBaseDeclarations(
originalSymbol,
contributedDeclarations,
result,
classScope,
FirTypeScope::getDirectOverriddenFunctions
)
}

fun checkPropertySymbolAndAddToResult(originalSymbol: FirCallableSymbol<*>) {
this.computeBaseDeclarations(
originalSymbol,
contributedDeclarations,
result,
classScope,
FirTypeScope::getDirectOverriddenProperties
)
}

val contributedDeclarationNames = contributedDeclarations.mapNotNullTo(mutableSetOf()) l@{
val classLookupTag = symbol.toLookupTag()
val realDeclarationNames = realDeclarations.mapNotNullTo(mutableSetOf()) l@{
val callableDeclaration = (it as? FirCallableMemberDeclaration<*>) ?: return@l null
// TODO: for multi-inheritance, we may need much stronger conditions like something in [FakeOverrideGenerator]
// For now, collect non-abstract members only
if (callableDeclaration.status.modality == Modality.ABSTRACT) null
// We may need to create a new fake override; compute base symbols; or deal with name conflicts.
if (callableDeclaration.symbol.shouldHaveComputedBaseSymbolsForClass(classLookupTag) ||
callableDeclaration.allowsToHaveFakeOverrideIn(this) ||
callableDeclaration.visibility == Visibilities.Private
) null
// Otherwise, bail out early based on the name of the contributed member declaration
else callableDeclaration.symbol.callableId.callableName
}

val superTypesCallableNames = classScope.getCallableNames().filter { it !in contributedDeclarationNames }
val superTypesCallableNames = classScope.getCallableNames().filter { it !in realDeclarationNames }
for (name in superTypesCallableNames) {
classScope.processFunctionsByName(name) { functionSymbol ->
// TODO: MANY_* as well as some conflict diagnostics
//if (functionSymbol is FirIntersectionOverrideFunctionSymbol)
// functionSymbol.intersections.forEach(::checkFunctionSymbolAndAddToResult)
//else
checkFunctionSymbolAndAddToResult(functionSymbol)
computeFakeOverrideStubsForSymbol(
functionSymbol,
realDeclarations,
result,
classScope,
FirTypeScope::getDirectOverriddenFunctions
)
}

classScope.processPropertiesByName(name) { propertySymbol ->
// TODO: MANY_* as well as some conflict diagnostics
//if (propertySymbol is FirIntersectionOverridePropertySymbol)
// propertySymbol.intersections.forEach(::checkPropertySymbolAndAddToResult)
//else
checkPropertySymbolAndAddToResult(propertySymbol)
computeFakeOverrideStubsForSymbol(
propertySymbol,
realDeclarations,
result,
classScope,
FirTypeScope::getDirectOverriddenProperties
)
}
}

baseSymbolsForFakeOverrides = result
fakeOverrideStubs = result
return result
}

private inline fun <reified D : FirCallableMemberDeclaration<D>, reified S : FirCallableSymbol<D>> FirClass<*>.computeBaseDeclarations(
private inline fun <
reified D : FirCallableMemberDeclaration<D>,
reified S : FirCallableSymbol<D>
> FirClass<*>.computeFakeOverrideStubsForSymbol(
originalSymbol: FirCallableSymbol<*>,
contributedDeclarations: Collection<FirDeclaration>,
result: MutableList<FirCallableSymbol<*>>,
realDeclarations: Collection<FirDeclaration>,
result: MutableList<FirFakeOverrideStub>,
scope: FirTypeScope,
computeDirectOverridden: FirTypeScope.(S) -> List<S>,
) {
if (originalSymbol !is S || originalSymbol.fir in contributedDeclarations) return
if (originalSymbol !is S || originalSymbol.fir in realDeclarations) return
val classLookupTag = symbol.toLookupTag()
val originalDeclaration = originalSymbol.fir
if (originalSymbol.dispatchReceiverClassOrNull() == classLookupTag && !originalDeclaration.origin.fromSupertypes) return
Expand All @@ -92,12 +105,16 @@ private inline fun <reified D : FirCallableMemberDeclaration<D>, reified S : Fir
originalSymbol.shouldHaveComputedBaseSymbolsForClass(classLookupTag) -> {
// Substitution or intersection case.
// The current one is a FIR declaration for that fake override, and we can compute base symbols from it.
computeBaseSymbols(originalSymbol, computeDirectOverridden, scope, classLookupTag)
result.add(
FirFakeOverrideStub.FromScope(
originalSymbol, computeBaseSymbols(originalSymbol, computeDirectOverridden, scope, classLookupTag)
)
)
}
originalDeclaration.allowsToHaveFakeOverrideIn(firClass = this) -> {
// Trivial fake override case.
// FIR2IR will create a fake override in BE IR directly, and the current one _is_ the base declaration.
result.add(originalSymbol)
result.add(FirFakeOverrideStub.Trivial(originalSymbol))
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,11 +187,6 @@ private object IsReferredViaField : FirDeclarationDataKey()
var FirProperty.isFromVararg: Boolean? by FirDeclarationDataRegistry.data(IsFromVarargKey)
var FirProperty.isReferredViaField: Boolean? by FirDeclarationDataRegistry.data(IsReferredViaField)

private object BaseSymbolsForFakeOverrides : FirDeclarationDataKey()

var FirClass<*>.baseSymbolsForFakeOverrides: Collection<FirCallableSymbol<*>>?
by FirDeclarationDataRegistry.data(BaseSymbolsForFakeOverrides)

// See [BindingContext.BACKING_FIELD_REQUIRED]
val FirProperty.hasBackingField: Boolean
get() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 = ""
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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?>) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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?) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

import kotlin.reflect.*

class A: KSuspendFunction0<Unit> {}
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class A<!>: KSuspendFunction0<Unit> {}
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ fun case2() {

// TESTCASE NUMBER: 3

class Case3 : BaseKotlin() {}
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>class Case3<!> : BaseKotlin() {}

fun case3() {
val v = Case3()
Expand All @@ -73,7 +73,7 @@ fun case3() {
*/
abstract class AbstractClassCase4 : BaseKotlin() {}

class Case4 : AbstractClassCase4() {}
<!ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED!>class Case4<!> : AbstractClassCase4() {}

fun case4() {
val v = Case4()
Expand Down

0 comments on commit ff00017

Please sign in to comment.