*******************************************************************************/
package org.eclipse.jdt.internal.compiler.ast;
-import org.eclipse.jdt.internal.compiler.impl.*;
import org.eclipse.jdt.internal.compiler.codegen.*;
import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.lookup.*;
public abstract class Statement extends ASTNode {
}
return false;
}
-
+
+ /**
+ * Generate invocation arguments, considering varargs methods
+ */
+ public void generateArguments(MethodBinding binding, Expression[] arguments, BlockScope currentScope, CodeStream codeStream) {
+
+ if (binding.isVarargs()) {
+ // 5 possibilities exist for a call to the vararg method foo(int i, int ... value) :
+ // foo(1), foo(1, null), foo(1, 2), foo(1, 2, 3, 4) & foo(1, new int[] {1, 2})
+ TypeBinding[] params = binding.parameters;
+ int paramLength = params.length;
+ int varArgIndex = paramLength - 1;
+ for (int i = 0; i < varArgIndex; i++) {
+ arguments[i].generateCode(currentScope, codeStream, true);
+ }
+
+ ArrayBinding varArgsType = (ArrayBinding) params[varArgIndex]; // parameterType has to be an array type
+ int argLength = arguments == null ? 0 : arguments.length;
+
+ generateVarargsArgument: {
+ if (argLength >= paramLength) {
+ // right number of arguments - could be inexact - pass argument as is
+ TypeBinding lastType = arguments[varArgIndex].resolvedType;
+ if (lastType == NullBinding || varArgsType.dimensions() == lastType.dimensions()) {
+ // foo(1, new int[]{2, 3}) or foo(1, null) --> last arg is passed as-is
+ arguments[varArgIndex].generateCode(currentScope, codeStream, true);
+ break generateVarargsArgument;
+ }
+ // right number but not directly compatible or too many arguments - wrap extra into array
+ // called with (argLength - lastIndex) elements : foo(1, 2) or foo(1, 2, 3, 4)
+ // need to gen elements into an array, then gen each remaining element into created array
+ codeStream.generateInlinedValue(argLength - varArgIndex);
+ codeStream.newArray(varArgsType); // create a mono-dimensional array
+ int elementsTypeID = varArgsType.elementsType().id;
+ for (int i = varArgIndex; i < argLength; i++) {
+ codeStream.dup();
+ codeStream.generateInlinedValue(i - varArgIndex);
+ arguments[i].generateCode(currentScope, codeStream, true);
+ codeStream.arrayAtPut(elementsTypeID, false);
+ }
+ } else { // not enough arguments - pass extra empty array
+ // scenario: foo(1) --> foo(1, new int[0])
+ // generate code for an empty array of parameterType
+ codeStream.generateInlinedValue(0);
+ codeStream.newArray(varArgsType); // create a mono-dimensional array
+ }
+ }
+ } else if (arguments != null) { // standard generation for method arguments
+ for (int i = 0, max = arguments.length; i < max; i++)
+ arguments[i].generateCode(currentScope, codeStream, true);
+ }
+ }
+
public abstract void generateCode(BlockScope currentScope, CodeStream codeStream);
public boolean isEmptyBlock() {
public abstract void resolve(BlockScope scope);
+ /**
+ * Returns case constant associated to this statement (NotAConstant if none)
+ */
public Constant resolveCase(BlockScope scope, TypeBinding testType, SwitchStatement switchStatement) {
// statement within a switch that are not case are treated as normal statement....
resolve(scope);
- return null;
+ return NotAConstant;
}
}