KT-729 Need to support arrays as varargs: front-end checks done

#KT-729 In progress
This commit is contained in:
Andrey Breslav
2012-03-23 22:45:19 +01:00
parent 7708b2d009
commit cf108765ae
18 changed files with 215 additions and 76 deletions
@@ -79,9 +79,9 @@ public abstract class AnnotationCodegen {
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : resolvedCall.getValueArguments().entrySet()) {
ResolvedValueArgument valueArgument = entry.getValue();
if (!(valueArgument instanceof DefaultValueArgument)) {
List<JetExpression> valueArguments = valueArgument.getArgumentExpressions();
List<ValueArgument> valueArguments = valueArgument.getArguments();
assert valueArguments.size() == 1 : "Number of assertions on " + resolvedCall.getResultingDescriptor() + " = " + valueArguments.size(); // todo
CompileTimeConstant<?> compileTimeConstant = bindingContext.get(BindingContext.COMPILE_TIME_VALUE, valueArguments.get(0));
CompileTimeConstant<?> compileTimeConstant = bindingContext.get(BindingContext.COMPILE_TIME_VALUE, valueArguments.get(0).getArgumentExpression());
assert compileTimeConstant != null;
Object value = compileTimeConstant.getValue();
@@ -1495,7 +1495,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
ResolvedValueArgument resolvedValueArgument = valueArguments.get(valueParameterDescriptor.getIndex());
if(resolvedValueArgument instanceof ExpressionValueArgument) {
ExpressionValueArgument valueArgument = (ExpressionValueArgument) resolvedValueArgument;
gen(valueArgument.getExpression(), valueParameterTypes.get(index));
gen(valueArgument.getValueArgument().getArgumentExpression(), valueParameterTypes.get(index));
}
else if(resolvedValueArgument instanceof DefaultValueArgument) {
Type type = valueParameterTypes.get(index);
@@ -1522,14 +1522,14 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
Type type = asmType(outType);
assert type.getSort() == Type.ARRAY;
Type elementType = correctElementType(type);
int size = valueArgument.getArgumentExpressions().size();
int size = valueArgument.getArguments().size();
v.iconst(valueArgument.getArgumentExpressions().size());
v.iconst(valueArgument.getArguments().size());
v.newarray(elementType);
for(int i = 0; i != size; ++i) {
v.dup();
v.iconst(i);
gen(valueArgument.getArgumentExpressions().get(i), elementType);
gen(valueArgument.getArguments().get(i).getArgumentExpression(), elementType);
StackValue.arrayElement(elementType, false).store(v);
}
}
@@ -19,6 +19,7 @@ package org.jetbrains.jet.lang.diagnostics;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNameIdentifierOwner;
import com.intellij.psi.impl.source.tree.LeafPsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
@@ -113,6 +114,7 @@ public interface Errors {
DiagnosticFactory<JetReferenceExpression> ARGUMENT_PASSED_TWICE = DiagnosticFactory.create(ERROR, "An argument is already passed for this parameter");
UnresolvedReferenceDiagnosticFactory NAMED_PARAMETER_NOT_FOUND = UnresolvedReferenceDiagnosticFactory.create("Cannot find a parameter with this name");
DiagnosticFactory<JetExpression> VARARG_OUTSIDE_PARENTHESES = DiagnosticFactory.create(ERROR, "Passing value as a vararg is only allowed inside a parenthesized argument list");
DiagnosticFactory<LeafPsiElement> NON_VARARG_SPREAD = DiagnosticFactory.create(ERROR, "The spread operator (*foo) may only be applied in a vararg position");
DiagnosticFactory<JetExpression> MANY_FUNCTION_LITERAL_ARGUMENTS = DiagnosticFactory.create(ERROR, "Only one function literal is allowed outside a parenthesized argument list");
DiagnosticFactory<PsiElement> PROPERTY_WITH_NO_TYPE_NO_INITIALIZER = DiagnosticFactory.create(ERROR, "This property must either have a type annotation or be initialized");
@@ -1812,7 +1812,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
/*
* valueArguments
* : "(" (SimpleName "=")? ("out" | "ref")? element{","} ")"
* : "(" (SimpleName "=")? "*"? element{","} ")"
* ;
*/
public void parseValueArgumentList() {
@@ -1841,7 +1841,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
}
/*
* (SimpleName "=")? element
* (SimpleName "=")? "*"? element
*/
private void parseValueArgument() {
PsiBuilder.Marker argument = mark();
@@ -1853,6 +1853,9 @@ public class JetExpressionParsing extends AbstractJetParsing {
argName.done(VALUE_ARGUMENT_NAME);
advance(); // EQ
}
if (at(MUL)) {
advance(); // MUL
}
parseExpression();
argument.done(VALUE_ARGUMENT);
}
@@ -18,9 +18,11 @@ package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.impl.source.tree.LeafPsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetNodeTypes;
import org.jetbrains.jet.lexer.JetTokens;
/**
* @author max
@@ -61,4 +63,10 @@ public class JetValueArgument extends JetElement implements ValueArgument {
public PsiElement asElement() {
return this;
}
@Override
public LeafPsiElement getSpreadElement() {
ASTNode node = getNode().findChildByType(JetTokens.MUL);
return node == null ? null : (LeafPsiElement) node.getPsi();
}
}
@@ -17,6 +17,7 @@
package org.jetbrains.jet.lang.psi;
import com.intellij.psi.PsiElement;
import com.intellij.psi.impl.source.tree.LeafPsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -36,4 +37,7 @@ public interface ValueArgument {
@NotNull
PsiElement asElement();
/* The '*' in something like foo(*arr) i.e. pass an array as a number of vararg arguments */
@Nullable
LeafPsiElement getSpreadElement();
}
@@ -107,10 +107,10 @@ public class AnnotationResolver {
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> descriptorToArgument :
results.getResultingCall().getValueArguments().entrySet()) {
// TODO: are varargs supported here?
List<JetExpression> argumentExpressions = descriptorToArgument.getValue().getArgumentExpressions();
List<ValueArgument> valueArguments = descriptorToArgument.getValue().getArguments();
ValueParameterDescriptor parameterDescriptor = descriptorToArgument.getKey();
for (JetExpression argument : argumentExpressions) {
arguments.add(resolveAnnotationArgument(argument, parameterDescriptor.getType(), trace));
for (ValueArgument argument : valueArguments) {
arguments.add(resolveAnnotationArgument(argument.getArgumentExpression(), parameterDescriptor.getType(), trace));
}
}
descriptor.setValueArguments(arguments);
@@ -19,6 +19,7 @@ package org.jetbrains.jet.lang.resolve.calls;
import com.google.common.collect.Lists;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.impl.source.tree.LeafPsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.*;
@@ -37,9 +38,6 @@ public class CallMaker {
private final JetExpression expression;
private final PsiElement reportErrorsOn;
private ExpressionValueArgument(@NotNull JetExpression expression) {
this(expression, expression);
}
private ExpressionValueArgument(@Nullable JetExpression expression, @NotNull PsiElement reportErrorsOn) {
this.expression = expression;
@@ -67,6 +65,10 @@ public class CallMaker {
return reportErrorsOn;
}
@Override
public LeafPsiElement getSpreadElement() {
return null;
}
}
private static class CallImpl implements Call {
@@ -467,19 +467,20 @@ public class CallResolver {
// Value parameters
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : candidateCall.getValueArguments().entrySet()) {
ResolvedValueArgument valueArgument = entry.getValue();
ResolvedValueArgument resolvedValueArgument = entry.getValue();
ValueParameterDescriptor valueParameterDescriptor = candidateWithFreshVariables.getValueParameters().get(entry.getKey().getIndex());
JetType effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor);
for (JetExpression expression : valueArgument.getArgumentExpressions()) {
for (ValueArgument valueArgument : resolvedValueArgument.getArguments()) {
// TODO : more attempts, with different expected types
JetType effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument);
// Here we type check expecting an error type (that is a subtype of any type and a supertype of any type
// and throw the results away
// We'll type check the arguments later, with the inferred types expected
TemporaryBindingTrace traceForUnknown = TemporaryBindingTrace.create(context.trace);
JetType type = expressionTypingServices.getType(context.scope, expression, substituteDontCare.substitute(valueParameterDescriptor.getType(), Variance.INVARIANT), traceForUnknown);
JetType type = expressionTypingServices.getType(context.scope, valueArgument.getArgumentExpression(), substituteDontCare.substitute(valueParameterDescriptor.getType(), Variance.INVARIANT), traceForUnknown);
if (type != null && !ErrorUtils.isErrorType(type)) {
constraintSystem.addSubtypingConstraint(VALUE_ARGUMENT.assertSubtyping(type, effectiveExpectedType));
}
@@ -525,14 +526,6 @@ public class CallResolver {
}
}
private static JetType getEffectiveExpectedType(ValueParameterDescriptor valueParameterDescriptor) {
JetType effectiveExpectedType = valueParameterDescriptor.getVarargElementType();
if (effectiveExpectedType == null) {
effectiveExpectedType = valueParameterDescriptor.getType();
}
return effectiveExpectedType;
}
private static void recordAutoCastIfNecessary(ReceiverDescriptor receiver, BindingTrace trace) {
if (receiver instanceof AutoCastReceiver) {
AutoCastReceiver autoCastReceiver = (AutoCastReceiver) receiver;
@@ -635,19 +628,19 @@ public class CallResolver {
ValueParameterDescriptor parameterDescriptor = entry.getKey();
ResolvedValueArgument resolvedArgument = entry.getValue();
JetType parameterType = getEffectiveExpectedType(parameterDescriptor);
List<JetExpression> argumentExpressions = resolvedArgument.getArgumentExpressions();
for (JetExpression argumentExpression : argumentExpressions) {
if (argumentExpression == null) {
throw new IllegalStateException("A null instead of an expression in the arguments for " + entry.getKey());
}
JetType type = expressionTypingServices.getType(context.scope, argumentExpression, parameterType, context.dataFlowInfo, context.candidateCall.getTrace());
for (ValueArgument argument : resolvedArgument.getArguments()) {
JetExpression expression = argument.getArgumentExpression();
if (expression == null) continue;
JetType expectedType = getEffectiveExpectedType(parameterDescriptor, argument);
JetType type = expressionTypingServices.getType(context.scope, expression, expectedType, context.dataFlowInfo, context.candidateCall.getTrace());
if (type == null || ErrorUtils.isErrorType(type)) {
context.candidateCall.argumentHasNoType();
}
else if (!typeChecker.isSubtypeOf(type, parameterType)) {
// VariableDescriptor variableDescriptor = AutoCastUtils.getVariableDescriptorFromSimpleName(temporaryTrace.getBindingContext(), argumentExpression);
else if (!typeChecker.isSubtypeOf(type, expectedType)) {
// VariableDescriptor variableDescriptor = AutoCastUtils.getVariableDescriptorFromSimpleName(temporaryTrace.getBindingContext(), argument);
// if (variableDescriptor != null) {
// JetType autoCastType = null;
// for (JetType possibleType : dataFlowInfo.getPossibleTypesForVariable(variableDescriptor)) {
@@ -658,10 +651,10 @@ public class CallResolver {
// }
// if (autoCastType != null) {
// if (AutoCastUtils.isStableVariable(variableDescriptor)) {
// temporaryTrace.record(AUTOCAST, argumentExpression, autoCastType);
// temporaryTrace.record(AUTOCAST, argument, autoCastType);
// }
// else {
// temporaryTrace.report(AUTOCAST_IMPOSSIBLE.on(argumentExpression, autoCastType, variableDescriptor));
// temporaryTrace.report(AUTOCAST_IMPOSSIBLE.on(argument, autoCastType, variableDescriptor));
// result = false;
// }
// }
@@ -674,6 +667,31 @@ public class CallResolver {
return result;
}
@NotNull
private JetType getEffectiveExpectedType(ValueParameterDescriptor parameterDescriptor, ValueArgument argument) {
if (argument.getSpreadElement() != null) {
if (parameterDescriptor.getVarargElementType() == null) {
// Spread argument passed to a non-vararg parameter, an error is already reported by ValueArgumentsToParametersMapper
return ErrorUtils.createErrorType("Don't care");
}
else {
return parameterDescriptor.getType();
}
}
else {
if (argument.isNamed()) {
return parameterDescriptor.getType();
}
else {
JetType varargElementType = parameterDescriptor.getVarargElementType();
if (varargElementType == null) {
return parameterDescriptor.getType();
}
return varargElementType;
}
}
}
@NotNull
private <D extends CallableDescriptor> OverloadResolutionResultsImpl<D> computeResultAndReportErrors(
BindingTrace trace,
@@ -17,7 +17,7 @@
package org.jetbrains.jet.lang.resolve.calls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.ValueArgument;
import java.util.Collections;
import java.util.List;
@@ -32,8 +32,8 @@ public class DefaultValueArgument implements ResolvedValueArgument {
@NotNull
@Override
public List<JetExpression> getArgumentExpressions() {
return Collections.emptyList(); //throw new UnsupportedOperationException("Look into the default value of the parameter");
public List<ValueArgument> getArguments() {
return Collections.emptyList();
}
@Override
@@ -19,6 +19,7 @@ package org.jetbrains.jet.lang.resolve.calls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.ValueArgument;
import java.util.Collections;
import java.util.List;
@@ -27,27 +28,28 @@ import java.util.List;
* @author abreslav
*/
public class ExpressionValueArgument implements ResolvedValueArgument {
private final JetExpression expression;
private final ValueArgument valueArgument;
public ExpressionValueArgument(@Nullable JetExpression expression) {
this.expression = expression;
public ExpressionValueArgument(@Nullable ValueArgument valueArgument) {
this.valueArgument = valueArgument;
}
// Nullable when something like f(a, , b) was in the source code
@Nullable
public JetExpression getExpression() {
return expression;
public ValueArgument getValueArgument() {
return valueArgument;
}
@NotNull
@Override
public List<JetExpression> getArgumentExpressions() {
if (expression == null) return Collections.emptyList();
return Collections.singletonList(expression);
public List<ValueArgument> getArguments() {
if (valueArgument == null) return Collections.emptyList();
return Collections.singletonList(valueArgument);
}
@Override
public String toString() {
return expression.getText();
JetExpression expression = valueArgument.getArgumentExpression();
return expression == null ? "no expression" : expression.getText();
}
}
@@ -120,12 +120,12 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements ResolvedC
}
public void recordTypeArgument(@NotNull TypeParameterDescriptor typeParameter, @NotNull JetType typeArgument) {
assert !typeArguments.containsKey(typeParameter);
assert !typeArguments.containsKey(typeParameter) : typeParameter + " -> " + typeArgument;
typeArguments.put(typeParameter, typeArgument);
}
public void recordValueArgument(@NotNull ValueParameterDescriptor valueParameter, @NotNull ResolvedValueArgument valueArgument) {
assert !valueArguments.containsKey(valueParameter);
assert !valueArguments.containsKey(valueParameter) : valueParameter + " -> " + valueArgument;
valueArguments.put(valueParameter, valueArgument);
}
@@ -17,7 +17,7 @@
package org.jetbrains.jet.lang.resolve.calls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.ValueArgument;
import java.util.List;
@@ -26,6 +26,6 @@ import java.util.List;
*/
public interface ResolvedValueArgument {
@NotNull
List<JetExpression> getArgumentExpressions();
List<ValueArgument> getArguments();
}
@@ -18,6 +18,7 @@ package org.jetbrains.jet.lang.resolve.calls;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.intellij.psi.impl.source.tree.LeafPsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
@@ -67,8 +68,8 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
ValueArgument valueArgument = valueArguments.get(i);
if (valueArgument.isNamed()) {
someNamed = true;
JetReferenceExpression nameReference = valueArgument.getArgumentName().getReferenceExpression();
ValueParameterDescriptor valueParameterDescriptor = parameterByName.get(valueArgument.getArgumentName().getReferenceExpression().getReferencedName());
JetSimpleNameExpression nameReference = valueArgument.getArgumentName().getReferenceExpression();
ValueParameterDescriptor valueParameterDescriptor = parameterByName.get(nameReference.getReferencedName());
if (valueParameterDescriptor == null) {
temporaryTrace.report(NAMED_PARAMETER_NOT_FOUND.on(nameReference));
error = true;
@@ -200,13 +201,14 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
varargs.put(valueParameterDescriptor, vararg);
candidateCall.recordValueArgument(valueParameterDescriptor, vararg);
}
JetExpression expression = valueArgument.getArgumentExpression();
if (expression != null) {
vararg.getArgumentExpressions().add(expression);
}
vararg.addArgument(valueArgument);
}
else {
ResolvedValueArgument argument = new ExpressionValueArgument(valueArgument.getArgumentExpression());
LeafPsiElement spread = valueArgument.getSpreadElement();
if (spread != null) {
candidateCall.getTrace().report(NON_VARARG_SPREAD.on(spread));
}
ResolvedValueArgument argument = new ExpressionValueArgument(valueArgument);
candidateCall.recordValueArgument(valueParameterDescriptor, argument);
}
}
@@ -19,6 +19,7 @@ package org.jetbrains.jet.lang.resolve.calls;
import com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.ValueArgument;
import java.util.Iterator;
import java.util.List;
@@ -27,20 +28,25 @@ import java.util.List;
* @author abreslav
*/
public class VarargValueArgument implements ResolvedValueArgument {
private final List<JetExpression> values = Lists.newArrayList();
private final List<ValueArgument> arguments = Lists.newArrayList();
public void addArgument(@NotNull ValueArgument argument) {
arguments.add(argument);
}
@NotNull
@Override
public List<JetExpression> getArgumentExpressions() {
return values;
@NotNull
public List<ValueArgument> getArguments() {
return arguments;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder("vararg:{");
for (Iterator<JetExpression> iterator = values.iterator(); iterator.hasNext(); ) {
JetExpression expression = iterator.next();
builder.append(expression.getText());
for (Iterator<ValueArgument> iterator = arguments.iterator(); iterator.hasNext(); ) {
ValueArgument valueArgument = iterator.next();
JetExpression expression = valueArgument.getArgumentExpression();
builder.append(expression == null ? "no expression" : expression.getText());
if (iterator.hasNext()) {
builder.append(", ");
}
@@ -0,0 +1,92 @@
fun <T> array1(vararg a : T) = a
fun main(args : Array<String>) {
val a = array1("a", "b")
val b = array1(1, 1)
join(1)
join(1, "2")
join(1, "2", "3")
join(<!NON_VARARG_SPREAD!>*<!>1, "2")
join(1, *<!TYPE_MISMATCH!>"2"<!>)
join(x = 1, a = <!TYPE_MISMATCH!>"2"<!>)
join(x = <!NON_VARARG_SPREAD!>*<!>1, a = *<!TYPE_MISMATCH!>"2"<!>)
join(x = 1, a = *a)
join(x = 1, a = *<!TYPE_MISMATCH!>b<!>)
join(1, *a)
join(1, *<!TYPE_MISMATCH!>b<!>)
join(1, *a, "3")
join(1, *<!TYPE_MISMATCH!>b<!>, "3")
join(1, "4", *a, "3")
join(1, "4", *<!TYPE_MISMATCH!>b<!>, "3")
join(1, "4", *a)
join(1, "4", *a, *a, "3")
join(1, "4", *a, *<!TYPE_MISMATCH!>b<!>, "3")
join(a = *a, x = 1)
join(a = *<!TYPE_MISMATCH!>b<!>, x = 1)
joinG<String>(1, "2")
joinG<String>(<!NON_VARARG_SPREAD!>*<!>1, "2")
joinG<String>(1, *<!TYPE_MISMATCH!>"2"<!>)
joinG<String>(x = 1, a = *a)
joinG<String>(x = 1, a = <!TYPE_MISMATCH!>"2"<!>)
joinG<String>(x = <!NON_VARARG_SPREAD!>*<!>1, a = *<!TYPE_MISMATCH!>"2"<!>)
joinG<String>(1, *a)
joinG<String>(1, *a, "3")
joinG<String>(1, "4", *a, "3")
joinG<String>(1, "4", *a)
joinG<String>(1, "4", *a, *a, "3")
joinG<String>(a = *a, x = 1)
joinG(1, "2")
joinG(<!NON_VARARG_SPREAD!>*<!>1, "2")
<!TYPE_INFERENCE_FAILED!>joinG(1, *<!TYPE_MISMATCH!>"2"<!>)<!>
joinG(x = 1, a = *a)
<!TYPE_INFERENCE_FAILED!>joinG(x = 1, a = <!TYPE_MISMATCH!>"2"<!>)<!>
<!TYPE_INFERENCE_FAILED!>joinG(x = <!NON_VARARG_SPREAD!>*<!>1, a = *<!TYPE_MISMATCH!>"2"<!>)<!>
joinG(1, *a)
joinG(1, *a, "3")
joinG(1, "4", *a, "3")
joinG(1, "4", *a)
joinG(1, "4", *a, *a, "3")
joinG(a = *a, x = 1)
val x1 = joinT(1, "2")
x1 : String?
val x2 = joinT(<!NON_VARARG_SPREAD!>*<!>1, "2")
x2 : String?
val x6 = joinT(1, *a)
x6 : String?
val x7 = joinT(1, *a, "3")
x7 : String?
val x8 = joinT(1, "4", *a, "3")
x8 : String?
val x9 = joinT(1, "4", *a)
x9 : String?
val x10 = joinT(1, "4", *a, *a, "3")
x10 : String?
val x11 = joinT(a = *a, x = 1)
x11 : String?
val x12 = joinT(x = 1, a = *a)
x12 : String?
}
fun join(x : Int, vararg a : String) : String {
val b = StringBuilder(x.toString())
for (s in a) {
b.append(s)
}
return b.toString()!!
}
fun <T> joinG(x : Int, vararg a : T) : String {
val b = StringBuilder(x.toString())
for (s in a) {
b.append(s)
}
return b.toString()!!
}
fun <T> joinT(<!UNUSED_PARAMETER!>x<!> : Int, vararg <!UNUSED_PARAMETER!>a<!> : T) : T? {
return null
}
+1 -2
View File
@@ -152,7 +152,6 @@ longTemplate
: "${" expression "}"
;
isRHS
: pattern
;
@@ -232,7 +231,7 @@ typeArguments
;
valueArguments
: "(" (SimpleName "=")? expression{","} ")"
: "(" (SimpleName "=")? "*"? expression{","} ")"
;
jump
@@ -27,6 +27,7 @@ import org.jetbrains.jet.lang.descriptors.VariableAsFunctionDescriptor;
import org.jetbrains.jet.lang.psi.JetCallExpression;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
import org.jetbrains.jet.lang.psi.ValueArgument;
import org.jetbrains.jet.lang.resolve.calls.*;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.AbstractTranslator;
@@ -121,24 +122,24 @@ public final class CallExpressionTranslator extends AbstractTranslator {
@NotNull
private List<JsExpression> translateSingleArgument(@NotNull ResolvedValueArgument actualArgument,
@NotNull ValueParameterDescriptor parameterDescriptor) {
List<JetExpression> argumentExpressions = actualArgument.getArgumentExpressions();
List<ValueArgument> valueArguments = actualArgument.getArguments();
if (actualArgument instanceof VarargValueArgument) {
return translateVarargArgument(argumentExpressions);
return translateVarargArgument(valueArguments);
}
if (actualArgument instanceof DefaultValueArgument) {
JetExpression defaultArgument = getDefaultArgument(bindingContext(), parameterDescriptor);
return Arrays.asList(Translation.translateAsExpression(defaultArgument, context()));
}
assert actualArgument instanceof ExpressionValueArgument;
assert argumentExpressions.size() == 1;
return Arrays.asList(Translation.translateAsExpression(argumentExpressions.get(0), context()));
assert valueArguments.size() == 1;
return Arrays.asList(Translation.translateAsExpression(valueArguments.get(0).getArgumentExpression(), context()));
}
@NotNull
private List<JsExpression> translateVarargArgument(@NotNull List<JetExpression> arguments) {
private List<JsExpression> translateVarargArgument(@NotNull List<ValueArgument> arguments) {
List<JsExpression> translatedArgs = Lists.newArrayList();
for (JetExpression argument : arguments) {
translatedArgs.add(Translation.translateAsExpression(argument, context()));
for (ValueArgument argument : arguments) {
translatedArgs.add(Translation.translateAsExpression(argument.getArgumentExpression(), context()));
}
if (isNativeFunctionCall) {
return translatedArgs;