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 {
+
 }