aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormclay2009-03-08 16:42:18 (EDT)
committersefftinge2009-03-08 16:42:18 (EDT)
commit99fad5578572a3fa87098ba6c2b22a7332b7ff18 (patch)
tree1acf3681e313ba73e7fbe13a23480791d613f278
parentfd900f5f2c54fcdc3db22ebcc52814453646358b (diff)
downloadorg.eclipse.xtext-99fad5578572a3fa87098ba6c2b22a7332b7ff18.zip
org.eclipse.xtext-99fad5578572a3fa87098ba6c2b22a7332b7ff18.tar.gz
org.eclipse.xtext-99fad5578572a3fa87098ba6c2b22a7332b7ff18.tar.bz2
[Code Completion] Compute proposals for two different contexts https://bugs.eclipse.org/bugs/show_bug.cgi?id=263770
-rw-r--r--plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/IProposalProvider.java75
-rw-r--r--plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/AbstractJavaProposalProvider.java128
-rw-r--r--plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/DefaultContentAssistCalculator.java90
-rw-r--r--plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/DefaultContentAssistProcessor.java192
-rw-r--r--plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/JavaReflectiveMethodInvoker.java3
-rw-r--r--plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/ProposalFilterSorterUtil.java37
-rw-r--r--plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/XtextCompletionProposal.java54
-rw-r--r--plugins/org.eclipse.xtext.xtend/src/org/eclipse/xtext/xtend/contentassist/AbstractXtendProposalProvider.java32
-rw-r--r--tests/org.eclipse.xtext.ui.common.tests/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/ContentAssistProcessorTestBuilder.java44
-rw-r--r--tests/org.eclipse.xtext.ui.common.tests/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/DefaultContentAssistProcessorTest.java49
-rw-r--r--tests/org.eclipse.xtext.ui.common.tests/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/TwoContextsContentAssistTest.java5
11 files changed, 248 insertions, 461 deletions
diff --git a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/IProposalProvider.java b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/IProposalProvider.java
index 05ba96d..1b7691f 100644
--- a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/IProposalProvider.java
+++ b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/IProposalProvider.java
@@ -1,3 +1,11 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Michael Clay 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.xtext.ui.common.editor.contentassist;
import java.util.List;
@@ -10,20 +18,16 @@ import org.eclipse.xtext.Keyword;
import org.eclipse.xtext.RuleCall;
/**
- *
* @author Sven Efftinge - Initial contribution and API
* @author Michael Clay
*/
public interface IProposalProvider {
-
/**
* Is invoked by the framework if (with respect to the grammar) it is
* possible that the keyword passed as first parameter can occur next up.
*
- * @param keyword
- * the <code>Keyword</code> to be completed
- * @param contentAssistContext
- * the current context of the content assist
+ * @param keyword the <code>Keyword</code> to be completed
+ * @param contentAssistContext the current context of the content assist
* @return a list of matching {@link ICompletionProposal}
*/
List<? extends ICompletionProposal> completeKeyword(Keyword keyword, IContentAssistContext contentAssistContext);
@@ -32,10 +36,8 @@ public interface IProposalProvider {
* Is invoked by the framework if (with respect to the grammar) it is
* possible that the rule call passed as first parameter can occur next up.
*
- * @param ruleCall
- * the <code>RuleCall</code> to be completed
- * @param contentAssistContext
- * the current context of the content assist
+ * @param ruleCall the <code>RuleCall</code> to be completed
+ * @param contentAssistContext the current context of the content assist
* @return a list of matching {@link ICompletionProposal}
*/
List<? extends ICompletionProposal> completeRuleCall(RuleCall ruleCall, IContentAssistContext contentAssistContext);
@@ -44,10 +46,8 @@ public interface IProposalProvider {
* Is invoked by the framework if (with respect to the grammar) it is
* possible that the assignment passed as first parameter can occur next up.
*
- * @param assignment
- * the <code>Assignment</code> to be completed
- * @param contentAssistContext
- * the current context of the content assist
+ * @param assignment the <code>Assignment</code> to be completed
+ * @param contentAssistContext the current context of the content assist
* @return a list of matching {@link ICompletionProposal}
*/
List<? extends ICompletionProposal> completeAssignment(Assignment assignment, IContentAssistContext contentAssistContext);
@@ -56,10 +56,8 @@ public interface IProposalProvider {
* Returns the context type that can handle template insertion at the given
* region in the viewer's document.
*
- * @param keyword
- * the <code>Keyword</code> to be completed
- * @param contentAssistContext
- * the current context of the content assist
+ * @param keyword the <code>Keyword</code> to be completed
+ * @param contentAssistContext the current context of the content assist
* @return the context type that can handle template expansion for the given
* location, or <code>null</code> if none exists
*/
@@ -69,37 +67,40 @@ public interface IProposalProvider {
* Returns the context type that can handle template insertion at the given
* region in the viewer's document.
*
- * @param ruleCall
- * the <code>RuleCall</code>
- * @param contentAssistContext
- * the current context of the content assist
+ * @param ruleCall the <code>RuleCall</code>
+ * @param contentAssistContext the current context of the content assist
* @return the context type that can handle template expansion for the given
* location, or <code>null</code> if none exists
*/
TemplateContextType getTemplateContextType(RuleCall ruleCall, IContentAssistContext contentAssistContext);
-
+
/**
* Returns the templates valid for the context type specified by
* <code>contextTypeId</code>.
*
- * @param contextTypeId
- * the context type id
+ * @param contextTypeId the context type id
* @return the templates valid for this context type id
*/
Template[] getTemplates(String contextTypeId);
-
+
/**
- * Used to filter and sort a list of completion proposals. This method is
- * invoked by the framework after all possible completions have been
- * collected.
+ * Used to filter the given list of completion proposals.
+ * <p/>
+ * This method is after all possible completions and templates have been collected.
*
- * @param completionProposalList
- * matching {@link ICompletionProposal} to sort and filter
- * @param contentAssistContext
- * the current context of the content assist
- * @return the sorted and filtered <code>ICompletionProposal</code> list.
+ * @param completionProposalList the collected list of {@link ICompletionProposal} to filter
+ * @param contentAssistContext the current context of the content assist
+ * @return the filtered <code>ICompletionProposal</code> list.
*/
- List<? extends ICompletionProposal> sortAndFilter(List<? extends ICompletionProposal> completionProposalList,
- IContentAssistContext contentAssistContext);
-
+ List<? extends ICompletionProposal> filter(List<ICompletionProposal> completionProposalList,IContentAssistContext contentAssistContext);
+
+ /**
+ * Used to sort the given list of completion proposals.
+ * <p/>
+ * This method is after all possible completions and templates have been collected and filtered.
+ *
+ * @param completionProposalList the collected list of {@link ICompletionProposal} to sort
+ * @return the sorted <code>ICompletionProposal</code> list.
+ */
+ List<? extends ICompletionProposal> sort(List<ICompletionProposal> completionProposalList);
}
diff --git a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/AbstractJavaProposalProvider.java b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/AbstractJavaProposalProvider.java
index c28854d..5b01ea7 100644
--- a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/AbstractJavaProposalProvider.java
+++ b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/AbstractJavaProposalProvider.java
@@ -45,16 +45,13 @@ import com.google.inject.Inject;
* @author Jan Köhnlein - Initial contribution and API
*/
public abstract class AbstractJavaProposalProvider implements IProposalProvider {
-
// constants
// protected static final String LEXER_RULE_ID = "ID";
protected static final String LEXER_RULE_INT = "INT";
protected static final String LEXER_RULE_STRING = "STRING";
// logger available to subclasses
- protected final static Logger logger = Logger
- .getLogger(IProposalProvider.class);
-
+ protected final static Logger logger = Logger.getLogger(IProposalProvider.class);
@Inject
protected IScopeProvider scopeProvider;
@@ -63,7 +60,6 @@ public abstract class AbstractJavaProposalProvider implements IProposalProvider
protected AbstractJavaProposalProvider() {
invoker = new JavaReflectiveMethodInvoker(this);
}
-
/**
* @see org.eclipse.xtext.ui.common.editor.contentassist.IProposalProvider#completeKeyword(Keyword,
* IContentAssistContext)
@@ -71,10 +67,8 @@ public abstract class AbstractJavaProposalProvider implements IProposalProvider
public List<? extends ICompletionProposal> completeKeyword(Keyword keyword,
IContentAssistContext contentAssistContext) {
if (logger.isDebugEnabled()) {
- logger.debug("completeKeyword '" + keyword.getValue()
- + "' for model '" + contentAssistContext.getModel()
- + "' and prefix '"
- + contentAssistContext.getMatchString().trim() + "'");
+ logger.debug("completeKeyword '" + keyword.getValue()+ "' for model '" + contentAssistContext.getModel()
+ + "' and prefix '"+ contentAssistContext.getMatchString().trim() + "'");
}
return Collections.singletonList(createCompletionProposal(keyword,
keyword.getValue(), contentAssistContext));
@@ -87,41 +81,21 @@ public abstract class AbstractJavaProposalProvider implements IProposalProvider
public List<? extends ICompletionProposal> completeRuleCall(
RuleCall ruleCall, IContentAssistContext contentAssistContext) {
if (logger.isDebugEnabled()) {
- logger
- .debug("completeRuleCall '"
- + ruleCall.getRule().getName()
- + "' cardinality '"
- + ruleCall.getCardinality()
- + "' for model '"
- + contentAssistContext.getModel()
- + "' and prefix '"
- + contentAssistContext.getMatchString().trim()
- .trim() + "'");
+ logger.debug("completeRuleCall '"+ ruleCall.getRule().getName()+ "' cardinality '"
+ + ruleCall.getCardinality()+ "' for model '"+ contentAssistContext.getModel()
+ + "' and prefix '"+ contentAssistContext.getMatchString().trim().trim() + "'");
}
-
AbstractRule calledRule = ruleCall.getRule();
-
if (calledRule instanceof TerminalRule) {
- return completeTerminalRuleRuleCall((TerminalRule) calledRule, ruleCall,
- contentAssistContext);
+ return completeTerminalRuleRuleCall((TerminalRule) calledRule, ruleCall,contentAssistContext);
} else if (calledRule.getType() != null) {
-
TypeRef typeRef = calledRule.getType();
-
- return invokeMethod(
- "complete"
- + Strings.toFirstUpper(typeRef.getMetamodel()
- .getAlias()) + "_"
+ return invokeMethod("complete"+ Strings.toFirstUpper(typeRef.getMetamodel().getAlias()) + "_"
+ Strings.toFirstUpper(typeRef.getClassifier().getName()),
- Arrays
- .<Class<?>> asList(
- RuleCall.class,
- contentAssistContext.getModel() == null ? EObject.class
- : contentAssistContext.getModel()
- .getClass(),
- IContentAssistContext.class), Arrays
- .asList(ruleCall, contentAssistContext.getModel(),
- contentAssistContext));
+ Arrays.<Class<?>> asList(RuleCall.class,contentAssistContext.getModel() == null ?
+ EObject.class : contentAssistContext.getModel().getClass(),
+ IContentAssistContext.class), Arrays.asList(ruleCall,
+ contentAssistContext.getModel(),contentAssistContext));
}
return Collections.emptyList();
}
@@ -134,12 +108,9 @@ public abstract class AbstractJavaProposalProvider implements IProposalProvider
Assignment assignment, IContentAssistContext contentAssistContext) {
ParserRule parserRule = GrammarUtil.containingParserRule(assignment);
// TODO : Better call completeRuleCall ?
- return invokeMethod("complete"
- + Strings.toFirstUpper(parserRule.getName()) + "_"
- + Strings.toFirstUpper(assignment.getFeature()), Arrays
- .<Class<?>> asList(Assignment.class,
- IContentAssistContext.class), Arrays.asList(assignment,
- contentAssistContext));
+ return invokeMethod("complete"+ Strings.toFirstUpper(parserRule.getName()) + "_"+
+ Strings.toFirstUpper(assignment.getFeature()), Arrays.<Class<?>> asList(Assignment.class,
+ IContentAssistContext.class), Arrays.asList(assignment,contentAssistContext));
}
/**
@@ -149,20 +120,13 @@ public abstract class AbstractJavaProposalProvider implements IProposalProvider
protected ICompletionProposal createCompletionProposal(
AbstractElement abstractElement, String displayString,
IContentAssistContext contentAssistContext) {
- return new XtextCompletionProposal(abstractElement, displayString,
- contentAssistContext);
+ return new XtextCompletionProposal(abstractElement, displayString,contentAssistContext);
}
@SuppressWarnings("unchecked")
- protected List<? extends ICompletionProposal> invokeMethod(
- String methodName, List<Class<?>> parameterTypes,
+ protected List<? extends ICompletionProposal> invokeMethod(String methodName, List<Class<?>> parameterTypes,
List<?> parameterValues) {
- try {
- return (List<? extends ICompletionProposal>) invoker.invoke(
- methodName, parameterTypes, parameterValues);
- } catch (NullPointerException exc) {
- return null;
- }
+ return (List<? extends ICompletionProposal>) invoker.invoke(methodName, parameterTypes, parameterValues);
}
/**
@@ -231,23 +195,21 @@ public abstract class AbstractJavaProposalProvider implements IProposalProvider
*/
protected abstract String getDefaultImageFilePath();
- /**
- * Concrete subclasses can override this for custom sort and filter
- * behavior. Called right after all completion proposals have been
- * collected.
- *
- * The default behavior of this implementation is to filter duplicates and
- * to trim matching <code>ICompletionProposal#displayString</code> with
- * matching prefix values.
- *
- * @see #sortAndFilter(List, EObject, String, IDocument, int, AbstractNode,
- * LeafNode)
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.xtext.ui.common.editor.contentassist.IProposalProvider#filter(java.util.List, org.eclipse.xtext.ui.common.editor.contentassist.IContentAssistContext)
*/
- public List<? extends ICompletionProposal> sortAndFilter(
- List<? extends ICompletionProposal> completionProposalList,
+ public List<? extends ICompletionProposal> filter(List<ICompletionProposal> completionProposalList,
IContentAssistContext contentAssistContext) {
- return ProposalFilterSorterUtil.sortAndFilter(completionProposalList,
- contentAssistContext);
+ return ProposalFilterSorterUtil.filter(completionProposalList,contentAssistContext);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.xtext.ui.common.editor.contentassist.IProposalProvider#sort(java.util.List)
+ */
+ public List<? extends ICompletionProposal> sort(List<ICompletionProposal> completionProposalList) {
+ return ProposalFilterSorterUtil.sort(completionProposalList);
}
/**
@@ -259,29 +221,21 @@ public abstract class AbstractJavaProposalProvider implements IProposalProvider
* assignment
*/
protected List<? extends ICompletionProposal> lookupCrossReference(
- CrossReference crossReference,
- IContentAssistContext contentAssistContext) {
-
+ CrossReference crossReference,IContentAssistContext contentAssistContext) {
List<ICompletionProposal> completionProposalList = new ArrayList<ICompletionProposal>();
-
if (scopeProvider != null) {
ParserRule containingParserRule = GrammarUtil
.containingParserRule(crossReference);
if (!GrammarUtil.isDatatypeRule(containingParserRule)) {
- final EClass eClass = (EClass) containingParserRule.getType().getClassifier();
- final EReference ref = GrammarUtil.getReference(crossReference,
- eClass);
- final String trimmedPrefix = contentAssistContext
- .getMatchString().trim();
- final Iterable<IScopedElement> candidates = scopeProvider
- .getScope(contentAssistContext.getModel(), ref)
+ EClass eClass = (EClass) containingParserRule.getType().getClassifier();
+ EReference ref = GrammarUtil.getReference(crossReference,eClass);
+ String trimmedPrefix = contentAssistContext.getMatchString().trim();
+ Iterable<IScopedElement> candidates = scopeProvider.getScope(contentAssistContext.getModel(), ref)
.getAllContents();
for (IScopedElement candidate : candidates) {
- if (candidate.name() != null
- && isCandidateMatchingPrefix(contentAssistContext
+ if (candidate.name() != null && isCandidateMatchingPrefix(contentAssistContext
.getModel(), ref, candidate, trimmedPrefix)) {
- completionProposalList.add(createCompletionProposal(
- crossReference, candidate.name(),
+ completionProposalList.add(createCompletionProposal(crossReference, candidate.name(),
contentAssistContext));
}
}
@@ -294,9 +248,7 @@ public abstract class AbstractJavaProposalProvider implements IProposalProvider
protected boolean isCandidateMatchingPrefix(EObject model, EReference ref,
IScopedElement candidate, String prefix) {
if (candidate.name() == null)
- throw new IllegalArgumentException(
- "unnamed candidates may not be proposed");
- return candidate.name().regionMatches(true, 0, prefix, 0,
- prefix.length());
+ throw new IllegalArgumentException("unnamed candidates may not be proposed");
+ return candidate.name().regionMatches(true, 0, prefix, 0,prefix.length());
}
}
diff --git a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/DefaultContentAssistCalculator.java b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/DefaultContentAssistCalculator.java
index 42624a5..3887552 100644
--- a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/DefaultContentAssistCalculator.java
+++ b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/DefaultContentAssistCalculator.java
@@ -11,35 +11,27 @@ package org.eclipse.xtext.ui.common.editor.contentassist.impl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
-import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.EReference;
import org.eclipse.xtext.AbstractElement;
import org.eclipse.xtext.AbstractRule;
import org.eclipse.xtext.Alternatives;
import org.eclipse.xtext.Assignment;
import org.eclipse.xtext.CrossReference;
-import org.eclipse.xtext.EcoreUtil2;
import org.eclipse.xtext.GrammarUtil;
import org.eclipse.xtext.Group;
import org.eclipse.xtext.Keyword;
import org.eclipse.xtext.ParserRule;
import org.eclipse.xtext.RuleCall;
-import org.eclipse.xtext.crossref.ILinkingService;
-import org.eclipse.xtext.crossref.impl.IllegalNodeException;
import org.eclipse.xtext.parsetree.AbstractNode;
-import org.eclipse.xtext.parsetree.NodeUtil;
import org.eclipse.xtext.parsetree.ParseTreeUtil;
import org.eclipse.xtext.ui.common.editor.contentassist.IContentAssistCalculator;
import org.eclipse.xtext.ui.common.editor.contentassist.IContentAssistContext;
import org.eclipse.xtext.util.XtextSwitch;
-import com.google.inject.Inject;
-
/**
* Provides a default implementation of interface {@link IContentAssistContext} designed as <b>Switch</b> over the
* Xtext ecore inheritance hierarchy to calculate and resolve (or flatten) 'container' level elements like
@@ -53,59 +45,19 @@ import com.google.inject.Inject;
*/
public class DefaultContentAssistCalculator extends XtextSwitch<List<AbstractElement>> implements IContentAssistCalculator {
- @Inject
- private ILinkingService linkingService;
-
public List<AbstractElement> computeProposalElements(IContentAssistContext contentAssistContext) {
-
List<AbstractElement> computedElementList = new ArrayList<AbstractElement>();
-
- Set<AbstractElement> nextValidElementSet = new LinkedHashSet<AbstractElement>();
-
AbstractNode referenceNode=contentAssistContext.getReferenceNode();
- /**
- * in case of a cross reference which isn't linked properly we evaluate or
- * propose it again
- */
- if (referenceNode != null && referenceNode.getGrammarElement() instanceof CrossReference && !isLinked(referenceNode)) {
- nextValidElementSet.add(getAbstractElement(referenceNode));
- nextValidElementSet.addAll(ParseTreeUtil.getElementSetValidFromOffset(contentAssistContext.getRootNode(),
- referenceNode, contentAssistContext.getOffSet()));
- } else if (referenceNode == contentAssistContext.getNode()) {
- if (referenceNode == null)
- throw new NullPointerException("Unexpected: referenceNode is null.");
- /**
- * in case of 'at-the-end' of the previous,completed element we evaluate
- * it again for 'right-to-left-backtracking' cases (e.g. for keyword
- * 'kind' kind>|< |=cursorpos)
- */
- Assignment containingAssignment = GrammarUtil.containingAssignment(referenceNode.getGrammarElement());
-
- if (referenceNode.getGrammarElement() instanceof RuleCall && containingAssignment != null) {
- nextValidElementSet.add(containingAssignment);
- nextValidElementSet.addAll(ParseTreeUtil.getElementSetValidFromOffset(contentAssistContext
- .getRootNode(), referenceNode, contentAssistContext.getOffSet()));
- }
- else {
- nextValidElementSet = ParseTreeUtil.getElementSetValidFromOffset(contentAssistContext.getRootNode(),
- referenceNode, contentAssistContext.getOffSet());
- nextValidElementSet.add(getAbstractElement(referenceNode));
- }
- }
- else if (referenceNode != null){
- nextValidElementSet = ParseTreeUtil.getElementSetValidFromOffset(contentAssistContext.getRootNode(),
- referenceNode, contentAssistContext.getOffSet());
- }
-
+ Set<AbstractElement> nextValidElementSet = ParseTreeUtil.getElementSetValidFromOffset(
+ contentAssistContext.getRootNode(),referenceNode, contentAssistContext.getOffSet());
+
for (Iterator<AbstractElement> iterator = nextValidElementSet.iterator(); iterator.hasNext();) {
AbstractElement abstractElement = iterator.next();
computedElementList.addAll(doSwitch(abstractElement));
}
-
return computedElementList;
}
-
@Override
public List<AbstractElement> caseAlternatives(Alternatives alternatives) {
List<AbstractElement> elementList = new ArrayList<AbstractElement>();
@@ -144,12 +96,8 @@ public class DefaultContentAssistCalculator extends XtextSwitch<List<AbstractEle
@Override
public List<AbstractElement> caseRuleCall(RuleCall ruleCall) {
- List<AbstractElement> elementList = new ArrayList<AbstractElement>();
-
- elementList.add(ruleCall);
-
+ List<AbstractElement> elementList = new ArrayList<AbstractElement>(Collections.singleton(ruleCall));
AbstractRule abstractRule = ruleCall.getRule();
-
if (abstractRule instanceof ParserRule) {
addWithNullCheck(elementList, doSwitch(((ParserRule) abstractRule).getAlternatives()));
}
@@ -172,35 +120,11 @@ public class DefaultContentAssistCalculator extends XtextSwitch<List<AbstractEle
}
}
- private AbstractElement getAbstractElement(AbstractNode lastCompleteNode) {
- return (AbstractElement) (lastCompleteNode.getGrammarElement() instanceof ParserRule ?
- ((ParserRule)lastCompleteNode.getGrammarElement()).getAlternatives(): lastCompleteNode.getGrammarElement());
- }
-
- private boolean isLinked(AbstractNode lastCompleteNode) {
- EObject semanticModel = NodeUtil.getNearestSemanticObject(lastCompleteNode);
- CrossReference crossReference = (CrossReference) lastCompleteNode.getGrammarElement();
- EReference eReference = GrammarUtil.getReference(crossReference, semanticModel.eClass());
-
- List<EObject> referencedObjects = EcoreUtil2.getAllReferencedObjects(semanticModel, eReference);
-
- if (referencedObjects.isEmpty())
- return false;
- try {
- List<EObject> linkCandidates = linkingService.getLinkedObjects(semanticModel, eReference, lastCompleteNode);
- return !linkCandidates.isEmpty() && referencedObjects.containsAll(linkCandidates);
- } catch( IllegalNodeException ex) {
- return false;
- }
- }
-
private boolean isOptional(AbstractElement groupElement) {
boolean isOptional = true;
-
if ((groupElement instanceof Group || groupElement instanceof Alternatives) && !GrammarUtil.isOptionalCardinality(groupElement)) {
-
- EList<AbstractElement> abstractTokens = groupElement instanceof Group ? ((Group) groupElement).getTokens() : ((Alternatives) groupElement).getGroups();
-
+ EList<AbstractElement> abstractTokens = groupElement instanceof Group ?
+ ((Group) groupElement).getTokens() : ((Alternatives) groupElement).getGroups();
for (Iterator<AbstractElement> iterator = abstractTokens.iterator(); isOptional && iterator.hasNext();) {
AbstractElement abstractElement = iterator.next();
isOptional = isOptional(abstractElement);
@@ -211,6 +135,4 @@ public class DefaultContentAssistCalculator extends XtextSwitch<List<AbstractEle
}
return isOptional;
}
-
-
}
diff --git a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/DefaultContentAssistProcessor.java b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/DefaultContentAssistProcessor.java
index a820d9f..a20759e 100644
--- a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/DefaultContentAssistProcessor.java
+++ b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/DefaultContentAssistProcessor.java
@@ -24,16 +24,16 @@ import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.contentassist.IContextInformationValidator;
import org.eclipse.jface.text.templates.TemplateContextType;
-import org.eclipse.swt.custom.StyledText;
import org.eclipse.xtext.AbstractElement;
import org.eclipse.xtext.Assignment;
+import org.eclipse.xtext.CrossReference;
import org.eclipse.xtext.Keyword;
import org.eclipse.xtext.RuleCall;
+import org.eclipse.xtext.TerminalRule;
import org.eclipse.xtext.XtextPackage;
import org.eclipse.xtext.parser.IParseResult;
import org.eclipse.xtext.parsetree.AbstractNode;
import org.eclipse.xtext.parsetree.CompositeNode;
-import org.eclipse.xtext.parsetree.LeafNode;
import org.eclipse.xtext.parsetree.NodeUtil;
import org.eclipse.xtext.parsetree.ParseTreeUtil;
import org.eclipse.xtext.resource.XtextResource;
@@ -43,6 +43,7 @@ import org.eclipse.xtext.ui.common.editor.contentassist.IProposalProvider;
import org.eclipse.xtext.ui.common.editor.contentassist.ITemplateContentAssistProcessor;
import org.eclipse.xtext.ui.core.editor.model.IXtextDocument;
import org.eclipse.xtext.ui.core.editor.model.UnitOfWork;
+import org.eclipse.xtext.util.Strings;
import com.google.inject.Inject;
@@ -54,54 +55,22 @@ import com.google.inject.Inject;
* @author Jan K&ouml;hnlein
*/
public class DefaultContentAssistProcessor implements IContentAssistProcessor {
-
// logger available to subclasses
protected final Logger logger = Logger.getLogger(getClass());
-
@Inject
protected ITemplateContentAssistProcessor templateContentAssistProcessor;
-
@Inject
protected IContentAssistCalculator contentAssistCalculator;
-
@Inject
protected IProposalProvider proposalProvider;
-
/**
* Computes the possible grammar elements following the one at the given offset and calls the respective methods on
* the proposal provider.
*/
public ICompletionProposal[] computeCompletionProposals(final ITextViewer viewer, final int offset) {
-
IXtextDocument document = (IXtextDocument) viewer.getDocument();
-
- return document.readOnly(new UnitOfWork<ICompletionProposal[]>() {
-
- public ICompletionProposal[] exec(XtextResource resource) throws Exception {
-
- IContentAssistContext contentAssistContext = createContext(resource, viewer, offset);
-
- List<AbstractElement> computeProposalElements = contentAssistCalculator
- .computeProposalElements(contentAssistContext);
-
- List<ICompletionProposal> completionProposalList = collectCompletionProposals(computeProposalElements,
- contentAssistContext);
-
- for (TemplateContextType templateContextType : collectTemplateContextTypes(computeProposalElements,
- contentAssistContext)) {
- addTemplates(viewer, offset, contentAssistContext, templateContextType, completionProposalList);
- }
-
- List<? extends ICompletionProposal> processedCompletionProposalList = proposalProvider.sortAndFilter(
- completionProposalList, contentAssistContext);
-
- return processedCompletionProposalList.toArray(new ICompletionProposal[processedCompletionProposalList
- .size()]);
- }
-
- });
+ return document.readOnly(new ContentAssistProcessorUow(offset, viewer));
}
-
/*
* (non-Javadoc)
* @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getCompletionProposalAutoActivationCharacters()
@@ -141,26 +110,7 @@ public class DefaultContentAssistProcessor implements IContentAssistProcessor {
public IContextInformationValidator getContextInformationValidator() {
return new ContextInformationValidator(this);
}
-
- /**
- * adds templates to the list of proposals
- *
- * @param viewer the viewer whose document is used to compute the proposals
- * @param offset an offset within the document for which completions should be computed
- * @param contentAssistContext the current context of the content assist proposal request
- * @param templateContextType within which templates are resolved
- * @param completionProposalList list of proposal to add to
- */
- protected void addTemplates(ITextViewer viewer, int offset, IContentAssistContext contentAssistContext,
- TemplateContextType templateContextType, List<ICompletionProposal> completionProposalList) {
- if (templateContentAssistProcessor != null) {
- templateContentAssistProcessor.setContentAssistContext(contentAssistContext);
- templateContentAssistProcessor.setContextType(templateContextType);
- completionProposalList.addAll(Arrays.asList(templateContentAssistProcessor.computeCompletionProposals(
- viewer, offset)));
- }
- }
-
+
protected List<ICompletionProposal> collectCompletionProposals(List<AbstractElement> computeProposalElements, IContentAssistContext contentAssistContext) {
List<ICompletionProposal> completionProposalList = new ArrayList<ICompletionProposal>();
for (AbstractElement computeProposalElement : computeProposalElements) {
@@ -201,82 +151,116 @@ public class DefaultContentAssistProcessor implements IContentAssistProcessor {
break;
case XtextPackage.ASSIGNMENT:
// TODO: change interface
- // templateContextType =
- // proposalProvider.getTemplateContextType((Assignment)
- // computeProposalElement, contentAssistContext);
+ // templateContextType =
+ // proposalProvider.getTemplateContextType((Assignment)computeProposalElement, contentAssistContext);
// addIfNotNull(templateContextTypes, templateContextType);
break;
}
}
return templateContextTypes;
}
-
+ /**
+ * Adds templates to the list of proposals,
+ *
+ * @param viewer the viewer whose document is used to compute the proposals
+ * @param offset an offset within the document for which completions should be computed
+ * @param contentAssistContext the current context of the content assist proposal request
+ * @param templateContextType within which templates are resolved
+ * @param completionProposalList list of proposal to add to
+ */
+ protected void addTemplates(ITextViewer viewer, int offset, IContentAssistContext contentAssistContext,
+ TemplateContextType templateContextType, List<ICompletionProposal> completionProposalList) {
+ if (templateContentAssistProcessor != null) {
+ templateContentAssistProcessor.setContentAssistContext(contentAssistContext);
+ templateContentAssistProcessor.setContextType(templateContextType);
+ completionProposalList.addAll(Arrays.asList(templateContentAssistProcessor.computeCompletionProposals(
+ viewer, offset)));
+ }
+ }
/**
* Creates a new <code>IContentAssistContext</code> with all required informations for the current CA request.
*
* @param resource the underlying EMF resource to read (parse) from
* @param viewer the viewer whose document is used to compute the proposals
- * @param offset an offset within the document for which the context should be created
- * @return a matching context containing all necessary informations for the current content assist request
+ * @param offset the offset within the resource for which the context should be created
+ * @return a list of applicable <code>IContentAssistContext</code>
*/
- protected IContentAssistContext createContext(XtextResource resource, ITextViewer viewer, final int offset) {
-
+ protected List<IContentAssistContext> createContextList(XtextResource resource, String text, final int offset) {
+ List<IContentAssistContext> result = new ArrayList<IContentAssistContext>();
IParseResult parseResult = resource.getParseResult();
-
Assert.isNotNull(parseResult);
-
CompositeNode rootNode = parseResult.getRootNode();
-
AbstractNode referenceNode = ParseTreeUtil.getLastCompleteNodeByOffset(rootNode, offset);
-
- EObject model = NodeUtil.getNearestSemanticObject(referenceNode);
-
- AbstractNode node = ParseTreeUtil.getCurrentOrFollowingNodeByOffset(rootNode, offset);
-
- String matchingString = node == null ? "" : calculateMatchString(viewer, offset, node);
-
- /**
- *
- * if cursor is behind a complete keyword, accept any input => empty
- *
- * TODO: Find a way to distinguish between keywords like "+" or "-" and
- * "extends" or "class" in the latter case, the prefix "" would not
- * always be sufficient
- * XXX SZ: the formatter may help to answer this question
- */
- if (node != null && node.getGrammarElement() instanceof Keyword
- && (node instanceof LeafNode && ((LeafNode) node).getText().equals(matchingString))) {
- matchingString = "";
+ AbstractNode nodeAtOffset = ParseTreeUtil.getCurrentOrFollowingNodeByOffset(rootNode, offset);
+
+ if (referenceNode.getOffset()+referenceNode.getLength() == offset) {
+ AbstractNode precedingReferenceNode = ParseTreeUtil.getLastCompleteNodeByOffset(rootNode,Math.max(0, referenceNode.getOffset()-1));
+ String matchingString = calculateMatchString(nodeAtOffset,text, offset);
+ result.add(newCompletionProposal(matchingString, offset, rootNode, precedingReferenceNode));
+ if (!Strings.isEmpty(matchingString) &&
+ referenceNode.getGrammarElement() instanceof Keyword ||
+ referenceNode.getGrammarElement() instanceof CrossReference ||
+ (referenceNode.getGrammarElement() instanceof RuleCall &&
+ ((RuleCall)referenceNode.getGrammarElement()).getRule() instanceof TerminalRule)) {
+ result.add(newCompletionProposal("", offset, rootNode, referenceNode));
+ }
+ } else {
+ String matchingString = calculateMatchString(nodeAtOffset,text, offset);
+ result.add(newCompletionProposal(matchingString, offset, rootNode, referenceNode));
}
-
- return new ContentAssistContext(model, offset, matchingString, node, referenceNode, rootNode);
+
+ return result;
}
-
/**
- * Calculates the match string of the current <code>IContentAssistContext</code> based on the
- * specified location within the text viewer.
+ * Calculates the match string of the based on the specified location within the given text.
*
- * @param viewer the viewer whose document is used to compute the proposals
+ * @param caretNode the node at the current caret position
+ * @param text the text to compute the matching string
* @param offset an offset within the document for which the matchstring should be computed
* @return a matching string
*/
- protected String calculateMatchString(ITextViewer viewer, int offset,AbstractNode node) {
-
- String prefix = "";
-
- StyledText textWidget = viewer.getTextWidget();
+ protected String calculateMatchString(AbstractNode caretNode, String text, int offset) {
+ StringBuilder matchString = new StringBuilder();
+ char c = ' ';
+ while (offset>caretNode.getOffset() && !Character.isWhitespace(c = text.charAt(--offset))) {
+ matchString.insert(0, c);
+ }
+ return matchString.toString();
+ }
+
+ private ContentAssistContext newCompletionProposal(String matchingString, final int offset, CompositeNode rootNode,
+ AbstractNode referenceNode) {
+ EObject model = NodeUtil.getNearestSemanticObject(referenceNode);
+ AbstractNode node = ParseTreeUtil.getCurrentOrFollowingNodeByOffset(rootNode, offset);
+ return new ContentAssistContext(model, offset, matchingString, node, referenceNode, rootNode);
+ }
+
+ private final class ContentAssistProcessorUow implements UnitOfWork<ICompletionProposal[]> {
+ private final int offset;
+ private final ITextViewer viewer;
+
+ private ContentAssistProcessorUow(int offset, ITextViewer viewer) {
+ this.offset = offset;
+ this.viewer = viewer;
+ }
- if (textWidget.getCharCount() > 0) {
- int boundedOffset = Math.min(offset, textWidget.getCharCount()) - 1;
- if (node.getTotalOffset() <= boundedOffset) {
- prefix = textWidget.getText(node.getTotalOffset(), boundedOffset).trim();
+ public ICompletionProposal[] exec(XtextResource resource) throws Exception {
+ List<ICompletionProposal> completionProposalList = new ArrayList<ICompletionProposal>();
+ for (IContentAssistContext contentAssistContext : createContextList(
+ resource, viewer.getTextWidget().getText(), offset)) {
+ List<AbstractElement> computedElements = contentAssistCalculator
+ .computeProposalElements(contentAssistContext);
+ completionProposalList.addAll(collectCompletionProposals(computedElements,contentAssistContext));
+ for (TemplateContextType templateContextType : collectTemplateContextTypes(computedElements,
+ contentAssistContext)) {
+ addTemplates(viewer, offset, contentAssistContext, templateContextType, completionProposalList);
+ }
+ proposalProvider.filter(completionProposalList,contentAssistContext);
}
+ proposalProvider.sort(completionProposalList);
+ return completionProposalList.toArray(new ICompletionProposal[completionProposalList.size()]);
}
-
- return prefix;
}
-
-
}
diff --git a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/JavaReflectiveMethodInvoker.java b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/JavaReflectiveMethodInvoker.java
index fe2dd04..410017f 100644
--- a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/JavaReflectiveMethodInvoker.java
+++ b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/JavaReflectiveMethodInvoker.java
@@ -39,8 +39,7 @@ public class JavaReflectiveMethodInvoker {
if (method == null) {
return null;
}
- Object result = invokeMethod(method, target, parameterValues.toArray(new Object[] {}));
- return result;
+ return invokeMethod(method, target, parameterValues.toArray(new Object[] {}));
}
private final Method findMethod(Class<?> clazz, String name, Class<?>... paramTypes) {
diff --git a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/ProposalFilterSorterUtil.java b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/ProposalFilterSorterUtil.java
index 5aa1fc9..1ce2b99 100644
--- a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/ProposalFilterSorterUtil.java
+++ b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/ProposalFilterSorterUtil.java
@@ -18,29 +18,31 @@ import org.apache.log4j.Logger;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.xtext.ui.common.editor.contentassist.IContentAssistContext;
import org.eclipse.xtext.ui.common.editor.contentassist.IProposalProvider;
+import org.eclipse.xtext.util.Strings;
/**
* @author Jan Köhnlein - Initial contribution and API
+ * @author Michael Clay - Initial contribution and API
*/
public class ProposalFilterSorterUtil {
+ private static Logger logger = Logger.getLogger(IProposalProvider.class);
+
protected static final Comparator<ICompletionProposal> PROPOSAL_COMPARATOR = new Comparator<ICompletionProposal>() {
public int compare(ICompletionProposal o1, ICompletionProposal o2) {
return o1.getDisplayString().compareTo(o2.getDisplayString());
}
};
- private static Logger logger = Logger.getLogger(IProposalProvider.class);
-
- public static List<? extends ICompletionProposal> sortAndFilter(
+ public static List<? extends ICompletionProposal> filter(
List<? extends ICompletionProposal> completionProposalList, IContentAssistContext contentAssistContext) {
Map<String, ICompletionProposal> displayString2ICompletionProposalMap = new HashMap<String, ICompletionProposal>();
for (Iterator<? extends ICompletionProposal> iterator = completionProposalList.iterator(); iterator.hasNext();) {
ICompletionProposal completionProposal = iterator.next();
- // filter duplicate
if (!displayString2ICompletionProposalMap.containsKey(completionProposal.getDisplayString())) {
displayString2ICompletionProposalMap.put(completionProposal.getDisplayString(), completionProposal);
- // filter by prefix
- if (isFiltered(completionProposal)) {
+ if (!Strings.isEmpty(contentAssistContext.getMatchString()) &&
+ (!completionProposal.getDisplayString().toUpperCase().startsWith(contentAssistContext.getMatchString().toUpperCase()) ||
+ completionProposal.getDisplayString().equalsIgnoreCase(contentAssistContext.getMatchString()))) {
if (logger.isDebugEnabled()) {
logger.debug("filter completionProposal '" + completionProposal + "'");
}
@@ -54,27 +56,12 @@ public class ProposalFilterSorterUtil {
iterator.remove();
}
}
- Collections.sort(completionProposalList, PROPOSAL_COMPARATOR);
return completionProposalList;
}
-
- /**
- * The default behavior of this method delegates to
- * {@link XtextCompletionProposal#matches(String)} to test if the given
- * prefix string matches or not.
- *
- * @param completionProposal
- * contains information used to present the proposed completion
- * to the user
- * @return true or false whether the given prefix matches the text of this
- * completion proposal
- */
- protected static boolean isFiltered(ICompletionProposal completionProposal) {
- if (completionProposal instanceof XtextCompletionProposal) {
- XtextCompletionProposal xtextCompletionProposal = (XtextCompletionProposal) completionProposal;
- return !xtextCompletionProposal.matches();
- }
- return false;
+
+ public static List<? extends ICompletionProposal> sort(List<? extends ICompletionProposal> completionProposalList) {
+ Collections.sort(completionProposalList, PROPOSAL_COMPARATOR);
+ return completionProposalList;
}
}
diff --git a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/XtextCompletionProposal.java b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/XtextCompletionProposal.java
index 2dfcceb..93aa551 100644
--- a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/XtextCompletionProposal.java
+++ b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/XtextCompletionProposal.java
@@ -1,7 +1,6 @@
package org.eclipse.xtext.ui.common.editor.contentassist.impl;
import org.apache.log4j.Logger;
-import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
@@ -9,10 +8,6 @@ import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.xtext.AbstractElement;
-import org.eclipse.xtext.CrossReference;
-import org.eclipse.xtext.GrammarUtil;
-import org.eclipse.xtext.Keyword;
-import org.eclipse.xtext.ParserRule;
import org.eclipse.xtext.ui.common.editor.contentassist.IContentAssistContext;
/**
@@ -28,7 +23,6 @@ public class XtextCompletionProposal implements ICompletionProposal {
// logger available to subclasses
protected final Logger logger = Logger.getLogger(XtextCompletionProposal.class);
- private final AbstractElement abstractElement;
private final String text;
private int selectionOffset;
@@ -37,19 +31,14 @@ public class XtextCompletionProposal implements ICompletionProposal {
private int nodeTotalOffset;
private int nodeTotalLength;
private String matchString;
- private EObject grammarElement;
- private boolean isCusorAtEndOfLastCompleteNode;
public XtextCompletionProposal(AbstractElement abstractElement, String displayString,
IContentAssistContext contentAssistContext) {
- this.abstractElement = abstractElement;
this.text = displayString;
this.offset = contentAssistContext.getOffSet();
this.nodeTotalOffset = contentAssistContext.getNode().getTotalOffset();
this.nodeTotalLength = contentAssistContext.getNode().getTotalLength();
this.matchString = contentAssistContext.getMatchString();
- this.grammarElement = contentAssistContext.getNode().getGrammarElement();
- this.isCusorAtEndOfLastCompleteNode = contentAssistContext.getNode() == contentAssistContext.getReferenceNode();
}
public void apply(IDocument document) {
@@ -87,52 +76,9 @@ public class XtextCompletionProposal implements ICompletionProposal {
return new Point(this.selectionOffset, 0);
}
- /**
- *
- * @return true or false whether the given prefix matches the text of this
- * completion proposal
- */
- public boolean matches() {
- boolean matches = true;
- AbstractElement abstractElement = null;
- if (this.abstractElement instanceof Keyword || this.abstractElement instanceof CrossReference) {
- abstractElement = GrammarUtil.containingAssignment(this.abstractElement);
- }
- if (null == abstractElement) {
- abstractElement = this.abstractElement;
- }
- boolean candidateToCompare = false;
-
- // means if we are at the end of a complete token we want to filter only
- // equal grammarelements (not the 'next' ones)
- if (isCusorAtEndOfLastCompleteNode && abstractElement.equals(getCurrentGrammarElement())) {
- candidateToCompare = true;
- }
- else if (!isCusorAtEndOfLastCompleteNode) {
- candidateToCompare = true;
- }
- if (candidateToCompare
- && (!"".equals(matchString.trim()) && !getDisplayString().toUpperCase().trim().startsWith(
- matchString.toUpperCase().trim()))) {
- matches = false;
- }
- return matches;
- }
-
@Override
public String toString() {
return "XtextCompletionPoposal[text='" + this.text + "']";
}
- /**
- * @return the grammar element of the current node
- */
- public EObject getCurrentGrammarElement() {
- EObject containingAssignment = GrammarUtil.containingAssignment(grammarElement);
- if (containingAssignment == null) {
- return grammarElement instanceof ParserRule ? ((ParserRule) grammarElement).getAlternatives()
- : grammarElement;
- }
- return containingAssignment;
- }
}
diff --git a/plugins/org.eclipse.xtext.xtend/src/org/eclipse/xtext/xtend/contentassist/AbstractXtendProposalProvider.java b/plugins/org.eclipse.xtext.xtend/src/org/eclipse/xtext/xtend/contentassist/AbstractXtendProposalProvider.java
index 5e19132..d614583 100644
--- a/plugins/org.eclipse.xtext.xtend/src/org/eclipse/xtext/xtend/contentassist/AbstractXtendProposalProvider.java
+++ b/plugins/org.eclipse.xtext.xtend/src/org/eclipse/xtext/xtend/contentassist/AbstractXtendProposalProvider.java
@@ -12,8 +12,6 @@ import java.util.Collections;
import java.util.List;
import org.apache.log4j.Logger;
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.templates.Template;
import org.eclipse.jface.text.templates.TemplateContextType;
@@ -25,8 +23,6 @@ import org.eclipse.xtext.ParserRule;
import org.eclipse.xtext.RuleCall;
import org.eclipse.xtext.TerminalRule;
import org.eclipse.xtext.TypeRef;
-import org.eclipse.xtext.parsetree.AbstractNode;
-import org.eclipse.xtext.parsetree.LeafNode;
import org.eclipse.xtext.ui.common.editor.contentassist.IContentAssistContext;
import org.eclipse.xtext.ui.common.editor.contentassist.IProposalProvider;
import org.eclipse.xtext.ui.common.editor.contentassist.impl.AbstractJavaProposalProvider;
@@ -168,21 +164,21 @@ public abstract class AbstractXtendProposalProvider extends AbstractXtendService
protected String getDefaultImageFilePath() {
return "icons/editor.gif";
}
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.xtext.ui.common.editor.contentassist.IProposalProvider#filter(java.util.List, org.eclipse.xtext.ui.common.editor.contentassist.IContentAssistContext)
+ */
+ public List<? extends ICompletionProposal> filter(List<ICompletionProposal> completionProposalList,
+ IContentAssistContext contentAssistContext) {
+ return ProposalFilterSorterUtil.filter(completionProposalList,contentAssistContext);
+ }
- /**
- * Concrete subclasses can override this for custom sort and filter
- * behavior. Called right after all completion proposals have been
- * collected.
- *
- * The default behavior of this implementation is to filter duplicates and
- * to trim matching <code>ICompletionProposal#displayString</code> with
- * matching prefix values.
- *
- * @see #sortAndFilter(List, EObject, String, IDocument, int, AbstractNode,
- * LeafNode)
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.xtext.ui.common.editor.contentassist.IProposalProvider#sort(java.util.List)
*/
- public List<? extends ICompletionProposal> sortAndFilter(
- List<? extends ICompletionProposal> completionProposalList, IContentAssistContext contentAssistContext) {
- return ProposalFilterSorterUtil.sortAndFilter(completionProposalList, contentAssistContext);
+ public List<? extends ICompletionProposal> sort(List<ICompletionProposal> completionProposalList) {
+ return ProposalFilterSorterUtil.sort(completionProposalList);
}
}
diff --git a/tests/org.eclipse.xtext.ui.common.tests/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/ContentAssistProcessorTestBuilder.java b/tests/org.eclipse.xtext.ui.common.tests/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/ContentAssistProcessorTestBuilder.java
index 3b769ab..c4bd6e9 100644
--- a/tests/org.eclipse.xtext.ui.common.tests/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/ContentAssistProcessorTestBuilder.java
+++ b/tests/org.eclipse.xtext.ui.common.tests/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/ContentAssistProcessorTestBuilder.java
@@ -13,7 +13,8 @@
*******************************************************************************/
package org.eclipse.xtext.ui.common.editor.contentassist.impl;
-import static org.easymock.EasyMock.*;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
@@ -128,24 +129,19 @@ public class ContentAssistProcessorTestBuilder extends AbstractXtextTests {
public ContentAssistProcessorTestBuilder assertMatchString(String matchString)
throws Exception {
-
- final String currentModelToParse = getModel();
-
+ String currentModelToParse = getModel();
final XtextResource xtextResource = getResource(new StringInputStream(currentModelToParse));
-
- final IXtextDocument xtextDocument = getDocument(xtextResource);
-
- IContentAssistContext contentAssistContext = new DefaultContentAssistProcessor() {
+ List<IContentAssistContext> contentAssistContextList = new DefaultContentAssistProcessor() {
@Override
- public IContentAssistContext createContext(XtextResource resource, ITextViewer viewer, int offset) {
- IContentAssistContext createContext = super.createContext(resource,viewer,offset);
- return createContext;
+ public List<IContentAssistContext> createContextList(XtextResource resource, String text, final int offset) {
+ return super.createContextList(xtextResource, text, offset);
}
- }.createContext(xtextResource, resetTextViewerMock(currentModelToParse, xtextDocument),cursorPosition);
-
-
- assertEquals(matchString, contentAssistContext.getMatchString());
-
+ }.createContextList(xtextResource, currentModelToParse,cursorPosition);
+
+ for (IContentAssistContext contentAssistContext : contentAssistContextList) {
+ assertEquals(matchString, contentAssistContext.getMatchString());
+ break;
+ }
return this;
}
@@ -169,8 +165,15 @@ public class ContentAssistProcessorTestBuilder extends AbstractXtextTests {
ICompletionProposal[] computeCompletionProposals = computeCompletionProposals(currentModelToParse,
cursorPosition);
+ StringBuffer computedProposals = new StringBuffer();
+ for (int i = 0; i < computeCompletionProposals.length; i++) {
+ computedProposals.append(computeCompletionProposals[i].getDisplayString());
+ if (i<(computeCompletionProposals.length-1)) {
+ computedProposals.append(",");
+ }
+ }
assertEquals("expect only " + completionProposalCount + " CompletionProposal item for model '"
- + currentModelToParse + "'", completionProposalCount, computeCompletionProposals.length);
+ + currentModelToParse + "' but got '"+computedProposals+"'", completionProposalCount, computeCompletionProposals.length);
return this;
}
@@ -211,7 +214,7 @@ public class ContentAssistProcessorTestBuilder extends AbstractXtextTests {
private ITextViewer resetTextViewerMock(final String currentModelToParse, final IXtextDocument xtextDocument) {
EasyMock.reset(textViewerMock);
expect(textViewerMock.getDocument()).andReturn(xtextDocument);
- expect(textViewerMock.getTextWidget()).andReturn(newStyledTextWidgetMock(currentModelToParse));
+ expect(textViewerMock.getTextWidget()).andReturn(newStyledTextWidgetMock(currentModelToParse)).times(2);
replay(textViewerMock);
return textViewerMock;
}
@@ -234,6 +237,11 @@ public class ContentAssistProcessorTestBuilder extends AbstractXtextTests {
public String getText(int start, int end) {
return testDslModel.substring(start, end + 1);
}
+
+ @Override
+ public String getText() {
+ return testDslModel;
+ }
};
}
diff --git a/tests/org.eclipse.xtext.ui.common.tests/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/DefaultContentAssistProcessorTest.java b/tests/org.eclipse.xtext.ui.common.tests/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/DefaultContentAssistProcessorTest.java
index da97e85..c45ee91 100644
--- a/tests/org.eclipse.xtext.ui.common.tests/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/DefaultContentAssistProcessorTest.java
+++ b/tests/org.eclipse.xtext.ui.common.tests/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/DefaultContentAssistProcessorTest.java
@@ -40,9 +40,8 @@ import com.google.inject.Injector;
* @author Jan Koehnlein
* @see org.eclipse.xtext.ui.common.editor.contentassist.impl.DefaultContentAssistProcessor
*/
-public class DefaultContentAssistProcessorTest extends AbstractXtextTests
-{
-
+public class DefaultContentAssistProcessorTest extends AbstractXtextTests {
+
private ISetup getRefGrammarSetup() {
return new ReferenceGrammarTestLanguageStandaloneSetup() {
@Override
@@ -80,11 +79,12 @@ public class DefaultContentAssistProcessorTest extends AbstractXtextTests
}
public void testComputePrefix() throws Exception {
+ String model = "spielplatz 1 \"SpielplatzBeschreibung\" { kind(k1 0) kind(k2 0) erwachsener(e1 0) erwachsener(e2 0) ";
newBuilder(getRefGrammarSetup())
- .append("foo fvdf dfv(").assertMatchString("(").reset()
- .append("foo fvdf dfv").assertMatchString("dfv").reset()
- .append("foo fvdf dfv_").assertMatchString("dfv_").reset()
- .append("foo fvdf dfv_ ").assertMatchString("").reset()
+ .append(model+" familie( dfv(").assertMatchString("(").reset()
+ .append(model+" familie( dfv").assertMatchString("dfv").reset()
+ .append(model+" familie( dfv_").assertMatchString("dfv_").reset()
+ .append(model+" familie( dfv_ ").assertMatchString("").reset()
.append("").assertMatchString("");
}
@@ -134,13 +134,13 @@ public class DefaultContentAssistProcessorTest extends AbstractXtextTests
builder.append(" ER").assertText("erwachsener");
builder.append(" SP").assertText("spielzeug");
builder.append(" FA").assertText("familie");
- builder.append(" familie ( KEY").assertText("keyword");
- builder.append(" familie ( K").assertText("keyword");
+ builder.append(" familie ( KEY").assertText("keyword","e1","e2");
+ builder.append(" familie ( K").assertText("keyword","e1","e2");
builder.append(" familie ( keyword E").assertText("e1", "e2");
- builder.append(" familie ( keyword e1 E").assertText("e1", "e2");
+ builder.append(" familie ( keyword e1 E").assertText("e1", "e2","k1","k2");
builder.append(" familie ( keyword e1 e2 K").assertText("k1", "k2", ",", ")");
- builder.append(" familie ( keyword e1 e2 k1,K").assertText("k1", "k2", ",", ")");
- builder.append(" familie ( keyword e1 e2 k1,k2").assertText("k2", ",", ")");
+ builder.append(" familie ( keyword e1 e2 k1,K").assertText(",", ")");
+ builder.append(" familie ( keyword e1 e2 k1,k2").assertText(",", ")");
}
/**
@@ -189,8 +189,7 @@ public class DefaultContentAssistProcessorTest extends AbstractXtextTests
"R3",
"\"Keyword_Value\"",
"(",
- "[",
- "+=" // TODO: Why does this proposal come up?
+ "["
);
}
@@ -200,8 +199,7 @@ public class DefaultContentAssistProcessorTest extends AbstractXtextTests
.appendNl("R1 ();")
.append("R2 rule :").assertText(
"R1",
- "R2",
- ":" // TODO: Why does this proposal come up?
+ "R2"
);
}
@@ -223,25 +221,22 @@ public class DefaultContentAssistProcessorTest extends AbstractXtextTests
.appendNl("MyRule : 'foo' name=ID; ").assertText(
"ParserRule_Name", "terminal"
);
-
}
/**
- * SZ: uncomment because it fails and neither the result nor the excpectation
- * seem to be right
* regression test for:
*
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=260825
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=262313
*/
-// public void testCompleteAssignmentWithBacktracking() throws Exception {
-// newBuilder(getXtextGrammarSetup())
-// .appendNl("grammar foo with org.eclipse.xtext.common.Terminals")
-// .appendNl("generate foo \"foo\"")
-// .append("MyRule : 'foo' name").assertText(
-// "*", "+", "+=", ";", "=", "?", "?="
-// );
-// }
+ public void testCompleteAssignmentWithBacktracking() throws Exception {
+ newBuilder(getXtextGrammarSetup())
+ .appendNl("grammar foo with org.eclipse.xtext.common.Terminals")
+ .appendNl("generate foo \"foo\"")
+ .append("MyRule : 'foo' name").assertText("\"Keyword_Value\"", "(", "*", "+", "+=", ";", "=", "?", "?=",
+ "Assignment_Feature", "MyRule", "{");
+
+ }
public void testKeywordWithBackslashes() throws Exception {
newBuilder(getKeywordsLangSetup())
diff --git a/tests/org.eclipse.xtext.ui.common.tests/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/TwoContextsContentAssistTest.java b/tests/org.eclipse.xtext.ui.common.tests/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/TwoContextsContentAssistTest.java
index 8d86507..f642c9c 100644
--- a/tests/org.eclipse.xtext.ui.common.tests/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/TwoContextsContentAssistTest.java
+++ b/tests/org.eclipse.xtext.ui.common.tests/src/org/eclipse/xtext/ui/common/editor/contentassist/impl/TwoContextsContentAssistTest.java
@@ -27,10 +27,7 @@ import com.google.inject.Injector;
public class TwoContextsContentAssistTest extends AbstractXtextTests {
public void testTwoContexts() throws Exception {
- System.err.println(getClass().getSimpleName()+" says: PLEASE ACTIVATE ME!");
-// newBuilder(getGrammarSetup())
-// .append("Foo; FooBar; Bar refersTo Foo").assertText(
-// ";", "FooBar");
+ newBuilder(getGrammarSetup()).append("Foo; FooBar; Bar refersTo Foo").assertText(";", "FooBar");
}
/**