| author | mclay | 2008-10-29 17:18:00 (EDT) |
|---|---|---|
| committer | sefftinge | 2008-10-29 17:18:00 (EDT) |
| commit | 34b462e9d321767cba589318ed38ad32f0191b84 (patch) (side-by-side diff) | |
| tree | 647614db23b71e74aa3c221f669ab6a786247df9 | |
| parent | 0164a2e1985a375aae5857e9f91568cd0664cbc0 (diff) | |
| download | org.eclipse.xtext-34b462e9d321767cba589318ed38ad32f0191b84.zip org.eclipse.xtext-34b462e9d321767cba589318ed38ad32f0191b84.tar.gz org.eclipse.xtext-34b462e9d321767cba589318ed38ad32f0191b84.tar.bz2 | |
add: extend generated ProposalProvider to include callback methods for AbstractRules with associated TypeRef
4 files changed, 124 insertions, 41 deletions
diff --git a/devtools/org.eclipse.xtext.reference/src/org/eclipse/xtext/reference/ReferenceGrammar.xtext b/devtools/org.eclipse.xtext.reference/src/org/eclipse/xtext/reference/ReferenceGrammar.xtext index edb1d9e..4aaaba4 100644 --- a/devtools/org.eclipse.xtext.reference/src/org/eclipse/xtext/reference/ReferenceGrammar.xtext +++ b/devtools/org.eclipse.xtext.reference/src/org/eclipse/xtext/reference/ReferenceGrammar.xtext @@ -3,29 +3,37 @@ * 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 -* +* http://www.eclipse.org/legal/epl-v10.html +* *******************************************************************************/ -language org. eclipse. xtext. reference. ReferenceGrammar -generate ReferenceGrammar "http://eclipse.org/xtext/reference/ReferenceGrammar" - - Spielplatz : - ( "spielplatz" groesse = INT ( beschreibung = STRING ) ? "{" ( kinder += Kind | erzieher += Erwachsener | spielzeuge += Spielzeug | familie += Familie ) * "}" ) ? ; - - Person : - Kind | Erwachsener ; - - Kind : - "kind" "(" name = ID age = INT ")" ; - - Erwachsener : - "erwachsener" "(" name = ID age = INT ")" ; - - Spielzeug : - "spielzeug" "(" name = ID farbe = Farbe ")" ; - - Familie : - "familie" "(" mutter=[Erwachsener] vater=[Erwachsener] kinder+=[Kind] ("," kinder+=[Kind])* ")" ; - - Farbe : - wert=("ROT" | "BLAU" | "GELB" | "GRÜN");
\ No newline at end of file +language org.eclipse.xtext.reference.ReferenceGrammar +generate ReferenceGrammar "http://eclipse.org/xtext/reference/ReferenceGrammar" +import "classpath:/org/eclipse/xtext/reference/ReferenceModel.ecore" as ReferenceModel + + +Spielplatz : + ( "spielplatz" groesse = INT ( beschreibung = STRING ) ? "{" + ( kinder += Kind | erzieher += Erwachsener | spielzeuge += Spielzeug | familie += Familie + | types += CustomTypeParserRule ) * "}" + ) ? ; + +Person : + Kind | Erwachsener ; + +Kind : + "kind" "(" name = ID age = INT ")" ; + +Erwachsener : + "erwachsener" "(" name = ID age = INT ")" ; + +Spielzeug : + "spielzeug" "(" name = ID farbe = Farbe ")" ; + +Familie : + "familie" "(" name=("keyword" | STRING | ID) mutter=[Erwachsener] vater=[Erwachsener] kinder+=[Kind] ("," kinder+=[Kind])* ")" ; + +Farbe : + wert=("ROT" | "BLAU" | "GELB" | "GRÜN"); + +CustomTypeParserRule returns ReferenceModel::CustomType : + 'type' name=ID; diff --git a/devtools/org.eclipse.xtext.reference/src/org/eclipse/xtext/reference/ReferenceModel.ecore b/devtools/org.eclipse.xtext.reference/src/org/eclipse/xtext/reference/ReferenceModel.ecore new file mode 100644 index 0000000..489921f --- a/dev/null +++ b/devtools/org.eclipse.xtext.reference/src/org/eclipse/xtext/reference/ReferenceModel.ecore @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ecore:EPackage xmi:version="2.0" + xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="ReferenceModel" + nsURI="http://eclipse.org/xtext/reference/ReferenceModel" nsPrefix="ReferenceModel"> + <eClassifiers xsi:type="ecore:EClass" name="CustomType"> + <eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> + </eClassifiers> +</ecore:EPackage> 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 1830bd6..9023603 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 @@ -9,9 +9,14 @@ 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.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.LexerRule; +import org.eclipse.xtext.ParserRule; import org.eclipse.xtext.RuleCall; import org.eclipse.xtext.parsetree.CompositeNode; import org.eclipse.xtext.parsetree.LeafNode; @@ -31,10 +36,7 @@ public abstract class AbstractProposalProvider implements IProposalProvider { /* * (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) + * @see org.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) { @@ -49,11 +51,7 @@ public abstract class AbstractProposalProvider implements IProposalProvider { /* * (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) + * @see org.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) { @@ -61,6 +59,12 @@ public abstract class AbstractProposalProvider implements IProposalProvider { logger.debug("completeRuleCall '" + ruleCall.getName() + "' cardinality '" + ruleCall.getCardinality() + "' for model '" + model + "' and prefix '" + prefix.trim() + "'"); } + AbstractRule calledRule = GrammarUtil.calledRule(ruleCall); + + if (calledRule instanceof LexerRule) { + return doCompleteLexerRuleRuleCall((LexerRule) calledRule, ruleCall, offset); + } + return Collections.emptyList(); } @@ -82,10 +86,32 @@ public abstract class AbstractProposalProvider implements IProposalProvider { List<? extends ICompletionProposal> completionProposalList) { return completionProposalList; } + + /** + * Concrete subclasses can override this to provide a more meaningful and sophisticated behaviour + * whenever a list of ICompletionProposal's should be computed for simple <code>LexerRule</code> call's. + * + * This implementation returns one <code>ICompletionProposal</code> with a displayString composed + * of the name of the containing rule plus the featurename of an optional assignment and at the end the name + * of the given LexerRule. (e.i. ParserRuleName+AssignmentFeatureName+LexerRuleName) + * + * @param lexerRule the 'called' LexerRule instance + * @param ruleCall the ruleCall for the provided lexerRule + * @param offset an offset within the document for which completions should be computed + * @return a computed list of <code>ICompletionProposal</code> for the given <code>LexerRule</code> + */ + protected List<? extends ICompletionProposal> doCompleteLexerRuleRuleCall(LexerRule lexerRule,RuleCall ruleCall, int offset) { + ParserRule containingParserRule = GrammarUtil.containingParserRule(ruleCall); + Assignment containingAssignment = GrammarUtil.containingAssignment(ruleCall); + String defaultDisplayString = containingParserRule.getName() + + (null != containingAssignment ? firstLetterCapitalized(containingAssignment.getFeature()) : "") + + lexerRule.getName(); + return Collections.singletonList(createCompletionProposal(defaultDisplayString, offset)); + } /** * - * @return the id of the plug-in containing the image file; + * @return the id of the plug-in containing the image files; * <code>null</code> is returned if the plug-in does not exist */ protected abstract String getPluginId(); @@ -93,7 +119,8 @@ public abstract class AbstractProposalProvider implements IProposalProvider { /** * 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. + * typically be shown to the left of the <code>ICompletionProposal</code> + * display string. * * @return the image file path of the default image to be shown or * <code>null</code> if no image is desired @@ -103,14 +130,17 @@ public abstract class AbstractProposalProvider implements IProposalProvider { /** * 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. + * 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) { + 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)) { @@ -136,5 +166,17 @@ public abstract class AbstractProposalProvider implements IProposalProvider { return new XtextCompletionProposal(text, new StyledString(text), text, getDefaultImageFilePath(), getPluginId(), offset); } + + /** + * @param text to apply + * @return the provided string with the first letter capitalized + */ + protected final String firstLetterCapitalized(String text) { + if (text == null || text.length() == 0) { + return text; + } + return text.substring(0, 1).toUpperCase() + text.substring(1, text.length()); + } + } 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 b907c82..9ab1f03 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 @@ -31,6 +31,7 @@ import org.eclipse.xtext.Group; import org.eclipse.xtext.Keyword; import org.eclipse.xtext.ParserRule; import org.eclipse.xtext.RuleCall; +import org.eclipse.xtext.TypeRef; import org.eclipse.xtext.parser.IParseResult; import org.eclipse.xtext.parsetree.AbstractNode; import org.eclipse.xtext.parsetree.CompositeNode; @@ -83,7 +84,8 @@ public class DefaultContentAssistProcessor implements IContentAssistProcessor { List<ICompletionProposal> completionProposalList = new ArrayList<ICompletionProposal>(); - for (Iterator<AbstractElement> iterator = calculatePossibleElementSet(lastCompleteNode, grammarElement) + Set<AbstractElement> calculatePossibleElementSet = calculatePossibleElementSet(lastCompleteNode, grammarElement); + for (Iterator<AbstractElement> iterator = calculatePossibleElementSet .iterator(); iterator.hasNext();) { AbstractElement nextElement = iterator.next(); @@ -141,6 +143,27 @@ public class DefaultContentAssistProcessor implements IContentAssistProcessor { if (null != ruleCallProposalList) { completionProposalList.addAll(ruleCallProposalList); } + + AbstractRule calledRule = GrammarUtil.calledRule((RuleCall) abstractElement); + + if (calledRule.getType()!=null) { + + TypeRef typeRef = calledRule.getType(); + + Method method = findMethod(proposalProvider.getClass(), + "complete" + firstLetterCapitalized(typeRef.getAlias()) + + firstLetterCapitalized(typeRef.getName()), RuleCall.class, EObject.class, + String.class, IDocument.class, int.class); + + Collection<? extends ICompletionProposal> proposalList = invokeMethod(method, proposalProvider, + abstractElement, currentLeafNode, prefix, xtextDocument, offset); + + if (null != proposalList) { + completionProposalList.addAll(proposalList); + } + + } + } } } @@ -378,6 +401,7 @@ public class DefaultContentAssistProcessor implements IContentAssistProcessor { @SuppressWarnings("unchecked") private final Collection<ICompletionProposal> invokeMethod(Method method, Object target, Object... args) { + try { return (Collection<ICompletionProposal>) method.invoke(target, args); } |

