KT-729 Need to support arrays as varargs: front-end checks done
#KT-729 In progress
This commit is contained in:
@@ -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,
|
||||
|
||||
+3
-3
@@ -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
|
||||
|
||||
+11
-9
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -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();
|
||||
|
||||
}
|
||||
|
||||
+9
-7
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+13
-7
@@ -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
|
||||
}
|
||||
|
||||
@@ -152,7 +152,6 @@ longTemplate
|
||||
: "${" expression "}"
|
||||
;
|
||||
|
||||
|
||||
isRHS
|
||||
: pattern
|
||||
;
|
||||
@@ -232,7 +231,7 @@ typeArguments
|
||||
;
|
||||
|
||||
valueArguments
|
||||
: "(" (SimpleName "=")? expression{","} ")"
|
||||
: "(" (SimpleName "=")? "*"? expression{","} ")"
|
||||
;
|
||||
|
||||
jump
|
||||
|
||||
+8
-7
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user