FIR: Support inherited default parameters
This commit is contained in:
+31
@@ -7,8 +7,14 @@ package org.jetbrains.kotlin.fir.java.scopes
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirSimpleFunctionImpl
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.java.JavaTypeParameterStack
|
||||
import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass
|
||||
import org.jetbrains.kotlin.fir.java.declarations.FirJavaMethod
|
||||
import org.jetbrains.kotlin.fir.java.declarations.FirJavaValueParameter
|
||||
import org.jetbrains.kotlin.fir.java.types.FirJavaTypeRef
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction.NEXT
|
||||
@@ -103,6 +109,31 @@ class JavaClassUseSiteMemberScope(
|
||||
}
|
||||
}
|
||||
|
||||
override fun createFunctionCopy(firSimpleFunction: FirSimpleFunction, newSymbol: FirNamedFunctionSymbol): FirSimpleFunctionImpl {
|
||||
if (firSimpleFunction !is FirJavaMethod) return super.createFunctionCopy(firSimpleFunction, newSymbol)
|
||||
return FirJavaMethod(
|
||||
firSimpleFunction.session,
|
||||
firSimpleFunction.source,
|
||||
newSymbol,
|
||||
firSimpleFunction.name,
|
||||
firSimpleFunction.visibility,
|
||||
firSimpleFunction.modality,
|
||||
firSimpleFunction.returnTypeRef as FirJavaTypeRef,
|
||||
firSimpleFunction.status.isStatic
|
||||
)
|
||||
}
|
||||
|
||||
override fun createValueParameterCopy(parameter: FirValueParameter, newDefaultValue: FirExpression?): FirValueParameterImpl {
|
||||
if (parameter !is FirJavaValueParameter) return super.createValueParameterCopy(parameter, newDefaultValue)
|
||||
return FirJavaValueParameter(
|
||||
parameter.session,
|
||||
parameter.source,
|
||||
parameter.name,
|
||||
parameter.returnTypeRef as FirJavaTypeRef,
|
||||
parameter.isVararg
|
||||
)
|
||||
}
|
||||
|
||||
override fun processPropertiesByName(name: Name, processor: (FirCallableSymbol<*>) -> ProcessorAction): ProcessorAction {
|
||||
val getterName = Name.identifier(getterPrefix + name.asString().capitalize())
|
||||
return processAccessorFunctionsAndPropertiesByName(name, getterName, isGetter = true, processor = processor)
|
||||
|
||||
+2
-2
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
|
||||
abstract class AbstractFirOverrideScope(val session: FirSession, private val overrideChecker: FirOverrideChecker) : FirScope() {
|
||||
abstract class AbstractFirOverrideScope(val session: FirSession, protected val overrideChecker: FirOverrideChecker) : FirScope() {
|
||||
//base symbol as key, overridden as value
|
||||
val overrideByBase = mutableMapOf<FirCallableSymbol<*>, FirCallableSymbol<*>?>()
|
||||
|
||||
@@ -55,4 +55,4 @@ abstract class AbstractFirOverrideScope(val session: FirSession, private val ove
|
||||
return override
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+76
-4
@@ -6,11 +6,19 @@
|
||||
package org.jetbrains.kotlin.fir.scopes.impl
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirSimpleFunctionImpl
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.scopes.FirOverrideChecker
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
abstract class AbstractFirUseSiteMemberScope(
|
||||
@@ -22,13 +30,13 @@ abstract class AbstractFirUseSiteMemberScope(
|
||||
override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> ProcessorAction): ProcessorAction {
|
||||
val overrideCandidates = mutableSetOf<FirFunctionSymbol<*>>()
|
||||
if (!declaredMemberScope.processFunctionsByName(name) {
|
||||
overrideCandidates += it
|
||||
processor(it)
|
||||
val symbol = processInheritedDefaultParameters(it)
|
||||
overrideCandidates += symbol
|
||||
processor(symbol)
|
||||
}
|
||||
) return ProcessorAction.STOP
|
||||
|
||||
return superTypesScope.processFunctionsByName(name) {
|
||||
|
||||
val overriddenBy = it.getOverridden(overrideCandidates)
|
||||
if (overriddenBy == null) {
|
||||
processor(it)
|
||||
@@ -38,6 +46,70 @@ abstract class AbstractFirUseSiteMemberScope(
|
||||
}
|
||||
}
|
||||
|
||||
private fun processInheritedDefaultParameters(symbol: FirFunctionSymbol<*>): FirFunctionSymbol<*> {
|
||||
val firSimpleFunction = symbol.fir as? FirSimpleFunction ?: return symbol
|
||||
if (firSimpleFunction.valueParameters.isEmpty() || firSimpleFunction.valueParameters.any { it.defaultValue != null }) return symbol
|
||||
|
||||
var foundFir: FirFunction<*>? = null
|
||||
superTypesScope.processFunctionsByName(symbol.callableId.callableName) { superSymbol ->
|
||||
val superFunctionFir = superSymbol.fir
|
||||
if (superFunctionFir is FirSimpleFunction && overrideChecker.isOverriddenFunction(firSimpleFunction, superFunctionFir) &&
|
||||
superFunctionFir.valueParameters.any { parameter -> parameter.defaultValue != null }
|
||||
) {
|
||||
foundFir = superFunctionFir
|
||||
ProcessorAction.STOP
|
||||
} else {
|
||||
ProcessorAction.NEXT
|
||||
}
|
||||
}
|
||||
|
||||
if (foundFir == null) return symbol
|
||||
|
||||
val newSymbol = FirNamedFunctionSymbol(symbol.callableId, false, null)
|
||||
|
||||
createFunctionCopy(firSimpleFunction, newSymbol).apply {
|
||||
resolvePhase = firSimpleFunction.resolvePhase
|
||||
typeParameters += firSimpleFunction.typeParameters
|
||||
valueParameters += firSimpleFunction.valueParameters.zip(foundFir.valueParameters)
|
||||
.map { (overrideParameter, overriddenParameter) ->
|
||||
if (overriddenParameter.defaultValue != null)
|
||||
createValueParameterCopy(overrideParameter, overriddenParameter.defaultValue).apply {
|
||||
annotations += overrideParameter.annotations
|
||||
}
|
||||
else
|
||||
overrideParameter
|
||||
}
|
||||
}
|
||||
|
||||
return newSymbol
|
||||
}
|
||||
|
||||
protected open fun createFunctionCopy(firSimpleFunction: FirSimpleFunction, newSymbol: FirNamedFunctionSymbol): FirSimpleFunctionImpl =
|
||||
FirSimpleFunctionImpl(
|
||||
firSimpleFunction.source,
|
||||
firSimpleFunction.session,
|
||||
firSimpleFunction.returnTypeRef,
|
||||
firSimpleFunction.receiverTypeRef,
|
||||
firSimpleFunction.name,
|
||||
firSimpleFunction.status,
|
||||
newSymbol
|
||||
)
|
||||
|
||||
protected open fun createValueParameterCopy(parameter: FirValueParameter, newDefaultValue: FirExpression?): FirValueParameterImpl =
|
||||
with(parameter) {
|
||||
FirValueParameterImpl(
|
||||
source,
|
||||
session,
|
||||
returnTypeRef,
|
||||
name,
|
||||
FirVariableSymbol(parameter.symbol.callableId),
|
||||
newDefaultValue,
|
||||
isCrossinline,
|
||||
isNoinline,
|
||||
isVararg
|
||||
)
|
||||
}
|
||||
|
||||
override fun processClassifiersByName(
|
||||
name: Name,
|
||||
processor: (FirClassifierSymbol<*>) -> ProcessorAction
|
||||
@@ -47,4 +119,4 @@ abstract class AbstractFirUseSiteMemberScope(
|
||||
}
|
||||
return superTypesScope.processClassifiersByName(name, processor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
interface I1 {
|
||||
fun foo(x: Int = 1)
|
||||
}
|
||||
|
||||
interface I2 {
|
||||
fun bar(x: String = "", y: Int)
|
||||
}
|
||||
|
||||
class A : I1, I2 {
|
||||
override fun foo(x: Int) {}
|
||||
override fun bar(x: String, y: Int) {}
|
||||
}
|
||||
|
||||
fun foo(a: A) {
|
||||
a.foo()
|
||||
a.foo(1)
|
||||
|
||||
a.<!INAPPLICABLE_CANDIDATE!>bar<!>()
|
||||
a.<!INAPPLICABLE_CANDIDATE!>bar<!>("")
|
||||
a.bar(y = 1)
|
||||
a.bar("", 2)
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
FILE: defaultFromOverrides.kt
|
||||
public abstract interface I1 : R|kotlin/Any| {
|
||||
public abstract fun foo(x: R|kotlin/Int| = Int(1)): R|kotlin/Unit|
|
||||
|
||||
}
|
||||
public abstract interface I2 : R|kotlin/Any| {
|
||||
public abstract fun bar(x: R|kotlin/String| = String(), y: R|kotlin/Int|): R|kotlin/Unit|
|
||||
|
||||
}
|
||||
public final class A : R|I1|, R|I2| {
|
||||
public constructor(): R|A| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final override fun foo(x: R|kotlin/Int|): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
public final override fun bar(x: R|kotlin/String|, y: R|kotlin/Int|): R|kotlin/Unit| {
|
||||
}
|
||||
|
||||
}
|
||||
public final fun foo(a: R|A|): R|kotlin/Unit| {
|
||||
R|<local>/a|.R|/A.foo|()
|
||||
R|<local>/a|.R|/A.foo|(Int(1))
|
||||
R|<local>/a|.<Inapplicable(PARAMETER_MAPPING_ERROR): [/A.bar]>#()
|
||||
R|<local>/a|.<Inapplicable(PARAMETER_MAPPING_ERROR): [/A.bar]>#(String())
|
||||
R|<local>/a|.R|/A.bar|(y = Int(1))
|
||||
R|<local>/a|.R|/A.bar|(String(), Int(2))
|
||||
}
|
||||
+5
@@ -245,6 +245,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
|
||||
runTest("compiler/fir/resolve/testData/resolve/arguments/default.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("defaultFromOverrides.kt")
|
||||
public void testDefaultFromOverrides() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/arguments/defaultFromOverrides.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("fieldPlusAssign.kt")
|
||||
public void testFieldPlusAssign() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/arguments/fieldPlusAssign.kt");
|
||||
|
||||
Reference in New Issue
Block a user