diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassUseSiteMemberScope.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassUseSiteMemberScope.kt index 1339715d448..8789c86c531 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassUseSiteMemberScope.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassUseSiteMemberScope.kt @@ -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) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/AbstractFirOverrideScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/AbstractFirOverrideScope.kt index a2897aaf6da..54087d7dff4 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/AbstractFirOverrideScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/AbstractFirOverrideScope.kt @@ -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<*>?>() @@ -55,4 +55,4 @@ abstract class AbstractFirOverrideScope(val session: FirSession, private val ove return override } -} \ No newline at end of file +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/AbstractFirUseSiteMemberScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/AbstractFirUseSiteMemberScope.kt index e4029dfcdf8..200ce1c350d 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/AbstractFirUseSiteMemberScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/AbstractFirUseSiteMemberScope.kt @@ -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>() 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) } -} \ No newline at end of file +} diff --git a/compiler/fir/resolve/testData/resolve/arguments/defaultFromOverrides.kt b/compiler/fir/resolve/testData/resolve/arguments/defaultFromOverrides.kt new file mode 100644 index 00000000000..6995c3c4d61 --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/arguments/defaultFromOverrides.kt @@ -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.bar() + a.bar("") + a.bar(y = 1) + a.bar("", 2) +} diff --git a/compiler/fir/resolve/testData/resolve/arguments/defaultFromOverrides.txt b/compiler/fir/resolve/testData/resolve/arguments/defaultFromOverrides.txt new file mode 100644 index 00000000000..572f865b1f3 --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/arguments/defaultFromOverrides.txt @@ -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() + } + + 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|/a|.R|/A.foo|() + R|/a|.R|/A.foo|(Int(1)) + R|/a|.#() + R|/a|.#(String()) + R|/a|.R|/A.bar|(y = Int(1)) + R|/a|.R|/A.bar|(String(), Int(2)) + } diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java index 0e2650c115b..cb4c378b08b 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java @@ -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");