summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormclay2008-10-28 16:27:53 (EDT)
committer sefftinge2008-10-28 16:27:53 (EDT)
commit240191ab164c0dc9bf87a60ca710d7037bcfe256 (patch)
tree2ad22b4d0553ef9a43e08291f7cab42bf8c0b854
parenteaddf762b35bd6ac8378597e39817722b9ac682c (diff)
downloadorg.eclipse.xtext-240191ab164c0dc9bf87a60ca710d7037bcfe256.zip
org.eclipse.xtext-240191ab164c0dc9bf87a60ca710d7037bcfe256.tar.gz
org.eclipse.xtext-240191ab164c0dc9bf87a60ca710d7037bcfe256.tar.bz2
upd: refactor common/generic behaviour from generated IProposalProvider into AbstractProposalProvider and remove dependency from generated IProposalProvider to ContentAssistor
-rw-r--r--devtools/org.eclipse.xtext.reference.ui/src/org/eclipse/xtext/reference/ui/services/contentassist/XtextCompletionProposal.java2
-rw-r--r--plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/AbstractProposalProvider.java140
-rw-r--r--plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/DefaultContentAssistProcessor.java57
-rw-r--r--plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/IProposalProvider.java32
-rw-r--r--plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/XtextSourceViewerConfiguration.java10
5 files changed, 194 insertions, 47 deletions
diff --git a/devtools/org.eclipse.xtext.reference.ui/src/org/eclipse/xtext/reference/ui/services/contentassist/XtextCompletionProposal.java b/devtools/org.eclipse.xtext.reference.ui/src/org/eclipse/xtext/reference/ui/services/contentassist/XtextCompletionProposal.java
index ecfb61f..1c8d391 100644
--- a/devtools/org.eclipse.xtext.reference.ui/src/org/eclipse/xtext/reference/ui/services/contentassist/XtextCompletionProposal.java
+++ b/devtools/org.eclipse.xtext.reference.ui/src/org/eclipse/xtext/reference/ui/services/contentassist/XtextCompletionProposal.java
@@ -35,7 +35,7 @@ import org.eclipse.xtext.reference.ui.Activator;
public class XtextCompletionProposal implements ICompletionProposal, ICompletionProposalExtension2,
ICompletionProposalExtension6 {
- Logger logger = Logger.getLogger(XtextCompletionProposal.class);
+ private final Logger logger = Logger.getLogger(XtextCompletionProposal.class);
private final Proposal proposal;
private final int offset;
diff --git a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/AbstractProposalProvider.java b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/AbstractProposalProvider.java
new file mode 100644
index 0000000..1830bd6
--- /dev/null
+++ b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/AbstractProposalProvider.java
@@ -0,0 +1,140 @@
+package org.eclipse.xtext.ui.common.editor.codecompletion;
+
+import java.util.ArrayList;
+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.viewers.StyledString;
+import org.eclipse.xtext.CrossReference;
+import org.eclipse.xtext.EcoreUtil2;
+import org.eclipse.xtext.Keyword;
+import org.eclipse.xtext.RuleCall;
+import org.eclipse.xtext.parsetree.CompositeNode;
+import org.eclipse.xtext.parsetree.LeafNode;
+
+/**
+ * Convenient super class for <code>IProposalProvider</code> implementations.
+ *
+ * @author Michael Clay - Initial contribution and API
+ *
+ * @see IProposalProvider
+ */
+public abstract class AbstractProposalProvider implements IProposalProvider {
+
+ protected static final String LEXER_RULE_ID = "ID";
+ // logger available to subclasses
+ protected final Logger logger = Logger.getLogger(getClass());
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider#
+ * completeKeyword(org.eclipse.xtext.Keyword, org.eclipse.emf.ecore.EObject,
+ * java.lang.String, org.eclipse.jface.text.IDocument, int)
+ */
+ public List<? extends ICompletionProposal> completeKeyword(Keyword keyword, EObject model, String prefix,
+ IDocument doc, int offset) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("completeKeyword '" + keyword.getValue() + "' for model '" + model + "' and prefix '"
+ + prefix.trim() + "'");
+ }
+ String text = keyword.getValue().length() == 1 ? keyword.getValue() : keyword.getValue() + " ";
+
+ return Collections.singletonList(createCompletionProposal(text, offset));
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider#
+ * completeRuleCall(org.eclipse.xtext.RuleCall,
+ * org.eclipse.emf.ecore.EObject, java.lang.String,
+ * org.eclipse.jface.text.IDocument, int)
+ */
+ public List<? extends ICompletionProposal> completeRuleCall(RuleCall ruleCall, EObject model, String prefix,
+ IDocument doc, int offset) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("completeRuleCall '" + ruleCall.getName() + "' cardinality '" + ruleCall.getCardinality()
+ + "' for model '" + model + "' and prefix '" + prefix.trim() + "'");
+ }
+ return Collections.emptyList();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @seeorg.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider#
+ * sortAndFilter(java.util.List)
+ */
+ public List<? extends ICompletionProposal> sortAndFilter(List<? extends ICompletionProposal> completionProposalList) {
+ return doSortAndFilter(completionProposalList);
+ }
+
+ /**
+ * Concrete subclasses can override this for custom sort and filter
+ * behavior. Gets called after all completion proposals have been collected.
+ */
+ protected List<? extends ICompletionProposal> doSortAndFilter(
+ List<? extends ICompletionProposal> completionProposalList) {
+ return completionProposalList;
+ }
+
+ /**
+ *
+ * @return the id of the plug-in containing the image file;
+ * <code>null</code> is returned if the plug-in does not exist
+ */
+ protected abstract String getPluginId();
+
+ /**
+ * Returns the the relative path of the default image file, relative to the
+ * root of the containing plug-in; the path must be legal The image would
+ * typically be shown to the left of the display string.
+ *
+ * @return the image file path of the default image to be shown or
+ * <code>null</code> if no image is desired
+ * @see #getPluginId()
+ */
+ protected abstract String getDefaultImageFilePath();
+
+ /**
+ * Concrete subclasses can override this to provide custom lookup behaviour
+ * for <code>CrossReference</code>. The default behaviour of this method is
+ * to lookup all <code>RuleCall</code> within the current parsetree matching
+ * the type of the given CrossReference.
+ *
+ * @return a list of <code>ICompletionProposal</code> matching the given
+ * assignment
+ */
+ protected List<? extends ICompletionProposal> lookupCrossReference(CrossReference crossReference, EObject model, int offset) {
+ List<ICompletionProposal> completionProposalList = new ArrayList<ICompletionProposal>();
+ for (CompositeNode compositeNode : EcoreUtil2.getAllContentsOfType(EcoreUtil2.getRootContainer(model),
+ CompositeNode.class)) {
+ if (compositeNode.getGrammarElement() instanceof RuleCall
+ && crossReference.getType().getName().equals(
+ ((RuleCall) compositeNode.getGrammarElement()).getName())) {
+ for (LeafNode leafNode : compositeNode.getLeafNodes()) {
+ if (leafNode.getGrammarElement() instanceof RuleCall
+ && LEXER_RULE_ID.equalsIgnoreCase(((RuleCall) leafNode.getGrammarElement()).getName())) {
+ completionProposalList.add(createCompletionProposal(leafNode.getText(), offset));
+ }
+ }
+ }
+ }
+ return completionProposalList;
+ }
+
+ /**
+ * @return a new <code>XtextCompletionProposal</code> for the given text and
+ * offset.
+ */
+ protected final XtextCompletionProposal createCompletionProposal(String text, int offset) {
+ return new XtextCompletionProposal(text, new StyledString(text), text, getDefaultImageFilePath(),
+ getPluginId(), offset);
+ }
+
+}
diff --git a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/DefaultContentAssistProcessor.java b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/DefaultContentAssistProcessor.java
index f47ab7b..b907c82 100644
--- a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/DefaultContentAssistProcessor.java
+++ b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/DefaultContentAssistProcessor.java
@@ -24,14 +24,11 @@ import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.contentassist.IContextInformationValidator;
import org.eclipse.xtext.AbstractElement;
import org.eclipse.xtext.AbstractRule;
-import org.eclipse.xtext.Action;
import org.eclipse.xtext.Alternatives;
import org.eclipse.xtext.Assignment;
-import org.eclipse.xtext.CrossReference;
import org.eclipse.xtext.GrammarUtil;
import org.eclipse.xtext.Group;
import org.eclipse.xtext.Keyword;
-import org.eclipse.xtext.LexerRule;
import org.eclipse.xtext.ParserRule;
import org.eclipse.xtext.RuleCall;
import org.eclipse.xtext.parser.IParseResult;
@@ -63,6 +60,7 @@ public class DefaultContentAssistProcessor implements IContentAssistProcessor {
if (proposalProvider != null) {
IDocument document = viewer.getDocument();
if (document instanceof XtextDocument) {
+
XtextDocument xtextDocument = (XtextDocument) document;
CompositeNode rootNode = xtextDocument.readOnly(new UnitOfWork<CompositeNode>() {
@@ -89,14 +87,14 @@ public class DefaultContentAssistProcessor implements IContentAssistProcessor {
.iterator(); iterator.hasNext();) {
AbstractElement nextElement = iterator.next();
- List<EObject> resolvedElementOrRuleList = resolveElement(nextElement, true);
+ List<EObject> resolvedElementOrRuleList = resolveElement(nextElement);
collectCompletionProposalList(resolvedElementOrRuleList, completionProposalList, xtextDocument,
currentLeafNode, prefix, offset);
}
if (completionProposalList != null) {
- List<ICompletionProposal> sortAndFilter = proposalProvider.sortAndFilter(completionProposalList);
+ List<? extends ICompletionProposal> sortAndFilter = proposalProvider.sortAndFilter(completionProposalList);
return (ICompletionProposal[]) sortAndFilter.toArray(new ICompletionProposal[] {});
}
@@ -127,36 +125,33 @@ public class DefaultContentAssistProcessor implements IContentAssistProcessor {
+ firstLetterCapitalized(assignment.getFeature()), Assignment.class, EObject.class,
String.class, IDocument.class, int.class);
- Collection<ICompletionProposal> assignmentProposalList = invokeMethod(method, proposalProvider,
+ Collection<? extends ICompletionProposal> assignmentProposalList = invokeMethod(method, proposalProvider,
assignment, currentLeafNode, prefix, xtextDocument, offset);
- completionProposalList.addAll(assignmentProposalList);
+ if (null != assignmentProposalList) {
+ completionProposalList.addAll(assignmentProposalList);
+ }
+
}
else if (abstractElement instanceof RuleCall) {
- List<ICompletionProposal> proposalList = this.proposalProvider.completeRuleCall(
- (RuleCall) abstractElement, currentLeafNode, prefix, xtextDocument);
- if (null == proposalList || proposalList.isEmpty()) {
- collectCompletionProposalList(
- resolveElement((AbstractElement) abstractElement.eContainer(), false),
- completionProposalList, xtextDocument, currentLeafNode, prefix, offset);
+
+ List<? extends ICompletionProposal> ruleCallProposalList = this.proposalProvider.completeRuleCall(
+ (RuleCall) abstractElement, currentLeafNode, prefix, xtextDocument,offset);
+
+ if (null != ruleCallProposalList) {
+ completionProposalList.addAll(ruleCallProposalList);
}
}
- else if (abstractElement instanceof LexerRule) {
- }
- else if (abstractElement instanceof CrossReference) {
- }
- else if (abstractElement instanceof Action) {
- }
}
}
- protected final List<EObject> resolveElement(AbstractElement abstractElement, boolean resolveRuleCall) {
+ protected final List<EObject> resolveElement(AbstractElement abstractElement) {
List<EObject> elementList = new ArrayList<EObject>();
if (abstractElement instanceof Alternatives) {
for (AbstractElement alternativeElement : ((Alternatives) abstractElement).getGroups()) {
- elementList.addAll(resolveElement(alternativeElement, resolveRuleCall));
+ elementList.addAll(resolveElement(alternativeElement));
}
}
else if (abstractElement instanceof Group) {
@@ -165,7 +160,7 @@ public class DefaultContentAssistProcessor implements IContentAssistProcessor {
.hasNext()
&& includeNext;) {
AbstractElement groupElement = iterator.next();
- elementList.addAll(resolveElement(groupElement, resolveRuleCall));
+ elementList.addAll(resolveElement(groupElement));
includeNext = GrammarUtil.isOptionalCardinality(groupElement);
}
@@ -174,26 +169,24 @@ public class DefaultContentAssistProcessor implements IContentAssistProcessor {
Assignment assignment = (Assignment) abstractElement;
- if (assignment.getTerminal() instanceof RuleCall && resolveRuleCall) {
- elementList.addAll(resolveElement(assignment.getTerminal(), resolveRuleCall));
+ if (assignment.getTerminal() instanceof RuleCall) {
+ elementList.addAll(resolveElement(assignment.getTerminal()));
}
else if (assignment.getTerminal() instanceof Alternatives) {
- elementList.addAll(resolveElement(assignment.getTerminal(), resolveRuleCall));
- }
- else {
- elementList.add(assignment);
+ elementList.addAll(resolveElement(assignment.getTerminal()));
}
+ elementList.add(assignment);
+
}
else if (abstractElement instanceof RuleCall) {
+ elementList.add(abstractElement);
+
AbstractRule abstractRule = GrammarUtil.calledRule((RuleCall) abstractElement);
if (abstractRule instanceof ParserRule) {
- elementList.addAll(resolveElement(((ParserRule) abstractRule).getAlternatives(), resolveRuleCall));
- }
- else {
- elementList.add(abstractElement);
+ elementList.addAll(resolveElement(((ParserRule) abstractRule).getAlternatives()));
}
}
else {
diff --git a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/IProposalProvider.java b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/IProposalProvider.java
index 1e80bf5..d622fdd 100644
--- a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/IProposalProvider.java
+++ b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/IProposalProvider.java
@@ -35,38 +35,42 @@ import org.eclipse.xtext.RuleCall;
* public List<ICompletionProposal> completeMyTypeName(Assignment ele, MyType model, String prefix, IDocument doc) {...}
* </code>
*
+ * @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 occure next up.
+ * can occur next up.
*
- * @param ele - the keyword to be completed
+ * @param keyword - the keyword to be completed
* @param model - the most specific model element under the cursor.
* @param prefix - the prefix under the cursor or null if there is no prefix
- * @param doc - the IDocument instance used by the editor
- * @return
+ * @param document - the IDocument instance used by the editor
+ * @param offset - an offset within the document for which completions should be computed
+ * @return a list of matching {@link ICompletionProposal}
*/
- public List<ICompletionProposal> completeKeyword(Keyword ele, EObject model, String prefix, IDocument doc,int offset);
+ public List<? extends ICompletionProposal> completeKeyword(Keyword keyword, EObject model, String prefix, IDocument document,int offset);
/**
* Is invoked by the framework if (with respect to the grammar) it is possible that the keyword passed as first parameter
* can occure next up.
*
- * @param ele - the keyword to be completed
+ * @param ruleCall - the keyword to be completed
* @param model - the most specific model element under the cursor.
* @param prefix - the prefix under the cursor or null if there is no prefix
- * @param doc - the IDocument instance used by the editor
- * @return
+ * @param document - the IDocument instance used by the editor
+ * @param offset - an offset within the document for which completions should be computed
+ * @return a list of matching {@link ICompletionProposal}
*/
- public List<ICompletionProposal> completeRuleCall(RuleCall ele, EObject model, String prefix, IDocument doc);
+ public List<? extends ICompletionProposal> completeRuleCall(RuleCall ruleCall, EObject model, String prefix, IDocument document,int offset);
/**
- * used to filter and sort a list of completion proposals.
- * is invoked by the framework after all possible completions have been collected.
- * @param proposals
- * @return
+ * Used to filter and sort a list of completion proposals.
+ * This method is invoked by the framework after all possible completions have been collected.
+ * @param completionProposalList
+ * @return the sorted and filtered <code>ICompletionProposal</code> list.
*/
- public List<ICompletionProposal> sortAndFilter(List<ICompletionProposal> proposals);
+ public List<? extends ICompletionProposal> sortAndFilter(List<? extends ICompletionProposal> completionProposalList);
}
diff --git a/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/XtextSourceViewerConfiguration.java b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/XtextSourceViewerConfiguration.java
index d0e5262..efd48af 100644
--- a/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/XtextSourceViewerConfiguration.java
+++ b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/XtextSourceViewerConfiguration.java
@@ -1,6 +1,8 @@
package org.eclipse.xtext.ui.core.editor;
import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.contentassist.ContentAssistant;
+import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.jface.text.contentassist.IContentAssistant;
import org.eclipse.jface.text.presentation.IPresentationReconciler;
import org.eclipse.jface.text.presentation.PresentationReconciler;
@@ -17,6 +19,10 @@ public class XtextSourceViewerConfiguration extends TextSourceViewerConfiguratio
@Inject(optional = true)
private IContentAssistant contentAssistant;
+
+
+ @Inject(optional = true)
+ private IContentAssistProcessor contentAssistProcessor;
@Inject(optional = true)
private ITokenScanner tokenScanner;
@@ -25,6 +31,10 @@ public class XtextSourceViewerConfiguration extends TextSourceViewerConfiguratio
public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) {
if (contentAssistant instanceof ISourceViewerAware)
((ISourceViewerAware) contentAssistant).setSourceViewer(sourceViewer);
+ if (contentAssistant instanceof ContentAssistant && contentAssistProcessor != null) {
+ ((ContentAssistant) contentAssistant).setContentAssistProcessor(contentAssistProcessor,
+ IDocument.DEFAULT_CONTENT_TYPE);
+ }
return contentAssistant;
}