From ea6076f6384d347fe0157d85eb78c2ae811f87e2 Mon Sep 17 00:00:00 2001 From: pTalanov Date: Sat, 5 May 2012 16:51:24 +0400 Subject: [PATCH] KT-1865 Calls with default argument values are generated incorrectly #KT-1865 Fixed --- .../k2js/test/semantics/MiscTest.java | 4 + .../AbstractCallExpressionTranslator.java | 8 +- .../k2js/translate/utils/BindingUtils.java | 98 ++++++++++--------- .../expression/misc/cases/KT-1865.kt | 11 +++ 4 files changed, 73 insertions(+), 48 deletions(-) create mode 100644 js/js.translator/testFiles/expression/misc/cases/KT-1865.kt diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/MiscTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/MiscTest.java index 7fac6d8226b..c9c770d744e 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/MiscTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/MiscTest.java @@ -125,4 +125,8 @@ public final class MiscTest extends AbstractExpressionTest { public void testExtensionLiteralCalledInsideExtensionFunction() throws Exception { checkFooBoxIsTrue("extensionLiteralCalledInsideExtensionFunction.kt"); } + + public void testKt1865() throws Exception { + checkFooBoxIsTrue("KT-1865.kt"); + } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/reference/AbstractCallExpressionTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/reference/AbstractCallExpressionTranslator.java index 02bf303717d..b19818a5ef1 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/reference/AbstractCallExpressionTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/reference/AbstractCallExpressionTranslator.java @@ -51,20 +51,20 @@ public abstract class AbstractCallExpressionTranslator extends AbstractTranslato protected final CallType callType; protected AbstractCallExpressionTranslator(@NotNull JetCallExpression expression, - @Nullable JsExpression receiver, - @NotNull CallType type, @NotNull TranslationContext context) { + @Nullable JsExpression receiver, + @NotNull CallType type, @NotNull TranslationContext context) { super(context); this.expression = expression; this.resolvedCall = getResolvedCallForCallExpression(bindingContext(), expression); this.receiver = receiver; - callType = type; + this.callType = type; } abstract public boolean shouldWrapVarargInArray(); @NotNull protected List translateSingleArgument(@NotNull ResolvedValueArgument actualArgument, - @NotNull ValueParameterDescriptor parameterDescriptor) { + @NotNull ValueParameterDescriptor parameterDescriptor) { List valueArguments = actualArgument.getArguments(); if (actualArgument instanceof VarargValueArgument) { return translateVarargArgument(valueArguments); diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java index a6fcbf75dbb..11090c851b7 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java @@ -55,41 +55,41 @@ public final class BindingUtils { DeclarationDescriptor descriptor = context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, expression); assert descriptor != null; assert descriptorClass.isInstance(descriptor) - : expression.toString() + " expected to have of type" + descriptorClass.toString(); + : expression.toString() + " expected to have of type" + descriptorClass.toString(); //noinspection unchecked - return (D)descriptor; + return (D) descriptor; } @NotNull public static ClassDescriptor getClassDescriptor(@NotNull BindingContext context, - @NotNull JetClassOrObject declaration) { + @NotNull JetClassOrObject declaration) { return getDescriptorForExpression(context, declaration, ClassDescriptor.class); } @NotNull public static NamespaceDescriptor getNamespaceDescriptor(@NotNull BindingContext context, - @NotNull JetFile declaration) { + @NotNull JetFile declaration) { NamespaceDescriptor namespaceDescriptor = - context.get(BindingContext.FQNAME_TO_NAMESPACE_DESCRIPTOR, JetPsiUtil.getFQName(declaration)); + context.get(BindingContext.FQNAME_TO_NAMESPACE_DESCRIPTOR, JetPsiUtil.getFQName(declaration)); assert namespaceDescriptor != null : "File should have a namespace descriptor."; return namespaceDescriptor; } @NotNull public static FunctionDescriptor getFunctionDescriptor(@NotNull BindingContext context, - @NotNull JetDeclarationWithBody declaration) { + @NotNull JetDeclarationWithBody declaration) { return getDescriptorForExpression(context, declaration, FunctionDescriptor.class); } @NotNull public static PropertyDescriptor getPropertyDescriptor(@NotNull BindingContext context, - @NotNull JetProperty declaration) { + @NotNull JetProperty declaration) { return getDescriptorForExpression(context, declaration, PropertyDescriptor.class); } @NotNull public static JetClass getClassForDescriptor(@NotNull BindingContext context, - @NotNull ClassDescriptor descriptor) { + @NotNull ClassDescriptor descriptor) { JetClass result = (JetClass) BindingContextUtils.classDescriptorToDeclaration(context, descriptor); if (result == null) { throw new IllegalStateException("JetClass not found for " + descriptor); @@ -99,15 +99,15 @@ public final class BindingUtils { @NotNull public static JetFunction getFunctionForDescriptor(@NotNull BindingContext context, - @NotNull SimpleFunctionDescriptor descriptor) { + @NotNull SimpleFunctionDescriptor descriptor) { PsiElement result = BindingContextUtils.callableDescriptorToDeclaration(context, descriptor); assert result instanceof JetFunction : "SimpleFunctionDescriptor should have declaration of type JetFunction"; - return (JetFunction)result; + return (JetFunction) result; } @NotNull public static List getDeclarationsForNamespace(@NotNull BindingContext bindingContext, - @NotNull NamespaceDescriptor namespace) { + @NotNull NamespaceDescriptor namespace) { List declarations = new ArrayList(); for (DeclarationDescriptor descriptor : getContainedDescriptorsWhichAreNotPredefined(namespace)) { if (descriptor instanceof NamespaceDescriptor) { @@ -123,22 +123,22 @@ public final class BindingUtils { @Nullable private static JetDeclaration getDeclarationForDescriptor(@NotNull BindingContext context, - @NotNull DeclarationDescriptor descriptor) { + @NotNull DeclarationDescriptor descriptor) { PsiElement result = BindingContextUtils.descriptorToDeclaration(context, descriptor); if (result == null) { //TODO: never get there return null; } assert result instanceof JetDeclaration : "Descriptor should correspond to an element."; - return (JetDeclaration)result; + return (JetDeclaration) result; } @NotNull private static JetParameter getParameterForDescriptor(@NotNull BindingContext context, - @NotNull ValueParameterDescriptor descriptor) { + @NotNull ValueParameterDescriptor descriptor) { PsiElement result = BindingContextUtils.descriptorToDeclaration(context, descriptor); assert result instanceof JetParameter : "ValueParameterDescriptor should have corresponding JetParameter."; - return (JetParameter)result; + return (JetParameter) result; } public static boolean hasAncestorClass(@NotNull BindingContext context, @NotNull JetClassOrObject classDeclaration) { @@ -155,7 +155,7 @@ public final class BindingUtils { @NotNull public static JetType getTypeByReference(@NotNull BindingContext context, - @NotNull JetTypeReference typeReference) { + @NotNull JetTypeReference typeReference) { JetType result = context.get(BindingContext.TYPE, typeReference); assert result != null : "TypeReference should reference a type"; return result; @@ -163,29 +163,29 @@ public final class BindingUtils { @NotNull public static ClassDescriptor getClassDescriptorForTypeReference(@NotNull BindingContext context, - @NotNull JetTypeReference typeReference) { + @NotNull JetTypeReference typeReference) { return getClassDescriptorForType(getTypeByReference(context, typeReference)); } @Nullable public static PropertyDescriptor getPropertyDescriptorForConstructorParameter(@NotNull BindingContext context, - @NotNull JetParameter parameter) { + @NotNull JetParameter parameter) { return context.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter); } @Nullable public static JetProperty getPropertyForDescriptor(@NotNull BindingContext context, - @NotNull PropertyDescriptor property) { + @NotNull PropertyDescriptor property) { PsiElement result = BindingContextUtils.descriptorToDeclaration(context, property); if (!(result instanceof JetProperty)) { return null; } - return (JetProperty)result; + return (JetProperty) result; } @NotNull public static DeclarationDescriptor getDescriptorForReferenceExpression(@NotNull BindingContext context, - @NotNull JetReferenceExpression reference) { + @NotNull JetReferenceExpression reference) { DeclarationDescriptor referencedDescriptor = getNullableDescriptorForReferenceExpression(context, reference); assert referencedDescriptor != null : "Reference expression must reference a descriptor."; return referencedDescriptor; @@ -194,7 +194,7 @@ public final class BindingUtils { //TODO: remove? @Nullable public static DeclarationDescriptor getNullableDescriptorForReferenceExpression(@NotNull BindingContext context, - @NotNull JetReferenceExpression reference) { + @NotNull JetReferenceExpression reference) { return context.get(BindingContext.REFERENCE_TARGET, reference); } @@ -204,7 +204,7 @@ public final class BindingUtils { @NotNull public static ResolvedCall getResolvedCall(@NotNull BindingContext context, - @NotNull JetExpression expression) { + @NotNull JetExpression expression) { ResolvedCall resolvedCall = context.get(BindingContext.RESOLVED_CALL, expression); assert resolvedCall != null : "Must resolve to a call."; return resolvedCall; @@ -212,18 +212,18 @@ public final class BindingUtils { @NotNull public static ResolvedCall getResolvedCallForProperty(@NotNull BindingContext context, - @NotNull JetExpression expression) { + @NotNull JetExpression expression) { ResolvedCall resolvedCall = context.get(BindingContext.RESOLVED_CALL, expression); assert resolvedCall != null : "Must resolve to a call."; if (resolvedCall instanceof VariableAsFunctionResolvedCall) { - return ((VariableAsFunctionResolvedCall)resolvedCall).getVariableCall(); + return ((VariableAsFunctionResolvedCall) resolvedCall).getVariableCall(); } return resolvedCall; } @NotNull public static ResolvedCall getResolvedCallForCallExpression(@NotNull BindingContext context, - @NotNull JetCallExpression expression) { + @NotNull JetCallExpression expression) { JetExpression calleeExpression = PsiUtils.getCallee(expression); return getResolvedCall(context, calleeExpression); } @@ -237,20 +237,20 @@ public final class BindingUtils { @Nullable public static FunctionDescriptor getFunctionDescriptorForOperationExpression(@NotNull BindingContext context, - @NotNull JetOperationExpression expression) { + @NotNull JetOperationExpression expression) { DeclarationDescriptor descriptorForReferenceExpression = getNullableDescriptorForReferenceExpression - (context, expression.getOperationReference()); + (context, expression.getOperationReference()); if (descriptorForReferenceExpression == null) return null; assert descriptorForReferenceExpression instanceof FunctionDescriptor - : "Operation should resolve to function descriptor."; - return (FunctionDescriptor)descriptorForReferenceExpression; + : "Operation should resolve to function descriptor."; + return (FunctionDescriptor) descriptorForReferenceExpression; } @NotNull public static DeclarationDescriptor getDescriptorForElement(@NotNull BindingContext context, - @NotNull PsiElement element) { + @NotNull PsiElement element) { DeclarationDescriptor descriptor = context.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element); assert descriptor != null : element + " doesn't have a descriptor."; return descriptor; @@ -267,17 +267,27 @@ public final class BindingUtils { @NotNull public static JetExpression getDefaultArgument(@NotNull BindingContext context, - @NotNull ValueParameterDescriptor parameterDescriptor) { - assert parameterDescriptor.hasDefaultValue() : "Unsupplied parameter must have default value."; - JetParameter psiParameter = getParameterForDescriptor(context, parameterDescriptor); + @NotNull ValueParameterDescriptor parameterDescriptor) { + ValueParameterDescriptor descriptorWhichDeclaresDefaultValue = getOriginalDescriptorWhichDeclaresDefaultValue(parameterDescriptor); + JetParameter psiParameter = getParameterForDescriptor(context, descriptorWhichDeclaresDefaultValue); JetExpression defaultValue = psiParameter.getDefaultValue(); assert defaultValue != null : "No default value found in PSI."; return defaultValue; } + private static ValueParameterDescriptor getOriginalDescriptorWhichDeclaresDefaultValue( + @NotNull ValueParameterDescriptor parameterDescriptor) { + ValueParameterDescriptor result = parameterDescriptor; + assert result.hasDefaultValue() : "Unsupplied parameter must have default value."; + while (!result.declaresDefaultValue()) { + result = result.getOverriddenDescriptors().iterator().next(); + } + return result; + } + @NotNull public static FunctionDescriptor getIteratorFunction(@NotNull BindingContext context, - @NotNull JetExpression rangeExpression) { + @NotNull JetExpression rangeExpression) { FunctionDescriptor functionDescriptor = context.get(BindingContext.LOOP_RANGE_ITERATOR, rangeExpression); assert functionDescriptor != null : "Range expression must have a descriptor for iterator function."; return functionDescriptor; @@ -285,7 +295,7 @@ public final class BindingUtils { @NotNull public static FunctionDescriptor getNextFunction(@NotNull BindingContext context, - @NotNull JetExpression rangeExpression) { + @NotNull JetExpression rangeExpression) { FunctionDescriptor functionDescriptor = context.get(BindingContext.LOOP_RANGE_NEXT, rangeExpression); assert functionDescriptor != null : "Range expression must have a descriptor for next function."; return functionDescriptor; @@ -293,7 +303,7 @@ public final class BindingUtils { @NotNull public static CallableDescriptor getHasNextCallable(@NotNull BindingContext context, - @NotNull JetExpression rangeExpression) { + @NotNull JetExpression rangeExpression) { CallableDescriptor hasNextDescriptor = context.get(BindingContext.LOOP_RANGE_HAS_NEXT, rangeExpression); assert hasNextDescriptor != null : "Range expression must have a descriptor for hasNext function or property."; return hasNextDescriptor; @@ -301,7 +311,7 @@ public final class BindingUtils { @NotNull public static PropertyDescriptor getPropertyDescriptorForObjectDeclaration(@NotNull BindingContext context, - @NotNull JetObjectDeclarationName name) { + @NotNull JetObjectDeclarationName name) { PropertyDescriptor propertyDescriptor = context.get(BindingContext.OBJECT_DECLARATION, name); assert propertyDescriptor != null; return propertyDescriptor; @@ -309,7 +319,7 @@ public final class BindingUtils { @NotNull public static Set getAllNonNativeNamespaceDescriptors(@NotNull BindingContext context, - @NotNull List files) { + @NotNull List files) { Set descriptorSet = Sets.newHashSet(); for (JetFile file : files) { //TODO: can't be @@ -323,7 +333,7 @@ public final class BindingUtils { @NotNull public static JetType getTypeForExpression(@NotNull BindingContext context, - @NotNull JetExpression expression) { + @NotNull JetExpression expression) { JetType type = context.get(BindingContext.EXPRESSION_TYPE, expression); assert type != null; return type; @@ -331,8 +341,8 @@ public final class BindingUtils { @NotNull public static ResolvedCall getResolvedCallForArrayAccess(@NotNull BindingContext context, - @NotNull JetArrayAccessExpression arrayAccessExpression, - boolean isGet) { + @NotNull JetArrayAccessExpression arrayAccessExpression, + boolean isGet) { ResolvedCall resolvedCall = context.get(isGet ? INDEXED_LVALUE_GET : INDEXED_LVALUE_SET, arrayAccessExpression); @@ -341,9 +351,9 @@ public final class BindingUtils { } public static ConstructorDescriptor getConstructor(@NotNull BindingContext bindingContext, - @NotNull JetClassOrObject declaration) { + @NotNull JetClassOrObject declaration) { ConstructorDescriptor primaryConstructor = - getClassDescriptor(bindingContext, declaration).getUnsubstitutedPrimaryConstructor(); + getClassDescriptor(bindingContext, declaration).getUnsubstitutedPrimaryConstructor(); assert primaryConstructor != null : "Traits do not have initialize methods."; return primaryConstructor; } diff --git a/js/js.translator/testFiles/expression/misc/cases/KT-1865.kt b/js/js.translator/testFiles/expression/misc/cases/KT-1865.kt new file mode 100644 index 00000000000..9f87cb1ea1b --- /dev/null +++ b/js/js.translator/testFiles/expression/misc/cases/KT-1865.kt @@ -0,0 +1,11 @@ +package foo + +open class A { + open fun foo(a : Int = 1) = a +} + +class B : A() { + override fun foo(a : Int) = a + 1 +} + +fun box() = (B().foo() == 2) \ No newline at end of file