Switched declaration/definition resolution to IService and the resolver.

Change-Id: I301a50209df0b1204de0545c26a65dc03fad44e1
diff --git a/plugins/org.eclipse.acceleo.aql.ls/src/org/eclipse/acceleo/aql/ls/services/textdocument/AcceleoLocationLinkResolver.java b/plugins/org.eclipse.acceleo.aql.ls/src/org/eclipse/acceleo/aql/ls/services/textdocument/AcceleoLocationLinkResolver.java
index a32f651..7630b72 100644
--- a/plugins/org.eclipse.acceleo.aql.ls/src/org/eclipse/acceleo/aql/ls/services/textdocument/AcceleoLocationLinkResolver.java
+++ b/plugins/org.eclipse.acceleo.aql.ls/src/org/eclipse/acceleo/aql/ls/services/textdocument/AcceleoLocationLinkResolver.java
@@ -27,7 +27,9 @@
 import org.eclipse.acceleo.aql.parser.AcceleoAstUtils;
 import org.eclipse.acceleo.aql.parser.AcceleoParser;
 import org.eclipse.acceleo.query.ast.VariableDeclaration;
+import org.eclipse.acceleo.query.runtime.IService;
 import org.eclipse.acceleo.query.runtime.namespace.IQualifiedNameResolver;
+import org.eclipse.acceleo.query.runtime.namespace.ISourceLocation;
 import org.eclipse.emf.common.util.URI;
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.ecore.EOperation;
@@ -256,6 +258,9 @@
 			// Still, support it just in case...
 			locationLink = createLocationLinkFromRangeToAqlDestination(originSelectionRange,
 					(EObject)destination);
