Improve EOperation handling
* Use the static signature of the EOperation to locate the
implementation method, so that it can be invoked on any
type-compatible list of arguments.
Previously the lookup was done on the exact types of the runtime
arguments, so an EOperation op(T) could not be invoked on an argument
whose type was a strict sub-type of T.
* Handle multi-valued EParameters, which in Java will be generated as
EList parameters.
* Avoid a reflective lookup on each invocation. We now rely only on the
static signature of the EOperation, so the lookup can be done only
once on initialization.
Change-Id: I133844bc233f7de547b0a98a847112f480627ac0
Signed-off-by: Pierre-Charles David <pierre-charles.david@obeo.fr>
diff --git a/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/parser/Query.g4 b/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/parser/Query.g4
index 9eb1d3c..77eb649 100644
--- a/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/parser/Query.g4
+++ b/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/parser/Query.g4
@@ -81,7 +81,7 @@
|'true' #TrueLit
|'false' #FalseLit
|'null' #NullLit
- |'Sequence{' expressionSequence'}' #ExplicitSeqLit
+ |'Sequence{' expressionSequence '}' #ExplicitSeqLit
|'OrderedSet{' expressionSequence '}' #ExplicitSetLit
| Ident '::' Ident '::' Ident #EnumLit
| Ident '::' Ident ':' #ErrorEnumLit
diff --git a/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/runtime/impl/EOperationService.java b/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/runtime/impl/EOperationService.java
index 7b8c377..a5c1a3a 100644
--- a/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/runtime/impl/EOperationService.java
+++ b/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/runtime/impl/EOperationService.java
@@ -13,6 +13,7 @@
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
@@ -66,6 +67,11 @@
private final EOperation eOperation;
/**
+ * The Java method which actually implements the EOperation.
+ */
+ private final Method method;
+
+ /**
* Creates a new service instance given a method and an instance.
*
* @param eOperation
@@ -73,6 +79,43 @@
*/
public EOperationService(EOperation eOperation) {
this.eOperation = eOperation;
+ this.method = lookupMethod(this.eOperation);
+ }
+
+ /**
+ * Finds the Java {@link Method} which implements a given {@link EOperation}.
+ *
+ * @param operation
+ * the {@link EOperation} to look for.
+ * @return the Java method which implements the {@link EOperation}, or <code>null</code> if none could be
+ * found.
+ */
+ private Method lookupMethod(EOperation operation) {
+ Method result;
+
+ final Class<?> containerClass = operation.getEContainingClass().getInstanceClass();
+ if (containerClass != null) {
+ final Class<?>[] argumentClasses = new Class<?>[operation.getEParameters().size()];
+ for (int i = 0; i < argumentClasses.length; i++) {
+ EParameter param = operation.getEParameters().get(i);
+ if (param.isMany()) {
+ argumentClasses[i] = EList.class;
+ } else {
+ argumentClasses[i] = param.getEType().getInstanceClass();
+ }
+ }
+ try {
+ result = containerClass.getMethod(operation.getName(), argumentClasses);
+ } catch (SecurityException e) {
+ result = null;
+ } catch (NoSuchMethodException e) {
+ result = null;
+ }
+ } else {
+ result = null;
+ }
+
+ return result;
}
/**
@@ -125,54 +168,39 @@
@Override
protected Object internalInvoke(Object[] arguments) throws Exception {
final Object result;
- final Object[] localArguments = Arrays.copyOfRange(arguments, 1, arguments.length);
- final Object receiver = arguments[0];
-
- if (!eOperation.getEContainingClass().isSuperTypeOf(((EObject)receiver).eClass())) {
- // This will be the case for EObject contained eOperations : eContents, eContainer,
- // eCrossReferences... are available to be called, but "EObject" is not a modeled super-type
- // of the receiver; this "eInvoke" will fail. Fall back to plain reflection.
- result = eOperationJavaInvoke(eOperation.getName(), receiver, localArguments);
- } else if (hasEInvoke(receiver)) {
- final EList<Object> eArguments = new BasicEList<Object>(arguments.length);
- for (int i = 1; i < arguments.length; ++i) {
- eArguments.add(arguments[i]);
- }
- result = ((EObject)receiver).eInvoke(eOperation, eArguments);
- } else {
- result = eOperationJavaInvoke(eOperation.getName(), receiver, localArguments);
- }
-
- return result;
- }
-
- /**
- * Call the {@link EOperation} thru a Java invoke.
- *
- * @param operationName
- * the {@link EOperation#getName() name}
- * @param receiver
- * the receiver
- * @param arguments
- * arguments
- * @return the {@link EOperation} result if any, {@link Nothing} otherwise
- * @throws Exception
- * if the invoked {@link EOperation} fail
- */
- private Object eOperationJavaInvoke(String operationName, final Object receiver, final Object[] arguments)
- throws Exception {
- final Object result;
-
- final Class<?>[] argumentClasses = new Class<?>[arguments.length];
- for (int i = 0; i < arguments.length; i++) {
- if (arguments[i] != null) {
- argumentClasses[i] = arguments[i].getClass();
+ final EObject receiver = (EObject)arguments[0];
+ final Object[] localArguments = new Object[arguments.length];
+ for (int i = 1; i < arguments.length; ++i) {
+ if (eOperation.getEParameters().get(i - 1).isMany()) {
+ localArguments[i] = new BasicEList<Object>((Collection<?>)arguments[i]);
} else {
- argumentClasses[i] = null;
+ localArguments[i] = arguments[i];
}
}
- final Method method = receiver.getClass().getMethod(operationName, argumentClasses);
- result = method.invoke(receiver, arguments);
+
+ if (!eOperation.getEContainingClass().isSuperTypeOf(receiver.eClass())) {
+ if (method != null) {
+ final Object[] parameters = Arrays.copyOfRange(localArguments, 1, localArguments.length);
+ result = eOperationJavaInvoke(method, receiver, parameters);
+ } else {
+ throw new IllegalStateException(String.format(
+ "EOperation %s not in %s type hierarchy of %s and no %s method in %s", getName(),
+ getEOperation().getEContainingClass().getName(), receiver.eClass().getName(),
+ getName(), receiver.getClass().getName()));
+ }
+ } else if (hasEInvoke(receiver)) {
+ final EList<Object> eArguments = new BasicEList<Object>(localArguments.length);
+ for (int i = 1; i < localArguments.length; ++i) {
+ eArguments.add(localArguments[i]);
+ }
+ result = receiver.eInvoke(eOperation, eArguments);
+ } else if (method != null) {
+ final Object[] parameters = Arrays.copyOfRange(localArguments, 1, localArguments.length);
+ result = eOperationJavaInvoke(method, receiver, parameters);
+ } else {
+ throw new IllegalStateException(String.format("No eInvoke nor %s methods in %s", getName(),
+ receiver.getClass().getName()));
+ }
return result;
}
@@ -186,17 +214,39 @@
* <code>false</code> otherwise
*/
private boolean hasEInvoke(Object object) {
- Method method = null;
+ Method eInvokeMethod = null;
try {
- method = object.getClass().getDeclaredMethod("eInvoke", int.class, EList.class);
+ eInvokeMethod = object.getClass().getDeclaredMethod("eInvoke", int.class, EList.class);
} catch (NoSuchMethodException e) {
// nothing to do here
} catch (SecurityException e) {
// nothing to do here
}
- return method != null;
+ return eInvokeMethod != null;
+ }
+
+ /**
+ * Call the {@link EOperation} thru a Java invoke.
+ *
+ * @param eInvokeMethod
+ * the {@link Method}
+ * @param receiver
+ * the receiver
+ * @param arguments
+ * arguments
+ * @return the {@link EOperation} result if any, {@link Nothing} otherwise
+ * @throws Exception
+ * if the invoked {@link EOperation} fail
+ */
+ private Object eOperationJavaInvoke(Method eInvokeMethod, final Object receiver, final Object[] arguments)
+ throws Exception {
+ if (eInvokeMethod != null && receiver != null) {
+ return eInvokeMethod.invoke(receiver, arguments);
+ } else {
+ throw new IllegalArgumentException();
+ }
}
/**
@@ -244,17 +294,23 @@
} else if (iType instanceof EClassifierType) {
eClassifiers = new LinkedHashSet<EClassifier>();
eClassifiers.add(((EClassifierType)iType).getType());
+ } else if (iType instanceof SequenceType) {
+ eClassifiers = new LinkedHashSet<EClassifier>();
+ eClassifiers.add(EcorePackage.eINSTANCE.getEEList());
} else if (iType instanceof IJavaType) {
- if (iType.getType() != null) {
+ if (iType.getType() == null) {
+ eClassifiers = new LinkedHashSet<EClassifier>();
+ eClassifiers.add(null);
+ } else if (List.class.isAssignableFrom(((IJavaType)iType).getType())) {
+ eClassifiers = new LinkedHashSet<EClassifier>();
+ eClassifiers.add(EcorePackage.eINSTANCE.getEEList());
+ } else {
eClassifiers = queryEnvironment.getEPackageProvider().getEClassifiers(
((IJavaType)iType).getType());
if (eClassifiers == null) {
canMatch = false;
break;
}
- } else {
- eClassifiers = new LinkedHashSet<EClassifier>();
- eClassifiers.add(null);
}
} else {
throw new AcceleoQueryValidationException(iType.getClass().getCanonicalName());
diff --git a/query/tests/org.eclipse.acceleo.query.tests/model/nooperationreflection.ecore b/query/tests/org.eclipse.acceleo.query.tests/model/nooperationreflection.ecore
index c83df76..9dcc9df 100644
--- a/query/tests/org.eclipse.acceleo.query.tests/model/nooperationreflection.ecore
+++ b/query/tests/org.eclipse.acceleo.query.tests/model/nooperationreflection.ecore
@@ -6,5 +6,11 @@
<eOperations name="eOperationNoReflection" lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString">
<eParameters name="message" lowerBound="1" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
</eOperations>
+ <eOperations name="eOperationNoReflectionSubParameterType" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString">
+ <eParameters name="classifier" lowerBound="1" eType="ecore:EClass http://www.eclipse.org/emf/2002/Ecore#//EClassifier"/>
+ </eOperations>
+ <eOperations name="eOperationNoReflectionListParameter" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString">
+ <eParameters name="classifiers" lowerBound="1" upperBound="-1" eType="ecore:EClass http://www.eclipse.org/emf/2002/Ecore#//EClassifier"/>
+ </eOperations>
</eClassifiers>
</ecore:EPackage>
diff --git a/query/tests/org.eclipse.acceleo.query.tests/model/nooperationreflection.genmodel b/query/tests/org.eclipse.acceleo.query.tests/model/nooperationreflection.genmodel
index 96f5b9f..7a8ce55 100644
--- a/query/tests/org.eclipse.acceleo.query.tests/model/nooperationreflection.genmodel
+++ b/query/tests/org.eclipse.acceleo.query.tests/model/nooperationreflection.genmodel
@@ -10,6 +10,12 @@
<genOperations ecoreOperation="nooperationreflection.ecore#//NoOperationReflection/eOperationNoReflection">
<genParameters ecoreParameter="nooperationreflection.ecore#//NoOperationReflection/eOperationNoReflection/message"/>
</genOperations>
+ <genOperations ecoreOperation="nooperationreflection.ecore#//NoOperationReflection/eOperationNoReflectionSubParameterType">
+ <genParameters ecoreParameter="nooperationreflection.ecore#//NoOperationReflection/eOperationNoReflectionSubParameterType/classifier"/>
+ </genOperations>
+ <genOperations ecoreOperation="nooperationreflection.ecore#//NoOperationReflection/eOperationNoReflectionListParameter">
+ <genParameters ecoreParameter="nooperationreflection.ecore#//NoOperationReflection/eOperationNoReflectionListParameter/classifiers"/>
+ </genOperations>
</genClasses>
</genPackages>
</genmodel:GenModel>
diff --git a/query/tests/org.eclipse.acceleo.query.tests/src-gen-nooperationreflection/nooperationreflection/NoOperationReflection.java b/query/tests/org.eclipse.acceleo.query.tests/src-gen-nooperationreflection/nooperationreflection/NoOperationReflection.java
index 296581e..69ce6a4 100644
--- a/query/tests/org.eclipse.acceleo.query.tests/src-gen-nooperationreflection/nooperationreflection/NoOperationReflection.java
+++ b/query/tests/org.eclipse.acceleo.query.tests/src-gen-nooperationreflection/nooperationreflection/NoOperationReflection.java
@@ -2,6 +2,8 @@
*/
package nooperationreflection;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
/**
@@ -23,4 +25,20 @@
*/
String eOperationNoReflection(String message);
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @model classifierRequired="true"
+ * @generated
+ */
+ String eOperationNoReflectionSubParameterType(EClassifier classifier);
+
+ /**
+ * <!-- begin-user-doc -->
+ * <!-- end-user-doc -->
+ * @model classifiersRequired="true" classifiersMany="true"
+ * @generated
+ */
+ String eOperationNoReflectionListParameter(EList<EClassifier> classifiers);
+
} // NoOperationReflection
diff --git a/query/tests/org.eclipse.acceleo.query.tests/src-gen-nooperationreflection/nooperationreflection/impl/NoOperationReflectionImpl.java b/query/tests/org.eclipse.acceleo.query.tests/src-gen-nooperationreflection/nooperationreflection/impl/NoOperationReflectionImpl.java
index 2ef1d00..19ea8f1 100644
--- a/query/tests/org.eclipse.acceleo.query.tests/src-gen-nooperationreflection/nooperationreflection/impl/NoOperationReflectionImpl.java
+++ b/query/tests/org.eclipse.acceleo.query.tests/src-gen-nooperationreflection/nooperationreflection/impl/NoOperationReflectionImpl.java
@@ -2,16 +2,16 @@
*/
package nooperationreflection.impl;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.impl.MinimalEObjectImpl;
+
import nooperationreflection.NoOperationReflection;
import nooperationreflection.NooperationreflectionPackage;
-import org.eclipse.emf.ecore.EClass;
-
-import org.eclipse.emf.ecore.impl.MinimalEObjectImpl;
-
/**
- * <!-- begin-user-doc -->
- * An implementation of the model object '<em><b>No Operation Reflection</b></em>'.
+ * <!-- begin-user-doc --> An implementation of the model object '<em><b>No Operation Reflection</b></em>'.
* <!-- end-user-doc -->
* <p>
* </p>
@@ -20,8 +20,8 @@
*/
public class NoOperationReflectionImpl extends MinimalEObjectImpl.Container implements NoOperationReflection {
/**
- * <!-- begin-user-doc -->
- * <!-- end-user-doc -->
+ * <!-- begin-user-doc --> <!-- end-user-doc -->
+ *
* @generated
*/
protected NoOperationReflectionImpl() {
@@ -29,8 +29,8 @@
}
/**
- * <!-- begin-user-doc -->
- * <!-- end-user-doc -->
+ * <!-- begin-user-doc --> <!-- end-user-doc -->
+ *
* @generated
*/
@Override
@@ -39,12 +39,35 @@
}
/**
- * <!-- begin-user-doc -->
- * <!-- end-user-doc -->
+ * <!-- begin-user-doc --> <!-- end-user-doc -->
+ *
* @generated NOT
*/
public String eOperationNoReflection(String message) {
return message;
}
-} //NoOperationReflectionImpl
+ /**
+ * <!-- begin-user-doc --> <!-- end-user-doc -->
+ *
+ * @generated NOT
+ */
+ public String eOperationNoReflectionSubParameterType(EClassifier classifier) {
+ return classifier.getName();
+ }
+
+ /**
+ * <!-- begin-user-doc --> <!-- end-user-doc -->
+ *
+ * @generated NOT
+ */
+ public String eOperationNoReflectionListParameter(EList<EClassifier> classifiers) {
+ final StringBuilder result = new StringBuilder();
+
+ for (EClassifier classifer : classifiers) {
+ result.append(classifer.getName());
+ }
+
+ return result.toString();
+ }
+} // NoOperationReflectionImpl
diff --git a/query/tests/org.eclipse.acceleo.query.tests/src-gen-nooperationreflection/nooperationreflection/impl/NooperationreflectionPackageImpl.java b/query/tests/org.eclipse.acceleo.query.tests/src-gen-nooperationreflection/nooperationreflection/impl/NooperationreflectionPackageImpl.java
index 105b991..9fe8dcd 100644
--- a/query/tests/org.eclipse.acceleo.query.tests/src-gen-nooperationreflection/nooperationreflection/impl/NooperationreflectionPackageImpl.java
+++ b/query/tests/org.eclipse.acceleo.query.tests/src-gen-nooperationreflection/nooperationreflection/impl/NooperationreflectionPackageImpl.java
@@ -162,6 +162,12 @@
EOperation op = addEOperation(noOperationReflectionEClass, ecorePackage.getEString(), "eOperationNoReflection", 1, 1, IS_UNIQUE, IS_ORDERED);
addEParameter(op, ecorePackage.getEString(), "message", 1, 1, IS_UNIQUE, IS_ORDERED);
+ op = addEOperation(noOperationReflectionEClass, ecorePackage.getEString(), "eOperationNoReflectionSubParameterType", 0, 1, IS_UNIQUE, IS_ORDERED);
+ addEParameter(op, ecorePackage.getEClassifier(), "classifier", 1, 1, IS_UNIQUE, IS_ORDERED);
+
+ op = addEOperation(noOperationReflectionEClass, ecorePackage.getEString(), "eOperationNoReflectionListParameter", 0, 1, IS_UNIQUE, IS_ORDERED);
+ addEParameter(op, ecorePackage.getEClassifier(), "classifiers", 1, -1, IS_UNIQUE, IS_ORDERED);
+
// Create resource
createResource(eNS_URI);
}
diff --git a/query/tests/org.eclipse.acceleo.query.tests/src/org/eclipse/acceleo/query/parser/tests/EvaluationTest.java b/query/tests/org.eclipse.acceleo.query.tests/src/org/eclipse/acceleo/query/parser/tests/EvaluationTest.java
index 1a2893d..150286a 100644
--- a/query/tests/org.eclipse.acceleo.query.tests/src/org/eclipse/acceleo/query/parser/tests/EvaluationTest.java
+++ b/query/tests/org.eclipse.acceleo.query.tests/src/org/eclipse/acceleo/query/parser/tests/EvaluationTest.java
@@ -321,6 +321,29 @@
}
@Test
+ public void eOperationNoReflectionSubParameterTypeTest() {
+ Map<String, Object> variables = Maps.newHashMap();
+ final NoOperationReflection self = NooperationreflectionPackage.eINSTANCE
+ .getNooperationreflectionFactory().createNoOperationReflection();
+ variables.put("self", self);
+ assertOKResultEquals("EClass", engine.eval(builder
+ .build("self.eOperationNoReflectionSubParameterType(ecore::EClass)"), variables));
+ }
+
+ @Test
+ public void eOperationNoReflectionListParameterTest() {
+ Map<String, Object> variables = Maps.newHashMap();
+ final NoOperationReflection self = NooperationreflectionPackage.eINSTANCE
+ .getNooperationreflectionFactory().createNoOperationReflection();
+ variables.put("self", self);
+ assertOKResultEquals(
+ "EClassEOperation",
+ engine.eval(
+ builder.build("self.eOperationNoReflectionListParameter(Sequence{ecore::EClass, ecore::EOperation})"),
+ variables));
+ }
+
+ @Test
public void serviceNullParameterTest() {
Map<String, Object> variables = Maps.newHashMap();
variables.put("self", EcorePackage.eINSTANCE.getEClass());
diff --git a/query/tests/org.eclipse.acceleo.query.tests/src/org/eclipse/acceleo/query/parser/tests/ValidationTest.java b/query/tests/org.eclipse.acceleo.query.tests/src/org/eclipse/acceleo/query/parser/tests/ValidationTest.java
index 850c055..9ea70f9 100644
--- a/query/tests/org.eclipse.acceleo.query.tests/src/org/eclipse/acceleo/query/parser/tests/ValidationTest.java
+++ b/query/tests/org.eclipse.acceleo.query.tests/src/org/eclipse/acceleo/query/parser/tests/ValidationTest.java
@@ -50,6 +50,8 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import nooperationreflection.NooperationreflectionPackage;
+
public class ValidationTest {
QueryValidationEngine engine;
@@ -66,6 +68,7 @@
queryEnvironment = Query.newEnvironmentWithDefaultServices(null);
queryEnvironment.registerEPackage(EcorePackage.eINSTANCE);
queryEnvironment.registerEPackage(AnydslPackage.eINSTANCE);
+ queryEnvironment.registerEPackage(NooperationreflectionPackage.eINSTANCE);
final Set<IService> services = ServiceUtils.getServices(queryEnvironment, EObjectServices.class);
ServiceUtils.registerServices(queryEnvironment, services);
engine = new QueryValidationEngine(queryEnvironment);
@@ -77,6 +80,11 @@
final Set<IType> stuffTypes = new LinkedHashSet<IType>();
stuffTypes.add(new EClassifierType(queryEnvironment, EcorePackage.eINSTANCE.getEPackage()));
variableTypes.put("stuff", stuffTypes);
+ final Set<IType> noReflexionTypes = new LinkedHashSet<IType>();
+ noReflexionTypes.add(new EClassifierType(queryEnvironment, NooperationreflectionPackage.eINSTANCE
+ .getNoOperationReflection()));
+ variableTypes.put("noReflexion", noReflexionTypes);
+
}
@Test
@@ -121,7 +129,7 @@
@Test
public void variableNotRegisteredEClassifierTest() {
- queryEnvironment.removeEPackage(EcorePackage.eINSTANCE.getName());
+ queryEnvironment.removeEPackage(EcorePackage.eINSTANCE);
final IValidationResult validationResult = engine.validate("self", variableTypes);
final Expression ast = validationResult.getAstResult().getAst();
@@ -430,7 +438,7 @@
@Test
public void enumLiteralError() {
final IValidationResult validationResult = engine
- .validate("anydsl::Part::NotExisting", variableTypes);
+ .validate("anydsl::Part::NotExisting", variableTypes);
final Expression ast = validationResult.getAstResult().getAst();
Set<IType> possibleTypes = validationResult.getPossibleTypes(ast);
@@ -1035,8 +1043,8 @@
assertEquals(0, possibleTypes.size());
assertEquals(1, validationResult.getMessages().size());
assertValidationMessage(
- validationResult.getMessages().get(0),
- ValidationMessageLevel.ERROR,
+ validationResult.getMessages().get(0),
+ ValidationMessageLevel.ERROR,
"Couldn't find the 'triggerEOperationLookUp(EClassifier=EClass,org.eclipse.acceleo.query.runtime.Query)' service",
4, 36);
}
@@ -1093,8 +1101,8 @@
assertEquals(1, validationResult.getMessages().size());
assertValidationMessage(
- validationResult.getMessages().get(0),
- ValidationMessageLevel.ERROR,
+ validationResult.getMessages().get(0),
+ ValidationMessageLevel.ERROR,
"Nothing will be left after calling oclAsType:\nEClassifier=EPackage is not compatible with type EClassifierLiteral=EInt\nEClassifier=EAnnotation is not compatible with type EClassifierLiteral=EInt",
17, 40);
}
@@ -1131,6 +1139,59 @@
assertEquals(0, validationResult.getMessages().size());
}
+ @Test
+ public void eOperationNoReflectionTest() {
+ final IValidationResult validationResult = engine.validate(
+ "noReflexion.eOperationNoReflection('text')", variableTypes);
+
+ final Expression ast = validationResult.getAstResult().getAst();
+ final Set<IType> possibleTypes = validationResult.getPossibleTypes(ast);
+
+ assertEquals(1, possibleTypes.size());
+ final Iterator<IType> it = possibleTypes.iterator();
+ IType possibleType = it.next();
+ assertTrue(possibleType instanceof EClassifierType);
+ assertEquals(EcorePackage.eINSTANCE.getEString(), possibleType.getType());
+
+ assertEquals(0, validationResult.getMessages().size());
+ }
+
+ @Test
+ public void eOperationNoReflectionSubParameterTypeTest() {
+ final IValidationResult validationResult = engine.validate(
+ "noReflexion.eOperationNoReflectionSubParameterType(ecore::EClass)", variableTypes);
+
+ final Expression ast = validationResult.getAstResult().getAst();
+ final Set<IType> possibleTypes = validationResult.getPossibleTypes(ast);
+
+ assertEquals(1, possibleTypes.size());
+ final Iterator<IType> it = possibleTypes.iterator();
+ IType possibleType = it.next();
+ assertTrue(possibleType instanceof EClassifierType);
+ assertEquals(EcorePackage.eINSTANCE.getEString(), possibleType.getType());
+
+ assertEquals(0, validationResult.getMessages().size());
+ }
+
+ @Test
+ public void eOperationNoReflectionListParameterTest() {
+ final IValidationResult validationResult = engine
+ .validate(
+ "noReflexion.eOperationNoReflectionListParameter(Sequence{ecore::EClass, ecore::EOperation})",
+ variableTypes);
+
+ final Expression ast = validationResult.getAstResult().getAst();
+ final Set<IType> possibleTypes = validationResult.getPossibleTypes(ast);
+
+ assertEquals(1, possibleTypes.size());
+ final Iterator<IType> it = possibleTypes.iterator();
+ IType possibleType = it.next();
+ assertTrue(possibleType instanceof EClassifierType);
+ assertEquals(EcorePackage.eINSTANCE.getEString(), possibleType.getType());
+
+ assertEquals(0, validationResult.getMessages().size());
+ }
+
/**
* Asserts the given {@link IValidationMessage} against expected values.
*