From 80a7f92309b4048467fde84b93c05c3acb769b53 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Wed, 7 Feb 2018 17:47:54 +0100 Subject: [PATCH] Extract logic to get function parameters for default value generation For some reason, this logic was a bit different in JVM (FunctionCodegen) and JS (FunctionBodyTranslator). For example, in JS the EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND diagnostic was reported even in the case when no expected function was found for the actual function at all, which made it quite difficult to write multiplatform sources for JS stdlib where it both should be compiled as a part of the multiplatform project, and by itself (suppressing NO_ACTUAL_FOR_EXPECT): in the latter case, the new error must have been suppressed everywhere as well #KT-21913 --- .../kotlin/backend/common/CodegenUtil.kt | 28 ++++++++++++++++ .../kotlin/codegen/FunctionCodegen.java | 33 ++++--------------- .../utils/FunctionBodyTranslator.java | 21 ++---------- 3 files changed, 36 insertions(+), 46 deletions(-) diff --git a/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/CodegenUtil.kt b/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/CodegenUtil.kt index 3d391c17af2..d70875ec983 100644 --- a/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/CodegenUtil.kt +++ b/compiler/backend-common/src/org/jetbrains/kotlin/backend/common/CodegenUtil.kt @@ -20,11 +20,14 @@ import com.intellij.openapi.project.Project import com.intellij.psi.PsiElement import org.jetbrains.kotlin.backend.common.bridges.findInterfaceImplementation import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.diagnostics.DiagnosticSink +import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall @@ -175,4 +178,29 @@ object CodegenUtil { } return compatibleExpectedFunctions.firstOrNull() as FunctionDescriptor? } + + @JvmStatic + fun getFunctionParametersForDefaultValueGeneration( + descriptor: FunctionDescriptor, + trace: DiagnosticSink? + ): List { + if (descriptor.isActual) { + val expected = CodegenUtil.findExpectedFunctionForActual(descriptor) + if (expected != null && expected.valueParameters.any(ValueParameterDescriptor::declaresDefaultValue)) { + val element = DescriptorToSourceUtils.descriptorToDeclaration(expected) + if (element == null) { + if (trace != null) { + val actualDeclaration = DescriptorToSourceUtils.descriptorToDeclaration(descriptor) + ?: error("Not a source declaration: $descriptor") + trace.report(Errors.EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND.on(actualDeclaration)) + } + return descriptor.valueParameters + } + + return expected.valueParameters + } + } + + return descriptor.valueParameters + } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java index ee4c5252400..c260c817255 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java @@ -74,7 +74,6 @@ import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DEC import static org.jetbrains.kotlin.descriptors.ModalityKt.isOverridable; import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.*; import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUtilKt.isEffectivelyInlineOnly; -import static org.jetbrains.kotlin.diagnostics.Errors.EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND; import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.getSourceFromDescriptor; import static org.jetbrains.kotlin.resolve.DescriptorUtils.*; import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE; @@ -1110,16 +1109,9 @@ public class FunctionCodegen { GenerationState state = parentCodegen.state; JvmMethodSignature signature = state.getTypeMapper().mapSignatureWithGeneric(functionDescriptor, methodContext.getContextKind()); - List originalParameters = functionDescriptor.getValueParameters(); - List valueParameters; - if (functionDescriptor.isActual() && CollectionsKt.none(originalParameters, ValueParameterDescriptor::declaresDefaultValue)) { - FunctionDescriptor expected = CodegenUtil.findExpectedFunctionForActual(functionDescriptor); - assert expected != null : "Expected function should have been found earlier for " + functionDescriptor; - valueParameters = expected.getValueParameters(); - } - else { - valueParameters = originalParameters; - } + // 'null' because the "could not find expected declaration" error has been already reported in isDefaultNeeded earlier + List valueParameters = + CodegenUtil.getFunctionParametersForDefaultValueGeneration(functionDescriptor, null); boolean isStatic = isStaticMethod(methodContext.getContextKind(), functionDescriptor); FrameMap frameMap = createFrameMap(state, signature, functionDescriptor.getExtensionReceiverParameter(), valueParameters, isStatic); @@ -1260,22 +1252,9 @@ public class FunctionCodegen { } private boolean isDefaultNeeded(@NotNull FunctionDescriptor descriptor, @Nullable KtNamedFunction function) { - if (descriptor.isActual()) { - FunctionDescriptor expected = CodegenUtil.findExpectedFunctionForActual(descriptor); - if (expected != null && CollectionsKt.any(expected.getValueParameters(), ValueParameterDescriptor::declaresDefaultValue)) { - PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(expected); - if (element == null) { - if (function != null) { - state.getDiagnostics().report(EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND.on(function)); - } - return false; - } - - return true; - } - } - - return CollectionsKt.any(descriptor.getValueParameters(), ValueParameterDescriptor::declaresDefaultValue); + List parameters = + CodegenUtil.getFunctionParametersForDefaultValueGeneration(descriptor, state.getDiagnostics()); + return CollectionsKt.any(parameters, ValueParameterDescriptor::declaresDefaultValue); } private void generateBridge( diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/FunctionBodyTranslator.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/FunctionBodyTranslator.java index 09859db8069..727ee69f9a1 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/FunctionBodyTranslator.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/utils/FunctionBodyTranslator.java @@ -17,7 +17,6 @@ package org.jetbrains.kotlin.js.translate.utils; import com.intellij.psi.PsiElement; -import kotlin.collections.CollectionsKt; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.backend.common.CodegenUtil; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; @@ -25,7 +24,6 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor; import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; import org.jetbrains.kotlin.descriptors.FunctionDescriptor; import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor; -import org.jetbrains.kotlin.diagnostics.Errors; import org.jetbrains.kotlin.js.backend.ast.*; import org.jetbrains.kotlin.js.backend.ast.metadata.MetadataProperties; import org.jetbrains.kotlin.js.naming.NameSuggestion; @@ -38,7 +36,6 @@ import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator; import org.jetbrains.kotlin.psi.KtBlockExpression; import org.jetbrains.kotlin.psi.KtDeclarationWithBody; import org.jetbrains.kotlin.psi.KtExpression; -import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils; import org.jetbrains.kotlin.resolve.source.KotlinSourceElementKt; import org.jetbrains.kotlin.types.KotlinType; @@ -83,22 +80,8 @@ public final class FunctionBodyTranslator extends AbstractTranslator { @NotNull TranslationContext context ) { List valueParameters = descriptor.getValueParameters(); - List valueParametersForDefaultValue; - if (descriptor.isActual() && CollectionsKt.none(valueParameters, ValueParameterDescriptor::declaresDefaultValue)) { - FunctionDescriptor expected = CodegenUtil.findExpectedFunctionForActual(descriptor); - if (expected != null) { - valueParametersForDefaultValue = expected.getValueParameters(); - } - else { - PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(descriptor); - assert element != null : "No element found for descriptor: " + descriptor; - context.bindingTrace().report(Errors.EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND.on(element)); - valueParametersForDefaultValue = valueParameters; - } - } - else { - valueParametersForDefaultValue = valueParameters; - } + List valueParametersForDefaultValue = + CodegenUtil.getFunctionParametersForDefaultValueGeneration(descriptor, context.bindingTrace()); List result = new ArrayList<>(valueParameters.size()); for (int i = 0; i < valueParameters.size(); i++) {