+		} else if (destination instanceof IService<?>) {
+			locationLink = createLocationLinkFromRangeToServiceDestination(linkOrigin, originSelectionRange,
+					(IService<?>)destination);
 		} else if (destination instanceof java.lang.Class<?>) {
 			locationLink = createLocationLinkFromRangeToJavaClassDestination(linkOrigin, originSelectionRange,
 					(Class<?>)destination);
@@ -398,6 +403,50 @@
 	}
 
 	/**
+	 * Creates a {@link LocationLink} from the given {@link Range} to the given {@link IService} destination.
+	 * 
+	 * @param linkOrigin
+	 *            the (non-{@code null}) origin {@link EObject} of the link.
+	 * @param originSelectionRange
+	 *            the (non-{@code null}) origin selection {@link Range}.
+	 * @param destinationService
+	 *            the (non-{@code null}) destination {@link IService}.
+	 * @return the {@link LocationLink} from {@code originSelectionRange} to {@code destinationService}.
+	 */
+	private LocationLink createLocationLinkFromRangeToServiceDestination(EObject linkOrigin,
+			Range originSelectionRange, IService<?> destinationService) {
+		ASTNode acceleoAstNode = getAcceleoAstNodeContainingAqlElement(linkOrigin);
+		AcceleoTextDocument acceleoTextDocument = this.getAcceleoTextDocumentContaining(acceleoAstNode);
+
+		final IQualifiedNameResolver resolver = acceleoTextDocument.getQueryEnvironment().getLookupEngine()
+				.getResolver();
+
+		final ISourceLocation sourceLocation = resolver.getSourceLocation(destinationService);
+		final LocationLink locationLink;
+		if (sourceLocation != null) {
+			Position targetRangeStart = new Position(sourceLocation.getRange().getStart().getLine(),
+					sourceLocation.getRange().getStart().getColumn());
+			Position targetRangeEnd = new Position(sourceLocation.getRange().getEnd().getLine(),
+					sourceLocation.getRange().getEnd().getColumn());
+			Range targetRange = new Range(targetRangeStart, targetRangeEnd);
+
+			Position targetSelectionRangeStart = new Position(sourceLocation.getIdentifierRange().getStart()
+					.getLine(), sourceLocation.getIdentifierRange().getStart().getColumn());
+			Position targetSelectionRangeEnd = new Position(sourceLocation.getIdentifierRange().getEnd()
+					.getLine(), sourceLocation.getIdentifierRange().getEnd().getColumn());
+			Range targetSelectionRange = new Range(targetSelectionRangeStart, targetSelectionRangeEnd);
+
+			locationLink = new LocationLink(sourceLocation.getSourceURL().toString(), targetRange,
+					targetSelectionRange, originSelectionRange);
+		} else {
+			locationLink = createLocationLinkFromRangeToAnyDestination(linkOrigin, originSelectionRange,
+					destinationService.getOrigin());
+		}
+
+		return locationLink;
+	}
+
+	/**
 	 * Creates a {@link LocationLink} from the given {@link Range} to the given Java {@link Method}
 	 * destination.
 	 * 
diff --git a/plugins/org.eclipse.acceleo.aql/src/org/eclipse/acceleo/aql/location/aql/AqlDefinitionLocator.java b/plugins/org.eclipse.acceleo.aql/src/org/eclipse/acceleo/aql/location/aql/AqlDefinitionLocator.java
index 93d7194..e45ffb8 100644
--- a/plugins/org.eclipse.acceleo.aql/src/org/eclipse/acceleo/aql/location/aql/AqlDefinitionLocator.java
+++ b/plugins/org.eclipse.acceleo.aql/src/org/eclipse/acceleo/aql/location/aql/AqlDefinitionLocator.java
@@ -202,8 +202,8 @@
 			final Set<IService<?>> candidateServices = servicesValidationResult.getResolvedServices();
 
 			// Return links to all the candidates.
-			return candidateServices.stream().map(service -> new AqlLocationLinkToAny(call, service
-					.getOrigin())).collect(Collectors.toList());
+			return candidateServices.stream().map(service -> new AqlLocationLinkToAny(call, service)).collect(
+					Collectors.toList());
 		} finally {
 			queryEnvironment.getLookupEngine().popContext(contextQualifiedName);
 			queryEnvironment.getLookupEngine().getResolver().clear(Collections.singleton(
diff --git a/plugins/org.eclipse.acceleo.aql/src/org/eclipse/acceleo/aql/parser/ModuleLoader.java b/plugins/org.eclipse.acceleo.aql/src/org/eclipse/acceleo/aql/parser/ModuleLoader.java
index f839408..bfbab51 100644
--- a/plugins/org.eclipse.acceleo.aql/src/org/eclipse/acceleo/aql/parser/ModuleLoader.java
+++ b/plugins/org.eclipse.acceleo.aql/src/org/eclipse/acceleo/aql/parser/ModuleLoader.java
@@ -151,36 +151,43 @@
 			final ModuleElement moduleElement = (ModuleElement)service.getOrigin();
 			if (moduleElement.eContainer() instanceof Module) {
 				final Module module = (Module)moduleElement.eContainer();
-				final String qualifiedName = resolver.getQualifiedName(module);
-				final URL sourceURL = resolver.getSourceURL(qualifiedName);
+				if (module.eResource().getURI() != null) {
+					final String qualifiedName = module.eResource().getURI().toString().substring(
+							AcceleoParser.ACCELEOENV_URI_PROTOCOL.length());
 
-				final int identifierStartLine = module.getAst().getIdentifierStartLine(moduleElement);
-				final int identifierStartColumn = module.getAst().getIdentifierStartColumn(moduleElement);
-				final int identifierStartPosition = module.getAst().getIdentifierStartPosition(moduleElement);
-				final IPosition identifierStart = new Position(identifierStartLine, identifierStartColumn,
-						identifierStartPosition);
+					final URL sourceURL = resolver.getSourceURL(qualifiedName);
 
-				final int identifierEndLine = module.getAst().getIdentifierEndLine(moduleElement);
-				final int identifierEndColumn = module.getAst().getIdentifierEndColumn(moduleElement);
-				final int identifierEndPosition = module.getAst().getIdentifierEndPosition(moduleElement);
-				final IPosition identifierEnd = new Position(identifierEndLine, identifierEndColumn,
-						identifierEndPosition);
+					final int identifierStartLine = module.getAst().getIdentifierStartLine(moduleElement);
+					final int identifierStartColumn = module.getAst().getIdentifierStartColumn(moduleElement);
+					final int identifierStartPosition = module.getAst().getIdentifierStartPosition(
+							moduleElement);
+					final IPosition identifierStart = new Position(identifierStartLine, identifierStartColumn,
+							identifierStartPosition);
 
-				final IRange identifierRange = new Range(identifierStart, identifierEnd);
+					final int identifierEndLine = module.getAst().getIdentifierEndLine(moduleElement);
+					final int identifierEndColumn = module.getAst().getIdentifierEndColumn(moduleElement);
+					final int identifierEndPosition = module.getAst().getIdentifierEndPosition(moduleElement);
+					final IPosition identifierEnd = new Position(identifierEndLine, identifierEndColumn,
+							identifierEndPosition);
 
-				final int startLine = module.getAst().getStartLine(moduleElement);
-				final int startColumn = module.getAst().getStartColumn(moduleElement);
-				final int startPosition = module.getAst().getStartPosition(moduleElement);
-				final IPosition start = new Position(startLine, startColumn, startPosition);
+					final IRange identifierRange = new Range(identifierStart, identifierEnd);
 
-				final int endLine = module.getAst().getEndLine(moduleElement);
-				final int endColumn = module.getAst().getEndColumn(moduleElement);
-				final int endPosition = module.getAst().getEndPosition(moduleElement);
-				final IPosition end = new Position(endLine, endColumn, endPosition);
+					final int startLine = module.getAst().getStartLine(moduleElement);
+					final int startColumn = module.getAst().getStartColumn(moduleElement);
+					final int startPosition = module.getAst().getStartPosition(moduleElement);
+					final IPosition start = new Position(startLine, startColumn, startPosition);
 
-				final IRange range = new Range(start, end);
+					final int endLine = module.getAst().getEndLine(moduleElement);
+					final int endColumn = module.getAst().getEndColumn(moduleElement);
+					final int endPosition = module.getAst().getEndPosition(moduleElement);
+					final IPosition end = new Position(endLine, endColumn, endPosition);
 
-				res = new SourceLocation(sourceURL, identifierRange, range);
+					final IRange range = new Range(start, end);
+
+					res = new SourceLocation(sourceURL, identifierRange, range);
+				} else {
+					res = null;
+				}
 			} else {
 				res = null;
 			}
diff --git a/query/plugins/org.eclipse.acceleo.query.ide.jdt/src/org/eclipse/acceleo/query/ide/jdt/EclipseJDTJavaLoader.java b/query/plugins/org.eclipse.acceleo.query.ide.jdt/src/org/eclipse/acceleo/query/ide/jdt/EclipseJDTJavaLoader.java
index 0122b5c..4d2ae89 100644
--- a/query/plugins/org.eclipse.acceleo.query.ide.jdt/src/org/eclipse/acceleo/query/ide/jdt/EclipseJDTJavaLoader.java
+++ b/query/plugins/org.eclipse.acceleo.query.ide.jdt/src/org/eclipse/acceleo/query/ide/jdt/EclipseJDTJavaLoader.java
@@ -25,11 +25,13 @@
 import org.eclipse.acceleo.query.runtime.namespace.ISourceLocation;
 import org.eclipse.acceleo.query.runtime.namespace.ISourceLocation.IPosition;
 import org.eclipse.acceleo.query.runtime.namespace.ISourceLocation.IRange;
+import org.eclipse.core.runtime.NullProgressMonitor;
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.IMethod;
 import org.eclipse.jdt.core.ISourceRange;
 import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.core.dom.AST;
 import org.eclipse.jdt.core.dom.ASTParser;
 import org.eclipse.jdt.core.dom.CompilationUnit;
@@ -53,7 +55,7 @@
 
 	@Override
 	public ISourceLocation getSourceLocation(IQualifiedNameResolver resolver, IService<?> service) {
-		final ISourceLocation res;
+		ISourceLocation res = null;
 
 		IPosition identifierStart = new Position(0, 0, 0);
 		IPosition identifierEnd = new Position(0, 0, 0);
@@ -63,7 +65,6 @@
 		IPosition end = new Position(0, 0, 0);
 		final IRange range;
 
-		// TODO double check all of this
 		if (service.getOrigin() instanceof Method) {
 			final Method method = (Method)service.getOrigin();
 			URL sourceURL = null;
@@ -71,37 +72,44 @@
 				final IJavaProject project = ((EclipseJDTQualifiedNameResolver)resolver).getProject();
 				try {
 					final IType type = project.findType(method.getDeclaringClass().getCanonicalName());
-					// TODO might be null and also not reference the source file
-					sourceURL = type.getResource().getLocationURI().toURL();
-					final IMethod javaMethod = type.getMethod(method.getName(), getParamterTypes(method));
-					final ISourceRange methodIdentifierRange = javaMethod.getNameRange();
-					final ISourceRange sourceRange = javaMethod.getSourceRange();
+					if (type != null) {
+						type.getOpenable().open(new NullProgressMonitor());
+						sourceURL = type.getResource().getLocationURI().toURL();
+						final IMethod javaMethod = type.getMethod(method.getName(), getParamterTypes(method));
+						javaMethod.getOpenable().open(new NullProgressMonitor());
+						final ISourceRange methodIdentifierRange = javaMethod.getNameRange();
+						final ISourceRange sourceRange = javaMethod.getSourceRange();
 
-					final ASTParser parser = ASTParser.newParser(AST.JLS10);
-					parser.setSource(type.getCompilationUnit());
-					final CompilationUnit cu = (CompilationUnit)parser.createAST(null);
-					final int identifierStartOffset = methodIdentifierRange.getOffset();
-					identifierStart = new Position(cu.getLineNumber(identifierStartOffset), cu
-							.getColumnNumber(identifierStartOffset), identifierStartOffset);
-					final int identifierEndOffset = identifierStartOffset + methodIdentifierRange.getLength();
-					identifierEnd = new Position(cu.getLineNumber(identifierEndOffset), cu.getColumnNumber(
-							identifierEndOffset), identifierEndOffset);
+						final ASTParser parser = ASTParser.newParser(AST.JLS10);
+						parser.setSource(type.getCompilationUnit());
+						final CompilationUnit cu = (CompilationUnit)parser.createAST(null);
+						final int identifierStartOffset = methodIdentifierRange.getOffset();
+						identifierStart = new Position(cu.getLineNumber(identifierStartOffset) - 1, cu
+								.getColumnNumber(identifierStartOffset), identifierStartOffset);
+						final int identifierEndOffset = identifierStartOffset + methodIdentifierRange
+								.getLength();
+						identifierEnd = new Position(cu.getLineNumber(identifierEndOffset) - 1, cu
+								.getColumnNumber(identifierEndOffset), identifierEndOffset);
 
-					final int startOffset = sourceRange.getOffset();
-					start = new Position(cu.getLineNumber(startOffset), cu.getColumnNumber(startOffset),
-							startOffset);
-					final int endOffset = startOffset + sourceRange.getLength();
-					end = new Position(cu.getLineNumber(endOffset), cu.getColumnNumber(endOffset), endOffset);
+						final int startOffset = sourceRange.getOffset();
+						start = new Position(cu.getLineNumber(startOffset) - 1, cu.getColumnNumber(
+								startOffset), startOffset);
+						final int endOffset = startOffset + sourceRange.getLength();
+						end = new Position(cu.getLineNumber(endOffset) - 1, cu.getColumnNumber(endOffset),
+								endOffset);
+
+						identifierRange = new Range(identifierStart, identifierEnd);
+						range = new Range(start, end);
+						res = new SourceLocation(sourceURL, identifierRange, range);
+					} else {
+						res = null;
+					}
 				} catch (JavaModelException | MalformedURLException e) {
 					sourceURL = getDefaultSourceURL(resolver, method);
 				}
 			} else {
 				sourceURL = getDefaultSourceURL(resolver, method);
 			}
-
-			identifierRange = new Range(identifierStart, identifierEnd);
-			range = new Range(start, end);
-			res = new SourceLocation(sourceURL, identifierRange, range);
 		} else {
 			res = null;
 		}
@@ -113,7 +121,7 @@
 		final List<String> res = new ArrayList<String>();
 
 		for (Class<?> type : method.getParameterTypes()) {
-			res.add(type.getTypeName());
+			res.add(Signature.createTypeSignature(type.getSimpleName(), false));
 		}
 
 		return res.toArray(new String[res.size()]);
diff --git a/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/parser/Positions.java b/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/parser/Positions.java
index 975fc28..e4bdcd5 100644
--- a/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/parser/Positions.java
+++ b/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/parser/Positions.java
@@ -113,7 +113,7 @@
 	 * @return the identifier start column in the parsed text
 	 */
 	public Integer getIdentifierStartColumns(EObject node) {
-		return startColumns.get(node);
+		return identifierStartColumns.get(node);
 	}
 
 	/**
diff --git a/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/runtime/impl/namespace/Range.java b/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/runtime/impl/namespace/Range.java
index f30975c..7a7b8dc 100644
--- a/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/runtime/impl/namespace/Range.java
+++ b/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/runtime/impl/namespace/Range.java
@@ -40,7 +40,7 @@
 	}
 
 	@Override
-	public IPosition getStar() {
+	public IPosition getStart() {
 		return start;
 	}
 
diff --git a/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/runtime/impl/namespace/SourceLocation.java b/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/runtime/impl/namespace/SourceLocation.java
index a9c8cd5..53fd8f5 100644
--- a/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/runtime/impl/namespace/SourceLocation.java
+++ b/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/runtime/impl/namespace/SourceLocation.java
@@ -24,7 +24,7 @@
 	/**
 	 * The source {@link URL}.
 	 */
-	private static URL sourceURL;
+	private final URL sourceURL;
 
 	/**
 	 * The identifier {@link IRange}.
@@ -47,6 +47,7 @@
 	 *            the total {@link IRange}
 	 */
 	public SourceLocation(URL sourceURL, IRange identifierRange, IRange range) {
+		this.sourceURL = sourceURL;
 		this.identifierRange = identifierRange;
 		this.range = range;
 	}
diff --git a/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/runtime/namespace/ISourceLocation.java b/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/runtime/namespace/ISourceLocation.java
index c0a4e46..8f7af05 100644
--- a/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/runtime/namespace/ISourceLocation.java
+++ b/query/plugins/org.eclipse.acceleo.query/src/org/eclipse/acceleo/query/runtime/namespace/ISourceLocation.java
@@ -61,7 +61,7 @@
 		 * 
 		 * @return the start {@link IPosition}
 		 */
-		IPosition getStar();
+		IPosition getStart();
 
 		/**
 		 * Gets the end {@link IPosition}.