FirDefaultParametersResolver: process imported from objects properly

#KT-49083 Fixed
This commit is contained in:
Mikhail Glukhikh
2021-10-13 16:48:22 +03:00
committed by TeamCityServer
parent c5a4a5de42
commit 09bc729b0e
8 changed files with 79 additions and 15 deletions
@@ -5069,6 +5069,12 @@ public class DiagnosisCompilerFirTestdataTestGenerated extends AbstractDiagnosis
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/intellij/DailyAggregatedDoubleFactor.kt");
}
@Test
@TestMetadata("defaultParameterFromBase.kt")
public void testDefaultParameterFromBase() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/intellij/defaultParameterFromBase.kt");
}
@Test
@TestMetadata("EnumWithToString.kt")
public void testEnumWithToString() throws Exception {
@@ -0,0 +1,22 @@
FILE: defaultParameterFromBase.kt
public open class Base : R|kotlin/Any| {
public constructor(): R|Base| {
super<R|kotlin/Any|>()
}
public open fun foo(arg: R|kotlin/Int|, def: R|kotlin/String| = String()): R|kotlin/Unit| {
}
}
public final object Derived : R|Base| {
private constructor(): R|Derived| {
super<R|Base|>()
}
public final override fun foo(arg: R|kotlin/Int|, def: R|kotlin/String|): R|kotlin/Unit| {
}
}
public final fun test(): R|kotlin/Unit| {
Q|Derived|.R|/Derived.foo|(Int(42))
}
@@ -0,0 +1,11 @@
import Derived.foo
open class Base {
open fun foo(arg: Int, def: String = "") {}
}
object Derived : Base() {
override fun foo(arg: Int, def: String) {}
}
fun test() {
foo(42) // No value passed for parameter 'def'
}
@@ -5069,6 +5069,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/intellij/DailyAggregatedDoubleFactor.kt");
}
@Test
@TestMetadata("defaultParameterFromBase.kt")
public void testDefaultParameterFromBase() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/intellij/defaultParameterFromBase.kt");
}
@Test
@TestMetadata("EnumWithToString.kt")
public void testEnumWithToString() throws Exception {
@@ -5069,6 +5069,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/intellij/DailyAggregatedDoubleFactor.kt");
}
@Test
@TestMetadata("defaultParameterFromBase.kt")
public void testDefaultParameterFromBase() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/intellij/defaultParameterFromBase.kt");
}
@Test
@TestMetadata("EnumWithToString.kt")
public void testEnumWithToString() throws Exception {
@@ -8,26 +8,36 @@ package org.jetbrains.kotlin.fir.resolve
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSessionComponent
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.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.scopes.*
import org.jetbrains.kotlin.fir.scopes.impl.FirAbstractImportingScope
class FirDefaultParametersResolver : FirSessionComponent {
fun declaresDefaultValue(
session: FirSession,
scopeSession: ScopeSession,
valueParameter: FirValueParameter,
function: FirFunction,
originScope: FirScope?,
index: Int,
): Boolean {
if (valueParameter.defaultValue != null) return true
if (originScope !is FirTypeScope) return false
val symbol = function.symbol as? FirNamedFunctionSymbol ?: return false
if (function !is FirSimpleFunction) return false
val symbol = function.symbol
val typeScope = when (originScope) {
is FirTypeScope -> originScope
// imported from object case
is FirAbstractImportingScope -> {
val containingClass = function.getContainingClass(session) ?: return false
containingClass.scopeForClass(ConeSubstitutor.Empty, session, scopeSession)
}
else -> return false
}
var result = false
originScope.processOverriddenFunctions(symbol) { overridden ->
typeScope.processOverriddenFunctions(symbol) { overridden ->
if (overridden.fir.valueParameters[index].defaultValue != null) {
result = true
return@processOverriddenFunctions ProcessorAction.STOP
@@ -446,7 +446,7 @@ private fun initialTypeOfCandidate(candidate: Candidate, typeRef: FirResolvedTyp
return candidate.substitutor.substituteOrSelf(typeRef.type)
}
fun FirCallableDeclaration.getContainingClass(session: FirSession): FirRegularClass? = this.containingClassForStaticMemberAttr?.let { lookupTag ->
fun FirCallableDeclaration.getContainingClass(session: FirSession): FirRegularClass? = this.containingClass()?.let { lookupTag ->
session.symbolProvider.getSymbolByLookupTag(lookupTag)?.fir as? FirRegularClass
}
@@ -259,12 +259,15 @@ private class FirCallArgumentsProcessor(
for ((index, parameter) in parameters.withIndex()) {
if (!result.containsKey(parameter)) {
if (bodyResolveComponents.session.defaultParameterResolver.declaresDefaultValue(parameter, function, originScope, index)) {
result[parameter] = ResolvedCallArgument.DefaultArgument
} else if (parameter.isVararg) {
result[parameter] = ResolvedCallArgument.VarargArgument(emptyList())
} else {
addDiagnostic(NoValueForParameter(parameter, function))
when {
bodyResolveComponents.session.defaultParameterResolver.declaresDefaultValue(
useSiteSession, bodyResolveComponents.scopeSession, parameter, function, originScope, index
) ->
result[parameter] = ResolvedCallArgument.DefaultArgument
parameter.isVararg ->
result[parameter] = ResolvedCallArgument.VarargArgument(emptyList())
else ->
addDiagnostic(NoValueForParameter(parameter, function))
}
}
}