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.FirSession
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
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.JavaTypeParameterStack
|
||||||
import org.jetbrains.kotlin.fir.java.declarations.FirJavaClass
|
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.FirScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction.NEXT
|
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 {
|
override fun processPropertiesByName(name: Name, processor: (FirCallableSymbol<*>) -> ProcessorAction): ProcessorAction {
|
||||||
val getterName = Name.identifier(getterPrefix + name.asString().capitalize())
|
val getterName = Name.identifier(getterPrefix + name.asString().capitalize())
|
||||||
return processAccessorFunctionsAndPropertiesByName(name, getterName, isGetter = true, processor = processor)
|
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.AbstractFirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
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
|
//base symbol as key, overridden as value
|
||||||
val overrideByBase = mutableMapOf<FirCallableSymbol<*>, FirCallableSymbol<*>?>()
|
val overrideByBase = mutableMapOf<FirCallableSymbol<*>, FirCallableSymbol<*>?>()
|
||||||
|
|
||||||
@@ -55,4 +55,4 @@ abstract class AbstractFirOverrideScope(val session: FirSession, private val ove
|
|||||||
return override
|
return override
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+76
-4
@@ -6,11 +6,19 @@
|
|||||||
package org.jetbrains.kotlin.fir.scopes.impl
|
package org.jetbrains.kotlin.fir.scopes.impl
|
||||||
|
|
||||||
import org.jetbrains.kotlin.fir.FirSession
|
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.FirOverrideChecker
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
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
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
abstract class AbstractFirUseSiteMemberScope(
|
abstract class AbstractFirUseSiteMemberScope(
|
||||||
@@ -22,13 +30,13 @@ abstract class AbstractFirUseSiteMemberScope(
|
|||||||
override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> ProcessorAction): ProcessorAction {
|
override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> ProcessorAction): ProcessorAction {
|
||||||
val overrideCandidates = mutableSetOf<FirFunctionSymbol<*>>()
|
val overrideCandidates = mutableSetOf<FirFunctionSymbol<*>>()
|
||||||
if (!declaredMemberScope.processFunctionsByName(name) {
|
if (!declaredMemberScope.processFunctionsByName(name) {
|
||||||
overrideCandidates += it
|
val symbol = processInheritedDefaultParameters(it)
|
||||||
processor(it)
|
overrideCandidates += symbol
|
||||||
|
processor(symbol)
|
||||||
}
|
}
|
||||||
) return ProcessorAction.STOP
|
) return ProcessorAction.STOP
|
||||||
|
|
||||||
return superTypesScope.processFunctionsByName(name) {
|
return superTypesScope.processFunctionsByName(name) {
|
||||||
|
|
||||||
val overriddenBy = it.getOverridden(overrideCandidates)
|
val overriddenBy = it.getOverridden(overrideCandidates)
|
||||||
if (overriddenBy == null) {
|
if (overriddenBy == null) {
|
||||||
processor(it)
|
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(
|
override fun processClassifiersByName(
|
||||||
name: Name,
|
name: Name,
|
||||||
processor: (FirClassifierSymbol<*>) -> ProcessorAction
|
processor: (FirClassifierSymbol<*>) -> ProcessorAction
|
||||||
@@ -47,4 +119,4 @@ abstract class AbstractFirUseSiteMemberScope(
|
|||||||
}
|
}
|
||||||
return superTypesScope.processClassifiersByName(name, processor)
|
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");
|
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")
|
@TestMetadata("fieldPlusAssign.kt")
|
||||||
public void testFieldPlusAssign() throws Exception {
|
public void testFieldPlusAssign() throws Exception {
|
||||||
runTest("compiler/fir/resolve/testData/resolve/arguments/fieldPlusAssign.kt");
|
runTest("compiler/fir/resolve/testData/resolve/arguments/fieldPlusAssign.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user