| author | mclay | 2008-11-07 19:55:33 (EST) |
|---|---|---|
| committer | sefftinge | 2008-11-07 19:55:33 (EST) |
| commit | 6dc60517828857262bffb2d93186ff85844dfdd2 (patch) (side-by-side diff) | |
| tree | fe1cdaac7294b23a69b457cf21793d5a83ee5bdb | |
| parent | 28c35dc131252f7516ea14a52919ad56600c6892 (diff) | |
| download | org.eclipse.xtext-6dc60517828857262bffb2d93186ff85844dfdd2.zip org.eclipse.xtext-6dc60517828857262bffb2d93186ff85844dfdd2.tar.gz org.eclipse.xtext-6dc60517828857262bffb2d93186ff85844dfdd2.tar.bz2 | |
upd: keep working on CA enhancements
4 files changed, 134 insertions, 24 deletions
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 index 3193616..0eda0d4 100644 --- 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 @@ -2,7 +2,10 @@ package org.eclipse.xtext.ui.common.editor.codecompletion; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; import java.util.List; +import java.util.Map; import org.apache.log4j.Logger; import org.eclipse.emf.common.util.URI; @@ -20,6 +23,7 @@ import org.eclipse.xtext.ParserRule; import org.eclipse.xtext.RuleCall; import org.eclipse.xtext.crossref.ILinkingService; import org.eclipse.xtext.parsetree.AbstractNode; +import org.eclipse.xtext.parsetree.LeafNode; import org.eclipse.xtext.parsetree.NodeUtil; import org.eclipse.xtext.service.Inject; import org.eclipse.xtext.util.Pair; @@ -54,7 +58,6 @@ public abstract class AbstractProposalProvider implements IProposalProvider { + prefix.trim() + "'"); } String text = keyword.getValue().length() == 1 ? keyword.getValue() : keyword.getValue() + " "; - return Collections.singletonList(createCompletionProposal(text, offset)); } @@ -80,19 +83,63 @@ public abstract class AbstractProposalProvider implements IProposalProvider { /* * (non-Javadoc) - * - * @seeorg.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider#sortAndFilter(java.util.List) + * @see org.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider#sortAndFilter(java.util.List, org.eclipse.emf.ecore.EObject, java.lang.String) */ - public List<? extends ICompletionProposal> sortAndFilter(List<? extends ICompletionProposal> completionProposalList) { - return doSortAndFilter(completionProposalList); + public List<? extends ICompletionProposal> sortAndFilter( + List<? extends ICompletionProposal> completionProposalList, EObject model, String prefix) { + return doSortAndFilter(completionProposalList,model,prefix); } /** * Concrete subclasses can override this for custom sort and filter * behavior. Gets called after all completion proposals have been collected. + * + * The default behavior of this implementation is to sort duplicates and to trim + * matching <code>ICompletionProposal#displayString</code> with matching prefix values. + * + * @param completionProposalList matching {@link ICompletionProposal} to sort and filter + * @param model - the most specific model element under the cursor. + * @param prefix - the prefix under the cursor or null if there is no prefix + * @return the sorted and filtered <code>ICompletionProposal</code> list. + * */ protected List<? extends ICompletionProposal> doSortAndFilter( - List<? extends ICompletionProposal> completionProposalList) { + List<? extends ICompletionProposal> completionProposalList,EObject model,String prefix) { + + if (model instanceof LeafNode) { + + LeafNode leafNode = (LeafNode) model; + + Map<String,ICompletionProposal> displayString2ICompletionProposalMap = new HashMap<String,ICompletionProposal>(); + + for (Iterator<? extends ICompletionProposal> iterator = completionProposalList.iterator(); iterator.hasNext();) { + + ICompletionProposal completionProposal = iterator.next(); + + // filter duplicate displayString + if (!displayString2ICompletionProposalMap.containsKey(completionProposal.getDisplayString())) { + + displayString2ICompletionProposalMap.put(completionProposal.getDisplayString(), completionProposal); + + // trim displayString + if (leafNode.isHidden() && !"".equals(leafNode.getText().trim()) ) { + + if (completionProposal.getDisplayString().startsWith(leafNode.getText()) && + completionProposal instanceof XtextCompletionProposal) { + + XtextCompletionProposal xtextCompletionProposal = (XtextCompletionProposal) completionProposal; + + xtextCompletionProposal.setText(xtextCompletionProposal.getText().replaceFirst(leafNode.getText(), "")); + } else { + iterator.remove(); + } + } + } else { + iterator.remove(); + } + } + } + return completionProposalList; } 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 53fed4e..7b3c99e 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 @@ -12,7 +12,11 @@ import java.util.Set; import org.apache.log4j.Logger; import org.eclipse.core.runtime.Assert; +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.util.EcoreEList; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.contentassist.ContextInformationValidator; @@ -20,10 +24,11 @@ import org.eclipse.jface.text.contentassist.ICompletionProposal; import org.eclipse.jface.text.contentassist.IContentAssistProcessor; import org.eclipse.jface.text.contentassist.IContextInformation; import org.eclipse.jface.text.contentassist.IContextInformationValidator; -import org.eclipse.swt.custom.StyledText; import org.eclipse.xtext.AbstractElement; import org.eclipse.xtext.AbstractRule; import org.eclipse.xtext.Assignment; +import org.eclipse.xtext.CrossReference; +import org.eclipse.xtext.EcoreUtil2; import org.eclipse.xtext.GrammarUtil; import org.eclipse.xtext.Keyword; import org.eclipse.xtext.ParserRule; @@ -33,6 +38,7 @@ 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; import org.eclipse.xtext.service.Inject; @@ -64,7 +70,6 @@ public class DefaultContentAssistProcessor implements IContentAssistProcessor { if (proposalProvider != null) { - IDocument document = viewer.getDocument(); if (document instanceof XtextDocument) { @@ -85,17 +90,17 @@ public class DefaultContentAssistProcessor implements IContentAssistProcessor { AbstractNode lastCompleteNode = ParseTreeUtil.getLastCompleteNodeByOffset(rootNode, offset); - LeafNode currentLeafNode = (LeafNode) ParseTreeUtil.getCurrentNodeByOffset(rootNode, offset); + LeafNode currentLeafNode = ParseTreeUtil.getCurrentNodeByOffset(rootNode, offset); - String prefix = ""; - StyledText textWidget = viewer.getTextWidget(); - if (textWidget.getCharCount() > 0) { - int boundedOffset = Math.min(offset, textWidget.getCharCount()) -1; - if(currentLeafNode.getOffset() <= boundedOffset) - prefix = textWidget.getText(currentLeafNode.getOffset(), boundedOffset); - } + String prefix = null==currentLeafNode ? "" : currentLeafNode.getText(); Set<AbstractElement> nextValidElementSet = ParseTreeUtil.getElementSetValidFromOffset(rootNode,lastCompleteNode, offset); + /** + * in the case of a non linked crossreference we delegate to proposalProvider (again) + */ + if (lastCompleteNode.getGrammarElement() instanceof CrossReference && !isLinked(lastCompleteNode) ) { + nextValidElementSet.add((AbstractElement) lastCompleteNode.getGrammarElement().eContainer()); + } for (List<EObject> resolvedElementOrRuleList : new ProposalCandidateResolverSwitch(nextValidElementSet)) { @@ -106,10 +111,8 @@ public class DefaultContentAssistProcessor implements IContentAssistProcessor { } if (completionProposalList != null) { - List<? extends ICompletionProposal> sortAndFilter = proposalProvider - .sortAndFilter(completionProposalList); + List<? extends ICompletionProposal> sortAndFilter = proposalProvider.sortAndFilter(completionProposalList,currentLeafNode,prefix); completionProposals = sortAndFilter.toArray(new ICompletionProposal[] {}); - } } } @@ -304,6 +307,49 @@ public class DefaultContentAssistProcessor implements IContentAssistProcessor { private final String firstLetterCapitalized(String name) { return name.substring(0, 1).toUpperCase() + name.substring(1); } + + @SuppressWarnings("unchecked") + private boolean isLinked(AbstractNode lastCompleteNode) { + + EObject semanticModel = NodeUtil.getNearestSemanticObject(lastCompleteNode); + + EReference eReference = getReference((CrossReference) lastCompleteNode.getGrammarElement(), semanticModel.eClass()); + + if (eReference.getUpperBound() == 1 ) { + + if (null!=semanticModel.eGet(eReference)) { + return true; + } + } + else { + + EcoreEList<EObject> ecoreEList = (EcoreEList<EObject>) semanticModel.eGet(eReference); + + for (Iterator<EObject> iterator = ecoreEList.iterator(); iterator.hasNext();) { + + EObject object = iterator.next(); + + if (EcoreUtil2.getURIFragment(object).equalsIgnoreCase(((LeafNode)lastCompleteNode).getText())) { + return true; + } + } + } + + return false; + } + + private EReference getReference(CrossReference ref, EClass class1) { + + EList<EReference> references = class1.getEAllReferences(); + + String feature = GrammarUtil.containingAssignment(ref).getFeature(); + + for (EReference reference : references) { + if (!reference.isContainment() && reference.getName().equals(feature)) + return reference; + } + return null; + } } 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 d622fdd..394988f 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 @@ -69,8 +69,10 @@ public interface IProposalProvider { /** * 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 + * @param completionProposalList matching {@link ICompletionProposal} to sort and filter + * @param model - the most specific model element under the cursor. + * @param prefix - the prefix under the cursor or null if there is no prefix * @return the sorted and filtered <code>ICompletionProposal</code> list. */ - public List<? extends ICompletionProposal> sortAndFilter(List<? extends ICompletionProposal> completionProposalList); + public List<? extends ICompletionProposal> sortAndFilter(List<? extends ICompletionProposal> completionProposalList,EObject model,String prefix); } diff --git a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/XtextCompletionProposal.java b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/XtextCompletionProposal.java index 56856c4..9428dbd 100644 --- a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/XtextCompletionProposal.java +++ b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/XtextCompletionProposal.java @@ -2,9 +2,6 @@ package org.eclipse.xtext.ui.common.editor.codecompletion; import org.apache.log4j.Logger; import org.eclipse.core.runtime.Assert; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.DocumentEvent; @@ -75,6 +72,24 @@ public class XtextCompletionProposal implements ICompletionProposal, initializeImage(imageFilePath); } } + + /** + * Setter for the text to insert + * + * @param text + */ + public void setText(String text) { + this.text = text; + } + + + /** + * Getter for the text to insert + * @return the text to insert + */ + public String getText() { + return text; + } /* * (non-Javadoc) |

