diff options
author | djockel | 2014-05-04 14:33:28 +0000 |
---|---|---|
committer | djockel | 2014-05-04 14:33:28 +0000 |
commit | d4e9f7abfddfbd2851b17c88d6244f791f993fcd (patch) | |
tree | 71ddb1a842cbcd0d4a861dc52aff62b13bd7ac5d | |
parent | 5c83c2625e7c0b91989fe4b25089fbe9e575f96b (diff) | |
download | org.eclipse.xpand-d4e9f7abfddfbd2851b17c88d6244f791f993fcd.tar.gz org.eclipse.xpand-d4e9f7abfddfbd2851b17c88d6244f791f993fcd.tar.xz org.eclipse.xpand-d4e9f7abfddfbd2851b17c88d6244f791f993fcd.zip |
Fix for navigation issues:
- Bug 320982 - F3/Cmd+Click navigation not working for EXPAND statements
- Bug 312626 - [Navigation] Irritating Navigation with F3
- Bug 312616 - [Navigation] F3 should jump to the best match
8 files changed, 841 insertions, 465 deletions
diff --git a/plugins/org.eclipse.xpand.ui/src/org/eclipse/xpand/ui/editor/XpandHyperlinkDetector.java b/plugins/org.eclipse.xpand.ui/src/org/eclipse/xpand/ui/editor/XpandHyperlinkDetector.java index da6a2690..0154ce5b 100644 --- a/plugins/org.eclipse.xpand.ui/src/org/eclipse/xpand/ui/editor/XpandHyperlinkDetector.java +++ b/plugins/org.eclipse.xpand.ui/src/org/eclipse/xpand/ui/editor/XpandHyperlinkDetector.java @@ -4,7 +4,7 @@ * 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: committers of openArchitectureWare - initial API and * implementation ******************************************************************************/ @@ -12,6 +12,7 @@ package org.eclipse.xpand.ui.editor; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -20,8 +21,8 @@ import org.eclipse.internal.xpand2.ast.AbstractDefinition; import org.eclipse.internal.xpand2.ast.ExpandStatement; import org.eclipse.internal.xpand2.ast.Template; import org.eclipse.internal.xtend.expression.ast.DeclaredParameter; -import org.eclipse.internal.xtend.expression.ast.OperationCall; import org.eclipse.internal.xtend.type.baseimpl.PolymorphicResolver; +import org.eclipse.internal.xtend.type.baseimpl.types.CollectionTypeImpl; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.Region; import org.eclipse.ui.IEditorPart; @@ -33,6 +34,7 @@ import org.eclipse.xtend.shared.ui.core.IXtendXpandProject; import org.eclipse.xtend.shared.ui.core.search.SearchMatch; import org.eclipse.xtend.shared.ui.core.search.XtendXpandSearchEngine; import org.eclipse.xtend.shared.ui.editor.navigation.AbstractHyperlinkDetector; +import org.eclipse.xtend.shared.ui.editor.navigation.ContextComputer; import org.eclipse.xtend.shared.ui.editor.navigation.GenericHyperlink; import org.eclipse.xtend.typesystem.Type; @@ -41,92 +43,126 @@ import org.eclipse.xtend.typesystem.Type; */ public class XpandHyperlinkDetector extends AbstractHyperlinkDetector { - public XpandHyperlinkDetector(IEditorPart editor) { + public XpandHyperlinkDetector(final IEditorPart editor) { super(editor); } - - /** - * {@inheritDoc} - */ + @Override - protected List<GenericHyperlink> computeMatchesAndHyperlinks(IRegion hyperlinkRegion, String hyperlinkedWord, - IXtendXpandProject project) { + protected List<GenericHyperlink> computeMatchesAndHyperlinks( + final IRegion hyperlinkRegion, final String hyperlinkedWord, + final IXtendXpandProject project) { + + List<GenericHyperlink> links = super.computeMatchesAndHyperlinks( + hyperlinkRegion, hyperlinkedWord, project); + if (!links.isEmpty()) { + return links; + } + links = new ArrayList<GenericHyperlink>(); + IXpandResource xpandResource = (IXpandResource) Activator + .getExtXptModelManager().findExtXptResource(getFile()); + ExpandStatement statement = XtendXpandSearchEngine.findDefinition( + hyperlinkedWord, hyperlinkRegion, + (Template) xpandResource.getExtXptResource()); - IXpandResource xpandResource = (IXpandResource)Activator.getExtXptModelManager().findExtXptResource(getFile()); - - List<GenericHyperlink> links = createHyperlinkToImportedExtensions(xpandResource, hyperlinkRegion, hyperlinkedWord); - if (!links.isEmpty()) - return links; - - ExpandStatement statement = XtendXpandSearchEngine.findDefinition(hyperlinkedWord, hyperlinkRegion, (Template)xpandResource.getExtXptResource()); - - if (statement != null) { - List<AbstractDefinition> defmatches = XtendXpandSearchEngine.findDefinitionsByNameInResourceAndImports(project, statement.getDefinition().toString(), xpandResource); + if (statement == null) { + return Collections.<GenericHyperlink> emptyList(); + } + List<AbstractDefinition> defmatches = XtendXpandSearchEngine + .findDefinitionsByNameInResourceAndImports(project, statement + .getDefinition().toString(), xpandResource); + ContextComputer helper = computeContext(xpandResource, + statement.getTarget()); + if (helper == null || helper.getContext() == null) { + return useGenericHyplerlinkDetector(hyperlinkRegion, + hyperlinkedWord, project); + } + ExecutionContext ctx = helper.getContext(); + Type expandTargetType = null; + if (statement.getTarget() == null) + expandTargetType = ctx.getTypeForName(statement + .getContainingDefinition().getType().toString()); + else if (statement.getTarget().equals( + ExecutionContext.IMPLICIT_VARIABLE)) + expandTargetType = ctx.getTypeForName(statement + .getContainingDefinition().getType().toString()); + else + expandTargetType = statement.getTarget().analyze(ctx, + new HashSet<AnalysationIssue>()); - ExecutionContext ctx = Activator.getExecutionContext( - getXtendXpandProject().getProject()).cloneWithResource(statement.getContainingDefinition().getOwner()); - Type expandTargetType = null; - if (statement.getTarget() == null) - expandTargetType = ctx.getTypeForName(statement.getContainingDefinition().getType().toString()); + if (expandTargetType == null) + expandTargetType = ctx.getTypeForName(statement + .getContainingDefinition().getType().toString()); + if (expandTargetType instanceof CollectionTypeImpl) + expandTargetType = ((CollectionTypeImpl) expandTargetType) + .getInnerType(); + Type[] statementTypes = new Type[statement.getParameters().length]; + for (int i = 0; i < statementTypes.length; i++) { + statementTypes[i] = statement.getParameters()[i].analyze(ctx, + new HashSet<AnalysationIssue>()); + if (statementTypes[i] == null) + statementTypes[i] = ctx.getObjectType(); + } + for (AbstractDefinition definition : defmatches) { + int compare = isDefinitionAssignableFromExpandStatement(definition, + statementTypes, expandTargetType, ctx); + if (compare != -1) { + GenericHyperlink genericHyperlink = createGenericTemplateHyperlink( + hyperlinkedWord, statement, definition); + if (compare == 0) + links.add(0, genericHyperlink); else - if (statement.getTarget().equals(ExecutionContext.IMPLICIT_VARIABLE)) - expandTargetType = ctx.getTypeForName(statement.getContainingDefinition().getType().toString()); - else - expandTargetType = statement.getTarget().analyze(ctx, new HashSet<AnalysationIssue>()); - - if (expandTargetType == null) - expandTargetType = ctx.getTypeForName(statement.getContainingDefinition().getType().toString()); - Type[] statementTypes = new Type[statement.getParameters().length]; - for (int i = 0; i<statementTypes.length; i++) { - statementTypes[i] = statement.getParameters()[i].analyze(ctx, new HashSet<AnalysationIssue>()); - if (statementTypes[i] == null) statementTypes[i] = ctx.getObjectType(); - } - - for (AbstractDefinition definition : defmatches) { - if (isDefinitionAssignableFromExpandStatement(definition, statementTypes, expandTargetType, ctx)) { - SearchMatch match = new SearchMatch( - definition.getDefName().getStart(), - definition.getDefName().getEnd() - definition.getDefName().getStart(), - getXXResourceByName(definition.getFileName(), XpandUtil.TEMPLATE_EXTENSION).getUnderlyingStorage()); - GenericHyperlink genericHyperlink = new GenericHyperlink( - getWorkbenchPage(), - match, - new Region(statement.getDefinition().getStart(), statement.getDefinition().getEnd()-statement.getDefinition().getStart()), - computeHyperlinkLabel(hyperlinkedWord, definition.getTargetType(), definition.getParamsAsList(), getXXResourceByName(definition.getFileName(), XpandUtil.TEMPLATE_EXTENSION)) - ); - links.add(genericHyperlink); - } - } + links.add(genericHyperlink); } - OperationCall expression = null; - if (statement == null) //performance issue. If expand statement is found no need to search for extension. - expression = XtendXpandSearchEngine.findExpressionInTemplate(hyperlinkRegion, (Template)xpandResource.getExtXptResource()); - if (expression != null) - links = findExtensionMatches(hyperlinkRegion, hyperlinkedWord, project, xpandResource, links, expression.getParams().length); - - return links; + } + return links; + } + + /** + * @since 2.0 + */ + protected GenericHyperlink createGenericTemplateHyperlink( + final String hyperlinkedWord, final ExpandStatement statement, + final AbstractDefinition definition) { + SearchMatch match = new SearchMatch(definition.getDefName().getStart(), + definition.getDefName().getEnd() + - definition.getDefName().getStart(), + getXXResourceByName(definition.getFileName(), + XpandUtil.TEMPLATE_EXTENSION).getUnderlyingStorage()); + GenericHyperlink genericHyperlink = new GenericHyperlink( + getWorkbenchPage(), match, new Region(statement.getDefinition() + .getStart(), statement.getDefinition().getEnd() + - statement.getDefinition().getStart()), + computeHyperlinkLabel( + hyperlinkedWord, + definition.getTargetType(), + definition.getParamsAsList(), + getXXResourceByName(definition.getFileName(), + XpandUtil.TEMPLATE_EXTENSION))); + return genericHyperlink; } - - + /** - * Determines for a definitions, iff the definition can be called from an expand statement or not. - * Therefore the target type of the expand statement and all types of the parameters of the expand statement are computed. - * If no type can be computered, the type is set to <code>ObjectType</code>. + * Determines for a definitions, iff the definition can be called from an + * expand statement or not. Therefore the target type of the expand + * statement and all types of the parameters of the expand statement are + * computed. If no type can be computered, the type is set to + * <code>ObjectType</code>. * - * @param expandStatement - * The expand statement - * @param definition - * The definitions to check + * @param expandStatement + * The expand statement + * @param definition + * The definitions to check */ - private boolean isDefinitionAssignableFromExpandStatement(AbstractDefinition definition, Type[] statementTypes, - Type statementType, ExecutionContext ctx) { - + private int isDefinitionAssignableFromExpandStatement( + final AbstractDefinition definition, final Type[] statementTypes, + final Type statementType, final ExecutionContext ctx) { + Type defineType = ctx.getTypeForName(definition.getType().toString()); - if (defineType == null) + if (defineType == null) defineType = ctx.getObjectType(); - if (!statementType.isAssignableFrom(defineType)) - return false; - + if (!defineType.isAssignableFrom(statementType)) + return -1; + List<Type> definitionTypes = new ArrayList<Type>(); for (DeclaredParameter param : definition.getParams()) { Type paramType = ctx.getTypeForName(param.getType().toString()); @@ -135,7 +171,8 @@ public class XpandHyperlinkDetector extends AbstractHyperlinkDetector { else definitionTypes.add(ctx.getObjectType()); } - return PolymorphicResolver.typesComparator.compare(definitionTypes, Arrays.asList(statementTypes)) >=0; + return PolymorphicResolver.typesComparator.compare(definitionTypes, + Arrays.asList(statementTypes)); } - + } diff --git a/plugins/org.eclipse.xtend.check.ui/src/org/eclipse/xtend/check/ui/editor/CheckHyperlinkDetector.java b/plugins/org.eclipse.xtend.check.ui/src/org/eclipse/xtend/check/ui/editor/CheckHyperlinkDetector.java index 72e62281..1adbd92c 100644 --- a/plugins/org.eclipse.xtend.check.ui/src/org/eclipse/xtend/check/ui/editor/CheckHyperlinkDetector.java +++ b/plugins/org.eclipse.xtend.check.ui/src/org/eclipse/xtend/check/ui/editor/CheckHyperlinkDetector.java @@ -4,53 +4,22 @@ * 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: committers of openArchitectureWare - initial API and * implementation ******************************************************************************/ package org.eclipse.xtend.check.ui.editor; -import java.util.Collections; -import java.util.List; - -import org.eclipse.internal.xtend.expression.ast.OperationCall; -import org.eclipse.internal.xtend.xtend.ast.ExtensionFile; -import org.eclipse.jface.text.IRegion; import org.eclipse.ui.IEditorPart; -import org.eclipse.xtend.shared.ui.Activator; -import org.eclipse.xtend.shared.ui.core.IXtendXpandProject; -import org.eclipse.xtend.shared.ui.core.IXtendXpandResource; -import org.eclipse.xtend.shared.ui.core.search.XtendXpandSearchEngine; import org.eclipse.xtend.shared.ui.editor.navigation.AbstractHyperlinkDetector; -import org.eclipse.xtend.shared.ui.editor.navigation.GenericHyperlink; - /** * @author Darius Jockel - Initial contribution and API */ public class CheckHyperlinkDetector extends AbstractHyperlinkDetector { - public CheckHyperlinkDetector(IEditorPart editor) { + public CheckHyperlinkDetector(final IEditorPart editor) { super(editor); } - - @Override - protected List<GenericHyperlink> computeMatchesAndHyperlinks(IRegion hyperlinkRegion, String hyperlinkedWord, - IXtendXpandProject project) { - IXtendXpandResource resource = Activator.getExtXptModelManager().findExtXptResource(getFile()); - - List<GenericHyperlink> links = createHyperlinkToImportedExtensions(resource, hyperlinkRegion, hyperlinkedWord); - if (!links.isEmpty()) - return links; - - OperationCall expression = XtendXpandSearchEngine.findExpressionInExtensionFile(hyperlinkRegion, (ExtensionFile)resource.getExtXptResource()); - - if (expression == null) - return Collections.<GenericHyperlink>emptyList(); - - return findExtensionMatches(hyperlinkRegion, hyperlinkedWord, project, resource, links, expression.getParams().length); - } - - } diff --git a/plugins/org.eclipse.xtend.shared.ui/src/org/eclipse/xtend/shared/ui/core/search/XtendXpandSearchEngine.java b/plugins/org.eclipse.xtend.shared.ui/src/org/eclipse/xtend/shared/ui/core/search/XtendXpandSearchEngine.java index 95190544..c4738085 100644 --- a/plugins/org.eclipse.xtend.shared.ui/src/org/eclipse/xtend/shared/ui/core/search/XtendXpandSearchEngine.java +++ b/plugins/org.eclipse.xtend.shared.ui/src/org/eclipse/xtend/shared/ui/core/search/XtendXpandSearchEngine.java @@ -40,6 +40,7 @@ import org.eclipse.internal.xpand2.model.XpandResource; import org.eclipse.internal.xtend.expression.ast.AbstractExpressionVisitor; import org.eclipse.internal.xtend.expression.ast.Expression; import org.eclipse.internal.xtend.expression.ast.Identifier; +import org.eclipse.internal.xtend.expression.ast.ListLiteral; import org.eclipse.internal.xtend.expression.ast.OperationCall; import org.eclipse.internal.xtend.expression.ast.SyntaxElement; import org.eclipse.internal.xtend.xtend.ast.AbstractExtension; @@ -58,7 +59,7 @@ import org.eclipse.xtend.shared.ui.internal.XtendLog; /** * Search engine for Xtend. - * + * * @author Sven Efftinge (http://www.efftinge.de) * @author Peter Friese * @author Darius Jockel @@ -67,15 +68,21 @@ public class XtendXpandSearchEngine { public class ExpressionVisitor extends AbstractExpressionVisitor { public Set<OperationCall> targetStatement = new HashSet<OperationCall>(); - private final IRegion region; + private final String name; - public ExpressionVisitor(final IRegion region, Set<OperationCall> targetStatement){ - this.region = region; + /** + * @since 2.0 + */ + public ExpressionVisitor(final String name, + final Set<OperationCall> targetStatement) { this.targetStatement = targetStatement; + this.name = name; + } + @Override - protected Object visitOperationCall(OperationCall oc) { - if (oc.getStart()<= region.getOffset() && oc.getEnd() >= region.getOffset()+region.getLength()) + protected Object visitOperationCall(final OperationCall oc) { + if (name.equals(oc.getName().toString())) targetStatement.add(oc); if (oc.getTarget() != null) { oc.getTarget().accept(this); @@ -87,9 +94,18 @@ public class XtendXpandSearchEngine { } return oc; } + + @Override + protected Object visitListLiteral(final ListLiteral node) { + for (Expression element : node.getElements()) { + element.accept(this); + } + return node; + } } - public static List<Definition> findAllDefines(IXtendXpandProject project) { + public static List<Definition> findAllDefines( + final IXtendXpandProject project) { List<Definition> matches = new ArrayList<Definition>(); IXtendXpandResource[] resources = project.getRegisteredResources(); for (IXtendXpandResource res : resources) { @@ -107,7 +123,8 @@ public class XtendXpandSearchEngine { return matches; } - public static List<SearchMatch> findAllOccurrences(IXtendXpandProject project, String identifier) { + public static List<SearchMatch> findAllOccurrences( + final IXtendXpandProject project, final String identifier) { List<SearchMatch> matches = new ArrayList<SearchMatch>(); IXtendXpandResource[] resources = project.getRegisteredResources(); for (IXtendXpandResource res : resources) { @@ -118,9 +135,12 @@ public class XtendXpandSearchEngine { if (xdef instanceof Definition) { Definition def = (Definition) xdef; if (def.getName().equals(identifier)) { - int startOfDefnitionName = def.getDefName().getStart() - 1; - int lengthOfDefinitionName = def.getDefName().getEnd() - def.getDefName().getStart(); - matches.add(new SearchMatch(startOfDefnitionName, lengthOfDefinitionName, res + int startOfDefnitionName = def.getDefName() + .getStart() - 1; + int lengthOfDefinitionName = def.getDefName() + .getEnd() - def.getDefName().getStart(); + matches.add(new SearchMatch(startOfDefnitionName, + lengthOfDefinitionName, res .getUnderlyingStorage())); } } @@ -130,24 +150,29 @@ public class XtendXpandSearchEngine { // there is no visitor api or something similar so far, so we have // to use a reflective mechanism... - Set<ExpandStatement> ops = findRec(res.getExtXptResource(), ExpandStatement.class, new HashSet<Object>()); + Set<ExpandStatement> ops = findRec(res.getExtXptResource(), + ExpandStatement.class, new HashSet<Object>()); for (ExpandStatement expr : ops) { Identifier definition = expr.getDefinition(); String definitionFQN = definition.toString(); int lastIndexOf = definitionFQN.lastIndexOf(identifier); if (lastIndexOf > -1) { - int startOfDefinition = definition.getStart() + lastIndexOf - 1; + int startOfDefinition = definition.getStart() + lastIndexOf + - 1; int lengthOfDefinition = identifier.length(); - matches.add(new SearchMatch(startOfDefinition, lengthOfDefinition, res.getUnderlyingStorage())); + matches.add(new SearchMatch(startOfDefinition, + lengthOfDefinition, res.getUnderlyingStorage())); } } } - for (IProject p : project.getProject().getProject().getReferencingProjects()) { - IXtendXpandProject extxptp = Activator.getExtXptModelManager().findProject(p); + for (IProject p : project.getProject().getProject() + .getReferencingProjects()) { + IXtendXpandProject extxptp = Activator.getExtXptModelManager() + .findProject(p); if (extxptp != null) { matches.addAll(findAllOccurrences(extxptp, identifier)); } @@ -159,22 +184,27 @@ public class XtendXpandSearchEngine { * Find all operation invocations for the given identifier. Ignores * parameters and types as well as resource references (i.e. imports) */ - public static List<SearchMatch> findReferences(IXtendXpandProject project, String identifier) { + public static List<SearchMatch> findReferences( + final IXtendXpandProject project, final String identifier) { List<SearchMatch> matches = new ArrayList<SearchMatch>(); IXtendXpandResource[] resources = project.getRegisteredResources(); for (IXtendXpandResource res : resources) { // there is no visitor api or something similar so far, so we have // to use a reflective mechanism... - Set<OperationCall> ops = findRec(res.getExtXptResource(), OperationCall.class, new HashSet<Object>()); + Set<OperationCall> ops = findRec(res.getExtXptResource(), + OperationCall.class, new HashSet<Object>()); for (OperationCall expr : ops) { if (expr.getName().toString().equals(identifier)) { - matches.add(new SearchMatch(expr.getName().getStart() + 1, expr.getName().getEnd() - expr.getStart() - , res.getUnderlyingStorage())); + matches.add(new SearchMatch(expr.getName().getStart() + 1, + expr.getName().getEnd() - expr.getStart(), res + .getUnderlyingStorage())); } } } - for (IProject p : project.getProject().getProject().getReferencingProjects()) { - IXtendXpandProject extxptp = Activator.getExtXptModelManager().findProject(p); + for (IProject p : project.getProject().getProject() + .getReferencingProjects()) { + IXtendXpandProject extxptp = Activator.getExtXptModelManager() + .findProject(p); if (extxptp != null) { matches.addAll(findReferences(extxptp, identifier)); } @@ -186,7 +216,8 @@ public class XtendXpandSearchEngine { * Find all extension declarations for the given identifier. Ignores * parameters and types as well as resource references (i.e. imports) */ - public static List<SearchMatch> findDeclarations(IXtendXpandProject project, String identifier) { + public static List<SearchMatch> findDeclarations( + final IXtendXpandProject project, final String identifier) { List<SearchMatch> matches = new ArrayList<SearchMatch>(); IXtendXpandResource[] resources = project.getRegisteredResources(); for (IXtendXpandResource res : resources) { @@ -197,12 +228,12 @@ public class XtendXpandSearchEngine { AbstractExtension ae = (AbstractExtension) ext; if (ext.getName().equals(identifier)) { Identifier id = ae.getNameIdentifier(); - matches.add(new SearchMatch(id.getStart()+1, id.getEnd() - id.getStart() + 1 /* - * sorry - * for - * the - * "+1"-hack - */, res.getUnderlyingStorage())); + matches.add(new SearchMatch(id.getStart() + 1, id + .getEnd() - id.getStart() + 1 /* + * sorry for the + * "+1"-hack + */, res + .getUnderlyingStorage())); } } } @@ -214,8 +245,10 @@ public class XtendXpandSearchEngine { if (xdef instanceof Definition) { Definition def = (Definition) xdef; if (def.getName().equals(identifier)) { - matches.add(new SearchMatch(def.getDefName().getStart(), def.getDefName().getEnd() - - def.getDefName().getStart(), res.getUnderlyingStorage())); + matches.add(new SearchMatch(def.getDefName() + .getStart(), def.getDefName().getEnd() + - def.getDefName().getStart(), res + .getUnderlyingStorage())); } } } @@ -223,8 +256,10 @@ public class XtendXpandSearchEngine { } } try { - for (IProject p : project.getProject().getProject().getReferencedProjects()) { - IXtendXpandProject extxptp = Activator.getExtXptModelManager().findProject(p); + for (IProject p : project.getProject().getProject() + .getReferencedProjects()) { + IXtendXpandProject extxptp = Activator.getExtXptModelManager() + .findProject(p); if (extxptp != null) { matches.addAll(findDeclarations(extxptp, identifier)); } @@ -236,22 +271,25 @@ public class XtendXpandSearchEngine { } /** - * Find all reachable Xpand declarations by name in given template <em>resource</em> or imported templates. - * Type or parameters are ignored. + * Find all reachable Xpand declarations by name in given template + * <em>resource</em> or imported templates. Type or parameters are ignored. */ - public static List<AbstractDefinition> findDefinitionsByNameInResourceAndImports(IXtendXpandProject project, String identifier, XpandResource resource) { + public static List<AbstractDefinition> findDefinitionsByNameInResourceAndImports( + final IXtendXpandProject project, final String identifier, + final XpandResource resource) { List<AbstractDefinition> matches = new ArrayList<AbstractDefinition>(); - //The name of the definition + // The name of the definition String definitionName = XpandUtil.getLastSegment(identifier); - //If the definition qualifier is qualified, the name of the template + // If the definition qualifier is qualified, the name of the template String templateName = XpandUtil.withoutLastSegment(identifier); - XpandExecutionContext xctx = (XpandExecutionContext)Activator.getExecutionContext(project.getProject()).cloneWithResource(resource); + XpandExecutionContext xctx = (XpandExecutionContext) Activator + .getExecutionContext(project.getProject()).cloneWithResource( + resource); List<XpandResource> tpls = new ArrayList<XpandResource>(); - if (templateName != null && !templateName.equals("")) - { + if (templateName != null && !templateName.equals("")) { XpandResource xpandResource = xctx.findTemplate(templateName); if (xpandResource != null) tpls.add(xpandResource); @@ -259,23 +297,26 @@ public class XtendXpandSearchEngine { if (tpls.isEmpty()) { List<IXtendXpandResource> xtendXpandResources = new ArrayList<IXtendXpandResource>(); - for(String name : resource.getImportedNamespaces()) - xtendXpandResources.add(Activator.getExtXptModelManager().findXtendXpandResource( - name.replaceAll(XpandUtil.NS_DELIM, "/"), - XpandUtil.TEMPLATE_EXTENSION)); - - for (IXtendXpandResource res : xtendXpandResources) { - if (res != null && res.getExtXptResource() instanceof XpandResource) - tpls.add((XpandResource) res.getExtXptResource()); - } - tpls.add(resource); + for (String name : resource.getImportedNamespaces()) + xtendXpandResources.add(Activator.getExtXptModelManager() + .findXtendXpandResource( + name.replaceAll(XpandUtil.NS_DELIM, "/"), + XpandUtil.TEMPLATE_EXTENSION)); + + for (IXtendXpandResource res : xtendXpandResources) { + if (res != null + && res.getExtXptResource() instanceof XpandResource) + tpls.add((XpandResource) res.getExtXptResource()); + } + tpls.add(resource); } for (XpandResource tpl : tpls) { for (XpandDefinition xdef : tpl.getDefinitions()) { if (xdef instanceof Definition) { Definition def = (Definition) xdef; - if (XpandUtil.getLastSegment(def.getName()).equals(definitionName)) { + if (XpandUtil.getLastSegment(def.getName()).equals( + definitionName)) { matches.add(def); } } @@ -290,14 +331,18 @@ public class XtendXpandSearchEngine { } /** - * Find all reachable Extensions declarations with name <em>identifier</em> in given resource. - * - * @return A list of extensions imported by the IXtendXpandResource <em>resource</em> with given name <em>identifier</em> + * Find all reachable Extensions declarations with name <em>identifier</em> + * in given resource. + * + * @return A list of extensions imported by the IXtendXpandResource + * <em>resource</em> with given name <em>identifier</em> */ - public static List<Extension> findExtensionsByNameInResourceAndImports(IXtendXpandProject project, - String identifier, IXtendXpandResource resource) { + public static List<Extension> findExtensionsByNameInResourceAndImports( + final IXtendXpandProject project, final String identifier, + final IXtendXpandResource resource) { List<Extension> matches = new ArrayList<Extension>(); - ExecutionContext ctx = Activator.getExecutionContext(project.getProject()); + ExecutionContext ctx = Activator.getExecutionContext(project + .getProject()); ctx = ctx.cloneWithResource(resource.getExtXptResource()); final Set<? extends Extension> extensions = ctx.getAllExtensions(); for (Extension ext : extensions) { @@ -306,23 +351,24 @@ public class XtendXpandSearchEngine { } } if (!matches.isEmpty()) { - matches.add(matches.size(), matches.get(0)); - matches.remove(0); + matches.add(matches.size(), matches.get(0)); + matches.remove(0); } return matches; } - private static List<SearchMatch> sort(List<SearchMatch> searchmatches) { + private static List<SearchMatch> sort(final List<SearchMatch> searchmatches) { Collections.sort(searchmatches, new Comparator<SearchMatch>() { - public int compare(SearchMatch o1, SearchMatch o2) { + public int compare(final SearchMatch o1, final SearchMatch o2) { if (o1.getFile() == null) { return -1; } if (o2.getFile() == null) { return 1; } - int fileCompare = o1.getFile().getName().compareTo(o2.getFile().getName()); + int fileCompare = o1.getFile().getName() + .compareTo(o2.getFile().getName()); if (fileCompare == 0) { return ((Integer) o1.getOffSet()).compareTo(o2.getOffSet()); } @@ -333,7 +379,8 @@ public class XtendXpandSearchEngine { } @SuppressWarnings("unchecked") - private static <T extends SyntaxElement> Set<T> findRec(Object res, Class<T> clazz, Set<Object> visitedNodes) { + private static <T extends SyntaxElement> Set<T> findRec(final Object res, + final Class<T> clazz, final Set<Object> visitedNodes) { if (visitedNodes.contains(res)) { return Collections.emptySet(); } @@ -347,11 +394,13 @@ public class XtendXpandSearchEngine { Method[] methods = instanceClass.getMethods(); for (Method method : methods) { int mod = method.getModifiers(); - if (Modifier.isPublic(mod) && !Modifier.isStatic(mod) && method.getName().startsWith("get") + if (Modifier.isPublic(mod) && !Modifier.isStatic(mod) + && method.getName().startsWith("get") && method.getParameterTypes().length == 0) { Class<?> pType = method.getReturnType(); // if it's a SyntaxElement navigate it - if (Collection.class.isAssignableFrom(pType) || SyntaxElement.class.isAssignableFrom(pType)) { + if (Collection.class.isAssignableFrom(pType) + || SyntaxElement.class.isAssignableFrom(pType)) { Object invRes; try { invRes = method.invoke(res, new Object[] {}); @@ -372,175 +421,235 @@ public class XtendXpandSearchEngine { } /** - * Search a template for a {@link org.eclipse.internal.xtend.expression.ast.Expression Expression} inside region. - * + * Search a template for a + * {@link org.eclipse.internal.xtend.expression.ast.Expression Expression} + * inside region. + * * @param hyperlinkRegion - * The region inside the template to search for + * The region inside the template to search for * @param template - * the template to search inside - * - * @return Iff found, the Expression, - * else <code>null</code> + * the template to search inside + * + * @return Iff found, the Expression, else <code>null</code> + * @since 2.0 */ - public static OperationCall findExpressionInTemplate(final IRegion region, + public static OperationCall findExpressionInTemplate(final String name, final Template template) { final Set<OperationCall> targetStatement = new HashSet<OperationCall>(); AbstractDefinition[] defs = template.getAllDefinitions(); - final XtendXpandSearchEngine xxse= new XtendXpandSearchEngine(); - for (AbstractDefinition def : defs) { - if (!targetStatement.isEmpty()) - break; - def.accept(new AbstractXpandVisitor() { - @Override - protected Object visitExpressionStatement(ExpressionStatement node){ - if (node.getExpression() != null) - node.getExpression().accept(xxse.new ExpressionVisitor(region, targetStatement)); - return node; - } - @Override - protected Object visitExpandStatement(ExpandStatement node){ - if (node.getTarget() != null) - node.getTarget().accept(xxse.new ExpressionVisitor(region, targetStatement)); - if (node.getSeparator() != null) - node.getSeparator().accept(xxse.new ExpressionVisitor(region, targetStatement)); - if (node.getParameters() != null) - for (Expression param: node.getParameters()) - param.accept(xxse.new ExpressionVisitor(region, targetStatement)); - return node; - } - @Override - protected Object visitErrorStatement(ErrorStatement node){ - if (node.getMessage() != null) - node.getMessage().accept(xxse.new ExpressionVisitor(region, targetStatement)); - return node; - } - @Override - protected Object visitFileStatement(FileStatement node){ - if (node.getTargetFileName() != null) - node.getTargetFileName().accept(xxse.new ExpressionVisitor(region, targetStatement)); - visitChildren(node.getBodyAsList()); - return node; - } - @Override - protected Object visitForEachStatement(ForEachStatement node){ - if (node.getTarget() != null) - node.getTarget().accept(xxse.new ExpressionVisitor(region, targetStatement)); - if (node.getSeparator() != null) - node.getSeparator().accept(xxse.new ExpressionVisitor(region, targetStatement)); - visitChildren(node.getBodyAsList()); - return node; - } - @Override - protected Object visitIfStatement(IfStatement node){ - if (node.getCondition() != null) - node.getCondition().accept(xxse.new ExpressionVisitor(region, targetStatement)); - visitChildren(node.getBodyAsList()); - visitChild(node.getElseIf()); - return node; - } - @Override - protected Object visitLetStatement(LetStatement node){ - if (node.getVarValue() != null) - node.getVarValue().accept(xxse.new ExpressionVisitor(region, targetStatement)); - visitChildren(node.getBodyAsList()); - return node; - } - @Override - protected Object visitProtectStatement(ProtectStatement node){ - if (node.getCommentStart() != null) - node.getCommentStart().accept(xxse.new ExpressionVisitor(region, targetStatement)); - if (node.getCommentEnd() != null) - node.getCommentEnd().accept(xxse.new ExpressionVisitor(region, targetStatement)); - if (node.getId() != null) - node.getId().accept(xxse.new ExpressionVisitor(region, targetStatement)); - visitChildren(node.getBodyAsList()); - return node; - } - }); - if (!targetStatement.isEmpty()) - return targetStatement.iterator().next(); - } - return null; + final XtendXpandSearchEngine xxse = new XtendXpandSearchEngine(); + for (AbstractDefinition def : defs) { + if (!targetStatement.isEmpty()) + break; + def.accept(new AbstractXpandVisitor() { + @Override + protected Object visitExpressionStatement( + final ExpressionStatement node) { + if (node.getExpression() != null) + node.getExpression().accept( + xxse.new ExpressionVisitor(name, + targetStatement)); + return node; + } + + @Override + protected Object visitExpandStatement(final ExpandStatement node) { + if (node.getTarget() != null) + node.getTarget().accept( + xxse.new ExpressionVisitor(name, + targetStatement)); + if (node.getSeparator() != null) + node.getSeparator().accept( + xxse.new ExpressionVisitor(name, + targetStatement)); + if (node.getParameters() != null) + for (Expression param : node.getParameters()) + param.accept(xxse.new ExpressionVisitor(name, + targetStatement)); + return node; + } + + @Override + protected Object visitErrorStatement(final ErrorStatement node) { + if (node.getMessage() != null) + node.getMessage().accept( + xxse.new ExpressionVisitor(name, + targetStatement)); + return node; + } + + @Override + protected Object visitFileStatement(final FileStatement node) { + if (node.getTargetFileName() != null) + node.getTargetFileName().accept( + xxse.new ExpressionVisitor(name, + targetStatement)); + visitChildren(node.getBodyAsList()); + return node; + } + + @Override + protected Object visitForEachStatement( + final ForEachStatement node) { + if (node.getTarget() != null) + node.getTarget().accept( + xxse.new ExpressionVisitor(name, + targetStatement)); + if (node.getSeparator() != null) + node.getSeparator().accept( + xxse.new ExpressionVisitor(name, + targetStatement)); + visitChildren(node.getBodyAsList()); + return node; + } + + @Override + protected Object visitIfStatement(final IfStatement node) { + if (node.getCondition() != null) + node.getCondition().accept( + xxse.new ExpressionVisitor(name, + targetStatement)); + visitChildren(node.getBodyAsList()); + visitChild(node.getElseIf()); + return node; + } + + @Override + protected Object visitLetStatement(final LetStatement node) { + if (node.getVarValue() != null) + node.getVarValue().accept( + xxse.new ExpressionVisitor(name, + targetStatement)); + visitChildren(node.getBodyAsList()); + return node; + } + + @Override + protected Object visitProtectStatement( + final ProtectStatement node) { + if (node.getCommentStart() != null) + node.getCommentStart().accept( + xxse.new ExpressionVisitor(name, + targetStatement)); + if (node.getCommentEnd() != null) + node.getCommentEnd().accept( + xxse.new ExpressionVisitor(name, + targetStatement)); + if (node.getId() != null) + node.getId().accept( + xxse.new ExpressionVisitor(name, + targetStatement)); + visitChildren(node.getBodyAsList()); + return node; + } + }); + if (!targetStatement.isEmpty()) + return targetStatement.iterator().next(); + } + return null; } /** - * Search a ExtensionFile for a {@link org.eclipse.internal.xtend.expression.ast.OperationCall OperationCall} inside region. - * + * Search a ExtensionFile for a + * {@link org.eclipse.internal.xtend.expression.ast.OperationCall + * OperationCall} inside region. + * * @param hyperlinkRegion - * The region inside the template to search for + * The region inside the template to search for * @param extensionFile - * the ExtensionFile to search inside - * - * @return Iff found, the OperationCall, - * else <code>null</code> + * the ExtensionFile to search inside + * + * @return Iff found, the OperationCall, else <code>null</code> + * @since 2.0 */ - public static OperationCall findExpressionInExtensionFile(final IRegion region, - final ExtensionFile extensionFile) { + public static OperationCall findExpressionInExtensionFile( + final IRegion region, final ExtensionFile extensionFile, + final String name) { final Set<OperationCall> targetStatement = new HashSet<OperationCall>(); - final XtendXpandSearchEngine xxse= new XtendXpandSearchEngine(); - //handle Extensions + final XtendXpandSearchEngine xxse = new XtendXpandSearchEngine(); + // handle Extensions for (Extension extension : extensionFile.getExtensions()) { if (!targetStatement.isEmpty()) break; - if (extension instanceof AbstractExtensionDefinition && extension.getStart() <= region.getOffset() && - extension.getEnd() >= region.getOffset()+region.getLength()) { - AbstractExtensionDefinition abstractExtensionDefinition = (AbstractExtensionDefinition)extension; - abstractExtensionDefinition.getExpression().accept(xxse.new ExpressionVisitor(region, targetStatement)); + if (extension instanceof AbstractExtensionDefinition + && extension.getStart() <= region.getOffset() + && extension.getEnd() >= region.getOffset() + + region.getLength()) { + AbstractExtensionDefinition abstractExtensionDefinition = (AbstractExtensionDefinition) extension; + abstractExtensionDefinition.getExpression().accept( + xxse.new ExpressionVisitor(name, targetStatement)); } - } - //handle Arounds + } + // handle Arounds for (Around around : extensionFile.getArounds()) { if (!targetStatement.isEmpty()) break; - if (around.getStart() <= region.getOffset() && - around.getEnd() >= region.getOffset()+region.getLength()) - around.getExpression().accept(xxse.new ExpressionVisitor(region, targetStatement)); + if (around.getStart() <= region.getOffset() + && around.getEnd() >= region.getOffset() + + region.getLength()) + around.getExpression().accept( + xxse.new ExpressionVisitor(name, targetStatement)); } - //handle Checks + // handle Checks for (Check check : extensionFile.getChecks()) { if (!targetStatement.isEmpty()) break; - if (check.getStart() <= region.getOffset() && - check.getEnd() >= region.getOffset()+region.getLength()) - { - check.getMsg().accept(xxse.new ExpressionVisitor(region, targetStatement)); - check.getConstraint().accept(xxse.new ExpressionVisitor(region, targetStatement)); - if (check.getGuard() != null) - check.getGuard().accept(xxse.new ExpressionVisitor(region, targetStatement)); + if (check.getStart() <= region.getOffset() + && check.getEnd() >= region.getOffset() + + region.getLength()) { + check.getMsg().accept( + xxse.new ExpressionVisitor(name, targetStatement)); + check.getConstraint().accept( + xxse.new ExpressionVisitor(name, targetStatement)); + if (check.getGuard() != null) + check.getGuard().accept( + xxse.new ExpressionVisitor(name, targetStatement)); } } - return targetStatement.isEmpty()?null:targetStatement.iterator().next(); + if (targetStatement.isEmpty()) + return null; + OperationCall result = targetStatement.iterator().next(); + for (OperationCall call : targetStatement) { + if (call.getEnd() < result.getEnd() + || call.getStart() > result.getStart()) + result = call; + } + return result; } /** - * Search a template for a {@link org.eclipse.internal.xpand2.ast.ExpandStatement ExpandStatement} inside given region. - * + * Search a template for a + * {@link org.eclipse.internal.xpand2.ast.ExpandStatement ExpandStatement} + * inside given region. + * * @param region - * The region inside the template to search for + * The region inside the template to search for * @param template - * The template to search inside - * - * @return Iff found, the ExpandStatement, - * else <code>null</code> + * The template to search inside + * + * @return Iff found, the ExpandStatement, else <code>null</code> */ - public static ExpandStatement findDefinition(final String name, final IRegion region, Template template) { + public static ExpandStatement findDefinition(final String name, + final IRegion region, final Template template) { final Set<ExpandStatement> targetStatement = new HashSet<ExpandStatement>(); - for (AbstractDefinition def : template.getAllDefinitions()) { - if (!targetStatement.isEmpty()) - break; - def.accept(new AbstractXpandVisitor() { - @Override - protected Object visitExpandStatement(ExpandStatement node) { - if (node.getStart() <= region.getOffset() && - node.getEnd() >= region.getOffset()+region.getLength() && - node.getDefinition().toString().contains(name.trim())) - targetStatement.add(node); - return super.visitExpandStatement(node); - } - }); - if (!targetStatement.isEmpty()) - return targetStatement.iterator().next(); - } - return null; + for (AbstractDefinition def : template.getAllDefinitions()) { + if (!targetStatement.isEmpty()) + break; + def.accept(new AbstractXpandVisitor() { + @Override + protected Object visitExpandStatement(final ExpandStatement node) { + if (node.getStart() <= region.getOffset() + && node.getEnd() >= region.getOffset() + + region.getLength() + && node.getDefinition().toString() + .contains(name.trim())) + targetStatement.add(node); + return super.visitExpandStatement(node); + } + }); + if (!targetStatement.isEmpty()) + return targetStatement.iterator().next(); + } + return null; } } diff --git a/plugins/org.eclipse.xtend.shared.ui/src/org/eclipse/xtend/shared/ui/editor/navigation/AbstractHyperlinkDetector.java b/plugins/org.eclipse.xtend.shared.ui/src/org/eclipse/xtend/shared/ui/editor/navigation/AbstractHyperlinkDetector.java index c16875b8..77385c56 100644 --- a/plugins/org.eclipse.xtend.shared.ui/src/org/eclipse/xtend/shared/ui/editor/navigation/AbstractHyperlinkDetector.java +++ b/plugins/org.eclipse.xtend.shared.ui/src/org/eclipse/xtend/shared/ui/editor/navigation/AbstractHyperlinkDetector.java @@ -4,25 +4,38 @@ * 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: committers of openArchitectureWare - initial API and * implementation ******************************************************************************/ package org.eclipse.xtend.shared.ui.editor.navigation; import java.util.ArrayList; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.internal.xpand2.ast.AbstractDefinition; import org.eclipse.internal.xpand2.ast.ExtensionImportDeclaration; import org.eclipse.internal.xpand2.ast.Template; import org.eclipse.internal.xtend.expression.ast.DeclaredParameter; +import org.eclipse.internal.xtend.expression.ast.Expression; +import org.eclipse.internal.xtend.expression.ast.Literal; +import org.eclipse.internal.xtend.expression.ast.OperationCall; +import org.eclipse.internal.xtend.expression.ast.SyntaxElement; import org.eclipse.internal.xtend.expression.parser.SyntaxConstants; +import org.eclipse.internal.xtend.type.baseimpl.PolymorphicResolver; +import org.eclipse.internal.xtend.type.baseimpl.types.CollectionTypeImpl; import org.eclipse.internal.xtend.xtend.XtendFile; +import org.eclipse.internal.xtend.xtend.ast.Around; +import org.eclipse.internal.xtend.xtend.ast.Check; import org.eclipse.internal.xtend.xtend.ast.Extension; import org.eclipse.internal.xtend.xtend.ast.ExtensionFile; import org.eclipse.internal.xtend.xtend.ast.ExtensionImportStatement; +import org.eclipse.jdt.core.JavaCore; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.Region; @@ -30,11 +43,17 @@ import org.eclipse.jface.text.hyperlink.IHyperlink; import org.eclipse.jface.text.hyperlink.IHyperlinkDetector; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.xpand2.XpandExecutionContext; +import org.eclipse.xtend.expression.AnalysationIssue; +import org.eclipse.xtend.expression.ExecutionContext; +import org.eclipse.xtend.expression.ExecutionContextImpl; +import org.eclipse.xtend.expression.Variable; import org.eclipse.xtend.shared.ui.Activator; import org.eclipse.xtend.shared.ui.core.IXtendXpandProject; import org.eclipse.xtend.shared.ui.core.IXtendXpandResource; import org.eclipse.xtend.shared.ui.core.search.SearchMatch; import org.eclipse.xtend.shared.ui.core.search.XtendXpandSearchEngine; +import org.eclipse.xtend.typesystem.Type; /** * GenericHyperlinkDetector is used to detect hyperlinkable words inside Xtend @@ -47,49 +66,237 @@ public abstract class AbstractHyperlinkDetector implements IHyperlinkDetector { protected final IEditorPart editor; - public AbstractHyperlinkDetector(IEditorPart editor) { + public AbstractHyperlinkDetector(final IEditorPart editor) { this.editor = editor; } + protected List<GenericHyperlink> computeMatchesAndHyperlinks( + final IRegion hyperlinkRegion, final String hyperlinkedWord, + final IXtendXpandProject project) { + IXtendXpandResource resource = Activator.getExtXptModelManager() + .findExtXptResource(getFile()); + + List<GenericHyperlink> links = createHyperlinkToImportedExtensions( + resource, hyperlinkRegion, hyperlinkedWord); + if (!links.isEmpty()) + return links; + + OperationCall expression = null; + if (resource.getExtXptResource() instanceof XtendFile) { + expression = XtendXpandSearchEngine.findExpressionInExtensionFile( + hyperlinkRegion, + (ExtensionFile) resource.getExtXptResource(), + hyperlinkedWord); + } else { + expression = XtendXpandSearchEngine.findExpressionInTemplate( + hyperlinkedWord, (Template) resource.getExtXptResource()); + } + if (expression == null) + return useGenericHyplerlinkDetector(hyperlinkRegion, + hyperlinkedWord, project); + + List<Type> evaluatedParams = new ArrayList<Type>(); + ContextComputer helper = computeContext(resource, expression); + if (helper == null || helper.getContext() == null) { + return useGenericHyplerlinkDetector(hyperlinkRegion, + hyperlinkedWord, project); + } + ExecutionContext filledContext = helper.getContext(); + if (expression.getParams().length > 0) { + for (Expression ex : expression.getParams()) { + if (ex instanceof Literal) { + Type type = filledContext.getTypeForName(ex.getClass() + .getSimpleName().replaceFirst("Literal", "")); + evaluatedParams.add(type); + } else { + evaluatedParams.add(ex.analyze(filledContext, + new HashSet<AnalysationIssue>())); + } + } + } + Type targetType = null; + if (helper.expressionResult != null + && helper.expressionResult instanceof Type + && expression.getTarget() != null) { + targetType = (Type) helper.expressionResult; + } else { + final Variable var = filledContext + .getVariable(ExecutionContext.IMPLICIT_VARIABLE); + if (var != null) { + targetType = (Type) var.getValue(); + } + } + List<Extension> candidates = new ArrayList<Extension>(); + for (Extension candidate : filledContext.getAllExtensions()) { + if (hyperlinkedWord.equals(candidate.getName())) + candidates.add(candidate); + } + List<Extension> extmatches = new ArrayList<Extension>(candidates.size()); + for (Extension ext : candidates) { + int compare = PolymorphicResolver.typesComparator.compare( + ext.getParameterTypes(), evaluatedParams); + if (compare == 0) { + extmatches.add(0, ext); + } else { + if (compare == 1) { + extmatches.add(ext); + } + } + } + evaluatedParams.add(0, targetType); + for (Extension ext : candidates) { + int compare = PolymorphicResolver.typesComparator.compare( + ext.getParameterTypes(), evaluatedParams); + if (compare == 0) { + extmatches.add(0, ext); + } else { + if (compare == 1) { + extmatches.add(ext); + } + } + } + if (targetType instanceof CollectionTypeImpl) { + evaluatedParams.remove(0); + evaluatedParams.add(((CollectionTypeImpl) targetType) + .getInnerType()); + for (Extension ext : candidates) { + int compare = PolymorphicResolver.typesComparator.compare( + ext.getParameterTypes(), evaluatedParams); + if (compare == 0) { + extmatches.add(0, ext); + } else { + if (compare == 1) { + extmatches.add(ext); + } + } + } + } + return createHyperlink(hyperlinkRegion, hyperlinkedWord, links, + extmatches); + } + + /** + * @since 2.0 + */ + protected List<GenericHyperlink> useGenericHyplerlinkDetector( + final IRegion hyperlinkRegion, final String hyperlinkedWord, + final IXtendXpandProject project) { + GenericHyperlinkDetector genericHyperlinkDetector = new GenericHyperlinkDetector( + editor); + return genericHyperlinkDetector.computeMatchesAndHyperlinks( + hyperlinkRegion, hyperlinkedWord, project); + } + + /** + * @since 2.0 + */ + protected SyntaxElement findOwningElement(final IXtendXpandResource file, + final Expression expression) { + int start = expression.getStart(); + if (file.getExtXptResource() == null) { + return null; + } + if (file.getExtXptResource() instanceof ExtensionFile) { + ExtensionFile extensionFile = (ExtensionFile) file + .getExtXptResource(); + for (Extension ext : extensionFile.getExtensions()) { + if (ext.getStart() <= start && ext.getEnd() >= start) + return (SyntaxElement) ext; + } + for (Check ext : extensionFile.getChecks()) { + if (ext.getStart() <= start && ext.getEnd() >= start) + return ext; + } + for (Around ext : extensionFile.getArounds()) { + if (ext.getStart() <= start && ext.getEnd() >= start) + return ext; + } + } + if (file.getExtXptResource() instanceof Template) { + Template template = (Template) file.getExtXptResource(); + for (AbstractDefinition ext : template.getAllDefinitions()) { + if (ext.getStart() <= start && ext.getEnd() >= start) + return ext; + } + } + return null; + + } + + /** + * @since 2.0 + */ + protected ContextComputer computeContext(final IXtendXpandResource resource, + final Expression expression) { + final SyntaxElement element = findOwningElement(resource, expression); + final IResource file = (IResource) editor.getEditorInput().getAdapter( + IResource.class); + final IProject p = file.getProject(); + ExecutionContext c = Activator.getExecutionContext(JavaCore.create(p)); + ExecutionContextImpl context = (ExecutionContextImpl) c + .cloneWithResource(resource); + ContextComputer callback = new ContextComputer(expression); + context.setVetoableCallBack(callback); + if (element instanceof Extension) { + ((Extension) element).analyze(context, + new HashSet<AnalysationIssue>()); + } + if (element instanceof AbstractDefinition) { + ((AbstractDefinition) element).analyze( + (XpandExecutionContext) context, + new HashSet<AnalysationIssue>()); + } + if (element instanceof Check) { + ((Check) element).analyze(context, new HashSet<AnalysationIssue>()); + } + if (element instanceof Around) { + ((Around) element) + .analyze(context, new HashSet<AnalysationIssue>()); + } + return callback; + } + /** * {@inheritDoc} */ - public IHyperlink[] detectHyperlinks(ITextViewer textViewer, IRegion region, boolean canShowMultipleHyperlinks) { + public IHyperlink[] detectHyperlinks(final ITextViewer textViewer, + final IRegion region, final boolean canShowMultipleHyperlinks) { if (region == null || textViewer == null) { return null; } // get hyperlinked region - IRegion hyperlinkRegion = getHyperlinkRegion(textViewer, region.getOffset()); + IRegion hyperlinkRegion = getHyperlinkRegion(textViewer, + region.getOffset()); if (hyperlinkRegion == null) { return null; } // get the word that is hyperlinked - String hyperlinkedWord = textViewer.getDocument().get().substring(hyperlinkRegion.getOffset(), - hyperlinkRegion.getOffset() + hyperlinkRegion.getLength()); + String hyperlinkedWord = textViewer + .getDocument() + .get() + .substring( + hyperlinkRegion.getOffset(), + hyperlinkRegion.getOffset() + + hyperlinkRegion.getLength()); IXtendXpandProject project = getXtendXpandProject(); if (project != null) { - List<GenericHyperlink> links = computeMatchesAndHyperlinks(hyperlinkRegion, hyperlinkedWord, project); + List<GenericHyperlink> links = computeMatchesAndHyperlinks( + hyperlinkRegion, hyperlinkedWord, project); // must return null if no links found if (!links.isEmpty()) { - if (canShowMultipleHyperlinks) { - return links.toArray(new IHyperlink[links.size()]); + if (canShowMultipleHyperlinks) { + return links.toArray(new IHyperlink[links.size()]); } else { - return new IHyperlink[] { links.get(0) }; + return new IHyperlink[] { links.get(0) }; + } } } - } return null; } - /** - * Concrete classes have to implement strategies to compute hyperlinks. - */ - abstract protected List<GenericHyperlink> computeMatchesAndHyperlinks(IRegion hyperlinkRegion, String hyperlinkedWord, - IXtendXpandProject project); - protected IWorkbenchPage getWorkbenchPage() { return editor.getSite().getWorkbenchWindow().getActivePage(); } @@ -117,7 +324,8 @@ public abstract class AbstractHyperlinkDetector implements IHyperlinkDetector { * The cursor location. * @return The document region defining the hyperlinked word. */ - protected IRegion getHyperlinkRegion(ITextViewer textViewer, int offset) { + protected IRegion getHyperlinkRegion(final ITextViewer textViewer, + final int offset) { String currDoc = textViewer.getDocument().get(); // special handling if cursor is located at end of document @@ -134,7 +342,8 @@ public abstract class AbstractHyperlinkDetector implements IHyperlinkDetector { // find word end start++; int end = offset; - while (end < currDoc.length() && WordDetector.isWordPart(currDoc.charAt(end))) { + while (end < currDoc.length() + && WordDetector.isWordPart(currDoc.charAt(end))) { end++; } @@ -148,139 +357,163 @@ public abstract class AbstractHyperlinkDetector implements IHyperlinkDetector { return new Region(start, end - start); } - + /** * Provides a label for a extension or definition with given parameter list. * * @param name - * The name of the element - * @param params - * A list of parameters declared by the element {@link org.eclipse.internal.xtend.expression.ast.DeclaredParameter DeclaredParameter} + * The name of the element + * @param params + * A list of parameters declared by the element + * {@link org.eclipse.internal.xtend.expression.ast.DeclaredParameter + * DeclaredParameter} * - * @return A label: name(params,...) - FileName + * @return A label: name(params,...) - FileName */ - protected String computeHyperlinkLabel(String name, String typeName, List<DeclaredParameter> params, - IXtendXpandResource xxresource) { + protected String computeHyperlinkLabel(final String name, + final String typeName, final List<DeclaredParameter> params, + final IXtendXpandResource xxresource) { StringBuffer label = new StringBuffer(name); if (!params.isEmpty()) { label.append("("); - for (Iterator<DeclaredParameter> iter = params.iterator(); iter.hasNext();) { + for (Iterator<DeclaredParameter> iter = params.iterator(); iter + .hasNext();) { DeclaredParameter param = iter.next(); label.append(param.getType().toString()); - label.append(" "+param.getName().toString()); - if (iter.hasNext()) label.append(", "); - + label.append(" " + param.getName().toString()); + if (iter.hasNext()) + label.append(", "); + } label.append(")"); } if (typeName != null) - label.append(" : "+typeName); + label.append(" : " + typeName); if (!xxresource.getUnderlyingStorage().equals(getFile())) - label.append(" - " + xxresource.getUnderlyingStorage().getName().toString().replace("."+xxresource.getFileExtension(), "")); + label.append(" - " + + xxresource.getUnderlyingStorage().getName().toString() + .replace("." + xxresource.getFileExtension(), "")); return label.toString(); } - + protected IXtendXpandResource _xxresource = null; - + /** - * A cached getter for a {@link org.eclipse.xtend.shared.ui.core.IXtendXpandResource IXtendXpandResource}. + * A cached getter for a + * {@link org.eclipse.xtend.shared.ui.core.IXtendXpandResource + * IXtendXpandResource}. * - * @param fqName - * The full qualified name of the resource - * @param extension - * The kind of resource + * @param fqName + * The full qualified name of the resource + * @param extension + * The kind of resource * - * @return The value of _xxresource if _xxresource is filled and the names are equal. - * Otherwise the ModelManager tries to find that file. + * @return The value of _xxresource if _xxresource is filled and the names + * are equal. Otherwise the ModelManager tries to find that file. */ - protected IXtendXpandResource getXXResourceByName(String fqName, String extension) { - if (_xxresource != null && _xxresource.getFileExtension().equals(extension) && _xxresource.getFullyQualifiedName().equals(fqName)) + protected IXtendXpandResource getXXResourceByName(final String fqName, + final String extension) { + if (_xxresource != null + && _xxresource.getFileExtension().equals(extension) + && _xxresource.getFullyQualifiedName().equals(fqName)) return _xxresource; - else - { - _xxresource = Activator.getExtXptModelManager().findXtendXpandResource( - fqName.replaceAll(SyntaxConstants.NS_DELIM, "/"),extension); + else { + _xxresource = Activator.getExtXptModelManager() + .findXtendXpandResource( + fqName.replaceAll(SyntaxConstants.NS_DELIM, "/"), + extension); return _xxresource; } } - - /** - * Find an extension with name: <em>hyplerlinkedWord</em> in extension <em>xtendResource</em>. The extension and - * all (re)imported extensions are searched for. - */ - protected List<GenericHyperlink> findExtensionMatches(IRegion hyperlinkRegion, String hyperlinkedWord, IXtendXpandProject project, - IXtendXpandResource xtendResource, List<GenericHyperlink> links, int paramListLength) { - List<Extension> extmatches = XtendXpandSearchEngine.findExtensionsByNameInResourceAndImports(project, hyperlinkedWord, xtendResource); + + private List<GenericHyperlink> createHyperlink( + final IRegion hyperlinkRegion, final String hyperlinkedWord, + final List<GenericHyperlink> links, final List<Extension> extmatches) { for (Extension ext : extmatches) { - if ( ext.getFormalParameters().size() == paramListLength || - paramListLength+1 == ext.getFormalParameters().size() ) //implicit 'this' parameter { - SearchMatch match = new SearchMatch( - ext.getStart(), - ext.getEnd() - ext.getStart() + 1 /* - * sorry - * for - * the - * "+1"-hack - */, - getXXResourceByName(ext.getFileName(), XtendFile.FILE_EXTENSION).getUnderlyingStorage()); + SearchMatch match = new SearchMatch(ext.getStart(), + ext.getEnd() - ext.getStart() + 1 /* + * sorry for the + * "+1"-hack + */, + getXXResourceByName(ext.getFileName(), + XtendFile.FILE_EXTENSION) + .getUnderlyingStorage()); GenericHyperlink genericHyperlink = new GenericHyperlink( - getWorkbenchPage(), - match, - hyperlinkRegion, - computeHyperlinkLabel(hyperlinkedWord, (ext.getReturnTypeIdentifier() == null) ? null : ext.getReturnTypeIdentifier().toString(), ext.getFormalParameters(), getXXResourceByName(ext.getFileName(), XtendFile.FILE_EXTENSION)) - ); - + getWorkbenchPage(), match, hyperlinkRegion, + computeHyperlinkLabel( + hyperlinkedWord, + (ext.getReturnTypeIdentifier() == null) ? null + : ext.getReturnTypeIdentifier() + .toString(), + ext.getFormalParameters(), + getXXResourceByName(ext.getFileName(), + XtendFile.FILE_EXTENSION))); + links.add(genericHyperlink); } } return links; } - - protected List<GenericHyperlink> createHyperlinkToImportedExtensions(IXtendXpandResource resource, IRegion region, String hyperlinkedName) { + + protected List<GenericHyperlink> createHyperlinkToImportedExtensions( + final IXtendXpandResource resource, final IRegion region, + final String hyperlinkedName) { List<GenericHyperlink> links = new ArrayList<GenericHyperlink>(); IXtendXpandResource xxresource = null; - if (resource.getExtXptResource() instanceof ExtensionFile) - { - ExtensionFile extensionFile = (ExtensionFile)resource.getExtXptResource(); - for (ExtensionImportStatement importStatement : extensionFile.getExtImports()) - { - if (importStatement.getImportedId().toString().contains(hyperlinkedName) && - importStatement.getStart() <= region.getOffset() && - importStatement.getEnd() >= region.getOffset()+region.getLength()) - { - xxresource =Activator.getExtXptModelManager().findXtendXpandResource(importStatement.getImportedId().toString(), XtendFile.FILE_EXTENSION); - if (xxresource != null) - { + if (resource.getExtXptResource() instanceof ExtensionFile) { + ExtensionFile extensionFile = (ExtensionFile) resource + .getExtXptResource(); + for (ExtensionImportStatement importStatement : extensionFile + .getExtImports()) { + if (importStatement.getImportedId().toString() + .contains(hyperlinkedName) + && importStatement.getStart() <= region.getOffset() + && importStatement.getEnd() >= region.getOffset() + + region.getLength()) { + xxresource = Activator.getExtXptModelManager() + .findXtendXpandResource( + importStatement.getImportedId().toString(), + XtendFile.FILE_EXTENSION); + if (xxresource != null) { GenericHyperlink genericHyperlink = new GenericHyperlink( - getWorkbenchPage(), - new SearchMatch(0, 0, xxresource.getUnderlyingStorage()), - new Region(importStatement.getImportedId().getStart(), importStatement.getImportedId().getEnd() - importStatement.getImportedId().getStart()+1), - importStatement.getImportedId().toString() - ); + getWorkbenchPage(), new SearchMatch(0, 0, + xxresource.getUnderlyingStorage()), + new Region(importStatement.getImportedId() + .getStart(), importStatement + .getImportedId().getEnd() + - importStatement.getImportedId() + .getStart() + 1), + importStatement.getImportedId().toString()); links.add(genericHyperlink); } } } } - if (resource.getExtXptResource() instanceof Template) - { - Template template = (Template)resource.getExtXptResource(); - for (ExtensionImportDeclaration importStatement : template.getExtensions()) - { - if (importStatement.getImportString().toString().contains(hyperlinkedName) && - importStatement.getStart() <= region.getOffset() && - importStatement.getEnd() >= region.getOffset()+region.getLength()) - { - xxresource =Activator.getExtXptModelManager().findXtendXpandResource(importStatement.getImportString().toString(), XtendFile.FILE_EXTENSION); - if (xxresource != null) - { + if (resource.getExtXptResource() instanceof Template) { + Template template = (Template) resource.getExtXptResource(); + for (ExtensionImportDeclaration importStatement : template + .getExtensions()) { + if (importStatement.getImportString().toString() + .contains(hyperlinkedName) + && importStatement.getStart() <= region.getOffset() + && importStatement.getEnd() >= region.getOffset() + + region.getLength()) { + xxresource = Activator.getExtXptModelManager() + .findXtendXpandResource( + importStatement.getImportString() + .toString(), + XtendFile.FILE_EXTENSION); + if (xxresource != null) { GenericHyperlink genericHyperlink = new GenericHyperlink( - getWorkbenchPage(), - new SearchMatch(0, 0, xxresource.getUnderlyingStorage()), - new Region(importStatement.getImportString().getStart(), importStatement.getImportString().getEnd() - importStatement.getImportString().getStart()+1), - importStatement.getImportString().toString() - ); + getWorkbenchPage(), new SearchMatch(0, 0, + xxresource.getUnderlyingStorage()), + new Region(importStatement.getImportString() + .getStart(), importStatement + .getImportString().getEnd() + - importStatement.getImportString() + .getStart() + 1), + importStatement.getImportString().toString()); links.add(genericHyperlink); } } diff --git a/plugins/org.eclipse.xtend.shared.ui/src/org/eclipse/xtend/shared/ui/editor/navigation/ContextComputer.java b/plugins/org.eclipse.xtend.shared.ui/src/org/eclipse/xtend/shared/ui/editor/navigation/ContextComputer.java new file mode 100644 index 00000000..0b532072 --- /dev/null +++ b/plugins/org.eclipse.xtend.shared.ui/src/org/eclipse/xtend/shared/ui/editor/navigation/ContextComputer.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2014 itemis AG (http://www.itemis.eu) and others. + * 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 + *******************************************************************************/ +package org.eclipse.xtend.shared.ui.editor.navigation; + +import org.eclipse.internal.xtend.expression.ast.Expression; +import org.eclipse.internal.xtend.expression.ast.FeatureCall; +import org.eclipse.internal.xtend.expression.ast.SyntaxElement; +import org.eclipse.xtend.expression.ExecutionContext; +import org.eclipse.xtend.expression.VetoableCallback; + +/** + * Used by the {@link AbstractHyperlinkDetector} to compute the ExecutionContext + * for a given Expression. Iff the expression is a {@link FeatureCall} also the + * evaluated expression result of the target is stored. + * + * @author jockel - Initial contribution and API + * @since 2.0 + */ +public class ContextComputer implements VetoableCallback { + + private final Expression se; + ExecutionContext context = null; + Object expressionResult = null; + + public ContextComputer(final Expression se) { + this.se = se; + } + + public ExecutionContext getContext() { + return context; + } + + public boolean pre(final SyntaxElement ele, final ExecutionContext ctx) { + return true; + } + + public void post(final SyntaxElement ele, final ExecutionContext ctx, + final Object expressionResult) { + if (se.equals(ele)) { + context = ctx.cloneWithoutMonitor(); + } + if ((se instanceof FeatureCall) + && ele.equals(((FeatureCall) se).getTarget())) { + this.expressionResult = expressionResult; + } + } + +} diff --git a/plugins/org.eclipse.xtend.shared.ui/src/org/eclipse/xtend/shared/ui/editor/navigation/GenericHyperlinkDetector.java b/plugins/org.eclipse.xtend.shared.ui/src/org/eclipse/xtend/shared/ui/editor/navigation/GenericHyperlinkDetector.java index b213304c..c2392919 100644 --- a/plugins/org.eclipse.xtend.shared.ui/src/org/eclipse/xtend/shared/ui/editor/navigation/GenericHyperlinkDetector.java +++ b/plugins/org.eclipse.xtend.shared.ui/src/org/eclipse/xtend/shared/ui/editor/navigation/GenericHyperlinkDetector.java @@ -4,7 +4,7 @@ * 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: committers of openArchitectureWare - initial API and * implementation ******************************************************************************/ @@ -28,22 +28,24 @@ import org.eclipse.xtend.shared.ui.core.search.XtendXpandSearchEngine; */ public class GenericHyperlinkDetector extends AbstractHyperlinkDetector { - public GenericHyperlinkDetector(IEditorPart editor) { + public GenericHyperlinkDetector(final IEditorPart editor) { super(editor); } @Override - protected List<GenericHyperlink> computeMatchesAndHyperlinks(IRegion hyperlinkRegion, String hyperlinkedWord, - IXtendXpandProject project) { - List<SearchMatch> matches = XtendXpandSearchEngine.findDeclarations(project, hyperlinkedWord); + protected List<GenericHyperlink> computeMatchesAndHyperlinks( + final IRegion hyperlinkRegion, final String hyperlinkedWord, + final IXtendXpandProject project) { + List<SearchMatch> matches = XtendXpandSearchEngine.findDeclarations( + project, hyperlinkedWord); List<GenericHyperlink> links = new ArrayList<GenericHyperlink>(); for (SearchMatch searchMatch : matches) { - GenericHyperlink genericHyperlink = new GenericHyperlink(getWorkbenchPage(), searchMatch, - hyperlinkRegion, hyperlinkedWord); + GenericHyperlink genericHyperlink = new GenericHyperlink( + getWorkbenchPage(), searchMatch, hyperlinkRegion, + hyperlinkedWord); links.add(genericHyperlink); } return links; } - } diff --git a/plugins/org.eclipse.xtend.shared.ui/src/org/eclipse/xtend/shared/ui/expression/XpandPluginExecutionContext.java b/plugins/org.eclipse.xtend.shared.ui/src/org/eclipse/xtend/shared/ui/expression/XpandPluginExecutionContext.java index 6d3c62f3..c7e47841 100755 --- a/plugins/org.eclipse.xtend.shared.ui/src/org/eclipse/xtend/shared/ui/expression/XpandPluginExecutionContext.java +++ b/plugins/org.eclipse.xtend.shared.ui/src/org/eclipse/xtend/shared/ui/expression/XpandPluginExecutionContext.java @@ -32,6 +32,7 @@ import org.eclipse.xtend.expression.ResourceManager; import org.eclipse.xtend.expression.ResourceParser; import org.eclipse.xtend.expression.TypeSystemImpl; import org.eclipse.xtend.expression.Variable; +import org.eclipse.xtend.expression.VetoableCallback; import org.eclipse.xtend.shared.ui.core.IXtendXpandProject; import org.eclipse.xtend.shared.ui.core.internal.BuildState; import org.eclipse.xtend.typesystem.Type; @@ -55,7 +56,8 @@ public class XpandPluginExecutionContext extends final IXtendXpandProject xp, final Map<Pair<String, List<Type>>, Type> extensionsReturnTypeCache) { this(resourceManager, currentResource, typeSystem, vars, globalVars, - output, prs, monitor, xp, extensionsReturnTypeCache, null, null); + output, prs, monitor, xp, extensionsReturnTypeCache, null, + null, null); } /** @@ -73,13 +75,14 @@ public class XpandPluginExecutionContext extends final IXtendXpandProject xp, final Map<Pair<String, List<Type>>, Type> extensionsReturnTypeCache, final Map<Resource, Set<Extension>> allExtensionsPerResource, + final VetoableCallback vetoableCallback, final Cache<Triplet<Resource, String, List<Type>>, Extension> extensionsForNameAndTypesCache) { // to solve bug#312571: added DevNullExceptionHandler Without an // ExceptionHandler RuntimeExceptions will cause an abort of analyzing // Expressions. super(resourceManager, currentResource, typeSystem, vars, globalVars, output, prs, monitor, new DevNullExceptionHandler(), null, - null, allExtensionsPerResource, null, + null, allExtensionsPerResource, vetoableCallback, extensionsForNameAndTypesCache, extensionsReturnTypeCache, null); project = xp; } @@ -90,7 +93,8 @@ public class XpandPluginExecutionContext extends currentResource(), typeSystem, getVisibleVariables(), getGlobalVariables(), output, protectedRegionResolver, getMonitor(), project, extensionsReturnTypeCache, - allExtensionsPerResource, extensionsForNameAndTypesCache); + allExtensionsPerResource, callback, + extensionsForNameAndTypesCache); } public static class PluginResourceManager implements ResourceManager { diff --git a/plugins/org.eclipse.xtend.ui/src/org/eclipse/xtend/ui/editor/XtendHyperlinkDetector.java b/plugins/org.eclipse.xtend.ui/src/org/eclipse/xtend/ui/editor/XtendHyperlinkDetector.java index c7106994..64e6bb05 100644 --- a/plugins/org.eclipse.xtend.ui/src/org/eclipse/xtend/ui/editor/XtendHyperlinkDetector.java +++ b/plugins/org.eclipse.xtend.ui/src/org/eclipse/xtend/ui/editor/XtendHyperlinkDetector.java @@ -4,53 +4,22 @@ * 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: committers of openArchitectureWare - initial API and * implementation ******************************************************************************/ package org.eclipse.xtend.ui.editor; -import java.util.Collections; -import java.util.List; - -import org.eclipse.internal.xtend.expression.ast.OperationCall; -import org.eclipse.internal.xtend.xtend.ast.ExtensionFile; -import org.eclipse.jface.text.IRegion; import org.eclipse.ui.IEditorPart; -import org.eclipse.xtend.shared.ui.Activator; -import org.eclipse.xtend.shared.ui.core.IXtendXpandProject; -import org.eclipse.xtend.shared.ui.core.IXtendXpandResource; -import org.eclipse.xtend.shared.ui.core.search.XtendXpandSearchEngine; import org.eclipse.xtend.shared.ui.editor.navigation.AbstractHyperlinkDetector; -import org.eclipse.xtend.shared.ui.editor.navigation.GenericHyperlink; - /** * @author Darius Jockel - Initial contribution and API */ public class XtendHyperlinkDetector extends AbstractHyperlinkDetector { - public XtendHyperlinkDetector(IEditorPart editor) { + public XtendHyperlinkDetector(final IEditorPart editor) { super(editor); } - - @Override - protected List<GenericHyperlink> computeMatchesAndHyperlinks(IRegion hyperlinkRegion, String hyperlinkedWord, - IXtendXpandProject project) { - IXtendXpandResource resource = Activator.getExtXptModelManager().findExtXptResource(getFile()); - - List<GenericHyperlink> links = createHyperlinkToImportedExtensions(resource, hyperlinkRegion, hyperlinkedWord); - if (!links.isEmpty()) - return links; - - OperationCall expression = XtendXpandSearchEngine.findExpressionInExtensionFile(hyperlinkRegion, (ExtensionFile)resource.getExtXptResource()); - - if (expression == null) - return Collections.<GenericHyperlink>emptyList(); - - return findExtensionMatches(hyperlinkRegion, hyperlinkedWord, project, resource, links, expression.getParams().length); - } - - } |