Added support for varargs
diff --git a/plugins/org.eclipse.epsilon.eol.engine/src/org/eclipse/epsilon/eol/dom/FeatureCallExpression.java b/plugins/org.eclipse.epsilon.eol.engine/src/org/eclipse/epsilon/eol/dom/FeatureCallExpression.java
index cfbca99..0d51d45 100644
--- a/plugins/org.eclipse.epsilon.eol.engine/src/org/eclipse/epsilon/eol/dom/FeatureCallExpression.java
+++ b/plugins/org.eclipse.epsilon.eol.engine/src/org/eclipse/epsilon/eol/dom/FeatureCallExpression.java
@@ -80,12 +80,13 @@
}
/**
+ * Looks for the operation in the EolContext EolOperationFactory.
*
- * @param target
- * @param name The requested operation name
- * @param owningModel
+ * @param target The object this feature is called on.
+ * @param name The requested operation name.
+ * @param owningModel The model (optional).
* @param context The context from which the EolOperationFactory is derived.
- * @return The operation
+ * @return The operation.
* @throws EolIllegalOperationException
* @since 1.6
*/
diff --git a/plugins/org.eclipse.epsilon.eol.engine/src/org/eclipse/epsilon/eol/dom/OperationCallExpression.java b/plugins/org.eclipse.epsilon.eol.engine/src/org/eclipse/epsilon/eol/dom/OperationCallExpression.java
index daa8660..6b8f43f 100644
--- a/plugins/org.eclipse.epsilon.eol.engine/src/org/eclipse/epsilon/eol/dom/OperationCallExpression.java
+++ b/plugins/org.eclipse.epsilon.eol.engine/src/org/eclipse/epsilon/eol/dom/OperationCallExpression.java
@@ -142,8 +142,8 @@
return wrap(objectMethod.execute(nameExpression, context, nameExpression));
}
+ // Evaluate the parameters
ArrayList<Object> parameterValues = new ArrayList<>(parameterExpressions.size());
-
for (Expression parameter : parameterExpressions) {
parameterValues.add(executorFactory.execute(parameter, context));
}
diff --git a/plugins/org.eclipse.epsilon.eol.engine/src/org/eclipse/epsilon/eol/execute/introspection/java/ObjectMethod.java b/plugins/org.eclipse.epsilon.eol.engine/src/org/eclipse/epsilon/eol/execute/introspection/java/ObjectMethod.java
index f3bb0e4..7ed2e84 100644
--- a/plugins/org.eclipse.epsilon.eol.engine/src/org/eclipse/epsilon/eol/execute/introspection/java/ObjectMethod.java
+++ b/plugins/org.eclipse.epsilon.eol.engine/src/org/eclipse/epsilon/eol/execute/introspection/java/ObjectMethod.java
@@ -9,13 +9,16 @@
******************************************************************************/
package org.eclipse.epsilon.eol.execute.introspection.java;
+import java.lang.reflect.Array;
import java.lang.reflect.Method;
+import java.util.Collection;
import java.util.stream.BaseStream;
import org.eclipse.epsilon.common.module.ModuleElement;
import org.eclipse.epsilon.eol.exceptions.EolRuntimeException;
import org.eclipse.epsilon.eol.execute.context.IEolContext;
import org.eclipse.epsilon.eol.execute.context.concurrent.EolContextParallel;
import org.eclipse.epsilon.eol.execute.context.concurrent.IEolContextParallel;
+import org.eclipse.epsilon.eol.execute.operations.contributors.IterableOperationContributor;
import org.eclipse.epsilon.eol.util.ReflectionUtil;
public class ObjectMethod extends DisposableObject {
@@ -64,6 +67,22 @@
}
public Object execute(Object[] parameters, ModuleElement ast) throws EolRuntimeException {
+ if (method.isVarArgs()) {
+ int varargIndex = method.getParameterCount() - 1;
+ Object[] adjustedParams = new Object[method.getParameterCount()];
+ Class<?> varargType = method.getParameterTypes()[varargIndex].getComponentType();
+ for (int i = 0; i < varargIndex; i++) {
+ adjustedParams[i] = parameters[i];
+ }
+ int numberOfVarargs = parameters.length - varargIndex;
+ if (numberOfVarargs < 0) numberOfVarargs = 0;
+ Object varargParams = Array.newInstance(varargType, numberOfVarargs);
+ for (int i = 0; i < numberOfVarargs; i++) {
+ Array.set(varargParams, i, parameters[varargIndex + i]);
+ }
+ adjustedParams[adjustedParams.length-1] = varargParams;
+ parameters = adjustedParams;
+ }
return ReflectionUtil.executeMethod(object, method, ast, parameters);
}
diff --git a/plugins/org.eclipse.epsilon.eol.engine/src/org/eclipse/epsilon/eol/util/ReflectionUtil.java b/plugins/org.eclipse.epsilon.eol.engine/src/org/eclipse/epsilon/eol/util/ReflectionUtil.java
index 2ddec4e..0a20f0c 100644
--- a/plugins/org.eclipse.epsilon.eol.engine/src/org/eclipse/epsilon/eol/util/ReflectionUtil.java
+++ b/plugins/org.eclipse.epsilon.eol.engine/src/org/eclipse/epsilon/eol/util/ReflectionUtil.java
@@ -197,12 +197,18 @@
for (int stage = 0; stage < 2; ++stage) {
for (Method method : methods) {
if (getMethodName(method).equalsIgnoreCase(methodName)) {
-
Class<?>[] parameterTypes = method.getParameterTypes();
- boolean parametersMatch = parameterTypes.length == parameters.length;
+ boolean isVarargs = method.isVarArgs(),
+ parametersMatch = parameterTypes.length == parameters.length || isVarargs;
+
if (parametersMatch) {
//TODO: See why parameter type checking does not work with EolSequence
- for (int j = 0; j < parameterTypes.length && parametersMatch; j++) {
+ int varargIndex = method.getParameterCount() - 1;
+ int endIndex = isVarargs ? varargIndex : parameterTypes.length;
+ if (parameters.length < endIndex) {
+ continue;
+ }
+ for (int j = 0; j < endIndex && parametersMatch; j++) {
Class<?> parameterType = parameterTypes[j];
Object parameter = parameters[j];
if (allowContravariantConversionForParameters) {
@@ -212,10 +218,17 @@
parametersMatch = parametersMatch && parameterType.equals(parameter.getClass());
}
}
- if (parametersMatch) {
- return method;
+ if (isVarargs) {
+ Class<?> varargType = parameterTypes[varargIndex].getComponentType();
+ for (int va = varargIndex; va < parameters.length && parametersMatch; va++) {
+ Object parameter = parameters[va];
+ parametersMatch = (stage == 0 ? varargType.isInstance(parameter) : isInstance(varargType, parameter));
+ }
}
}
+ if (parametersMatch) {
+ return method;
+ }
}
}
}
diff --git a/tests/org.eclipse.epsilon.eol.engine.test.acceptance/src/org/eclipse/epsilon/eol/engine/test/acceptance/EolAcceptanceTestSuite.java b/tests/org.eclipse.epsilon.eol.engine.test.acceptance/src/org/eclipse/epsilon/eol/engine/test/acceptance/EolAcceptanceTestSuite.java
index e8bb409..fdf11f3 100644
--- a/tests/org.eclipse.epsilon.eol.engine.test.acceptance/src/org/eclipse/epsilon/eol/engine/test/acceptance/EolAcceptanceTestSuite.java
+++ b/tests/org.eclipse.epsilon.eol.engine.test.acceptance/src/org/eclipse/epsilon/eol/engine/test/acceptance/EolAcceptanceTestSuite.java
@@ -51,7 +51,7 @@
ContextlessFirstOrderOperationTests.class,
DomTests.class,
VariableTests.class,
- OperationOrderTests.class,
+ OperationTests.class,
PostfixOperatorTests.class,
CompositeAssignmentTests.class,
SwitchTests.class,
diff --git a/tests/org.eclipse.epsilon.eol.engine.test.acceptance/src/org/eclipse/epsilon/eol/engine/test/acceptance/OperationOrderTests.eol b/tests/org.eclipse.epsilon.eol.engine.test.acceptance/src/org/eclipse/epsilon/eol/engine/test/acceptance/OperationOrderTests.eol
deleted file mode 100644
index eb917be..0000000
--- a/tests/org.eclipse.epsilon.eol.engine.test.acceptance/src/org/eclipse/epsilon/eol/engine/test/acceptance/OperationOrderTests.eol
+++ /dev/null
@@ -1,4 +0,0 @@
-@test
-operation testSplit() {
- "foo,bar".split(",").first().println();
-}
\ No newline at end of file
diff --git a/tests/org.eclipse.epsilon.eol.engine.test.acceptance/src/org/eclipse/epsilon/eol/engine/test/acceptance/OperationTests.eol b/tests/org.eclipse.epsilon.eol.engine.test.acceptance/src/org/eclipse/epsilon/eol/engine/test/acceptance/OperationTests.eol
new file mode 100644
index 0000000..e259a2a
--- /dev/null
+++ b/tests/org.eclipse.epsilon.eol.engine.test.acceptance/src/org/eclipse/epsilon/eol/engine/test/acceptance/OperationTests.eol
@@ -0,0 +1,33 @@
+@test
+operation testSplit() {
+ "foo,bar".split(",").first().println();
+}
+
+@test
+operation testVarargs() {
+ var Paths = Native("java.nio.file.Paths");
+ var p = Paths.get("rel", "path", "to", "resource");
+ assertFalse(p.toFile().exists());
+ p = Paths.get("folder");
+ assertFalse(p.toFile().isFile());
+ p = Paths.get("first", "second");
+ assertFalse(p.toFile().exists());
+}
+
+@test
+operation testVarargsAmbigious() {
+ var s = Native("java.lang.String").format("foo");
+ assertEquals(3, s.length());
+ s = Native("java.lang.String").format("bazoo", null);
+ assertEquals(5, s.length());
+}
+
+@test
+operation testVarargsMissingParameters() {
+ assertError(Native("java.nio.file.Paths").get());
+}
+
+@test
+operation testVarargsInvalidNullLastParameter() {
+ assertError(Native("java.nio.file.Files").copy("a", "b", null));
+}
diff --git a/tests/org.eclipse.epsilon.eol.engine.test.acceptance/src/org/eclipse/epsilon/eol/engine/test/acceptance/OperationOrderTests.java b/tests/org.eclipse.epsilon.eol.engine.test.acceptance/src/org/eclipse/epsilon/eol/engine/test/acceptance/OperationTests.java
similarity index 94%
rename from tests/org.eclipse.epsilon.eol.engine.test.acceptance/src/org/eclipse/epsilon/eol/engine/test/acceptance/OperationOrderTests.java
rename to tests/org.eclipse.epsilon.eol.engine.test.acceptance/src/org/eclipse/epsilon/eol/engine/test/acceptance/OperationTests.java
index 299ec19..a0d7ac4 100644
--- a/tests/org.eclipse.epsilon.eol.engine.test.acceptance/src/org/eclipse/epsilon/eol/engine/test/acceptance/OperationOrderTests.java
+++ b/tests/org.eclipse.epsilon.eol.engine.test.acceptance/src/org/eclipse/epsilon/eol/engine/test/acceptance/OperationTests.java
@@ -1,19 +1,19 @@
-/*******************************************************************************
- * Copyright (c) 2008 The University of York.
- * This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License 2.0
- * which is available at https://www.eclipse.org/legal/epl-2.0/
- *
- * Contributors:
- * Dimitrios Kolovos - initial API and implementation
-******************************************************************************/
-
-package org.eclipse.epsilon.eol.engine.test.acceptance;
-
-import org.eclipse.epsilon.eol.engine.test.acceptance.eunit.EUnitRunner;
-import org.junit.runner.RunWith;
-
-@RunWith(EUnitRunner.class)
-public class OperationOrderTests {
-
+/*******************************************************************************
+ * Copyright (c) 2008 The University of York.
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ * Dimitrios Kolovos - initial API and implementation
+******************************************************************************/
+
+package org.eclipse.epsilon.eol.engine.test.acceptance;
+
+import org.eclipse.epsilon.eol.engine.test.acceptance.eunit.EUnitRunner;
+import org.junit.runner.RunWith;
+
+@RunWith(EUnitRunner.class)
+public class OperationTests {
+
}