Added JavaMethodReceiverService.
Change-Id: If692b4e05e89f6957a318b37daa3f8d08a444e86
diff --git a/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/runtime/ServiceUtils.java b/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/runtime/ServiceUtils.java
index e78df92..606d0f0 100644
--- a/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/runtime/ServiceUtils.java
+++ b/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/runtime/ServiceUtils.java
@@ -18,6 +18,7 @@
import java.util.Set;
import org.eclipse.acceleo.query.runtime.impl.EOperationService;
+import org.eclipse.acceleo.query.runtime.impl.JavaMethodReceiverService;
import org.eclipse.acceleo.query.runtime.impl.JavaMethodService;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
@@ -76,6 +77,28 @@
}
/**
+ * Gets the {@link Set} of {@link IService} for the given {@link Class} with receiver as first parameter.
+ *
+ * @param queryEnvironment
+ * the {@link IReadOnlyQueryEnvironment}
+ * @param cls
+ * the {@link Class}
+ * @return the {@link Set} of {@link IService} for the given {@link Class} with receiver as first
+ * parameter
+ */
+ public static Set<IService> getReceiverServices(IReadOnlyQueryEnvironment queryEnvironment, Class<?> cls) {
+ final Set<IService> result = new LinkedHashSet<IService>();
+
+ for (Method method : cls.getMethods()) {
+ if (isReveiverServiceMethod(method)) {
+ result.add(new JavaMethodReceiverService(method));
+ }
+ }
+
+ return result;
+ }
+
+ /**
* Gets the {@link Set} of {@link IService} for the given {@link Object instance}.
*
* @param queryEnvironment
@@ -150,6 +173,22 @@
}
/**
+ * Tells if a given {@link Method} is considered as a {@link IService} with receiver as first parameter.
+ * {@link Object} methods are not considered.
+ *
+ * @param method
+ * the {@link Method} to check
+ * @return <code>true</code> if a given {@link Method} is considered as a {@link IService} with receiver
+ * as first parameter, <code>false</code> otherwise
+ */
+ public static boolean isReveiverServiceMethod(Method method) {
+ // We do not register java.lang.Object method as
+ // having an expression calling the 'wait' or the notify service
+ // could yield problems that are difficult to track down.
+ return method.getDeclaringClass() != Object.class;
+ }
+
+ /**
* Registers a {@link Set} of {@link IService} to the given {@link IQueryEnvironment}.
*
* @param queryEnvironment
diff --git a/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/runtime/impl/JavaMethodReceiverService.java b/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/runtime/impl/JavaMethodReceiverService.java
new file mode 100644
index 0000000..faad4a9
--- /dev/null
+++ b/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/runtime/impl/JavaMethodReceiverService.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.query.runtime.impl;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.acceleo.query.runtime.IReadOnlyQueryEnvironment;
+import org.eclipse.acceleo.query.validation.type.IType;
+
+/**
+ * Implementation of an {@link org.eclipse.acceleo.query.runtime.IService IService} for {@link Method} with
+ * receiver as first parameter.
+ *
+ * @author <a href="mailto:yvan.lussaud@obeo.fr">Yvan Lussaud</a>
+ */
+public class JavaMethodReceiverService extends JavaMethodService {
+
+ /**
+ * Constructor.
+ *
+ * @param method
+ * the method that realizes the service
+ */
+ public JavaMethodReceiverService(Method method) {
+ super(method, null);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.query.runtime.IService#getShortSignature()
+ */
+ @Override
+ public String getShortSignature() {
+ final Class<?>[] parameters = getParameterTypes();
+ return serviceShortSignature(parameters);
+ }
+
+ /**
+ * Gets the parameter types including the receiver type.
+ *
+ * @return the parameter types including the receiver type
+ */
+ private Class<?>[] getParameterTypes() {
+ final Class<?>[] parameters = new Class<?>[getMethod().getParameterTypes().length + 1];
+ int i = 0;
+ parameters[i++] = getMethod().getDeclaringClass();
+ for (Class<?> cls : getMethod().getParameterTypes()) {
+ parameters[i++] = cls;
+ }
+ return parameters;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.query.runtime.IService#getLongSignature()
+ */
+ @Override
+ public String getLongSignature() {
+ return super.getLongSignature() + " (receiver as first parameter)";
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.query.runtime.IService#getParameterTypes(org.eclipse.acceleo.query.runtime.IReadOnlyQueryEnvironment)
+ */
+ @Override
+ public List<IType> getParameterTypes(IReadOnlyQueryEnvironment queryEnvironment) {
+ final List<IType> result = new ArrayList<IType>();
+
+ for (Class<?> cls : getParameterTypes()) {
+ result.add(getClassType(queryEnvironment, cls));
+ }
+
+ return result;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.query.runtime.IService#getNumberOfParameters()
+ */
+ @Override
+ public int getNumberOfParameters() {
+ return super.getNumberOfParameters() + 1;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.acceleo.query.runtime.impl.AbstractService#internalInvoke(java.lang.Object[])
+ */
+ @Override
+ protected Object internalInvoke(Object[] arguments) throws Exception {
+ final Object receiver = arguments[0];
+ final Object[] newArguments = new Object[arguments.length - 1];
+ for (int i = 0; i < newArguments.length; i++) {
+ newArguments[i] = arguments[i + 1];
+ }
+
+ return getMethod().invoke(receiver, newArguments);
+ }
+
+}
diff --git a/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/runtime/impl/JavaMethodService.java b/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/runtime/impl/JavaMethodService.java
index 5b11d50..460ecdd 100644
--- a/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/runtime/impl/JavaMethodService.java
+++ b/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/runtime/impl/JavaMethodService.java
@@ -35,8 +35,7 @@
import org.eclipse.emf.ecore.EObject;
/**
- * Abstract implementation of an {@link org.eclipse.acceleo.query.runtime.IService IService} for
- * {@link Method}.
+ * Implementation of an {@link org.eclipse.acceleo.query.runtime.IService IService} for {@link Method}.
*
* @author <a href="mailto:yvan.lussaud@obeo.fr">Yvan Lussaud</a>
*/
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 cfcf9a3..4dbbc8c 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
@@ -38,6 +38,7 @@
import org.eclipse.acceleo.query.tests.nestedpackages.root.child.grand_child.Grand_childFactory;
import org.eclipse.acceleo.query.tests.nestedpackages.root.child.grand_child.Grand_childPackage;
import org.eclipse.acceleo.query.tests.services.EObjectServices;
+import org.eclipse.acceleo.query.tests.services.ReceiverServices;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EPackage;
@@ -641,4 +642,27 @@
assertEquals("\u1F61C \u1F62D \u1F63D \u1F1EB\u1F1F7", result.getResult());
}
+
+ @Test
+ public void javaMethodReceiverServiceNoArg() {
+ Map<String, Object> variables = new HashMap<String, Object>();
+ variables.put("self", new ReceiverServices());
+ ServiceUtils.registerServices(queryEnvironment, ServiceUtils.getReceiverServices(queryEnvironment,
+ ReceiverServices.class));
+ EvaluationResult result = engine.eval(builder.build("self.noArg()"), variables);
+
+ assertEquals("noArgResult", result.getResult());
+ }
+
+ @Test
+ public void javaMethodReceiverServiceArg() {
+ Map<String, Object> variables = new HashMap<String, Object>();
+ variables.put("self", new ReceiverServices());
+ ServiceUtils.registerServices(queryEnvironment, ServiceUtils.getReceiverServices(queryEnvironment,
+ ReceiverServices.class));
+ EvaluationResult result = engine.eval(builder.build("self.arg('arg')"), variables);
+
+ assertEquals("argResultarg", result.getResult());
+ }
+
}
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 7418577..edbcc7c 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
@@ -33,6 +33,7 @@
import org.eclipse.acceleo.query.runtime.impl.QueryValidationEngine;
import org.eclipse.acceleo.query.tests.anydsl.AnydslPackage;
import org.eclipse.acceleo.query.tests.services.EObjectServices;
+import org.eclipse.acceleo.query.tests.services.ReceiverServices;
import org.eclipse.acceleo.query.validation.type.ClassType;
import org.eclipse.acceleo.query.validation.type.EClassifierLiteralType;
import org.eclipse.acceleo.query.validation.type.EClassifierSetLiteralType;
@@ -1400,6 +1401,46 @@
assertEquals(0, validationResult.getMessages().size());
}
+ @Test
+ public void javaMethodReceiverServiceNoArg() {
+ Set<IType> selfTypes = new LinkedHashSet<IType>();
+ selfTypes.add(new ClassType(queryEnvironment, ReceiverServices.class));
+ variableTypes.put("self", selfTypes);
+ ServiceUtils.registerServices(queryEnvironment, ServiceUtils.getReceiverServices(queryEnvironment,
+ ReceiverServices.class));
+
+ final IValidationResult validationResult = engine.validate("self.noArg()", 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 ClassType);
+ assertEquals(String.class, possibleType.getType());
+ assertEquals(0, validationResult.getMessages().size());
+ }
+
+ @Test
+ public void javaMethodReceiverServiceArg() {
+ Set<IType> selfTypes = new LinkedHashSet<IType>();
+ selfTypes.add(new ClassType(queryEnvironment, ReceiverServices.class));
+ variableTypes.put("self", selfTypes);
+ ServiceUtils.registerServices(queryEnvironment, ServiceUtils.getReceiverServices(queryEnvironment,
+ ReceiverServices.class));
+
+ final IValidationResult validationResult = engine.validate("self.arg('arg')", 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 ClassType);
+ assertEquals(String.class, possibleType.getType());
+ assertEquals(0, validationResult.getMessages().size());
+ }
+
/**
* Asserts the given {@link IValidationMessage} against expected values.
*
diff --git a/query/tests/org.eclipse.acceleo.query.tests/src/org/eclipse/acceleo/query/tests/services/ReceiverServices.java b/query/tests/org.eclipse.acceleo.query.tests/src/org/eclipse/acceleo/query/tests/services/ReceiverServices.java
new file mode 100644
index 0000000..e4d9b28
--- /dev/null
+++ b/query/tests/org.eclipse.acceleo.query.tests/src/org/eclipse/acceleo/query/tests/services/ReceiverServices.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Obeo.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.acceleo.query.tests.services;
+
+/**
+ * @author <a href="mailto:yvan.lussaud@obeo.fr">Yvan Lussaud</a>
+ */
+public class ReceiverServices {
+
+ private final String noArgResult = "noArgResult";
+
+ private final String argResult = "argResult";
+
+ public String noArg() {
+ return noArgResult;
+ }
+
+ public String arg(String arg) {
+ return argResult + arg;
+ }
+
+}