Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpguilet2017-12-13 15:29:47 +0000
committerPierre Guilet2018-01-22 15:04:51 +0000
commit7020d739907f91945c4fd8537938d61777480192 (patch)
treeab7b634de4ef40fd6728237b0ba4f22054e5fd14
parent0166c3c29a3b1d980e169a79129d6aae8a0a38b8 (diff)
downloadorg.eclipse.sirius-7020d739907f91945c4fd8537938d61777480192.tar.gz
org.eclipse.sirius-7020d739907f91945c4fd8537938d61777480192.tar.xz
org.eclipse.sirius-7020d739907f91945c4fd8537938d61777480192.zip
[471900] Support quick navigation to service method implementation
Hitting F3 when cursor is on a VSM service from AQL or Service interpreter expression will have the following effects: - if only one Java class contains the service, it is directly opened with Java editor. - if many classes contains the service, a wizard allows to choose which one is opened. Bug: 471900 Change-Id: I5bb9465b71f03fde161de6dda23b206a53b67a14 Signed-off-by: pguilet <pierre.guilet@obeo.fr>
-rw-r--r--plugins/org.eclipse.sirius.common.acceleo.aql/META-INF/MANIFEST.MF1
-rw-r--r--plugins/org.eclipse.sirius.common.acceleo.aql/src/org/eclipse/sirius/common/acceleo/aql/business/internal/AQLSiriusInterpreter.java39
-rw-r--r--plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/api/interpreter/IJavaAwareInterpreter.java32
-rw-r--r--plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/internal/interpreter/IService.java15
-rw-r--r--plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/internal/interpreter/MonomorphicService.java9
-rw-r--r--plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/internal/interpreter/PolymorphicService.java17
-rw-r--r--plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/internal/interpreter/ServiceInterpreter.java36
-rw-r--r--plugins/org.eclipse.sirius.diagram/src/org/eclipse/sirius/diagram/Messages.java2
-rw-r--r--plugins/org.eclipse.sirius.editor.diagram/src-gen/org/eclipse/sirius/diagram/editor/properties/sections/description/diagramdescription/DiagramDescriptionPreconditionExpressionPropertySection.java11
-rw-r--r--plugins/org.eclipse.sirius.editor/META-INF/MANIFEST.MF39
-rw-r--r--plugins/org.eclipse.sirius.editor/plugin.properties3
-rw-r--r--plugins/org.eclipse.sirius.editor/src-gen/org/eclipse/sirius/editor/editorPlugin/SiriusEditorPlugin.java32
-rw-r--r--plugins/org.eclipse.sirius.editor/src/org/eclipse/sirius/editor/Messages.java43
-rw-r--r--plugins/org.eclipse.sirius.editor/src/org/eclipse/sirius/editor/internal/navigation/INavigatorFromVSMExpression.java53
-rw-r--r--plugins/org.eclipse.sirius.editor/src/org/eclipse/sirius/editor/internal/navigation/NavigationByKeyListener.java89
-rw-r--r--plugins/org.eclipse.sirius.editor/src/org/eclipse/sirius/editor/internal/navigation/NavigationFromVSMExpressionRegistry.java56
-rw-r--r--plugins/org.eclipse.sirius.editor/src/org/eclipse/sirius/editor/internal/navigation/ServiceNavigator.java289
-rw-r--r--plugins/org.eclipse.sirius.tests.swtbot/data/unit/editor/vsm/completion/BasicService2.java25
-rw-r--r--plugins/org.eclipse.sirius.tests.swtbot/data/unit/editor/vsm/completion/MANIFEST.MF4
-rw-r--r--plugins/org.eclipse.sirius.tests.swtbot/data/unit/editor/vsm/completion/ServicesWithDependencies.java3
-rw-r--r--plugins/org.eclipse.sirius.tests.swtbot/data/unit/editor/vsm/completion/test.odesign1
-rw-r--r--plugins/org.eclipse.sirius.tests.swtbot/src/org/eclipse/sirius/tests/swtbot/editor/vsm/ServiceNavigationTest.java519
-rw-r--r--plugins/org.eclipse.sirius.tests.swtbot/src/org/eclipse/sirius/tests/swtbot/suite/AllTestSuite.java2
23 files changed, 1265 insertions, 55 deletions
diff --git a/plugins/org.eclipse.sirius.common.acceleo.aql/META-INF/MANIFEST.MF b/plugins/org.eclipse.sirius.common.acceleo.aql/META-INF/MANIFEST.MF
index 90403fe726..a7824e33b4 100644
--- a/plugins/org.eclipse.sirius.common.acceleo.aql/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.sirius.common.acceleo.aql/META-INF/MANIFEST.MF
@@ -18,5 +18,6 @@ Export-Package: org.eclipse.sirius.common.acceleo.aql.business;version="3.0.0",
org.eclipse.sirius.common.acceleo.aql.business.internal;x-internal:=true;version="3.0.0"
Bundle-ActivationPolicy: lazy
Import-Package: org.eclipse.acceleo.query.runtime;version="[5.0.0,6.0.0)",
+ org.eclipse.acceleo.query.runtime.impl,
org.eclipse.acceleo.query.validation.type;version="[5.0.0,6.0.0)"
Bundle-Localization: plugin
diff --git a/plugins/org.eclipse.sirius.common.acceleo.aql/src/org/eclipse/sirius/common/acceleo/aql/business/internal/AQLSiriusInterpreter.java b/plugins/org.eclipse.sirius.common.acceleo.aql/src/org/eclipse/sirius/common/acceleo/aql/business/internal/AQLSiriusInterpreter.java
index b838287163..af4c17fc0b 100644
--- a/plugins/org.eclipse.sirius.common.acceleo.aql/src/org/eclipse/sirius/common/acceleo/aql/business/internal/AQLSiriusInterpreter.java
+++ b/plugins/org.eclipse.sirius.common.acceleo.aql/src/org/eclipse/sirius/common/acceleo/aql/business/internal/AQLSiriusInterpreter.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2015, 2016 Obeo.
+ * Copyright (c) 2015, 2017 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
@@ -10,6 +10,7 @@
*******************************************************************************/
package org.eclipse.sirius.common.acceleo.aql.business.internal;
+import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
@@ -39,6 +40,7 @@ import org.eclipse.acceleo.query.runtime.QueryParsing;
import org.eclipse.acceleo.query.runtime.QueryValidation;
import org.eclipse.acceleo.query.runtime.ServiceUtils;
import org.eclipse.acceleo.query.runtime.ValidationMessageLevel;
+import org.eclipse.acceleo.query.runtime.impl.JavaMethodService;
import org.eclipse.acceleo.query.validation.type.ClassType;
import org.eclipse.acceleo.query.validation.type.EClassifierType;
import org.eclipse.acceleo.query.validation.type.ICollectionType;
@@ -65,6 +67,7 @@ import org.eclipse.sirius.common.tools.api.interpreter.EPackageLoadingCallback;
import org.eclipse.sirius.common.tools.api.interpreter.EvaluationException;
import org.eclipse.sirius.common.tools.api.interpreter.IInterpreterContext;
import org.eclipse.sirius.common.tools.api.interpreter.IInterpreterStatus;
+import org.eclipse.sirius.common.tools.api.interpreter.IJavaAwareInterpreter;
import org.eclipse.sirius.common.tools.api.interpreter.InterpreterStatusFactory;
import org.eclipse.sirius.common.tools.api.interpreter.ValidationResult;
import org.eclipse.sirius.common.tools.api.interpreter.VariableType;
@@ -77,12 +80,12 @@ import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
/**
- * A Sirius interpreter using the Acceleo Query Language. It only supports
- * expressions which are not using implicit variables.
+ * A Sirius interpreter using the Acceleo Query Language. It only supports expressions which are not using implicit
+ * variables.
*
* @author cedric
*/
-public class AQLSiriusInterpreter extends AcceleoAbstractInterpreter {
+public class AQLSiriusInterpreter extends AcceleoAbstractInterpreter implements IJavaAwareInterpreter {
private LoadingCache<String, AstResult> parsedExpressions;
@@ -314,11 +317,9 @@ public class AQLSiriusInterpreter extends AcceleoAbstractInterpreter {
for (IType type : aqlValidationResult.getPossibleTypes(aqlValidationResult.getAstResult().getAst())) {
IType actualType = type;
/*
- * Sirius has no notion of "multiple" or "collection" type in
- * its typesystem and will unwrap the collection when using its
- * result as the root of a new expression. It seems better to
- * return the type information than hide which leads to a
- * fall-back to EObject.
+ * Sirius has no notion of "multiple" or "collection" type in its typesystem and will unwrap the
+ * collection when using its result as the root of a new expression. It seems better to return the type
+ * information than hide which leads to a fall-back to EObject.
*/
if (type instanceof ICollectionType) {
actualType = ((ICollectionType) type).getCollectionType();
@@ -354,6 +355,20 @@ public class AQLSiriusInterpreter extends AcceleoAbstractInterpreter {
return result;
}
+ @Override
+ public Collection<Method> getImplementation(String serviceCall) {
+ javaExtensions.reloadIfNeeded();
+ Set<org.eclipse.acceleo.query.runtime.IService> registeredServices = queryEnvironment.getLookupEngine().getRegisteredServices();
+ List<Method> results = new ArrayList<Method>();
+ registeredServices.iterator().forEachRemaining(s -> {
+ if (s instanceof JavaMethodService) {
+ results.add(((JavaMethodService) s).getMethod());
+ }
+ });
+
+ return results;
+ }
+
/**
* return the cross reference provider used by this interpreter instance.
*
@@ -380,10 +395,8 @@ public class AQLSiriusInterpreter extends AcceleoAbstractInterpreter {
*/
public IQueryEnvironment getQueryEnvironment() {
/*
- * The JavaExtensionManager might impact the query environment when
- * loading classes. We trigger the reload before returning the
- * IQueryEnvironment so that it is properly configured with EPackages
- * and imports.
+ * The JavaExtensionManager might impact the query environment when loading classes. We trigger the reload
+ * before returning the IQueryEnvironment so that it is properly configured with EPackages and imports.
*/
this.javaExtensions.reloadIfNeeded();
diff --git a/plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/api/interpreter/IJavaAwareInterpreter.java b/plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/api/interpreter/IJavaAwareInterpreter.java
new file mode 100644
index 0000000000..5668f38d8d
--- /dev/null
+++ b/plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/api/interpreter/IJavaAwareInterpreter.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2017 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.sirius.common.tools.api.interpreter;
+
+import java.lang.reflect.Method;
+import java.util.Collection;
+
+/**
+ * Interface used by interpreters capable of interpreting JAVA services.
+ *
+ * @author <a href="mailto:pierre.guilet@obeo.fr">Pierre Guilet</a>
+ *
+ */
+public interface IJavaAwareInterpreter {
+ /**
+ * Returns the concrete methods which implement the service identified by the given expression.
+ *
+ * @param serviceCall
+ * the service call from which we want to extract corresponding {@link Method} if such elements exist.
+ * @return the concrete methods which implement the service identified by the given expression. An empty list if no
+ * such element exists.
+ */
+ Collection<Method> getImplementation(String serviceCall);
+}
diff --git a/plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/internal/interpreter/IService.java b/plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/internal/interpreter/IService.java
index a432b3e779..551ddd8433 100644
--- a/plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/internal/interpreter/IService.java
+++ b/plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/internal/interpreter/IService.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2013 THALES GLOBAL SERVICES.
+ * Copyright (c) 2013, 2017 THALES GLOBAL SERVICES.
* 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
@@ -10,6 +10,9 @@
*******************************************************************************/
package org.eclipse.sirius.common.tools.internal.interpreter;
+import java.lang.reflect.Method;
+import java.util.Collection;
+
import org.eclipse.sirius.common.tools.api.interpreter.EvaluationException;
/**
@@ -30,8 +33,7 @@ public interface IService {
*
* @param target
* a potential target object on which to invoke the service.
- * @return <code>true</code> iff this service can be invoked on the
- * specified target object.
+ * @return <code>true</code> iff this service can be invoked on the specified target object.
*/
boolean appliesTo(Object[] target);
@@ -45,4 +47,11 @@ public interface IService {
* if an error occurred during the invocation of the service.
*/
Object call(Object[] target) throws EvaluationException;
+
+ /**
+ * Returns the concrete methods which implement this service.
+ *
+ * @return the concrete methods which implement this service.
+ */
+ Collection<Method> getImplementations();
}
diff --git a/plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/internal/interpreter/MonomorphicService.java b/plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/internal/interpreter/MonomorphicService.java
index e10af9c201..9120edbc37 100644
--- a/plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/internal/interpreter/MonomorphicService.java
+++ b/plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/internal/interpreter/MonomorphicService.java
@@ -14,6 +14,8 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import org.eclipse.sirius.common.tools.Messages;
@@ -44,6 +46,7 @@ class MonomorphicService implements IMonomorphicService {
Preconditions.checkArgument(ServiceInterpreter.isValidServiceMethod(serviceMethod));
}
+ @Override
public String getName() {
return serviceMethod.getName();
}
@@ -65,6 +68,7 @@ class MonomorphicService implements IMonomorphicService {
return apply;
}
+ @Override
public Object call(Object[] target) throws EvaluationException {
Object result = null;
try {
@@ -105,4 +109,9 @@ class MonomorphicService implements IMonomorphicService {
return parametersTypes;
}
+ @Override
+ public Collection<Method> getImplementations() {
+ return Collections.singleton(this.serviceMethod);
+ }
+
}
diff --git a/plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/internal/interpreter/PolymorphicService.java b/plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/internal/interpreter/PolymorphicService.java
index 599c0e37f8..8260f5e080 100644
--- a/plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/internal/interpreter/PolymorphicService.java
+++ b/plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/internal/interpreter/PolymorphicService.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2013 THALES GLOBAL SERVICES.
+ * Copyright (c) 2013, 2017 THALES GLOBAL SERVICES.
* 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
@@ -10,7 +10,9 @@
*******************************************************************************/
package org.eclipse.sirius.common.tools.internal.interpreter;
+import java.lang.reflect.Method;
import java.text.MessageFormat;
+import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
@@ -24,8 +26,8 @@ import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
/**
- * A service which corresponds to more than one Java method. Which of the
- * methods will actually be invoked will depend on the target object.
+ * A service which corresponds to more than one Java method. Which of the methods will actually be invoked will depend
+ * on the target object.
*
* @author pcdavid
*/
@@ -83,4 +85,13 @@ class PolymorphicService implements IPolymorphicService {
public Set<IMonomorphicService> getImplementers() {
return implementers;
}
+
+ @Override
+ public Collection<Method> getImplementations() {
+ Collection<Method> result = Lists.newArrayList();
+ for (IMonomorphicService svc : this.implementers) {
+ result.addAll(svc.getImplementations());
+ }
+ return result;
+ }
}
diff --git a/plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/internal/interpreter/ServiceInterpreter.java b/plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/internal/interpreter/ServiceInterpreter.java
index 5b3f5b97a3..f924d4bf43 100644
--- a/plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/internal/interpreter/ServiceInterpreter.java
+++ b/plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/internal/interpreter/ServiceInterpreter.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2013 THALES GLOBAL SERVICES.
+ * Copyright (c) 2013, 2017 THALES GLOBAL SERVICES.
* 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
@@ -14,6 +14,7 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.text.MessageFormat;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
@@ -26,6 +27,7 @@ import org.eclipse.sirius.common.tools.api.interpreter.EvaluationException;
import org.eclipse.sirius.common.tools.api.interpreter.IInterpreter;
import org.eclipse.sirius.common.tools.api.interpreter.IInterpreterContext;
import org.eclipse.sirius.common.tools.api.interpreter.IInterpreterProvider;
+import org.eclipse.sirius.common.tools.api.interpreter.IJavaAwareInterpreter;
import org.eclipse.sirius.common.tools.api.interpreter.JavaExtensionsManager;
import org.eclipse.sirius.common.tools.api.interpreter.ValidationResult;
import org.eclipse.sirius.ext.base.Option;
@@ -35,12 +37,11 @@ import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
/**
- * A specialized interpreter which can only directly invoke Java service
- * methods.
+ * A specialized interpreter which can only directly invoke Java service methods.
*
* @author pcdavid
*/
-public class ServiceInterpreter extends VariableInterpreter implements org.eclipse.sirius.common.tools.api.interpreter.IInterpreter, IInterpreterProvider {
+public class ServiceInterpreter extends VariableInterpreter implements IJavaAwareInterpreter, org.eclipse.sirius.common.tools.api.interpreter.IInterpreter, IInterpreterProvider {
/** The Service interpreter prefix. */
public static final String PREFIX = "service:"; //$NON-NLS-1$
@@ -59,8 +60,7 @@ public class ServiceInterpreter extends VariableInterpreter implements org.eclip
private final Map<String, PolymorphicService> services = new HashMap<>();
/**
- * Used to retrieve the services instances we create so that we can
- * un-register those.
+ * Used to retrieve the services instances we create so that we can un-register those.
*/
private final Multimap<String, PolymorphicService> qualifiedNameToServices = HashMultimap.create();
@@ -135,7 +135,8 @@ public class ServiceInterpreter extends VariableInterpreter implements org.eclip
if (objectReceiver instanceof EObject) {
receiver = (EObject) objectReceiver;
} else {
- throw new EvaluationException(MessageFormat.format(Messages.ServiceInterpreter_invalidReceiver, serviceCall, objectReceiver != null ? objectReceiver.getClass().getName() : "null")); //$NON-NLS-1$
+ throw new EvaluationException(
+ MessageFormat.format(Messages.ServiceInterpreter_invalidReceiver, serviceCall, objectReceiver != null ? objectReceiver.getClass().getName() : "null")); //$NON-NLS-1$
}
}
int indexOfParenthesis = serviceCall.indexOf("("); //$NON-NLS-1$
@@ -166,6 +167,19 @@ public class ServiceInterpreter extends VariableInterpreter implements org.eclip
}
@Override
+ public Collection<Method> getImplementation(String serviceCall) {
+ javaExtensions.reloadIfNeeded();
+ String serviceName = serviceCall;
+
+ if (services.containsKey(serviceName)) {
+ IService service = services.get(serviceName);
+ return service.getImplementations();
+ }
+
+ return Collections.emptyList();
+ }
+
+ @Override
public void addImport(String dependency) {
javaExtensions.addImport(dependency);
}
@@ -202,8 +216,7 @@ public class ServiceInterpreter extends VariableInterpreter implements org.eclip
}
/**
- * Checks whether a Java method can be used as a service (in the sense of
- * this interpreter).
+ * Checks whether a Java method can be used as a service (in the sense of this interpreter).
*
* @param m
* the method to test.
@@ -261,9 +274,8 @@ public class ServiceInterpreter extends VariableInterpreter implements org.eclip
*/
public Map<String, IService> getServices() {
/*
- * The callback registered to the java extension manager might update
- * this.services depending on what is loaded. We make sure any pending
- * reload is done before returning this list.
+ * The callback registered to the java extension manager might update this.services depending on what is loaded.
+ * We make sure any pending reload is done before returning this list.
*/
javaExtensions.reloadIfNeeded();
diff --git a/plugins/org.eclipse.sirius.diagram/src/org/eclipse/sirius/diagram/Messages.java b/plugins/org.eclipse.sirius.diagram/src/org/eclipse/sirius/diagram/Messages.java
index e1bebc3315..05cbab665c 100644
--- a/plugins/org.eclipse.sirius.diagram/src/org/eclipse/sirius/diagram/Messages.java
+++ b/plugins/org.eclipse.sirius.diagram/src/org/eclipse/sirius/diagram/Messages.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2015 Obeo.
+ * Copyright (c) 2015, 2017 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
diff --git a/plugins/org.eclipse.sirius.editor.diagram/src-gen/org/eclipse/sirius/diagram/editor/properties/sections/description/diagramdescription/DiagramDescriptionPreconditionExpressionPropertySection.java b/plugins/org.eclipse.sirius.editor.diagram/src-gen/org/eclipse/sirius/diagram/editor/properties/sections/description/diagramdescription/DiagramDescriptionPreconditionExpressionPropertySection.java
index cb1c833b3e..042e47804d 100644
--- a/plugins/org.eclipse.sirius.editor.diagram/src-gen/org/eclipse/sirius/diagram/editor/properties/sections/description/diagramdescription/DiagramDescriptionPreconditionExpressionPropertySection.java
+++ b/plugins/org.eclipse.sirius.editor.diagram/src-gen/org/eclipse/sirius/diagram/editor/properties/sections/description/diagramdescription/DiagramDescriptionPreconditionExpressionPropertySection.java
@@ -14,6 +14,7 @@ package org.eclipse.sirius.diagram.editor.properties.sections.description.diagra
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.sirius.diagram.description.DescriptionPackage;
import org.eclipse.sirius.editor.editorPlugin.SiriusEditor;
+import org.eclipse.sirius.editor.internal.navigation.NavigationByKeyListener;
import org.eclipse.sirius.editor.properties.sections.common.AbstractTextWithButtonPropertySection;
import org.eclipse.sirius.editor.tools.api.assist.TypeContentProposalProvider;
import org.eclipse.sirius.editor.tools.internal.presentation.TextWithContentProposalDialog;
@@ -41,6 +42,7 @@ public class DiagramDescriptionPreconditionExpressionPropertySection extends Abs
/**
* @see org.eclipse.ui.views.properties.tabbed.view.ITabbedPropertySection#refresh()
*/
+ @Override
public void refresh() {
super.refresh();
@@ -53,6 +55,7 @@ public class DiagramDescriptionPreconditionExpressionPropertySection extends Abs
/**
* @see org.eclipse.sirius.diagram.editor.properties.sections.AbstractTextWithButtonPropertySection#getDefaultLabelText()
*/
+ @Override
protected String getDefaultLabelText() {
return "PreconditionExpression"; //$NON-NLS-1$
}
@@ -60,6 +63,7 @@ public class DiagramDescriptionPreconditionExpressionPropertySection extends Abs
/**
* @see org.eclipse.sirius.diagram.editor.properties.sections.AbstractTextWithButtonPropertySection#getLabelText()
*/
+ @Override
protected String getLabelText() {
String labelText;
labelText = super.getLabelText() + ":"; //$NON-NLS-1$
@@ -72,6 +76,7 @@ public class DiagramDescriptionPreconditionExpressionPropertySection extends Abs
/**
* @see org.eclipse.sirius.diagram.editor.properties.sections.AbstractTextWithButtonPropertySection#getFeature()
*/
+ @Override
public EAttribute getFeature() {
return DescriptionPackage.eINSTANCE.getDiagramDescription_PreconditionExpression();
}
@@ -79,6 +84,7 @@ public class DiagramDescriptionPreconditionExpressionPropertySection extends Abs
/**
* @see org.eclipse.sirius.diagram.editor.properties.sections.AbstractTextWithButtonPropertySection#getFeatureValue(String)
*/
+ @Override
protected Object getFeatureValue(String newText) {
return newText;
}
@@ -86,6 +92,7 @@ public class DiagramDescriptionPreconditionExpressionPropertySection extends Abs
/**
* @see org.eclipse.sirius.diagram.editor.properties.sections.AbstractTextWithButtonPropertySection#isEqual(String)
*/
+ @Override
protected boolean isEqual(String newText) {
return getFeatureAsText().equals(newText);
}
@@ -93,6 +100,7 @@ public class DiagramDescriptionPreconditionExpressionPropertySection extends Abs
/**
* {@inheritDoc}
*/
+ @Override
public void createControls(Composite parent, TabbedPropertySheetPage tabbedPropertySheetPage) {
super.createControls(parent, tabbedPropertySheetPage);
/*
@@ -111,6 +119,7 @@ public class DiagramDescriptionPreconditionExpressionPropertySection extends Abs
help.setToolTipText(getToolTipText());
TypeContentProposalProvider.bindPluginsCompletionProcessors(this, text);
+ text.addKeyListener(new NavigationByKeyListener(this, text, eObject));
// Start of user code create controls
@@ -121,6 +130,7 @@ public class DiagramDescriptionPreconditionExpressionPropertySection extends Abs
@Override
protected SelectionListener createButtonListener() {
return new SelectionAdapter() {
+ @Override
public void widgetSelected(SelectionEvent e) {
TextWithContentProposalDialog dialog = new TextWithContentProposalDialog(composite.getShell(), DiagramDescriptionPreconditionExpressionPropertySection.this, text.getText());
dialog.open();
@@ -133,6 +143,7 @@ public class DiagramDescriptionPreconditionExpressionPropertySection extends Abs
/**
* {@inheritDoc}
*/
+ @Override
protected String getPropertyDescription() {
return "The precondition is an expression preventing the creation of a diagram.\n If the precondition is set and the expression returns false on the root diagram\n element, then the diagram won't be created.";
}
diff --git a/plugins/org.eclipse.sirius.editor/META-INF/MANIFEST.MF b/plugins/org.eclipse.sirius.editor/META-INF/MANIFEST.MF
index f2050684bd..871dba130d 100644
--- a/plugins/org.eclipse.sirius.editor/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.sirius.editor/META-INF/MANIFEST.MF
@@ -22,11 +22,14 @@ Require-Bundle: org.eclipse.ui.views.properties.tabbed;bundle-version="3.5.300",
org.eclipse.pde.core;bundle-version="3.8.1",
org.eclipse.emf.edit.ui;bundle-version="2.8.0",
org.eclipse.acceleo.ui.interpreter;bundle-version="3.7.1",
- org.eclipse.jdt.core;bundle-version="3.12.3"
+ org.eclipse.jdt.core;bundle-version="3.12.3",
+ org.eclipse.jdt.ui;bundle-version="3.12.2"
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Eclipse-LazyStart: true
-Export-Package: org.eclipse.sirius.editor.assist.content;version="2.0.4",
+Export-Package: org.eclipse.sirius.editor;version="6.0.0",
+ org.eclipse.sirius.editor.assist.content;version="2.0.4",
org.eclipse.sirius.editor.editorPlugin;version="2.1.0",
+ org.eclipse.sirius.editor.internal.navigation;version="6.0.0";x-internal:=true,
org.eclipse.sirius.editor.properties;version="2.0.4",
org.eclipse.sirius.editor.properties.filters.audit.templateinformationsection;version="2.0.4",
org.eclipse.sirius.editor.properties.filters.common;version="2.0.4",
@@ -194,22 +197,22 @@ Export-Package: org.eclipse.sirius.editor.assist.content;version="2.0.4",
org.eclipse.sirius.editor.tools.api.editor;version="2.0.4",
org.eclipse.sirius.editor.tools.api.menu;version="2.1.0",
org.eclipse.sirius.editor.tools.api.perspectives;version="2.0.4",
- org.eclipse.sirius.editor.tools.internal.actions;x-internal:=true;version="2.0.4",
- org.eclipse.sirius.editor.tools.internal.assist;x-internal:=true;version="2.0.4",
- org.eclipse.sirius.editor.tools.internal.color;x-internal:=true;version="2.0.4",
- org.eclipse.sirius.editor.tools.internal.commands;x-internal:=true;version="3.0.0",
- org.eclipse.sirius.editor.tools.internal.editor;x-internal:=true;version="2.0.4",
- org.eclipse.sirius.editor.tools.internal.marker;x-internal:=true;version="2.0.4",
- org.eclipse.sirius.editor.tools.internal.menu;x-internal:=true;version="2.1.0",
- org.eclipse.sirius.editor.tools.internal.menu.child;x-internal:=true;version="2.1.0",
- org.eclipse.sirius.editor.tools.internal.menu.refactoring;x-internal:=true;version="2.1.0",
- org.eclipse.sirius.editor.tools.internal.menu.refactoring.border;x-internal:=true;version="2.0.4",
- org.eclipse.sirius.editor.tools.internal.outline;x-internal:=true;version="3.0.0",
- org.eclipse.sirius.editor.tools.internal.perspectives;x-internal:=true;version="2.0.4",
- org.eclipse.sirius.editor.tools.internal.presentation;x-internal:=true;version="2.1.0",
- org.eclipse.sirius.editor.tools.internal.property.filter;x-internal:=true;version="2.0.4",
- org.eclipse.sirius.editor.tools.internal.property.section;x-internal:=true;version="2.0.4",
- org.eclipse.sirius.editor.tools.internal.wizards;x-internal:=true;version="2.0.4",
+ org.eclipse.sirius.editor.tools.internal.actions;version="2.0.4";x-internal:=true,
+ org.eclipse.sirius.editor.tools.internal.assist;version="2.0.4";x-internal:=true,
+ org.eclipse.sirius.editor.tools.internal.color;version="2.0.4";x-internal:=true,
+ org.eclipse.sirius.editor.tools.internal.commands;version="3.0.0";x-internal:=true,
+ org.eclipse.sirius.editor.tools.internal.editor;version="2.0.4";x-internal:=true,
+ org.eclipse.sirius.editor.tools.internal.marker;version="2.0.4";x-internal:=true,
+ org.eclipse.sirius.editor.tools.internal.menu;version="2.1.0";x-internal:=true,
+ org.eclipse.sirius.editor.tools.internal.menu.child;version="2.1.0";x-internal:=true,
+ org.eclipse.sirius.editor.tools.internal.menu.refactoring;version="2.1.0";x-internal:=true,
+ org.eclipse.sirius.editor.tools.internal.menu.refactoring.border;version="2.0.4";x-internal:=true,
+ org.eclipse.sirius.editor.tools.internal.outline;version="3.0.0";x-internal:=true,
+ org.eclipse.sirius.editor.tools.internal.perspectives;version="2.0.4";x-internal:=true,
+ org.eclipse.sirius.editor.tools.internal.presentation;version="2.1.0";x-internal:=true,
+ org.eclipse.sirius.editor.tools.internal.property.filter;version="2.0.4";x-internal:=true,
+ org.eclipse.sirius.editor.tools.internal.property.section;version="2.0.4";x-internal:=true,
+ org.eclipse.sirius.editor.tools.internal.wizards;version="2.0.4";x-internal:=true,
org.eclipse.sirius.editor.utils;version="2.1.0",
org.eclipse.sirius.editor.wizards;version="2.0.4"
Bundle-ActivationPolicy: lazy
diff --git a/plugins/org.eclipse.sirius.editor/plugin.properties b/plugins/org.eclipse.sirius.editor/plugin.properties
index cfce8dbe52..91fb0c7c43 100644
--- a/plugins/org.eclipse.sirius.editor/plugin.properties
+++ b/plugins/org.eclipse.sirius.editor/plugin.properties
@@ -362,4 +362,7 @@ properties.TextWidgetConditionalStyle = 2000
properties.TextWidgetStyle = 1000
properties.WidgetStyle = 1000
+ServiceNavigator_targetInitialization_error=The service from expression {0} could not be opened with a Java editor. Make sure the service exists and its class is defined in the VSM as Java extension.
+ServiceNavigator_serviceNavigationDialog_title=Service navigation
+ServiceNavigator_serviceNavigationDialog_description=Select the class containing the service to edit.
#End of user code specific keys
diff --git a/plugins/org.eclipse.sirius.editor/src-gen/org/eclipse/sirius/editor/editorPlugin/SiriusEditorPlugin.java b/plugins/org.eclipse.sirius.editor/src-gen/org/eclipse/sirius/editor/editorPlugin/SiriusEditorPlugin.java
index 22346c5a11..1d0d210cc0 100644
--- a/plugins/org.eclipse.sirius.editor/src-gen/org/eclipse/sirius/editor/editorPlugin/SiriusEditorPlugin.java
+++ b/plugins/org.eclipse.sirius.editor/src-gen/org/eclipse/sirius/editor/editorPlugin/SiriusEditorPlugin.java
@@ -1,9 +1,10 @@
/*******************************************************************************
- * Copyright (c) 2007, 2013 THALES GLOBAL SERVICES.
+ * Copyright (c) 2007, 2017 THALES GLOBAL SERVICES.
* 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
*******************************************************************************/
@@ -14,6 +15,7 @@ import java.util.LinkedHashSet;
// Start of user code imports
import java.util.Set;
+import java.util.function.Supplier;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.emf.common.EMFPlugin;
@@ -22,6 +24,9 @@ import org.eclipse.emf.common.util.ResourceLocator;
import org.eclipse.emf.ecore.EPackage.Registry;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.sirius.editor.internal.navigation.INavigatorFromVSMExpression;
+import org.eclipse.sirius.editor.internal.navigation.NavigationFromVSMExpressionRegistry;
+import org.eclipse.sirius.editor.internal.navigation.ServiceNavigator;
import org.eclipse.sirius.editor.tools.api.ecore.WorkspaceEPackageRegistry;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTError;
@@ -79,6 +84,7 @@ public final class SiriusEditorPlugin extends EMFPlugin {
*
* @return the singleton instance.
*/
+ @Override
public ResourceLocator getPluginResourceLocator() {
return plugin;
}
@@ -184,6 +190,7 @@ public final class SiriusEditorPlugin extends EMFPlugin {
* The actual implementation of the Eclipse <b>Plugin</b>.
*/
public static class Implementation extends EclipseUIPlugin {
+
/**
* Creates an instance.
*/
@@ -196,6 +203,11 @@ public final class SiriusEditorPlugin extends EMFPlugin {
}
// Start of user code Implementation specifics
+ /**
+ * The {@link NavigationFromVSMExpressionRegistry} allowing to navigate to JAVA implementation from VSM expressions.
+ */
+ private NavigationFromVSMExpressionRegistry navigationRegistry;
+
@Override
public void start(BundleContext context) throws Exception {
super.start(context);
@@ -208,6 +220,14 @@ public final class SiriusEditorPlugin extends EMFPlugin {
}
}
}
+ navigationRegistry = new NavigationFromVSMExpressionRegistry();
+ Supplier<INavigatorFromVSMExpression> serviceNavigatorSupplier = new Supplier<INavigatorFromVSMExpression>() {
+ @Override
+ public INavigatorFromVSMExpression get() {
+ return new ServiceNavigator();
+ }
+ };
+ navigationRegistry.addNavigator(serviceNavigatorSupplier);
}
@Override
@@ -217,6 +237,16 @@ public final class SiriusEditorPlugin extends EMFPlugin {
workspaceEPackageRegistry.dispose(ResourcesPlugin.getWorkspace());
}
workspaceEPackageRegistry = null;
+ navigationRegistry = null;
+ }
+
+ /**
+ * Returns the {@link NavigationFromVSMExpressionRegistry} allowing to navigate to JAVA implementation from VSM expressions.
+ *
+ * @return the {@link NavigationFromVSMExpressionRegistry} allowing to navigate to JAVA implementation from VSM expressions.
+ */
+ public NavigationFromVSMExpressionRegistry getNavigationRegistry() {
+ return navigationRegistry;
}
/**
diff --git a/plugins/org.eclipse.sirius.editor/src/org/eclipse/sirius/editor/Messages.java b/plugins/org.eclipse.sirius.editor/src/org/eclipse/sirius/editor/Messages.java
new file mode 100644
index 0000000000..7abeb9863a
--- /dev/null
+++ b/plugins/org.eclipse.sirius.editor/src/org/eclipse/sirius/editor/Messages.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2015, 2017 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.sirius.editor;
+
+import org.eclipse.sirius.editor.editorPlugin.SiriusEditorPlugin;
+import org.eclipse.sirius.ext.base.I18N;
+import org.eclipse.sirius.ext.base.I18N.TranslatableMessage;
+
+/**
+ * Helper class to obtains translated strings.
+ *
+ * @author Florian Barbin
+ *
+ */
+public final class Messages {
+ static {
+ I18N.initializeMessages(Messages.class, SiriusEditorPlugin.INSTANCE);
+ }
+
+ // CHECKSTYLE:OFF
+
+ @TranslatableMessage
+ public static String ServiceNavigator_targetInitialization_error;
+
+ @TranslatableMessage
+ public static String ServiceNavigator_serviceNavigationDialog_title;
+
+ @TranslatableMessage
+ public static String ServiceNavigator_serviceNavigationDialog_description;
+
+ // CHECKSTYLE:ON
+ private Messages() {
+ // Prevents instanciation.
+ }
+}
diff --git a/plugins/org.eclipse.sirius.editor/src/org/eclipse/sirius/editor/internal/navigation/INavigatorFromVSMExpression.java b/plugins/org.eclipse.sirius.editor/src/org/eclipse/sirius/editor/internal/navigation/INavigatorFromVSMExpression.java
new file mode 100644
index 0000000000..ccad9b9e58
--- /dev/null
+++ b/plugins/org.eclipse.sirius.editor/src/org/eclipse/sirius/editor/internal/navigation/INavigatorFromVSMExpression.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2017 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.sirius.editor.internal.navigation;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.sirius.common.tools.api.contentassist.ContentContext;
+import org.eclipse.sirius.common.tools.api.interpreter.IInterpreterContext;
+import org.eclipse.sirius.editor.properties.sections.common.AbstractViewpointPropertySection;
+
+/**
+ * An {@link INavigatorFromVSMExpression} allows to navigate to any location from VSM expression content.
+ *
+ * @author <a href="mailto:pierre.guilet@obeo.fr">Pierre Guilet</a>
+ *
+ */
+public interface INavigatorFromVSMExpression {
+ /**
+ * Returns true if this navigator handles navigation from given expression and cursor position.
+ *
+ * @param propertySection
+ * the property section containing the VSM expression.
+ *
+ * @param targetEObject
+ * the {@link EObject} containing the expression from which we want to know if a navigation is available.
+ * @param contentContext
+ * the {@link ContentContext} containing the expression, the cursor position and the
+ * {@link IInterpreterContext}.
+ * @return true if this navigator handles navigation from given expression and cursor position. False otherwise.
+ */
+ boolean doProvideNavigationFor(AbstractViewpointPropertySection propertySection, EObject targetEObject, ContentContext contentContext);
+
+ /**
+ * Triggers the navigation provided by this navigator from given information.
+ *
+ * @param propertySection
+ * the property section containing the VSM expression.
+ *
+ * @param targetEObject
+ * the {@link EObject} containing the expression from which we want to know if a navigation is available.
+ * @param contentContext
+ * the {@link ContentContext} containing the expression, the cursor position and the
+ * {@link IInterpreterContext}.
+ */
+ void triggerNavigation(AbstractViewpointPropertySection propertySection, EObject targetEObject, ContentContext contentContext);
+}
diff --git a/plugins/org.eclipse.sirius.editor/src/org/eclipse/sirius/editor/internal/navigation/NavigationByKeyListener.java b/plugins/org.eclipse.sirius.editor/src/org/eclipse/sirius/editor/internal/navigation/NavigationByKeyListener.java
new file mode 100644
index 0000000000..7d7e77642c
--- /dev/null
+++ b/plugins/org.eclipse.sirius.editor/src/org/eclipse/sirius/editor/internal/navigation/NavigationByKeyListener.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (c) 2017 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.sirius.editor.internal.navigation;
+
+import java.util.Set;
+import java.util.function.Supplier;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.sirius.common.tools.api.contentassist.ContentContext;
+import org.eclipse.sirius.common.tools.api.interpreter.IInterpreterContext;
+import org.eclipse.sirius.editor.editorPlugin.SiriusEditorPlugin;
+import org.eclipse.sirius.editor.properties.sections.common.AbstractViewpointPropertySection;
+import org.eclipse.sirius.tools.api.interpreter.context.SiriusInterpreterContextFactory;
+import org.eclipse.sirius.ui.tools.api.assist.ContentProposalClient;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * Listen to F3 key hit when the cursor has focus on VSM expression and propagate the event to
+ * {@link INavigatorFromVSMExpression} of the current {@link NavigationFromVSMExpressionRegistry}.
+ *
+ * @author <a href="mailto:pierre.guilet@obeo.fr">Pierre Guilet</a>
+ *
+ */
+public class NavigationByKeyListener implements KeyListener {
+
+ /**
+ * The VSM object edited.
+ */
+ private EObject targetObject;
+
+ /**
+ * The text widget inside the property section that contains the expression string.
+ */
+ private Text textWidget;
+
+ /**
+ * The property section displaying the VSM expression.
+ */
+ private AbstractViewpointPropertySection propertySection;
+
+ /**
+ * Constructor.
+ *
+ * @param propertySection
+ * the property section containing the VSM expression.
+ * @param textWidget
+ * the widget containing the VSM expression.
+ * @param targetObject
+ * the {@link EObject} containing the VSM expression.
+ */
+ public NavigationByKeyListener(AbstractViewpointPropertySection propertySection, Text textWidget, EObject targetObject) {
+ this.targetObject = targetObject;
+ this.textWidget = textWidget;
+ this.propertySection = propertySection;
+ }
+
+ @Override
+ public void keyPressed(KeyEvent e) {
+ if (e.keyCode == SWT.F3) {
+ NavigationFromVSMExpressionRegistry navigationRegistry = SiriusEditorPlugin.getPlugin().getNavigationRegistry();
+ Set<Supplier<INavigatorFromVSMExpression>> navigators = navigationRegistry.getNavigators();
+ for (Supplier<INavigatorFromVSMExpression> navigatorSupplier : navigators) {
+ INavigatorFromVSMExpression navigator = navigatorSupplier.get();
+ IInterpreterContext interContext = SiriusInterpreterContextFactory.createInterpreterContext(targetObject, ((ContentProposalClient) propertySection).getFeature());
+ ContentContext contentContext = new ContentContext(textWidget.getText(), textWidget.getCaretPosition(), interContext);
+ if (navigator.doProvideNavigationFor(propertySection, targetObject, contentContext)) {
+ navigator.triggerNavigation(propertySection, targetObject, contentContext);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void keyReleased(KeyEvent e) {
+ // not used
+ }
+
+}
diff --git a/plugins/org.eclipse.sirius.editor/src/org/eclipse/sirius/editor/internal/navigation/NavigationFromVSMExpressionRegistry.java b/plugins/org.eclipse.sirius.editor/src/org/eclipse/sirius/editor/internal/navigation/NavigationFromVSMExpressionRegistry.java
new file mode 100644
index 0000000000..a5dcec22c5
--- /dev/null
+++ b/plugins/org.eclipse.sirius.editor/src/org/eclipse/sirius/editor/internal/navigation/NavigationFromVSMExpressionRegistry.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2017 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.sirius.editor.internal.navigation;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.function.Supplier;
+
+/**
+ * A registry containing {@link INavigatorFromVSMExpression} allowing to navigate from VSM expression content to another location.
+ *
+ * @author <a href="mailto:pierre.guilet@obeo.fr">Pierre Guilet</a>
+ *
+ */
+public class NavigationFromVSMExpressionRegistry {
+
+ /**
+ * All the registered {@link INavigatorFromVSMExpression}.
+ */
+ private Set<Supplier<INavigatorFromVSMExpression>> navigators;
+
+ /**
+ * Constructor.
+ */
+ public NavigationFromVSMExpressionRegistry() {
+ navigators = new HashSet<>();
+ }
+
+ /**
+ * Returns all {@link INavigatorFromVSMExpression} registered.
+ *
+ * @return all {@link INavigatorFromVSMExpression} registered
+ */
+ public Set<Supplier<INavigatorFromVSMExpression>> getNavigators() {
+ return navigators;
+ }
+
+ /**
+ * Add a new {@link INavigatorFromVSMExpression} to the registry.
+ *
+ * @param navigator
+ * the {@link INavigatorFromVSMExpression} to add.
+ */
+ public void addNavigator(Supplier<INavigatorFromVSMExpression> navigator) {
+ this.navigators.add(navigator);
+ }
+
+}
diff --git a/plugins/org.eclipse.sirius.editor/src/org/eclipse/sirius/editor/internal/navigation/ServiceNavigator.java b/plugins/org.eclipse.sirius.editor/src/org/eclipse/sirius/editor/internal/navigation/ServiceNavigator.java
new file mode 100644
index 0000000000..1295a363a9
--- /dev/null
+++ b/plugins/org.eclipse.sirius.editor/src/org/eclipse/sirius/editor/internal/navigation/ServiceNavigator.java
@@ -0,0 +1,289 @@
+/*******************************************************************************
+ * Copyright (c) 2017 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.sirius.editor.internal.navigation;
+
+import java.lang.reflect.Method;
+import java.text.MessageFormat;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.search.IJavaSearchConstants;
+import org.eclipse.jdt.core.search.IJavaSearchScope;
+import org.eclipse.jdt.core.search.SearchEngine;
+import org.eclipse.jdt.internal.ui.dialogs.OpenTypeSelectionDialog;
+import org.eclipse.jdt.ui.JavaUI;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.sirius.common.tools.api.contentassist.ContentContext;
+import org.eclipse.sirius.common.tools.api.interpreter.CompoundInterpreter;
+import org.eclipse.sirius.common.tools.api.interpreter.IInterpreter;
+import org.eclipse.sirius.common.tools.api.interpreter.IInterpreterContext;
+import org.eclipse.sirius.common.tools.api.interpreter.IJavaAwareInterpreter;
+import org.eclipse.sirius.common.tools.internal.interpreter.ServiceInterpreter;
+import org.eclipse.sirius.editor.Messages;
+import org.eclipse.sirius.editor.editorPlugin.SiriusEditorPlugin;
+import org.eclipse.sirius.editor.properties.sections.common.AbstractViewpointPropertySection;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+
+import com.google.common.collect.Lists;
+
+/**
+ * This navigator opens the JAVA editor on all the classes containing the method corresponding to a service call in a
+ * VSM expression. If two classes contains two method with the same name, we focus on the first one after opening.
+ *
+ * @author <a href="mailto:pierre.guilet@obeo.fr">Pierre Guilet</a>
+ *
+ */
+@SuppressWarnings("restriction")
+public class ServiceNavigator implements INavigatorFromVSMExpression {
+ /**
+ * The JAVA class representations containing the service used in a VSM expression and pointing out by the cursor.
+ */
+ private Set<IJavaElement> navigationTargets;
+
+ /**
+ * Initialize data structures.
+ */
+ public ServiceNavigator() {
+ navigationTargets = new HashSet<>();
+ }
+
+ @Override
+ public void triggerNavigation(AbstractViewpointPropertySection propertySection, EObject targetEObject, ContentContext contentContext) {
+ try {
+ if (navigationTargets.isEmpty()) {
+ initializeNavigationTarget(propertySection, targetEObject, contentContext);
+ }
+ if (navigationTargets.size() == 1) {
+ JavaUI.openInEditor(navigationTargets.iterator().next());
+ } else {
+ IJavaSearchScope javaSearchScope = SearchEngine.createJavaSearchScope(navigationTargets.toArray(new IJavaElement[0]));
+ OpenTypeSelectionDialog dialog = new OpenTypeSelectionDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), true, PlatformUI.getWorkbench().getProgressService(),
+ javaSearchScope, IJavaSearchConstants.METHOD);
+ dialog.setTitle(Messages.ServiceNavigator_serviceNavigationDialog_title);
+ dialog.setMessage(Messages.ServiceNavigator_serviceNavigationDialog_description);
+ dialog.setInitialPattern("?");
+ int result = dialog.open();
+ if (result == IDialogConstants.OK_ID) {
+ Object[] types = dialog.getResult();
+ Arrays.stream(types).forEach(type -> {
+ for (IJavaElement navigationTarget : navigationTargets) {
+ if (navigationTarget != null && navigationTarget.getParent().equals(type)) {
+ try {
+ JavaUI.openInEditor(navigationTarget);
+ } catch (PartInitException | JavaModelException e) {
+ SiriusEditorPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, SiriusEditorPlugin.PLUGIN_ID,
+ MessageFormat.format(Messages.ServiceNavigator_targetInitialization_error, contentContext.getContents()), e));
+ }
+ }
+ }
+ });
+ }
+ }
+ } catch (PartInitException | JavaModelException e) {
+ SiriusEditorPlugin.getPlugin().getLog()
+ .log(new Status(IStatus.ERROR, SiriusEditorPlugin.PLUGIN_ID, MessageFormat.format(Messages.ServiceNavigator_targetInitialization_error, contentContext.getContents()), e));
+ }
+ }
+
+ /**
+ * Initialize the {@link IJavaElement} list that are implementations of a same Java service call from a VSM
+ * expression.
+ *
+ * @param propertySection
+ * the property section containing the VSM expression.
+ * @param targetEObject
+ * the VSM object containing the expression from which we execute a navigation.
+ * @param contentContext
+ * the {@link ContentContext} containing the expression, the cursor position and the
+ * {@link IInterpreterContext}.
+ * @throws JavaModelException
+ * if the Java class containing the service cannot be retrieved as an {@link IJavaElement}.
+ */
+ @SuppressWarnings("static-access")
+ private void initializeNavigationTarget(AbstractViewpointPropertySection propertySection, EObject targetEObject, ContentContext contentContext) throws JavaModelException {
+ String vsmExpression = contentContext.getContents();
+ String serviceCallNameWithParenthesis = extractServiceCall(contentContext);
+ if (serviceCallNameWithParenthesis != null) {
+ String serviceCallName = serviceCallNameWithParenthesis;
+ int leftParenthesisIndex = serviceCallName.indexOf("(");
+ int rightParenthesisIndex = serviceCallName.indexOf(")");
+ if (leftParenthesisIndex != -1) {
+ serviceCallName = serviceCallName.substring(0, leftParenthesisIndex);
+ }
+ serviceCallName = serviceCallName.trim();
+ serviceCallName = serviceCallName.replaceAll("self.", "");
+ if (serviceCallName.startsWith(ServiceInterpreter.PREFIX)) {
+ serviceCallName.replaceFirst(ServiceInterpreter.PREFIX, "");
+ }
+ IInterpreter itp = CompoundInterpreter.INSTANCE.getInterpreterForExpression(vsmExpression);
+ if (itp instanceof IJavaAwareInterpreter) {
+ IInterpreterContext interpreterContext = contentContext.getInterpreterContext();
+ Collection<String> imports = interpreterContext.getDependencies();
+ for (String tempImport : imports) {
+ itp.addImport(tempImport);
+ }
+ Resource vsmResource = interpreterContext.getElement().eResource();
+ if (vsmResource != null) {
+ itp.setProperty(IInterpreter.FILES, Lists.newArrayList(vsmResource.getURI().toPlatformString(true)));
+ }
+ Collection<Method> implementations = ((IJavaAwareInterpreter) itp).getImplementation(serviceCallName);
+ Iterator<Method> methodIte = implementations.iterator();
+ while (methodIte.hasNext()) {
+ Method m = methodIte.next();
+ if (m != null) {
+ Resource vsm = targetEObject.eResource();
+ // CHECKSTYLE:OFF
+ if (vsm.getURI().isPlatformResource()) {
+ String projectName = vsm.getURI().segment(1);
+ IProject rawProject = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
+ if (rawProject != null) {
+ IJavaProject javaProject = JavaCore.getJavaCore().create(rawProject);
+ if (javaProject != null) {
+ IType serviceClass = javaProject.findType(m.getDeclaringClass().getName());
+ if (serviceClass != null && serviceClass.exists()) {
+ for (IMethod jm : serviceClass.getMethods()) {
+ boolean onlySelfParameter = leftParenthesisIndex == -1 && rightParenthesisIndex == -1;
+
+ if (jm.getElementName().equals(serviceCallName)) {
+ int methodParametersNumber = jm.getParameters().length;
+ long serviceParametersNumber = getServiceParametersNumber(vsmExpression, leftParenthesisIndex, rightParenthesisIndex);
+ if (!onlySelfParameter && methodParametersNumber == serviceParametersNumber || (onlySelfParameter && methodParametersNumber == 1)) {
+ navigationTargets.add(jm);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ // CHECKSTYLE:ON
+ }
+ }
+ }
+
+ /**
+ * Extract and return the service call part from given context if such call exists.
+ *
+ * @param contentContext
+ * the context from which service call part must be extracted.
+ * @return the service call part from given context if such call exists. Null otherwise.
+ */
+ private String extractServiceCall(ContentContext contentContext) {
+ String serviceName = null;
+ String expression = contentContext.getContents();
+ boolean isServiceInterpreterUsed = expression.startsWith(ServiceInterpreter.PREFIX);
+ int cursorPosition = contentContext.getPosition();
+ if (isServiceInterpreterUsed) {
+ expression = expression.replaceFirst(ServiceInterpreter.PREFIX, "");
+ if (cursorPosition > ServiceInterpreter.PREFIX.length()) {
+ cursorPosition = cursorPosition - ServiceInterpreter.PREFIX.length();
+ }
+ }
+ char[] expressionArray = expression.toCharArray();
+
+ int serviceCallStartPosition = -1;
+ int i = initSearchPosition(expressionArray, cursorPosition);
+ while (i >= 0 && serviceCallStartPosition == -1) {
+ char tempChar = expressionArray[i];
+ if (tempChar == '.' || tempChar == ':' || (tempChar == ' ')) {
+ serviceCallStartPosition = i + 1;
+ }
+ i--;
+ }
+ if (i == -1 && isServiceInterpreterUsed) {
+ serviceCallStartPosition = 0;
+ }
+ int serviceCallEndPosition = -1;
+ int j = initSearchPosition(expressionArray, cursorPosition);
+ while (j < expressionArray.length && serviceCallEndPosition == -1) {
+ char tempChar = expressionArray[j];
+ if (tempChar == ')') {
+ serviceCallEndPosition = j + 1;
+ }
+ j++;
+ }
+ if (serviceCallStartPosition != -1 && serviceCallEndPosition != -1) {
+ serviceName = expression.substring(serviceCallStartPosition, serviceCallEndPosition);
+ } else if (serviceCallEndPosition != -1) {
+ serviceCallStartPosition = expression.indexOf(".");
+ if (serviceCallStartPosition != -1 && serviceCallStartPosition < serviceCallEndPosition) {
+ serviceName = expression.substring(serviceCallStartPosition + 1, serviceCallEndPosition);
+ }
+ }
+ return serviceName;
+ }
+
+ /**
+ * Return the search position from cursor position. If the cursor position is out of range of the expression array
+ * length, then we use as start search position the closer index. Otherwise it is the cursor position.
+ *
+ * @param expressionArray
+ * the expression array from which we compute a starting search position.
+ * @param cursorPosition
+ * the cursor position from which we compute a starting search position.
+ * @return the search position from cursor position.
+ */
+ private int initSearchPosition(char[] expressionArray, int cursorPosition) {
+ int searchPosition = cursorPosition;
+ if (cursorPosition == -1) {
+ searchPosition = 0;
+ } else if (expressionArray.length == cursorPosition) {
+ searchPosition = expressionArray.length - 1;
+ }
+ return searchPosition;
+ }
+
+ private long getServiceParametersNumber(String vsmExpression, int leftParenthesisIndex, int rightParenthesisIndex) {
+ long serviceParametersNumber;
+ if (rightParenthesisIndex == leftParenthesisIndex + 1) {
+ serviceParametersNumber = 1;
+ } else {
+ long parameterSeparatorNumber = vsmExpression.chars().filter(ch -> ch == ',').count();
+ if (parameterSeparatorNumber == 0) {
+ serviceParametersNumber = 2;
+ } else {
+ serviceParametersNumber = parameterSeparatorNumber + 2;
+ }
+ }
+ return serviceParametersNumber;
+ }
+
+ @Override
+ public boolean doProvideNavigationFor(AbstractViewpointPropertySection propertySection, EObject targetEObject, ContentContext contentContext) {
+ try {
+ initializeNavigationTarget(propertySection, targetEObject, contentContext);
+ } catch (JavaModelException e) {
+ SiriusEditorPlugin.getPlugin().getLog()
+ .log(new Status(IStatus.ERROR, SiriusEditorPlugin.PLUGIN_ID, MessageFormat.format(Messages.ServiceNavigator_targetInitialization_error, contentContext.getContents()), e));
+ }
+ return !navigationTargets.isEmpty();
+ }
+
+}
diff --git a/plugins/org.eclipse.sirius.tests.swtbot/data/unit/editor/vsm/completion/BasicService2.java b/plugins/org.eclipse.sirius.tests.swtbot/data/unit/editor/vsm/completion/BasicService2.java
new file mode 100644
index 0000000000..5d25694b80
--- /dev/null
+++ b/plugins/org.eclipse.sirius.tests.swtbot/data/unit/editor/vsm/completion/BasicService2.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2018 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.sirius.test.design;
+
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage;
+
+public class BasicService2 {
+ public String sampleService(EObject ctx) {
+ return "sampleService";
+ }
+
+ public String sampleService(EObject ctx, EObject ctx2) {
+ return "sampleService2";
+ }
+}
diff --git a/plugins/org.eclipse.sirius.tests.swtbot/data/unit/editor/vsm/completion/MANIFEST.MF b/plugins/org.eclipse.sirius.tests.swtbot/data/unit/editor/vsm/completion/MANIFEST.MF
index 98524feca8..3f00a637f5 100644
--- a/plugins/org.eclipse.sirius.tests.swtbot/data/unit/editor/vsm/completion/MANIFEST.MF
+++ b/plugins/org.eclipse.sirius.tests.swtbot/data/unit/editor/vsm/completion/MANIFEST.MF
@@ -7,7 +7,7 @@ Bundle-Activator: org.eclipse.sirius.test.design.Activator
Require-Bundle: org.eclipse.ui,
org.eclipse.core.runtime,
org.eclipse.sirius,
- org.eclipse.sirius.common.acceleo.mtl
+ org.eclipse.sirius.common.acceleo.mtl,
+ org.eclipse.sirius.sample.interactions
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
-Import-Package: org.eclipse.sirius.sample.interactions
diff --git a/plugins/org.eclipse.sirius.tests.swtbot/data/unit/editor/vsm/completion/ServicesWithDependencies.java b/plugins/org.eclipse.sirius.tests.swtbot/data/unit/editor/vsm/completion/ServicesWithDependencies.java
index 8158a33033..dca6894dd2 100644
--- a/plugins/org.eclipse.sirius.tests.swtbot/data/unit/editor/vsm/completion/ServicesWithDependencies.java
+++ b/plugins/org.eclipse.sirius.tests.swtbot/data/unit/editor/vsm/completion/ServicesWithDependencies.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2016 Obeo.
+ * Copyright (c) 2016, 2017 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
@@ -34,5 +34,4 @@ public class ServicesWithDependencies {
createCallMessage.setName("testInteractionsWithServiceServiceCallOk");
return createCallMessage;
}
-
}
diff --git a/plugins/org.eclipse.sirius.tests.swtbot/data/unit/editor/vsm/completion/test.odesign b/plugins/org.eclipse.sirius.tests.swtbot/data/unit/editor/vsm/completion/test.odesign
index 8aa2f0cff1..6c988976cc 100644
--- a/plugins/org.eclipse.sirius.tests.swtbot/data/unit/editor/vsm/completion/test.odesign
+++ b/plugins/org.eclipse.sirius.tests.swtbot/data/unit/editor/vsm/completion/test.odesign
@@ -7,6 +7,7 @@
</defaultLayer>
</ownedRepresentations>
<ownedJavaExtensions qualifiedClassName="org.eclipse.sirius.test.design.BasicService"/>
+ <ownedJavaExtensions qualifiedClassName="org.eclipse.sirius.test.design.BasicService2"/>
<ownedJavaExtensions qualifiedClassName="org::eclipse::sirius::test::design::AcceleoMtlInterpreterTestModule"/>
<ownedJavaExtensions qualifiedClassName="org.eclipse.sirius.test.design.ServicesWithDependencies"/>
</ownedViewpoints>
diff --git a/plugins/org.eclipse.sirius.tests.swtbot/src/org/eclipse/sirius/tests/swtbot/editor/vsm/ServiceNavigationTest.java b/plugins/org.eclipse.sirius.tests.swtbot/src/org/eclipse/sirius/tests/swtbot/editor/vsm/ServiceNavigationTest.java
new file mode 100644
index 0000000000..17f868b1d4
--- /dev/null
+++ b/plugins/org.eclipse.sirius.tests.swtbot/src/org/eclipse/sirius/tests/swtbot/editor/vsm/ServiceNavigationTest.java
@@ -0,0 +1,519 @@
+/*******************************************************************************
+ * Copyright (c) 2018 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.sirius.tests.swtbot.editor.vsm;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.commands.common.CommandException;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspaceDescription;
+import org.eclipse.core.resources.IncrementalProjectBuilder;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.sirius.tests.support.api.EclipseTestsSupportHelper;
+import org.eclipse.sirius.tests.support.api.ICondition;
+import org.eclipse.sirius.tests.support.api.TestsUtil;
+import org.eclipse.sirius.tests.swtbot.Activator;
+import org.eclipse.sirius.tests.swtbot.support.api.editor.SWTBotSiriusHelper;
+import org.eclipse.sirius.ui.tools.internal.views.modelexplorer.ModelExplorerView;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotEditor;
+import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView;
+import org.eclipse.swtbot.swt.finder.SWTBot;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotTable;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotTableItem;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotText;
+import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem;
+import org.eclipse.ui.IEditorReference;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Test the service implementation navigation from VSM service call in
+ * interpreted expressions.
+ *
+ * @author <a href="mailto:pierre.guilet@obeo.fr">Pierre Guilet</a>
+ *
+ *
+ */
+public class ServiceNavigationTest extends AbstractContentAssistTest {
+
+ private final class JavaEditorOpenedCondition implements ICondition {
+ private boolean javaEditorOpened;
+
+ public JavaEditorOpenedCondition(boolean javaEditorOpened) {
+ this.javaEditorOpened = javaEditorOpened;
+ }
+
+ @Override
+ public boolean test() throws Exception {
+ SWTBotEditor activeEditor = bot.activeEditor();
+ IEditorReference reference = activeEditor.getReference();
+ return (javaEditorOpened && "org.eclipse.jdt.ui.CompilationUnitEditor".equals(reference.getId()))
+ || (!javaEditorOpened && !"org.eclipse.jdt.ui.CompilationUnitEditor".equals(reference.getId()));
+ }
+
+ @Override
+ public String getFailureMessage() {
+ return "Java editor has not been opened";
+ }
+ }
+
+ private static final String BASIC_SERVICE_JAVA = "BasicService.java";
+
+ private static final String BASIC_SERVICE_JAVA2 = "BasicService2.java";
+
+ private static final String PATH = "data/unit/editor/vsm/completion/";
+
+ private static final String VSM_PROJECT_NAME = "org.eclipse.sirius.test.design";
+
+ private static final String VSM = "test.odesign";
+
+ /**
+ *
+ */
+ private static final String TESTED_ODESIGN_NAME = "new" + VSM;
+
+ private SWTBotView propertiesBot;
+
+ @Override
+ protected void onSetUpBeforeClosingWelcomePage() throws Exception {
+ super.onSetUpBeforeClosingWelcomePage();
+ final IWorkspaceDescription description = ResourcesPlugin.getWorkspace().getDescription();
+ description.setAutoBuilding(false);
+ ResourcesPlugin.getWorkspace().setDescription(description);
+ // Wait the end of the current build and/or refresh.
+ waitJobsBuildOrRefresh();
+ }
+
+ @Override
+ protected void onSetUpAfterOpeningDesignerPerspective() throws Exception {
+ setErrorCatchActive(false);
+
+ // Load the target platform, if not already done, to allow compilation
+ // of the java services
+ TestsUtil.setTargetPlatform();
+ }
+
+ /**
+ * Initialize the context by copying new resources and waiting all build
+ * process.
+ *
+ * @exception InterruptedException
+ * if this thread is interrupted while waiting
+ * @exception OperationCanceledException
+ * if the progress monitor is canceled while waiting
+ * @exception CoreException
+ * In case of problem during setting workspace description to
+ * disable auto build.
+ * @throws CommandException
+ */
+ private void initContext(List<String> nodes) throws InterruptedException, OperationCanceledException, CoreException, CommandException {
+ designerPerspectives.openSiriusPerspective();
+
+ // Copy the sample ecore model for type completion
+ copyFileToTestProject(Activator.PLUGIN_ID, PATH, "test.ecore");
+
+ // Create VSM Project.
+ IProject viewpointSpecificationProject = ViewpointSpecificationProjectCreationTest.createViewpointSpecificationProject(bot, VSM_PROJECT_NAME, VSM);
+ // Wait the end of the current build and/or refresh.
+ viewpointSpecificationProject.refreshLocal(IProject.DEPTH_INFINITE, new NullProgressMonitor());
+ waitJobsBuildOrRefresh();
+
+ // Define the imports in the VSM and add Ecore dependency
+ String MANIFEST_MF = "MANIFEST.MF";
+ EclipseTestsSupportHelper.INSTANCE.copyFile(Activator.PLUGIN_ID, PATH + MANIFEST_MF, VSM_PROJECT_NAME + "/META-INF/" + MANIFEST_MF);
+ EclipseTestsSupportHelper.INSTANCE.copyFile(Activator.PLUGIN_ID, PATH + VSM, VSM_PROJECT_NAME + "/description/" + TESTED_ODESIGN_NAME);
+
+ // We open the new design used by the test. We avoid replacing the
+ // already existing one because sometime the refresh is not correctly
+ // done and tests can fail.
+ SWTBotView modelExplorerView = bot.viewById(ModelExplorerView.ID);
+ modelExplorerView.setFocus();
+ SWTBotTreeItem projectNode = modelExplorerView.bot().tree().expandNode("org.eclipse.sirius.test.design");
+ SWTBotTreeItem descriptionNode = projectNode.expandNode("description");
+ SWTBotTreeItem designNode = descriptionNode.getNode(TESTED_ODESIGN_NAME);
+ designNode.doubleClick();
+
+ waitJobsBuildOrRefresh();
+
+ // Copy the Java Service file
+ char pathSeparator = '/';
+ String package_name = VSM_PROJECT_NAME;
+ package_name = package_name.replace('.', pathSeparator);
+ String dest = VSM_PROJECT_NAME + "/src/" + package_name + pathSeparator;
+ EclipseTestsSupportHelper.INSTANCE.copyFile(Activator.PLUGIN_ID, PATH + BASIC_SERVICE_JAVA, dest + BASIC_SERVICE_JAVA);
+ EclipseTestsSupportHelper.INSTANCE.copyFile(Activator.PLUGIN_ID, PATH + BASIC_SERVICE_JAVA2, dest + BASIC_SERVICE_JAVA2);
+
+ waitJobsBuildOrRefresh();
+
+ // Launch a manual build and wait the end of the workspace build
+ ResourcesPlugin.getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, new NullProgressMonitor());
+ waitJobsBuildOrRefresh();
+
+ bot.activeEditor().setFocus();
+ SWTBotTreeItem lastExpandNode = bot.activeEditor().bot().tree().expandNode("platform:/resource/" + VSM_PROJECT_NAME + "/description/" + TESTED_ODESIGN_NAME);
+ for (String node : nodes) {
+ lastExpandNode = lastExpandNode.expandNode(node);
+ }
+ lastExpandNode.select();
+
+ propertiesBot = bot.viewByTitle("Properties");
+ propertiesBot.setFocus();
+ SWTBotSiriusHelper.selectPropertyTabItem("General");
+ }
+
+ /**
+ * @param string
+ */
+ private void expandNode(String string) {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ * @param string
+ */
+ private void getNode(String string) {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ * There is problem on linux with this test so we are waiting build or
+ * refresh jobs by joining them.
+ */
+ private void waitJobsBuildOrRefresh() throws InterruptedException, OperationCanceledException {
+ Job.getJobManager().join(ResourcesPlugin.FAMILY_MANUAL_BUILD, new NullProgressMonitor());
+ Job.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_BUILD, new NullProgressMonitor());
+ Job.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_REFRESH, new NullProgressMonitor());
+ Job.getJobManager().join(ResourcesPlugin.FAMILY_MANUAL_REFRESH, new NullProgressMonitor());
+ Job.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_BUILD, new NullProgressMonitor());
+ }
+
+ /**
+ * Check that Java service navigation from F3 key and a VSM expression works
+ * in the following context:
+ * <ul>
+ * <li>The expression calls the service interpreter.</li>
+ * <li>The cursor is at the starting position</li>
+ * <li>The service called is present in two different classes</li>
+ * <li>The service from which the navigation is done is the first one in the
+ * wizard.</li>
+ * </ul>
+ *
+ * @exception Exception
+ * if a problem occurs.
+ */
+ public void testServiceNavigationWithSameServiceInDifferentClasses() throws Exception {
+ List<String> expectedItemLabels = new ArrayList<>();
+ expectedItemLabels.add("BasicService - org.eclipse.sirius.test.design");
+ expectedItemLabels.add("BasicService2");
+ testNavigation("service:sampleService()", 2, expectedItemLabels, 0, 0);
+ }
+
+ /**
+ * Check that Java service navigation from F3 key and a VSM expression works
+ * in the following context:
+ * <ul>
+ * <li>The expression calls the service interpreter.</li>
+ * <li>The cursor is at the starting position</li>
+ * <li>The service called is present in two different classes</li>
+ * <li>The service from which the navigation is done is the second one in
+ * the wizard.</li>
+ * </ul>
+ *
+ * @exception Exception
+ * if a problem occurs.
+ */
+ public void testServiceNavigationWithSameServiceInDifferentClasses2() throws Exception {
+ List<String> expectedItemLabels = new ArrayList<>();
+ expectedItemLabels.add("BasicService - org.eclipse.sirius.test.design");
+ expectedItemLabels.add("BasicService2");
+ testNavigation("service:sampleService()", 2, expectedItemLabels, 1, 0);
+ }
+
+ /**
+ * Check that Java service navigation from F3 key and a VSM expression works
+ * in the following context:
+ * <ul>
+ * <li>The expression calls the service interpreter.</li>
+ * <li>The cursor is at the 12 index position</li>
+ * <li>The service called is present in one class</li>
+ * <li>The service is automatically opened in JAVA editor.</li>
+ * </ul>
+ *
+ * @exception Exception
+ * if a problem occurs.
+ */
+ public void testSingleServiceNavigation() throws Exception {
+ testNavigation("service:sampleService(self)", 1, null, -1, 12);
+ }
+
+ /**
+ * Check that Java service navigation from F3 key and a VSM expression works
+ * in the following context:
+ * <ul>
+ * <li>The expression calls the AQL interpreter.</li>
+ * <li>The cursor is at the starting position</li>
+ * <li>No service should be detected at the cursor position. So nothing
+ * should be done.</li>
+ * </ul>
+ *
+ * @exception Exception
+ * if a problem occurs.
+ */
+ public void testServiceNavigationWithAqlInterpreterFirstPosition() throws Exception {
+ testNavigation("aql:self.sampleService() and self.sampleService(self)->", 0, null, -1, 0);
+ }
+
+ /**
+ * Check that Java service navigation from F3 key and a VSM expression works
+ * in the following context:
+ * <ul>
+ * <li>The expression calls the AQL interpreter.</li>
+ * <li>The cursor is at the last position</li>
+ * <li>No service should be detected at the cursor position. So nothing
+ * should be done.</li>
+ * </ul>
+ *
+ * @exception Exception
+ * if a problem occurs.
+ */
+ public void testServiceNavigationWithAqlInterpreterLastPosition() throws Exception {
+ testNavigation("aql:self.sampleService() and self.sampleService(self)->", 0, null, -1, 55);
+ }
+
+ /**
+ * Check that Java service navigation from F3 key and a VSM expression works
+ * in the following context:
+ * <ul>
+ * <li>The expression calls the AQL interpreter.</li>
+ * <li>The cursor is at the 27 index position</li>
+ * <li>No service should be detected at the cursor position. So nothing
+ * should be done.</li>
+ * </ul>
+ *
+ * @exception Exception
+ * if a problem occurs.
+ */
+ public void testServiceNavigationWithAqlInterpreterMiddlePosition() throws Exception {
+ testNavigation("aql:self.sampleService() and self.sampleService(self)->", 0, null, -1, 27);
+ }
+
+ /**
+ * Check that Java service navigation from F3 key and a VSM expression works
+ * in the following context:
+ * <ul>
+ * <li>The expression calls the AQL interpreter.</li>
+ * <li>The cursor is at the 13 index position</li>
+ * <li>The service call at cursor position is present in two different
+ * classes</li>
+ * <li>The service from which the navigation is done is the second one in
+ * the wizard.</li>
+ * </ul>
+ *
+ * @exception Exception
+ * if a problem occurs.
+ */
+ public void testDualServiceNavigationWithAqlInterpreter() throws Exception {
+ List<String> expectedItemLabels = new ArrayList<>();
+ expectedItemLabels.add("BasicService - org.eclipse.sirius.test.design");
+ expectedItemLabels.add("BasicService2");
+ testNavigation("aql:self.sampleService() and self.sampleService(self)->", 2, expectedItemLabels, 1, 13);
+ }
+
+ /**
+ * Check that Java service navigation from F3 key and a VSM expression works
+ * in the following context:
+ * <ul>
+ * <li>The expression calls the AQL interpreter.</li>
+ * <li>The cursor is at the 9 index position</li>
+ * <li>The service call at cursor position is present in two different
+ * classes</li>
+ * <li>The service from which the navigation is done is the second one in
+ * the wizard.</li>
+ * </ul>
+ *
+ * @exception Exception
+ * if a problem occurs.
+ */
+ public void testDualServiceNavigationWithAqlInterpreter2() throws Exception {
+ List<String> expectedItemLabels = new ArrayList<>();
+ expectedItemLabels.add("BasicService - org.eclipse.sirius.test.design");
+ expectedItemLabels.add("BasicService2");
+ testNavigation("aql:self.sampleService() and self.sampleService(self)->", 2, expectedItemLabels, 1, 9);
+ }
+
+ /**
+ * Check that Java service navigation from F3 key and a VSM expression works
+ * in the following context:
+ * <ul>
+ * <li>The expression calls the AQL interpreter.</li>
+ * <li>The cursor is at the 23 index position</li>
+ * <li>The service call at cursor position is present in two different
+ * classes</li>
+ * <li>The service from which the navigation is done is the second one in
+ * the wizard.</li>
+ * </ul>
+ *
+ * @exception Exception
+ * if a problem occurs.
+ */
+ public void testDualServiceNavigationWithAqlInterpreter3() throws Exception {
+ List<String> expectedItemLabels = new ArrayList<>();
+ expectedItemLabels.add("BasicService - org.eclipse.sirius.test.design");
+ expectedItemLabels.add("BasicService2");
+ testNavigation("aql:self.sampleService() and self.sampleService(self)->", 2, expectedItemLabels, 1, 23);
+ }
+
+ /**
+ * Check that Java service navigation from F3 key and a VSM expression works
+ * in the following context:
+ * <ul>
+ * <li>The expression calls the AQL interpreter.</li>
+ * <li>The cursor is at the 38 index position</li>
+ * <li>The service call at cursor position is present in one class</li>
+ * <li>The service is automatically opened in JAVA editor.</li>
+ * </ul>
+ *
+ * @exception Exception
+ * if a problem occurs.
+ */
+ public void testSingleServiceNavigationWithAqlInterpreter() throws Exception {
+ testNavigation("aql:self.sampleService() and self.sampleService(self)->", 1, null, -1, 38);
+ }
+
+ /**
+ * Tests that Java service navigation from VSM expression is the expected
+ * one.
+ *
+ * @param vsmExpression
+ * the VSM expression used to test Java service navigation.
+ * @param matchingJavaServiceNumber
+ * the number of Java service that should be proposed for
+ * navigation.
+ * @param expectedItemLabels
+ * The Java service item's labels in their wizard's order.
+ * @param javaServiceIndex
+ * the index of the Java service item to open with Java editor
+ * when in Java service navigation wizard.
+ * @param cursorPosition
+ * the cursor position in the VSM expression before triggering
+ * navigation with F3 key.
+ *
+ * @throws InterruptedException
+ * if a problem occurs.
+ * @throws CoreException
+ * if a problem occurs.
+ * @throws CommandException
+ * if a problem occurs.
+ */
+ protected void testNavigation(String vsmExpression, int matchingJavaServiceNumber, List<String> expectedItemLabels, int javaServiceIndex, int cursorPosition)
+ throws InterruptedException, CoreException, CommandException {
+ if (TestsUtil.shouldSkipUnreliableTests()) {
+ return;
+ }
+
+ initContext(Lists.newArrayList("test", "VP", "Diag"));
+
+ // Init the Precondition Expression
+ SWTBotText precondition = propertiesBot.bot().text(3);
+ precondition.setFocus();
+ precondition.setText(vsmExpression);
+ TestsUtil.waitUntil(new ICondition() {
+
+ @Override
+ public boolean test() throws Exception {
+ return vsmExpression.equals(precondition.getText());
+ }
+
+ @Override
+ public String getFailureMessage() {
+ return null;
+ }
+
+ });
+ Display.getDefault().asyncExec(() -> {
+ // bot.pressShortcut does not work
+ precondition.widget.setSelection(cursorPosition);
+ Event event = new Event();
+ event.keyCode = SWT.F3;
+ precondition.widget.notifyListeners(SWT.KeyDown, event);
+ });
+ if (matchingJavaServiceNumber > 0) {
+ if (matchingJavaServiceNumber > 1) {
+ TestsUtil.waitUntil(new ICondition() {
+
+ @Override
+ public boolean test() throws Exception {
+
+ SWTBotShell shell = null;
+ try {
+ shell = bot.shell("Service navigation");
+ } catch (Exception e) {
+ // do nothing
+ }
+ return shell != null;
+ }
+
+ @Override
+ public String getFailureMessage() {
+ return "Service navigation wizard did not open.";
+ }
+ }, 10000);
+ SWTBotShell shell = bot.shell("Service navigation");
+ SWTBot wizardBot = shell.bot();
+ SWTBotTable table = wizardBot.table(0);
+ TestsUtil.waitUntil(new ICondition() {
+
+ @Override
+ public boolean test() throws Exception {
+ return table.rowCount() > 0;
+ }
+
+ @Override
+ public String getFailureMessage() {
+ return "The type navigation wizard was not filled with target Java services.";
+ }
+ }, 15000);
+
+ assertEquals("Wrong number of matching Java service implementations.", matchingJavaServiceNumber, table.rowCount());
+
+ if (expectedItemLabels != null) {
+ for (int i = 0; i < expectedItemLabels.size(); i++) {
+ SWTBotTableItem tableItem = table.getTableItem(i);
+ assertEquals("Unknown service: " + tableItem.getText(), expectedItemLabels.get(i), tableItem.getText());
+
+ }
+ }
+ if (javaServiceIndex >= 0) {
+ table.select(javaServiceIndex);
+ wizardBot.button("OK").click();
+ }
+ }
+ TestsUtil.waitUntil(new JavaEditorOpenedCondition(true));
+
+ }
+
+ if (matchingJavaServiceNumber == 0) {
+ TestsUtil.waitUntil(new JavaEditorOpenedCondition(false));
+ }
+
+ }
+}
diff --git a/plugins/org.eclipse.sirius.tests.swtbot/src/org/eclipse/sirius/tests/swtbot/suite/AllTestSuite.java b/plugins/org.eclipse.sirius.tests.swtbot/src/org/eclipse/sirius/tests/swtbot/suite/AllTestSuite.java
index ddf211fb91..9070e6fb1f 100644
--- a/plugins/org.eclipse.sirius.tests.swtbot/src/org/eclipse/sirius/tests/swtbot/suite/AllTestSuite.java
+++ b/plugins/org.eclipse.sirius.tests.swtbot/src/org/eclipse/sirius/tests/swtbot/suite/AllTestSuite.java
@@ -36,6 +36,7 @@ import org.eclipse.sirius.tests.swtbot.editor.vsm.MetamodelPropertyTabTests;
import org.eclipse.sirius.tests.swtbot.editor.vsm.MigrationOnVsmEditorReloadTest;
import org.eclipse.sirius.tests.swtbot.editor.vsm.OpeningContextTest;
import org.eclipse.sirius.tests.swtbot.editor.vsm.ResizeKindEditorTest;
+import org.eclipse.sirius.tests.swtbot.editor.vsm.ServiceNavigationTest;
import org.eclipse.sirius.tests.swtbot.editor.vsm.VSMEditorPropertiesTest;
import org.eclipse.sirius.tests.swtbot.editor.vsm.VSMFieldTest;
import org.eclipse.sirius.tests.swtbot.editor.vsm.ValidationEmptyNameTest;
@@ -125,6 +126,7 @@ public class AllTestSuite extends TestCase {
*/
public static void addGerritPart1(TestSuite suite) {
suite.addTest(new JUnit4TestAdapter(SWTBotBundlesReport.class));
+ suite.addTestSuite(ServiceNavigationTest.class);
suite.addTestSuite(ContentAssistTest.class);
suite.addTestSuite(FeatureAssistTest.class);
suite.addTestSuite(ResizeKindEditorTest.class);

Back to the top