| author | mclay | 2008-12-21 14:45:03 (EST) |
|---|---|---|
| committer | sefftinge | 2008-12-21 14:45:03 (EST) |
| commit | dd1c9e1f8db4096b4afef0c0f68d1f4c8e2e6c3c (patch) (side-by-side diff) | |
| tree | c5f850fceb4ede82d3e24b23849af448ab5f48f8 | |
| parent | 2329526861387056ac65c24e322de51efaf51135 (diff) | |
| download | org.eclipse.xtext-dd1c9e1f8db4096b4afef0c0f68d1f4c8e2e6c3c.zip org.eclipse.xtext-dd1c9e1f8db4096b4afef0c0f68d1f4c8e2e6c3c.tar.gz org.eclipse.xtext-dd1c9e1f8db4096b4afef0c0f68d1f4c8e2e6c3c.tar.bz2 | |
ASSIGNED - bug 241897: [Content Assist] Implement template proposals for Xtext CA
https://bugs.eclipse.org/bugs/show_bug.cgi?id=241897
31 files changed, 1836 insertions, 1113 deletions
diff --git a/devtools/org.eclipse.xtext.reference.ui/src-gen/org/eclipse/xtext/reference/ReferenceGrammarGenProposalProvider.java b/devtools/org.eclipse.xtext.reference.ui/src-gen/org/eclipse/xtext/reference/ReferenceGrammarGenProposalProvider.java index c702b0a..6fcc47c 100644 --- a/devtools/org.eclipse.xtext.reference.ui/src-gen/org/eclipse/xtext/reference/ReferenceGrammarGenProposalProvider.java +++ b/devtools/org.eclipse.xtext.reference.ui/src-gen/org/eclipse/xtext/reference/ReferenceGrammarGenProposalProvider.java @@ -6,239 +6,210 @@ package org.eclipse.xtext.reference; import java.util.Collections; import java.util.List; -import org.eclipse.emf.ecore.EObject; -import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.contentassist.ICompletionProposal; import org.eclipse.xtext.Assignment; import org.eclipse.xtext.CrossReference; import org.eclipse.xtext.RuleCall; import org.eclipse.xtext.ui.common.editor.codecompletion.AbstractProposalProvider; +import org.eclipse.xtext.ui.common.editor.codecompletion.IContentAssistContext; import org.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider; /** * Represents a generated, default implementation of interface {@link IProposalProvider}. * - * In addition to the declared methods, the framework tries to call grammar dependent methods for assignments using reflection. - * The signature of such methods invoked reflectively follows the following pattern: - * - * public List<ICompletionProposal> complete[Typename][featureName](Assignment ele, EObject model, String prefix) - * - * <b>Example</b> - * Given the following grammar : - * <code> - * RuleA returns MyType : - * "myType" name=ID; - * </code> - * - * One could provide the following method in an implementation of this interface: - * <code> - * public List<ICompletionProposal> completeMyTypeName(Assignment ele, EObject model, String prefix, IDocument doc) {...} - * </code> - * Note that if you have generated Java classes for your domain model (meta model) you can alternatively declare the second parameter using - * a specific type: - * <code> - * public List<ICompletionProposal> completeMyTypeName(Assignment ele, MyType model, String prefix, IDocument doc) {...} - * </code> - * + * @see org.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider */ public class ReferenceGrammarGenProposalProvider extends AbstractProposalProvider { // constants private static final String UI_PLUGIN_ID = "org.eclipse.xtext.reference.ui"; - public List<? extends ICompletionProposal> completeSpielplatzGroesse(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeSpielplatzGroesse(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeSpielplatzGroesse feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"1", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "1", contentAssistContext)); } - public List<? extends ICompletionProposal> completeSpielplatzBeschreibung(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeSpielplatzBeschreibung(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeSpielplatzBeschreibung feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"\"SpielplatzBeschreibung\"", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "\"SpielplatzBeschreibung\"", contentAssistContext)); } - public List<? extends ICompletionProposal> completeSpielplatzKinder(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeSpielplatzKinder(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeSpielplatzKinder feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeSpielplatzErzieher(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeSpielplatzErzieher(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeSpielplatzErzieher feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeSpielplatzSpielzeuge(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeSpielplatzSpielzeuge(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeSpielplatzSpielzeuge feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeSpielplatzFamilie(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeSpielplatzFamilie(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeSpielplatzFamilie feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeSpielplatzTypes(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeSpielplatzTypes(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeSpielplatzTypes feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeKindName(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeKindName(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeKindName feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"KindName", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "KindName", contentAssistContext)); } - public List<? extends ICompletionProposal> completeKindAge(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeKindAge(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeKindAge feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"1", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "1", contentAssistContext)); } - public List<? extends ICompletionProposal> completeErwachsenerName(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeErwachsenerName(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeErwachsenerName feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"ErwachsenerName", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "ErwachsenerName", contentAssistContext)); } - public List<? extends ICompletionProposal> completeErwachsenerAge(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeErwachsenerAge(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeErwachsenerAge feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"1", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "1", contentAssistContext)); } - public List<? extends ICompletionProposal> completeSpielzeugName(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeSpielzeugName(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeSpielzeugName feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"SpielzeugName", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "SpielzeugName", contentAssistContext)); } - public List<? extends ICompletionProposal> completeSpielzeugFarbe(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeSpielzeugFarbe(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeSpielzeugFarbe feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeFamilieName(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeFamilieName(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeFamilieName feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeFamilieMutter(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeFamilieMutter(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeFamilieMutter feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return lookupCrossReference(((CrossReference)assignment.getTerminal()), model, prefix, offset); + return lookupCrossReference(((CrossReference)assignment.getTerminal()), contentAssistContext); } - public List<? extends ICompletionProposal> completeFamilieVater(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeFamilieVater(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeFamilieVater feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return lookupCrossReference(((CrossReference)assignment.getTerminal()), model, prefix, offset); + return lookupCrossReference(((CrossReference)assignment.getTerminal()), contentAssistContext); } - public List<? extends ICompletionProposal> completeFamilieKinder(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeFamilieKinder(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeFamilieKinder feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return lookupCrossReference(((CrossReference)assignment.getTerminal()), model, prefix, offset); + return lookupCrossReference(((CrossReference)assignment.getTerminal()), contentAssistContext); } - public List<? extends ICompletionProposal> completeFarbeWert(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeFarbeWert(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeFarbeWert feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeCustomTypeParserRuleName(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeCustomTypeParserRuleName(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeCustomTypeParserRuleName feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"CustomTypeParserRuleName", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "CustomTypeParserRuleName", contentAssistContext)); } - public List<? extends ICompletionProposal> complete(RuleCall ruleCall, EObject model, String prefix, - IDocument doc, int offset) { + public List<? extends ICompletionProposal> complete(RuleCall ruleCall, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("complete '" + ruleCall.getRule().getName() + "' cardinality '" + ruleCall.getCardinality() - + "' for model '" + model + "' and prefix '" + prefix.trim() + "'"); + + "' for model '" + contentAssistContext.getModel() + "' and prefix '" + contentAssistContext.getMatchString() + "'"); } return Collections.emptyList(); } - - - - - - public List<? extends ICompletionProposal> completeReferenceModelCustomType(RuleCall ruleCall, EObject model, String prefix, - IDocument doc, int offset) { + public List<? extends ICompletionProposal> completeReferenceModelCustomType(RuleCall ruleCall, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeReferenceModelCustomType '" + ruleCall.getRule().getName() + "' cardinality '" + ruleCall.getCardinality() - + "' for model '" + model + "' and prefix '" + prefix.trim() + "'"); + + "' for model '" + contentAssistContext.getModel() + "' and prefix '" + contentAssistContext.getMatchString() + "'"); } return Collections.emptyList(); } diff --git a/examples/org.eclipse.xtext.example.fowlerdsl.ui/META-INF/MANIFEST.MF b/examples/org.eclipse.xtext.example.fowlerdsl.ui/META-INF/MANIFEST.MF index c58410d..79fd3ce 100644 --- a/examples/org.eclipse.xtext.example.fowlerdsl.ui/META-INF/MANIFEST.MF +++ b/examples/org.eclipse.xtext.example.fowlerdsl.ui/META-INF/MANIFEST.MF @@ -4,10 +4,13 @@ Bundle-Name: Xtext DSL Example UI (Incubation) Bundle-SymbolicName: org.eclipse.xtext.example.fowlerdsl.ui;singleton:=true Bundle-Vendor: Eclipse.org Bundle-Version: 0.7.0.qualifier -Eclipse-RegisterBuddy: org.eclipse.xtext.log4j +Eclipse-RegisterBuddy: org.eclipse.xtext.log4j,org.eclipse.xtext.service.ui,org.eclipse.xtext.service Bundle-RequiredExecutionEnvironment: J2SE-1.5 -Bundle-ActivationPolicy: lazy Export-Package: org.eclipse.xtext.example Require-Bundle: org.eclipse.xtext.example.fowlerdsl, org.eclipse.xtext.ui.core, - org.eclipse.xtext.ui.common + org.eclipse.xtext.ui.common, + org.eclipse.xtext.service.ui, + org.eclipse.xtext.service +Bundle-Activator: org.eclipse.xtext.example.Activator +Bundle-ActivationPolicy: lazy diff --git a/examples/org.eclipse.xtext.example.fowlerdsl.ui/plugin.xml b/examples/org.eclipse.xtext.example.fowlerdsl.ui/plugin.xml index 550f42e..9cd6e7c 100644 --- a/examples/org.eclipse.xtext.example.fowlerdsl.ui/plugin.xml +++ b/examples/org.eclipse.xtext.example.fowlerdsl.ui/plugin.xml @@ -49,4 +49,32 @@ label="Task Tags"> </keyword> </extension> + <extension point="org.eclipse.ui.editors.templates"> + <contextType name="templatesContextTypeEventsName" + class="org.eclipse.xtext.ui.common.editor.codecompletion.impl.XtextTemplateContextType" + id="org.eclipse.xtext.example.fowlerdsl.ui.templates.contextType.events"> + </contextType> + <contextType name="templatesContextTypeActionsName" + class="org.eclipse.xtext.ui.common.editor.codecompletion.impl.XtextTemplateContextType" + id="org.eclipse.xtext.example.fowlerdsl.ui.templates.contextType.actions"> + </contextType> + <contextType name="templatesContextTypeStateName" + class="org.eclipse.xtext.ui.common.editor.codecompletion.impl.XtextTemplateContextType" + id="org.eclipse.xtext.example.fowlerdsl.ui.templates.contextType.state"> + </contextType> + <contextType name="templatesContextTypeEventName" + class="org.eclipse.xtext.ui.common.editor.codecompletion.impl.XtextTemplateContextType" + id="org.eclipse.xtext.example.fowlerdsl.ui.templates.contextType.Event"> + </contextType> + <contextType name="templatesContextTypeCommandName" + class="org.eclipse.xtext.ui.common.editor.codecompletion.impl.XtextTemplateContextType" + id="org.eclipse.xtext.example.fowlerdsl.ui.templates.contextType.Command"> + </contextType> + <contextType name="templatesContextTypeTransitionName" + class="org.eclipse.xtext.ui.common.editor.codecompletion.impl.XtextTemplateContextType" + id="org.eclipse.xtext.example.fowlerdsl.ui.templates.contextType.Transition"> + </contextType> + <include file="templates/templates.xml" /> + </extension> + </plugin> diff --git a/examples/org.eclipse.xtext.example.fowlerdsl.ui/src-gen/org/eclipse/xtext/example/FowlerDslGenProposalProvider.java b/examples/org.eclipse.xtext.example.fowlerdsl.ui/src-gen/org/eclipse/xtext/example/FowlerDslGenProposalProvider.java index 9fc04fe..ff38345 100644 --- a/examples/org.eclipse.xtext.example.fowlerdsl.ui/src-gen/org/eclipse/xtext/example/FowlerDslGenProposalProvider.java +++ b/examples/org.eclipse.xtext.example.fowlerdsl.ui/src-gen/org/eclipse/xtext/example/FowlerDslGenProposalProvider.java @@ -6,169 +6,146 @@ package org.eclipse.xtext.example; import java.util.Collections; import java.util.List; -import org.eclipse.emf.ecore.EObject; -import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.contentassist.ICompletionProposal; import org.eclipse.xtext.Assignment; import org.eclipse.xtext.CrossReference; import org.eclipse.xtext.RuleCall; import org.eclipse.xtext.ui.common.editor.codecompletion.AbstractProposalProvider; +import org.eclipse.xtext.ui.common.editor.codecompletion.IContentAssistContext; import org.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider; /** * Represents a generated, default implementation of interface {@link IProposalProvider}. * - * In addition to the declared methods, the framework tries to call grammar dependent methods for assignments using reflection. - * The signature of such methods invoked reflectively follows the following pattern: - * - * public List<ICompletionProposal> complete[Typename][featureName](Assignment ele, EObject model, String prefix) - * - * <b>Example</b> - * Given the following grammar : - * <code> - * RuleA returns MyType : - * "myType" name=ID; - * </code> - * - * One could provide the following method in an implementation of this interface: - * <code> - * public List<ICompletionProposal> completeMyTypeName(Assignment ele, EObject model, String prefix, IDocument doc) {...} - * </code> - * Note that if you have generated Java classes for your domain model (meta model) you can alternatively declare the second parameter using - * a specific type: - * <code> - * public List<ICompletionProposal> completeMyTypeName(Assignment ele, MyType model, String prefix, IDocument doc) {...} - * </code> - * + * @see org.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider */ public class FowlerDslGenProposalProvider extends AbstractProposalProvider { // constants private static final String UI_PLUGIN_ID = "org.eclipse.xtext.example.fowlerdsl.ui"; - public List<? extends ICompletionProposal> completeStatemachineEvents(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeStatemachineEvents(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeStatemachineEvents feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeStatemachineCommands(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeStatemachineCommands(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeStatemachineCommands feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeStatemachineStates(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeStatemachineStates(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeStatemachineStates feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeEventResetting(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeEventResetting(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeEventResetting feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeEventName(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeEventName(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeEventName feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"EventName", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "EventName", contentAssistContext)); } - public List<? extends ICompletionProposal> completeEventCode(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeEventCode(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeEventCode feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"EventCode", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "EventCode", contentAssistContext)); } - public List<? extends ICompletionProposal> completeCommandName(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeCommandName(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeCommandName feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"CommandName", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "CommandName", contentAssistContext)); } - public List<? extends ICompletionProposal> completeCommandCode(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeCommandCode(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeCommandCode feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"CommandCode", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "CommandCode", contentAssistContext)); } - public List<? extends ICompletionProposal> completeStateName(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeStateName(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeStateName feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"StateName", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "StateName", contentAssistContext)); } - public List<? extends ICompletionProposal> completeStateActions(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeStateActions(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeStateActions feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return lookupCrossReference(((CrossReference)assignment.getTerminal()), model, prefix, offset); + return lookupCrossReference(((CrossReference)assignment.getTerminal()), contentAssistContext); } - public List<? extends ICompletionProposal> completeStateTransitions(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeStateTransitions(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeStateTransitions feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeTransitionEvent(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeTransitionEvent(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeTransitionEvent feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return lookupCrossReference(((CrossReference)assignment.getTerminal()), model, prefix, offset); + return lookupCrossReference(((CrossReference)assignment.getTerminal()), contentAssistContext); } - public List<? extends ICompletionProposal> completeTransitionState(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeTransitionState(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeTransitionState feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return lookupCrossReference(((CrossReference)assignment.getTerminal()), model, prefix, offset); + return lookupCrossReference(((CrossReference)assignment.getTerminal()), contentAssistContext); } - public List<? extends ICompletionProposal> complete(RuleCall ruleCall, EObject model, String prefix, - IDocument doc, int offset) { + public List<? extends ICompletionProposal> complete(RuleCall ruleCall, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("complete '" + ruleCall.getRule().getName() + "' cardinality '" + ruleCall.getCardinality() - + "' for model '" + model + "' and prefix '" + prefix.trim() + "'"); + + "' for model '" + contentAssistContext.getModel() + "' and prefix '" + contentAssistContext.getMatchString() + "'"); } return Collections.emptyList(); } diff --git a/examples/org.eclipse.xtext.example.fowlerdsl.ui/src/org/eclipse/xtext/example/Activator.java b/examples/org.eclipse.xtext.example.fowlerdsl.ui/src/org/eclipse/xtext/example/Activator.java new file mode 100644 index 0000000..c7ec9b0 --- a/dev/null +++ b/examples/org.eclipse.xtext.example.fowlerdsl.ui/src/org/eclipse/xtext/example/Activator.java @@ -0,0 +1,198 @@ +/******************************************************************************* + * Copyright (c) 2008 itemis AG (http://www.itemis.eu) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + *******************************************************************************/ +package org.eclipse.xtext.example; + +import java.io.IOException; +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +import org.apache.log4j.Logger; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.text.templates.ContextTypeRegistry; +import org.eclipse.jface.text.templates.persistence.TemplateStore; +import org.eclipse.ui.editors.text.templates.ContributionContextTypeRegistry; +import org.eclipse.ui.editors.text.templates.ContributionTemplateStore; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * The activator class controls the plug-in life cycle + */ +public class Activator extends AbstractUIPlugin { + + Logger logger = Logger.getLogger(Activator.class); + + // The plug-in ID + public static final String PLUGIN_ID = "org.eclipse.xtext.example.fowlerdsl.ui"; + + private static final String RESOURCE_NAME = PLUGIN_ID + ".messages"; + + + /** Key to store our templates. */ + private static final String TEMPLATES_KEY = PLUGIN_ID + ".templates"; + + public static final String PREFIX = Activator.PLUGIN_ID + ".templates.contextType."; + + public static final String EVENTS = PREFIX + "events"; + public static final String EVENT = PREFIX + "Event"; + public static final String COMMAND = PREFIX + "Command"; + public static final String TRANSITION = PREFIX + "Transition"; + public static final String ACTIONS = PREFIX + "actions"; + public static final String STATE = PREFIX + "state"; + // The shared instance + private static Activator plugin; + + private ResourceBundle resourceBundle; + private ContextTypeRegistry contextTypeRegistry; + private TemplateStore templateStore; + + /** + * The constructor + */ + public Activator() { + try { + resourceBundle = ResourceBundle.getBundle(RESOURCE_NAME); + } catch (MissingResourceException e) { + resourceBundle = null; + } + + } + + public ResourceBundle getResourceBundle() { + return resourceBundle; + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext + * ) + */ + public void start(BundleContext context) throws Exception { + super.start(context); + setDefault(this); + logger.debug("Starting fowlerdsl.ui activator: " + this.getClass().getName()); + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext + * ) + */ + public void stop(BundleContext context) throws Exception { + setDefault(null); + super.stop(context); + } + + /** + * Returns the shared instance + * + * @return the shared instance + */ + public static Activator getDefault() { + return plugin; + } + + private static void setDefault(Activator activator) { + plugin = activator; + } + + /** + * Returns the template context type registry for the Fowler-Dsl editor. + * + * @return the template context type registry for the Fowler-Dsl editor + */ + public ContextTypeRegistry getTemplateContextRegistry() { + if (contextTypeRegistry == null) { + ContributionContextTypeRegistry registry = new ContributionContextTypeRegistry(); + registry.addContextType(EVENTS); + registry.addContextType(ACTIONS); + registry.addContextType(TRANSITION); + registry.addContextType(EVENT); + registry.addContextType(COMMAND); + registry.addContextType(STATE); + contextTypeRegistry = registry; + } + return contextTypeRegistry; + } + + /** + * Returns the template store for the Fowler-Dsl editor. + * + * @return the template store for the Fowler-Dsl editor + */ + public TemplateStore getTemplateStore() { + if (templateStore == null) { + templateStore = new ContributionTemplateStore(getTemplateContextRegistry(), getPreferenceStore(), + TEMPLATES_KEY); + try { + templateStore.load(); + } + catch (IOException e) { + logger.error(e); + } + } + return templateStore; + } + + public static void log(IStatus status) { + getDefault().getLog().log(status); + } + + /** + * Writes the message to the plug-in's log + * + * @param message the text to write to the log + */ + public static void log(String message, Throwable exception) { + IStatus status = createErrorStatus(message, exception); + getDefault().getLog().log(status); + } + + public static void log(Throwable exception) { + getDefault().getLog().log(createErrorStatus( + getResourceString("Plugin.internal_error"), exception)); + } + /** + * Returns a new <code>IStatus</code> for this plug-in + */ + public static IStatus createErrorStatus(String message, + Throwable exception) { + if (message == null) { + message= ""; + } + return new Status(Status.ERROR, PLUGIN_ID, 0, message, exception); + } + + /** + * Returns the string from the plugin's resource bundle, + * or 'key' if not found. + */ + public static String getResourceString(String key) { + String bundleString; + ResourceBundle bundle = getDefault().getResourceBundle(); + if (bundle != null) { + try { + bundleString = bundle.getString(key); + } catch (MissingResourceException e) { + log(e); + bundleString = "!" + key + "!"; + } + } else { + bundleString = "!" + key + "!"; + } + return bundleString; + } + + +} diff --git a/examples/org.eclipse.xtext.example.fowlerdsl.ui/src/org/eclipse/xtext/example/FowlerDslProposalProvider.java b/examples/org.eclipse.xtext.example.fowlerdsl.ui/src/org/eclipse/xtext/example/FowlerDslProposalProvider.java new file mode 100644 index 0000000..2fd2394 --- a/dev/null +++ b/examples/org.eclipse.xtext.example.fowlerdsl.ui/src/org/eclipse/xtext/example/FowlerDslProposalProvider.java @@ -0,0 +1,28 @@ +package org.eclipse.xtext.example; + +import org.eclipse.jface.text.templates.Template; +import org.eclipse.jface.text.templates.TemplateContextType; +import org.eclipse.xtext.Keyword; +import org.eclipse.xtext.RuleCall; +import org.eclipse.xtext.ui.common.editor.codecompletion.IContentAssistContext; + +public class FowlerDslProposalProvider extends FowlerDslGenProposalProvider { + + @Override + public Template[] getTemplates(String contextTypeId) { + return Activator.getDefault().getTemplateStore().getTemplates(contextTypeId); + } + + @Override + public TemplateContextType getTemplateContextType(Keyword keyword, IContentAssistContext contentAssistContext) { + return Activator.getDefault().getTemplateContextRegistry() + .getContextType(Activator.PREFIX + keyword.getValue()); + } + + @Override + public TemplateContextType getTemplateContextType(RuleCall ruleCall, IContentAssistContext contentAssistContext) { + return Activator.getDefault().getTemplateContextRegistry().getContextType( + Activator.PREFIX + ruleCall.getRule().getName()); + } + +} diff --git a/examples/org.eclipse.xtext.example.fowlerdsl.ui/src/org/eclipse/xtext/example/FowlerDslUiConfig.java b/examples/org.eclipse.xtext.example.fowlerdsl.ui/src/org/eclipse/xtext/example/FowlerDslUiConfig.java index 6caf1f7..f25f3e2 100644 --- a/examples/org.eclipse.xtext.example.fowlerdsl.ui/src/org/eclipse/xtext/example/FowlerDslUiConfig.java +++ b/examples/org.eclipse.xtext.example.fowlerdsl.ui/src/org/eclipse/xtext/example/FowlerDslUiConfig.java @@ -1,11 +1,11 @@ /* Generated with Xtext -*/ + */ package org.eclipse.xtext.example; import java.util.Set; -import org.eclipse.xtext.service.AbstractServiceRegistrationFactory; +import org.eclipse.xtext.service.ServiceRegistry; /** * used to register components to be used within the IDE. @@ -13,7 +13,12 @@ import org.eclipse.xtext.service.AbstractServiceRegistrationFactory; public class FowlerDslUiConfig extends org.eclipse.xtext.example.GenFowlerDslUiConfig { public Set<IServiceRegistration> registrations() { - return super.registrations(); + Set<IServiceRegistration> registrations = super.registrations(); + registrations.addAll(scope(org.eclipse.xtext.example.IFowlerDsl.SCOPE).with( + org.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider.class, + org.eclipse.xtext.example.FowlerDslProposalProvider.class, ServiceRegistry.PRIORITY_MAX) + .registrations()); + return registrations; } } diff --git a/examples/org.eclipse.xtext.example.fowlerdsl.ui/templates/templates.xml b/examples/org.eclipse.xtext.example.fowlerdsl.ui/templates/templates.xml new file mode 100644 index 0000000..d8bc2b1 --- a/dev/null +++ b/examples/org.eclipse.xtext.example.fowlerdsl.ui/templates/templates.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8"?> +<templates> + <template name="empty Statemachine" description="template for an empty Statemachine" + id="org.eclipse.xtext.example.fowlerdsl.ui.templates.events" + context="org.eclipse.xtext.example.fowlerdsl.ui.templates.contextType.events" + enabled="true">events + startEvent START1 + stopEvent STOP2 + ${cursor} +end + +commands +end + +state start + startEvent => start +end + +state stop + stopEvent => stop +end + </template> + + <template name="state" description="state definition" + id="org.eclipse.xtext.example.fowlerdsl.ui.templates.state" + context="org.eclipse.xtext.example.fowlerdsl.ui.templates.contextType.state" + enabled="true">state ${name} + ${cursor} +end</template> + + <template name="transition" description="event transition" + id="org.eclipse.xtext.example.fowlerdsl.ui.templates.transition" + context="org.eclipse.xtext.example.fowlerdsl.ui.templates.contextType.Transition" + enabled="true">${event:CrossReference('Transition.event')} => ${state:CrossReference('Transition.state')}</template> + + <template name="event" description="event definition" + id="org.eclipse.xtext.example.fowlerdsl.ui.templates.event" + context="org.eclipse.xtext.example.fowlerdsl.ui.templates.contextType.Event" + enabled="true">${event} ${shortCode}</template> + + <template name="command" description="command definition" + id="org.eclipse.xtext.example.fowlerdsl.ui.templates.command" + context="org.eclipse.xtext.example.fowlerdsl.ui.templates.contextType.Command" + enabled="true">${command} ${shortCode}</template> + + <template name="actions" description="action definition" + id="org.eclipse.xtext.example.fowlerdsl.ui.templates.actions" + context="org.eclipse.xtext.example.fowlerdsl.ui.templates.contextType.actions" + enabled="true">actions {${action:CrossReference('State.actions')} ${cursor}}</template> + +</templates> 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 a9ce3a4..b2e4779 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 @@ -21,7 +21,8 @@ import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EReference; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.contentassist.ICompletionProposal; -import org.eclipse.jface.viewers.StyledString; +import org.eclipse.jface.text.templates.Template; +import org.eclipse.jface.text.templates.TemplateContextType; import org.eclipse.xtext.AbstractElement; import org.eclipse.xtext.AbstractRule; import org.eclipse.xtext.Assignment; @@ -35,6 +36,7 @@ import org.eclipse.xtext.crossref.IScopedElement; import org.eclipse.xtext.parsetree.AbstractNode; import org.eclipse.xtext.parsetree.LeafNode; import org.eclipse.xtext.service.Inject; +import org.eclipse.xtext.ui.common.editor.codecompletion.impl.XtextCompletionProposal; import org.eclipse.xtext.util.Strings; /** @@ -60,49 +62,67 @@ public abstract class AbstractProposalProvider implements IProposalProvider { /* * (non-Javadoc) - * - * @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) + * @see org.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider#completeKeyword(org.eclipse.xtext.Keyword, org.eclipse.xtext.ui.common.editor.codecompletion.IContentAssistContext) */ - public List<? extends ICompletionProposal> completeKeyword(Keyword keyword, EObject model, String prefix, - IDocument doc, int offset) { + public List<? extends ICompletionProposal> completeKeyword(Keyword keyword, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { - logger.debug("completeKeyword '" + keyword.getValue() + "' for model '" + model + "' and prefix '" - + prefix.trim() + "'"); + logger.debug("completeKeyword '" + keyword.getValue() + "' for model '" + contentAssistContext.getModel() + "' and prefix '" + + contentAssistContext.getMatchString().trim() + "'"); } String text = keyword.getValue().length() == 1 ? keyword.getValue() : keyword.getValue() + " "; - return Collections.singletonList(createCompletionProposal(keyword, model, text, offset)); + return Collections.singletonList(createCompletionProposal(keyword, text, contentAssistContext)); } /* * (non-Javadoc) - * - * @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) + * @see org.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider#completeRuleCall(org.eclipse.xtext.RuleCall, org.eclipse.xtext.ui.common.editor.codecompletion.IContentAssistContext) */ - public List<? extends ICompletionProposal> completeRuleCall(RuleCall ruleCall, EObject model, String prefix, - IDocument doc, int offset) { + public List<? extends ICompletionProposal> completeRuleCall(RuleCall ruleCall, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeRuleCall '" + ruleCall.getRule().getName() + "' cardinality '" + ruleCall.getCardinality() - + "' for model '" + model + "' and prefix '" + prefix.trim() + "'"); + + "' for model '" + contentAssistContext.getModel() + "' and prefix '" + contentAssistContext.getMatchString().trim().trim() + "'"); } AbstractRule calledRule = ruleCall.getRule(); if (calledRule instanceof LexerRule) { - return doCompleteLexerRuleRuleCall((LexerRule) calledRule, ruleCall, model, offset); + return doCompleteLexerRuleRuleCall((LexerRule) calledRule, ruleCall, contentAssistContext); } return Collections.emptyList(); } + + /* + * (non-Javadoc) + * @see org.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider#getTemplateContextType(org.eclipse.xtext.Keyword, org.eclipse.xtext.ui.common.editor.codecompletion.IContentAssistContext) + */ + public TemplateContextType getTemplateContextType(Keyword keyword, IContentAssistContext contentAssistContext) { + return null; + } /* * (non-Javadoc) - * - * @see org.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider#sortAndFilter(java.util.List, org.eclipse.emf.ecore.EObject, java.lang.String, org.eclipse.jface.text.IDocument, int, org.eclipse.xtext.parsetree.AbstractNode, org.eclipse.xtext.parsetree.LeafNode) + * @see org.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider#getTemplateContextType(org.eclipse.xtext.RuleCall, org.eclipse.xtext.ui.common.editor.codecompletion.IContentAssistContext) + */ + public TemplateContextType getTemplateContextType(RuleCall ruleCall, IContentAssistContext contentAssistContext) { + return null; + } + + /* + * (non-Javadoc) + * @see org.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider#getTemplates(java.lang.String) + */ + public Template[] getTemplates(String contextTypeId) { + return new Template[]{}; + } + + /* + * (non-Javadoc) + * @see org.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider#sortAndFilter(java.util.List, org.eclipse.xtext.ui.common.editor.codecompletion.IContentAssistContext) */ public List<? extends ICompletionProposal> sortAndFilter( - List<? extends ICompletionProposal> completionProposalList, EObject model, String prefix, - IDocument document, int offset) { - return doSortAndFilter(completionProposalList, model, prefix, document, offset); + List<? extends ICompletionProposal> completionProposalList, IContentAssistContext contentAssistContext) { + return doSortAndFilter(completionProposalList,contentAssistContext); } /** @@ -120,7 +140,7 @@ public abstract class AbstractProposalProvider implements IProposalProvider { * @return a computed list of <code>ICompletionProposal</code> for the given <code>LexerRule</code> */ protected List<? extends ICompletionProposal> doCompleteLexerRuleRuleCall(LexerRule lexerRule, RuleCall ruleCall, - EObject model, int offset) { + IContentAssistContext contentAssistContext) { ParserRule containingParserRule = GrammarUtil.containingParserRule(ruleCall); Assignment containingAssignment = GrammarUtil.containingAssignment(ruleCall); @@ -135,8 +155,7 @@ public abstract class AbstractProposalProvider implements IProposalProvider { defaultDisplayString = "\"" + defaultDisplayString + "\""; } - return Collections.singletonList(createCompletionProposal(containingAssignment, model, defaultDisplayString, - offset)); + return Collections.singletonList(createCompletionProposal(containingAssignment, defaultDisplayString, contentAssistContext)); } /** @@ -169,8 +188,7 @@ public abstract class AbstractProposalProvider implements IProposalProvider { * * @return a list of <code>ICompletionProposal</code> matching the given assignment */ - protected List<? extends ICompletionProposal> lookupCrossReference(CrossReference crossReference, EObject model, - String prefix, int offset) { + protected List<? extends ICompletionProposal> lookupCrossReference(CrossReference crossReference, IContentAssistContext contentAssistContext) { List<ICompletionProposal> completionProposalList = new ArrayList<ICompletionProposal>(); @@ -179,12 +197,12 @@ public abstract class AbstractProposalProvider implements IProposalProvider { if (!GrammarUtil.isDatatypeRule(containingParserRule)) { final EClass eClass = (EClass) containingParserRule.getType().getType(); final EReference ref = GrammarUtil.getReference(crossReference, eClass); - final String trimmedPrefix = prefix.trim(); - final Iterable<IScopedElement> candidates = linkingCandidatesService.getLinkingCandidates(model, ref); + final String trimmedPrefix = contentAssistContext.getMatchString().trim(); + final Iterable<IScopedElement> candidates = linkingCandidatesService.getLinkingCandidates(contentAssistContext.getModel(), ref); for (IScopedElement candidate : candidates) { - if (candidate.name() != null && isCandidateMatchingPrefix(model, ref, candidate, trimmedPrefix)) { + if (candidate.name() != null && isCandidateMatchingPrefix(contentAssistContext.getModel(), ref, candidate, trimmedPrefix)) { completionProposalList.add( - createCompletionProposal(crossReference, model, candidate.name(), offset)); + createCompletionProposal(crossReference, candidate.name(), contentAssistContext)); } } } @@ -202,10 +220,8 @@ public abstract class AbstractProposalProvider implements IProposalProvider { /** * @return a new <code>XtextCompletionProposal</code> for the given text and offset. */ - protected final XtextCompletionProposal createCompletionProposal(AbstractElement abstractElement, EObject model, - String text, int offset) { - return new XtextCompletionProposal(abstractElement, model, text, new StyledString(text), text, - getDefaultImageFilePath(), getPluginId(), offset); + protected ICompletionProposal createCompletionProposal(AbstractElement abstractElement, String displayString,IContentAssistContext contentAssistContext) { + return new XtextCompletionProposal(abstractElement,displayString,contentAssistContext); } /** @@ -218,8 +234,7 @@ public abstract class AbstractProposalProvider implements IProposalProvider { * @see #sortAndFilter(List, EObject, String, IDocument, int, AbstractNode, LeafNode) */ protected List<? extends ICompletionProposal> doSortAndFilter( - List<? extends ICompletionProposal> completionProposalList, EObject model, String prefix, - IDocument document, int offset) { + List<? extends ICompletionProposal> completionProposalList, IContentAssistContext contentAssistContext) { Map<String, ICompletionProposal> displayString2ICompletionProposalMap = new HashMap<String, ICompletionProposal>(); @@ -233,7 +248,7 @@ public abstract class AbstractProposalProvider implements IProposalProvider { displayString2ICompletionProposalMap.put(completionProposal.getDisplayString(), completionProposal); // filter by prefix - if (isFiltered(model, prefix, completionProposal)) { + if (isFiltered(completionProposal)) { if (logger.isDebugEnabled()) { logger.debug("filter completionProposal '" + completionProposal + "'"); } @@ -257,18 +272,16 @@ public abstract class AbstractProposalProvider implements IProposalProvider { * The default behaviour of this method delegates to {@link XtextCompletionProposal#matches(String)} to * test if the given prefix string matches or not. * - * @param model the last semtantically complete object - * @param prefix * @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 boolean isFiltered(EObject model, String prefix, ICompletionProposal completionProposal) { + protected boolean isFiltered(ICompletionProposal completionProposal) { if (completionProposal instanceof XtextCompletionProposal) { XtextCompletionProposal xtextCompletionProposal = (XtextCompletionProposal) completionProposal; - return !xtextCompletionProposal.matches(prefix); + return !xtextCompletionProposal.matches(); } return false; diff --git a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/ContentAssistContextAdapter.java b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/ContentAssistContextAdapter.java deleted file mode 100644 index 615ca53..0000000 --- a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/ContentAssistContextAdapter.java +++ b/dev/null @@ -1,150 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2008 itemis AG (http://www.itemis.eu) and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - *******************************************************************************/ -package org.eclipse.xtext.ui.common.editor.codecompletion; - -import org.eclipse.emf.common.notify.impl.AdapterImpl; -import org.eclipse.emf.ecore.EObject; -import org.eclipse.xtext.GrammarUtil; -import org.eclipse.xtext.ParserRule; -import org.eclipse.xtext.parsetree.AbstractNode; -import org.eclipse.xtext.parsetree.CompositeNode; - -/** - * Represents a custom emf adapter to adapt or extend the behaviour of emf - * models used to provide CA related context information. - * - * @author Michael Clay - Initial contribution and API - * @see org.eclipse.emf.common.notify.Adapter - */ -public class ContentAssistContextAdapter extends AdapterImpl { - - private CompositeNode rootNode; - - private AbstractNode lastCompleteNode; - - private AbstractNode currentNode; - - private String prefix; - - private int offset; - - public ContentAssistContextAdapter(CompositeNode rootNode, AbstractNode currentNode, AbstractNode lastCompleteNode, - int offset, String prefix) { - super(); - this.rootNode = rootNode; - this.currentNode = currentNode; - this.lastCompleteNode = lastCompleteNode; - this.offset = offset; - this.prefix = prefix; - } - - /** - * @return true or false wheter the cursor is at the the last complete node - */ - public boolean isCusorAtEndOfLastCompleteNode() { - return lastCompleteNode == currentNode; - } - - /** - * @return the grammar element of the current node - */ - public EObject getCurrentGrammarElement() { - - EObject grammarElement = GrammarUtil.containingAssignment(currentNode.getGrammarElement()); - - if (null == grammarElement) { - grammarElement = (currentNode.getGrammarElement() instanceof ParserRule ? ((ParserRule) currentNode - .getGrammarElement()).getAlternatives() - : currentNode.getGrammarElement()); - } - - return grammarElement; - } - - @Override - public boolean isAdapterForType(Object type) { - return type == ContentAssistContextAdapter.class; - } - - /** - * @return the rootNode - */ - public CompositeNode getRootNode() { - return rootNode; - } - - /** - * @param rootNode - * the rootNode to set - */ - public void setRootNode(CompositeNode rootNode) { - this.rootNode = rootNode; - } - - /** - * @return the lastCompleteNode - */ - public AbstractNode getLastCompleteNode() { - return lastCompleteNode; - } - - /** - * @param lastCompleteNode - * the lastCompleteNode to set - */ - public void setLastCompleteNode(AbstractNode lastCompleteNode) { - this.lastCompleteNode = lastCompleteNode; - } - - /** - * @return the currentNode - */ - public AbstractNode getCurrentNode() { - return currentNode; - } - - /** - * @param currentNode - * the currentNode to set - */ - public void setCurrentNode(AbstractNode currentNode) { - this.currentNode = currentNode; - } - - /** - * @return the prefix - */ - public String getPrefix() { - return prefix; - } - - /** - * @param prefix - * the prefix to set - */ - public void setPrefix(String prefix) { - this.prefix = prefix; - } - - /** - * @return the offset - */ - public int getOffset() { - return offset; - } - - /** - * @param offset - * the offset to set - */ - public void setOffset(int offset) { - this.offset = 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 a5a3f75..f685444 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 @@ -1,234 +1,180 @@ +/******************************************************************************* + * Copyright (c) 2008 itemis AG (http://www.itemis.eu) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ package org.eclipse.xtext.ui.common.editor.codecompletion; -import java.util.ArrayList; -import java.util.LinkedHashSet; +import java.util.Arrays; import java.util.List; -import java.util.Set; import org.apache.log4j.Logger; -import org.eclipse.core.runtime.Assert; -import org.eclipse.emf.common.notify.Adapter; -import org.eclipse.emf.ecore.EObject; -import org.eclipse.emf.ecore.EReference; -import org.eclipse.emf.ecore.util.EcoreUtil; -import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.contentassist.ContextInformationValidator; 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.jface.text.templates.TemplateContextType; import org.eclipse.xtext.AbstractElement; -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; -import org.eclipse.xtext.RuleCall; -import org.eclipse.xtext.crossref.ILinkingService; -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.IServiceScope; import org.eclipse.xtext.service.Inject; -import org.eclipse.xtext.ui.core.editor.model.IXtextDocument; -import org.eclipse.xtext.ui.core.editor.model.UnitOfWork; +import org.eclipse.xtext.service.ServiceRegistry; +import org.eclipse.xtext.ui.common.editor.codecompletion.impl.DefaultContentAssistContext; +import org.eclipse.xtext.ui.common.editor.codecompletion.impl.DefaultTemplateContentAssistProcessor; +import org.eclipse.xtext.ui.common.editor.codecompletion.impl.DefaultContentAssistCalculator; +import org.eclipse.xtext.ui.common.editor.codecompletion.impl.ProposalProviderInvokerSwitch; /** + * The default implementation of interface {@link IContentAssistProcessor} provided with Xtext. + * * @author Michael Clay - Initial contribution and API - * @author Dennis Hübner - Initial contribution and API * @author Heiko Behrens */ public class DefaultContentAssistProcessor implements IContentAssistProcessor { // logger available to subclasses protected final Logger logger = Logger.getLogger(getClass()); + + @Inject (optional=true) + private ITemplateContentAssistProcessor templateContentAssistProcessor; + @Inject (optional=true) + private IContentAssistCalculator contentAssistCalculator; + @Inject private IProposalProvider proposalProvider; @Inject - private ILinkingService linkingService; - + protected IServiceScope serviceScope; /** - * computes the possible grammar elements following the one at the given offset and calls the respective methods on + * Computes the possible grammar elements following the one at the given offset and calls the respective methods on * the proposal provider. */ public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, final int offset) { ICompletionProposal[] completionProposals = null; - IDocument document = viewer.getDocument(); - - if (document instanceof IXtextDocument) { - - List<ICompletionProposal> completionProposalList = new ArrayList<ICompletionProposal>(); - - IXtextDocument xtextDocument = (IXtextDocument) document; - - CompositeNode rootNode = xtextDocument.readOnly(new UnitOfWork<CompositeNode>() { - public CompositeNode exec(XtextResource resource) throws Exception { - IParseResult parseResult = resource.getParseResult(); - Assert.isNotNull(parseResult); - return parseResult.getRootNode(); - } - }); - - Assert.isNotNull(rootNode); - - AbstractNode lastCompleteNode = ParseTreeUtil.getLastCompleteNodeByOffset(rootNode, offset); - - AbstractNode currentNode = ParseTreeUtil.getCurrentOrFollowingNodeByOffset(rootNode, offset); - - String prefix = calculatePrefix(viewer, offset, currentNode); - - EObject model = lastCompleteNode instanceof AbstractNode ? NodeUtil - .getNearestSemanticObject((AbstractNode) lastCompleteNode) : lastCompleteNode; - - addOrReplaceCaContextAdapter(model, new ContentAssistContextAdapter(rootNode,currentNode,lastCompleteNode,offset,prefix)); - - Set<AbstractElement> nextValidElementSet = new LinkedHashSet<AbstractElement>(); - /** - * in case of a crossreference which isnt linked properly we evaluate or propose it again - */ - if (lastCompleteNode.getGrammarElement() instanceof CrossReference && !isLinked(lastCompleteNode)) { - nextValidElementSet.add(getAbstractElement(lastCompleteNode)); - nextValidElementSet.addAll(ParseTreeUtil.getElementSetValidFromOffset(rootNode, lastCompleteNode, - offset)); - } - /** - * 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) - */ - else if (lastCompleteNode == currentNode) { - - Assignment containingAssignment = GrammarUtil - .containingAssignment(lastCompleteNode.getGrammarElement()); - - if (lastCompleteNode.getGrammarElement() instanceof RuleCall && containingAssignment != null) { - nextValidElementSet.add(containingAssignment); - nextValidElementSet.addAll(ParseTreeUtil.getElementSetValidFromOffset(rootNode, lastCompleteNode, - offset)); - } - else { - nextValidElementSet = ParseTreeUtil.getElementSetValidFromOffset(rootNode, lastCompleteNode, offset); - nextValidElementSet.add(getAbstractElement(lastCompleteNode)); - } - } - else { - nextValidElementSet = ParseTreeUtil.getElementSetValidFromOffset(rootNode, lastCompleteNode, offset); - } - - ProposalProviderInvokerSwitch proposalProviderInvokerSwitch = new ProposalProviderInvokerSwitch(model, - document, offset, prefix, proposalProvider); - - for (List<EObject> resolvedElementOrRuleList : new ProposalCandidateResolverSwitch(nextValidElementSet)) { - - List<ICompletionProposal> collectedCompletionProposalList = proposalProviderInvokerSwitch - .collectCompletionProposalList(resolvedElementOrRuleList); - - completionProposalList.addAll(collectedCompletionProposalList); - } - - if (completionProposalList != null) { - List<? extends ICompletionProposal> processedCompletionProposalList = proposalProvider.sortAndFilter( - completionProposalList, model, prefix, document, offset); - completionProposals = processedCompletionProposalList.toArray( - new ICompletionProposal[processedCompletionProposalList.size()]); - } - + IContentAssistContext contentAssistContext = getContentAssistContext(viewer, offset); + + List<AbstractElement> computeProposalElements = getContentAssistCalculator().computeProposalElements( + contentAssistContext); + + ProposalProviderInvokerSwitch proposalProviderInvokerSwitch = new ProposalProviderInvokerSwitch( + contentAssistContext, proposalProvider); + + List<ICompletionProposal> completionProposalList = proposalProviderInvokerSwitch + .collectCompletionProposalList(computeProposalElements); + + for (TemplateContextType templateContextType : proposalProviderInvokerSwitch.getTemplateContextTypeList()) { + addTemplates(viewer, offset, contentAssistContext, templateContextType, completionProposalList); } + List<? extends ICompletionProposal> processedCompletionProposalList = proposalProvider.sortAndFilter( + completionProposalList, contentAssistContext); + + completionProposals = processedCompletionProposalList + .toArray(new ICompletionProposal[processedCompletionProposalList.size()]); + return completionProposals; } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getCompletionProposalAutoActivationCharacters() + */ public char[] getCompletionProposalAutoActivationCharacters() { return null; } + /* + * (non-Javadoc) + * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getErrorMessage() + */ public String getErrorMessage() { return null; } + /* + * (non-Javadoc) + * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#computeContextInformation(org.eclipse.jface.text.ITextViewer, int) + */ public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) { return null; } + /* + * (non-Javadoc) + * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationAutoActivationCharacters() + */ public char[] getContextInformationAutoActivationCharacters() { return null; } + /* + * (non-Javadoc) + * @see org.eclipse.jface.text.contentassist.IContentAssistProcessor#getContextInformationValidator() + */ public IContextInformationValidator getContextInformationValidator() { return new ContextInformationValidator(this); } - protected String calculatePrefix(ITextViewer viewer, final int offset, AbstractNode abstractNode) { - - if (abstractNode == null) - return ""; - - String prefix = ""; - StyledText textWidget = viewer.getTextWidget(); - if (textWidget.getCharCount() > 0) { - int boundedOffset = Math.min(offset, textWidget.getCharCount()) - 1; - if (abstractNode.getTotalOffset() <= boundedOffset) - prefix = textWidget.getText(abstractNode.getTotalOffset(), boundedOffset); - } - - // if cursor is behind a complete keyword, accept any input => empty - // prefix - // 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 - if (abstractNode.getGrammarElement() instanceof Keyword && (abstractNode instanceof LeafNode && ((LeafNode)abstractNode).getText().equals(prefix))) { - prefix = ""; + /** + * 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 (getTemplateContentAssistProcessor() != null) { + getTemplateContentAssistProcessor().setContentAssistContext(contentAssistContext); + getTemplateContentAssistProcessor().setContextType(templateContextType); + completionProposalList.addAll(Arrays.asList(getTemplateContentAssistProcessor().computeCompletionProposals( + viewer, offset))); } - - return prefix; } - - private void addOrReplaceCaContextAdapter(EObject model, ContentAssistContextAdapter contentAssistContextAdapter) { + /** + * @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 + * @return an implementation of <code>IContentAssistContext</code> + */ + protected IContentAssistContext getContentAssistContext(ITextViewer textViewer,int offset) { + return new DefaultContentAssistContext(textViewer,offset); - if (model != null) { - - Adapter existingAdapter = EcoreUtil.getAdapter(model.eAdapters(), ContentAssistContextAdapter.class); - - if (existingAdapter != null) { - model.eAdapters().remove(existingAdapter); - } - - model.eAdapters().add(contentAssistContextAdapter); - } } - - 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; - else { - List<EObject> linkCandidates = linkingService.getLinkedObjects(semanticModel, eReference, - (LeafNode) lastCompleteNode); - return !linkCandidates.isEmpty() && referencedObjects.containsAll(linkCandidates); + /** + * @return an implementation of <code>ITemplateContentAssistProcessor</code> + */ + protected ITemplateContentAssistProcessor getTemplateContentAssistProcessor() { + if (templateContentAssistProcessor == null) { + templateContentAssistProcessor = new DefaultTemplateContentAssistProcessor(); + ServiceRegistry.injectServices(this.serviceScope, templateContentAssistProcessor); } + return templateContentAssistProcessor; } - private AbstractElement getAbstractElement(AbstractNode lastCompleteNode) { - return (AbstractElement) (lastCompleteNode.getGrammarElement() instanceof ParserRule ? - ((ParserRule)lastCompleteNode.getGrammarElement()).getAlternatives(): lastCompleteNode.getGrammarElement()); + /** + * @return an implementation of <code>IContentAssistCalculator</code> + */ + protected IContentAssistCalculator getContentAssistCalculator() { + if (this.contentAssistCalculator == null) { + contentAssistCalculator = new DefaultContentAssistCalculator(); + ServiceRegistry.injectServices(this.serviceScope, contentAssistCalculator); + } + return contentAssistCalculator; } + + } diff --git a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/IContentAssistCalculator.java b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/IContentAssistCalculator.java new file mode 100644 index 0000000..9a265de --- a/dev/null +++ b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/IContentAssistCalculator.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2008 itemis AG (http://www.itemis.eu) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ +package org.eclipse.xtext.ui.common.editor.codecompletion; + +import java.util.List; + +import org.eclipse.xtext.AbstractElement; + +/** + * Strategy interface for calculating a list of <code>AbstractElement</code> elements which are applicable for + * the provided <code>IContentAssistContext</code>. + * + * @author Michael Clay - Initial contribution and API + */ +public interface IContentAssistCalculator { + + /** + * Calculate a list of <code>AbstractElement</code> matching the provided <code>IContentAssistContext</code>. + * + * @param contentAssistContext the current context of the content assist proposal request + * @return the list of <code>AbstractElement</code> matching the provided <code>IContentAssistContext</code>. + */ + List<AbstractElement> computeProposalElements(IContentAssistContext contentAssistContext); +} diff --git a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/IContentAssistContext.java b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/IContentAssistContext.java new file mode 100644 index 0000000..1bb6e44 --- a/dev/null +++ b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/IContentAssistContext.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2008 itemis AG (http://www.itemis.eu) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ +package org.eclipse.xtext.ui.common.editor.codecompletion; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.xtext.parsetree.AbstractNode; +import org.eclipse.xtext.parsetree.CompositeNode; +import org.eclipse.xtext.ui.core.editor.model.IXtextDocument; + +/** + * Abstraction of a commonly used set of attributes related to the current content assist request. + * + * @author Michael Clay - Initial contribution and API + */ +public interface IContentAssistContext { + /** + * @return the root node of the document which is used to compute the proposals + */ + CompositeNode getRootNode(); + + /** + * @return the string that is already entered by the user prior to requesting content assist + */ + String getMatchString(); + + /** + * @return the last node (on a none hidden channel) that starts at or spans across the cursor position the user requested content assist for + */ + AbstractNode getNode(); + + /** + * @return the nearest node with an existing grammar element set (i.e. valid according to the underlying grammar) + */ + AbstractNode getReferenceNode(); + + /** + * @return the most specific model element under the cursor the user requested content assist for + */ + EObject getModel(); + + /** + * @return the <code>XtextDocument</code> used to compute the proposals + */ + IXtextDocument getDocument(); + + /** + * @return the position in the document described by this context. + */ + int getOffSet(); + +} 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 c4d35f9..b86423f 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 @@ -2,13 +2,12 @@ package org.eclipse.xtext.ui.common.editor.codecompletion; import java.util.List; -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; import org.eclipse.xtext.Keyword; import org.eclipse.xtext.RuleCall; - /** * * This is just a marker interface. @@ -44,38 +43,60 @@ 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 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 document - the IDocument instance used by the editor - * @param offset - an offset within the document for which completions should be computed + * @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} */ - public List<? extends ICompletionProposal> completeKeyword(Keyword keyword, EObject model, String prefix, IDocument document,int offset); + List<? extends ICompletionProposal> completeKeyword(Keyword keyword, IContentAssistContext contentAssistContext); /** * 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 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 document - the IDocument instance used by the editor - * @param offset - an offset within the document for which completions should be computed + * @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} */ - public List<? extends ICompletionProposal> completeRuleCall(RuleCall ruleCall, EObject model, String prefix, IDocument document,int offset); - + List<? extends ICompletionProposal> completeRuleCall(RuleCall ruleCall, IContentAssistContext contentAssistContext); + + /** + * 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 + * @return the context type that can handle template expansion for the given location, or <code>null</code> if none exists + */ + TemplateContextType getTemplateContextType(Keyword keyword, IContentAssistContext contentAssistContext); + + /** + * 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 + * @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 + * @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. * @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 - * @param document - the IDocument instance used by the editor - * @param offset - an offset within the document for which completions should be computed + * @param contentAssistContext the current context of the content assist * @return the sorted and filtered <code>ICompletionProposal</code> list. - * */ - public List<? extends ICompletionProposal> sortAndFilter(List<? extends ICompletionProposal> completionProposalList,EObject model, String prefix, IDocument document,int offset); + List<? extends ICompletionProposal> sortAndFilter(List<? extends ICompletionProposal> completionProposalList,IContentAssistContext contentAssistContext); + + + } diff --git a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/ITemplateContentAssistProcessor.java b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/ITemplateContentAssistProcessor.java new file mode 100644 index 0000000..0dd0605 --- a/dev/null +++ b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/ITemplateContentAssistProcessor.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2008 itemis AG (http://www.itemis.eu) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + *******************************************************************************/ +package org.eclipse.xtext.ui.common.editor.codecompletion; + +import org.eclipse.jface.text.contentassist.IContentAssistProcessor; +import org.eclipse.jface.text.templates.TemplateContextType; + +/** + * Strategy interface for computing template proposals matching the given <code>TemplateContextType</code> and + * <code>IContentAssistContext</code>. + * + * @author Michael Clay - Initial contribution and API + */ +public interface ITemplateContentAssistProcessor extends IContentAssistProcessor { + + /** + * @param contextType the context type that can handle template expansion for the given contentAssistContext (must not be null) + */ + void setContextType(TemplateContextType contextType); + + /** + * @param contentAssistContext the current context of the content assist proposal request (must not be null) + */ + void setContentAssistContext(IContentAssistContext contentAssistContext); + +} diff --git a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/ProposalCandidateResolverSwitch.java b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/ProposalCandidateResolverSwitch.java deleted file mode 100644 index 91f1a09..0000000 --- a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/ProposalCandidateResolverSwitch.java +++ b/dev/null @@ -1,137 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2008 itemis AG (http://www.itemis.eu) and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - *******************************************************************************/ -package org.eclipse.xtext.ui.common.editor.codecompletion; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import org.eclipse.emf.ecore.EObject; -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.GrammarUtil; -import org.eclipse.xtext.Group; -import org.eclipse.xtext.ParserRule; -import org.eclipse.xtext.RuleCall; -import org.eclipse.xtext.util.XtextSwitch; - -/** - * Represents a <b>Switch</b> for the Xtext model's inheritance hierarchy to - * resolve (or flatten) 'container' level elements like <code>Group</code> or - * <code>Alternatives</code> to gather potential completion proposal candidates. - * - * It supports the call {@link #doSwitch(EObject) doSwitch(object)} instead of - * typical <code>if (x instanceof y)</code> code blocks. - * - * @author Michael Clay - Initial contribution and API - * @see org.eclipse.xtext.util.XtextSwitch - */ -public class ProposalCandidateResolverSwitch extends XtextSwitch<List<EObject>> implements Iterable<List<EObject>> { - - private Iterator<? extends EObject> delegatingIterator; - - /** - * @param elementCollection - * to iterate and resolve - */ - public ProposalCandidateResolverSwitch(Collection<? extends EObject> elementCollection) { - this.delegatingIterator = elementCollection.iterator(); - } - - /* - * (non-Javadoc) - * @see java.lang.Iterable#iterator() - */ - public Iterator<List<EObject>> iterator() { - return new Iterator<List<EObject>>() { - public boolean hasNext() { - return delegatingIterator.hasNext(); - } - - public List<EObject> next() { - return doSwitch(delegatingIterator.next()); - } - - public void remove() { - delegatingIterator.remove(); - } - - }; - } - - @Override - public List<EObject> caseAlternatives(Alternatives alternatives) { - List<EObject> elementList = new ArrayList<EObject>(); - for (AbstractElement alternativeElement : alternatives.getGroups()) { - addWithNullCheck(elementList, doSwitch(alternativeElement)); - } - return elementList; - } - - @Override - public List<EObject> caseGroup(Group group) { - List<EObject> elementList = new ArrayList<EObject>(); - boolean includeNext = true; - for (Iterator<AbstractElement> iterator = group.getAbstractTokens().iterator(); iterator.hasNext() - && includeNext;) { - AbstractElement groupElement = iterator.next(); - addWithNullCheck(elementList, doSwitch(groupElement)); - includeNext = GrammarUtil.isOptionalCardinality(groupElement); - } - return elementList; - } - - @Override - public List<EObject> caseAssignment(Assignment assignment) { - List<EObject> elementList = new ArrayList<EObject>(); - if (assignment.getTerminal() instanceof RuleCall) { - addWithNullCheck(elementList, doSwitch(assignment.getTerminal())); - } - else if (assignment.getTerminal() instanceof Alternatives) { - addWithNullCheck(elementList, doSwitch(assignment.getTerminal())); - } - elementList.add(assignment); - return elementList; - } - - @Override - public List<EObject> caseRuleCall(RuleCall ruleCall) { - List<EObject> elementList = new ArrayList<EObject>(); - elementList.add(ruleCall); - - AbstractRule abstractRule = ruleCall.getRule(); - - if (abstractRule instanceof ParserRule) { - addWithNullCheck(elementList, doSwitch(((ParserRule) abstractRule).getAlternatives())); - } - return elementList; - } - - @Override - public List<EObject> caseCrossReference(CrossReference crossReference) { - return Collections.singletonList(crossReference.eContainer()); - } - - @Override - public List<EObject> defaultCase(EObject object) { - return Collections.singletonList(object); - } - - private void addWithNullCheck(List<EObject> source, List<EObject> list) { - if (null != list) { - source.addAll(list); - } - } - -} diff --git a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/impl/DefaultContentAssistCalculator.java b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/impl/DefaultContentAssistCalculator.java new file mode 100644 index 0000000..6cc28e8 --- a/dev/null +++ b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/impl/DefaultContentAssistCalculator.java @@ -0,0 +1,193 @@ +/******************************************************************************* + * Copyright (c) 2008 itemis AG (http://www.itemis.eu) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + *******************************************************************************/ +package org.eclipse.xtext.ui.common.editor.codecompletion.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.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.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.parsetree.ParseTreeUtil; +import org.eclipse.xtext.service.Inject; +import org.eclipse.xtext.ui.common.editor.codecompletion.IContentAssistCalculator; +import org.eclipse.xtext.ui.common.editor.codecompletion.IContentAssistContext; +import org.eclipse.xtext.util.XtextSwitch; + +/** + * 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 + * <code>Group</code> or <code>Alternatives</code> to gather potential completion proposal candidates. + * + * It supports the call {@link #doSwitch(EObject) doSwitch(object)} instead of + * typical <code>if (x instanceof y)</code> code blocks. + * + * @author Michael Clay - Initial contribution and API + * @see org.eclipse.xtext.util.XtextSwitch + */ +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 crossreference which isnt linked properly we evaluate or + * propose it again + */ + if (referenceNode.getGrammarElement() instanceof CrossReference && !isLinked(referenceNode)) { + nextValidElementSet.add(getAbstractElement(referenceNode)); + nextValidElementSet.addAll(ParseTreeUtil.getElementSetValidFromOffset(contentAssistContext.getRootNode(), + referenceNode, contentAssistContext.getOffSet())); + } + /** + * 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) + */ + else if (referenceNode == contentAssistContext.getNode()) { + + 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 { + nextValidElementSet = ParseTreeUtil.getElementSetValidFromOffset(contentAssistContext.getRootNode(), + referenceNode, contentAssistContext.getOffSet()); + } + + for (Iterator<AbstractElement> iterator = nextValidElementSet.iterator(); iterator.hasNext();) { + AbstractElement abstractElement = (AbstractElement) iterator.next(); + computedElementList.addAll(doSwitch(abstractElement)); + } + + return computedElementList; + } + + + @Override + public List<AbstractElement> caseAlternatives(Alternatives alternatives) { + List<AbstractElement> elementList = new ArrayList<AbstractElement>(); + for (AbstractElement alternativeElement : alternatives.getGroups()) { + addWithNullCheck(elementList, doSwitch(alternativeElement)); + } + return elementList; + } + + @Override + public List<AbstractElement> caseGroup(Group group) { + List<AbstractElement> elementList = new ArrayList<AbstractElement>(); + boolean includeNext = true; + for (Iterator<AbstractElement> iterator = group.getAbstractTokens().iterator(); iterator.hasNext() + && includeNext;) { + AbstractElement groupElement = iterator.next(); + addWithNullCheck(elementList, doSwitch(groupElement)); + includeNext = GrammarUtil.isOptionalCardinality(groupElement); + } + return elementList; + } + + @Override + public List<AbstractElement> caseAssignment(Assignment assignment) { + List<AbstractElement> elementList = new ArrayList<AbstractElement>(); + if (assignment.getTerminal() instanceof RuleCall) { + addWithNullCheck(elementList, doSwitch(assignment.getTerminal())); + } + else if (assignment.getTerminal() instanceof Alternatives) { + addWithNullCheck(elementList, doSwitch(assignment.getTerminal())); + } + elementList.add(assignment); + return elementList; + } + + @Override + public List<AbstractElement> caseRuleCall(RuleCall ruleCall) { + List<AbstractElement> elementList = new ArrayList<AbstractElement>(); + + elementList.add(ruleCall); + + AbstractRule abstractRule = ruleCall.getRule(); + + if (abstractRule instanceof ParserRule) { + addWithNullCheck(elementList, doSwitch(((ParserRule) abstractRule).getAlternatives())); + } + return elementList; + } + + @Override + public List<AbstractElement> caseCrossReference(CrossReference crossReference) { + return Collections.singletonList(((AbstractElement)crossReference.eContainer())); + } + + @Override + public List<AbstractElement> defaultCase(EObject object) { + return Collections.singletonList(((AbstractElement)object)); + } + + private void addWithNullCheck(List<AbstractElement> source, List<AbstractElement> list) { + if (null != list) { + source.addAll(list); + } + } + + 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; + else { + List<EObject> linkCandidates = linkingService.getLinkedObjects(semanticModel, eReference, + (LeafNode) lastCompleteNode); + return !linkCandidates.isEmpty() && referencedObjects.containsAll(linkCandidates); + } + } + + +} diff --git a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/impl/DefaultContentAssistContext.java b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/impl/DefaultContentAssistContext.java new file mode 100644 index 0000000..ac1d29d --- a/dev/null +++ b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/impl/DefaultContentAssistContext.java @@ -0,0 +1,129 @@ +/******************************************************************************* + * Copyright (c) 2008 itemis AG (http://www.itemis.eu) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ +package org.eclipse.xtext.ui.common.editor.codecompletion.impl; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.xtext.Keyword; +import org.eclipse.xtext.parsetree.AbstractNode; +import org.eclipse.xtext.parsetree.CompositeNode; +import org.eclipse.xtext.parsetree.LeafNode; +import org.eclipse.xtext.ui.common.editor.codecompletion.IContentAssistContext; +import org.eclipse.xtext.ui.core.editor.IXtextSourceViewer; +import org.eclipse.xtext.ui.core.editor.model.IXtextDocument; + +/** + * Provides a default implementation of interface {@link IContentAssistContext}. + * + * @author Michael Clay - Initial contribution and API + * @see IContentAssistContext + */ +public class DefaultContentAssistContext implements IContentAssistContext { + + private IXtextSourceViewer xtextSourceViewer; + private IXtextDocument xtextDocument; + private ITextViewer textViewer; + private String matchString; + private int offset; + + public DefaultContentAssistContext(ITextViewer textViewer, int offset) { + this.xtextSourceViewer = ((IXtextSourceViewer) textViewer); + this.xtextDocument = (IXtextDocument) textViewer.getDocument(); + this.textViewer = textViewer; + this.offset = offset; + } + + /* + * (non-Javadoc) + * @see org.eclipse.xtext.ui.common.editor.codecompletion.IContentAssistContext#getDocument() + */ + public IXtextDocument getDocument() { + return this.xtextDocument; + } + + /* + * (non-Javadoc) + * @see org.eclipse.xtext.ui.common.editor.codecompletion.IContentAssistContext#getMatchString() + */ + public String getMatchString() { + if (this.matchString == null) { + this.matchString = calculateMatchString(this.textViewer, this.offset); + } + return this.matchString; + } + + /* + * (non-Javadoc) + * @see org.eclipse.xtext.ui.common.editor.codecompletion.IContentAssistContext#getModel() + */ + public EObject getModel() { + return this.xtextSourceViewer.getModel(this.offset); + } + + /* + * (non-Javadoc) + * @see org.eclipse.xtext.ui.common.editor.codecompletion.IContentAssistContext#getReferenceNode() + */ + public AbstractNode getReferenceNode() { + return this.xtextSourceViewer.getReferenceNode(this.offset); + } + + /* + * (non-Javadoc) + * @see org.eclipse.xtext.ui.common.editor.codecompletion.IContentAssistContext#getNode() + */ + public AbstractNode getNode() { + return this.xtextSourceViewer.getNode(this.offset); + } + + /* + * (non-Javadoc) + * @see org.eclipse.xtext.ui.common.editor.codecompletion.IContentAssistContext#getOffSet() + */ + public int getOffSet() { + return this.offset; + } + + /* + * (non-Javadoc) + * @see org.eclipse.xtext.ui.common.editor.codecompletion.IContentAssistContext#getRootNode() + */ + public CompositeNode getRootNode() { + return this.xtextSourceViewer.getRootNode(); + } + + protected String calculateMatchString(ITextViewer viewer, final int offset) { + + if (getNode() == null) + return ""; + + String prefix = ""; + + StyledText textWidget = viewer.getTextWidget(); + + if (textWidget.getCharCount() > 0) { + int boundedOffset = Math.min(offset, textWidget.getCharCount()) - 1; + if (getNode().getTotalOffset() <= boundedOffset) + prefix = textWidget.getText(getNode().getTotalOffset(), boundedOffset).trim(); + } + + // if cursor is behind a complete keyword, accept any input => empty + // prefix + // 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 + if (getNode().getGrammarElement() instanceof Keyword + && (getNode() instanceof LeafNode && ((LeafNode) getNode()).getText().equals(prefix))) { + prefix = ""; + } + + return prefix; + } + +} diff --git a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/impl/DefaultTemplateContentAssistProcessor.java b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/impl/DefaultTemplateContentAssistProcessor.java new file mode 100644 index 0000000..9a42ecb --- a/dev/null +++ b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/impl/DefaultTemplateContentAssistProcessor.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * Copyright (c) 2008 itemis AG (http://www.itemis.eu) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + *******************************************************************************/ +package org.eclipse.xtext.ui.common.editor.codecompletion.impl; + +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.contentassist.ICompletionProposal; +import org.eclipse.jface.text.templates.Template; +import org.eclipse.jface.text.templates.TemplateCompletionProcessor; +import org.eclipse.jface.text.templates.TemplateContext; +import org.eclipse.jface.text.templates.TemplateContextType; +import org.eclipse.swt.graphics.Image; +import org.eclipse.xtext.IMetamodelAccess; +import org.eclipse.xtext.service.Inject; +import org.eclipse.xtext.ui.common.editor.codecompletion.IContentAssistContext; +import org.eclipse.xtext.ui.common.editor.codecompletion.ILinkingCandidatesService; +import org.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider; +import org.eclipse.xtext.ui.common.editor.codecompletion.ITemplateContentAssistProcessor; + +/** + * Provides a default implementation of interface {@link ITemplateContentAssistProcessor}. + * + * @author Michael Clay - Initial contribution and API + */ +public class DefaultTemplateContentAssistProcessor extends TemplateCompletionProcessor implements ITemplateContentAssistProcessor { + + @Inject + private IProposalProvider proposalProvider; + + @Inject + private ILinkingCandidatesService linkingCandidatesService; + + @Inject + private IMetamodelAccess metamodelAccess; + + private TemplateContextType contextType; + + private IContentAssistContext contentAssistContext; + + @Override + public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) { + return super.computeCompletionProposals(viewer, offset); + } + + @Override + protected TemplateContextType getContextType(ITextViewer viewer, IRegion region) { + return this.contextType; + } + + @Override + protected Image getImage(Template template) { + return null; + } + + @Override + protected Template[] getTemplates(String contextTypeId) { + return this.proposalProvider.getTemplates(contextTypeId); + } + + @Override + protected TemplateContext createContext(ITextViewer viewer, IRegion region) { + + TemplateContextType contextType = getContextType(viewer, region); + + if (contextType != null) { + + return new XtextTemplateContext(contextType, viewer.getDocument(), + new Position(region.getOffset(), region.getLength()), + this.contentAssistContext, + this.linkingCandidatesService, + this.metamodelAccess); + } + return null; + } + + /* + * (non-Javadoc) + * @see org.eclipse.xtext.ui.common.editor.codecompletion.ITemplateContentAssistProcessor#setContextType(org.eclipse.jface.text.templates.TemplateContextType) + */ + public void setContextType(TemplateContextType contextType) { + this.contextType = contextType; + } + + /* + * (non-Javadoc) + * @see org.eclipse.xtext.ui.common.editor.codecompletion.ITemplateContentAssistProcessor#setContentAssistContext(org.eclipse.xtext.ui.common.editor.codecompletion.IContentAssistContext) + */ + public void setContentAssistContext(IContentAssistContext contentAssistContext) { + this.contentAssistContext = contentAssistContext; + } + + +} diff --git a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/ProposalProviderInvokerSwitch.java b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/impl/ProposalProviderInvokerSwitch.java index bb58a4a..643390e 100644 --- a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/ProposalProviderInvokerSwitch.java +++ b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/impl/ProposalProviderInvokerSwitch.java @@ -6,11 +6,12 @@ * http://www.eclipse.org/legal/epl-v10.html * *******************************************************************************/ -package org.eclipse.xtext.ui.common.editor.codecompletion; +package org.eclipse.xtext.ui.common.editor.codecompletion.impl; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; @@ -19,8 +20,9 @@ import java.util.Map; import org.eclipse.core.runtime.Assert; 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.TemplateContextType; +import org.eclipse.xtext.AbstractElement; import org.eclipse.xtext.AbstractRule; import org.eclipse.xtext.Assignment; import org.eclipse.xtext.GrammarUtil; @@ -28,12 +30,14 @@ import org.eclipse.xtext.Keyword; import org.eclipse.xtext.ParserRule; import org.eclipse.xtext.RuleCall; import org.eclipse.xtext.TypeRef; +import org.eclipse.xtext.ui.common.editor.codecompletion.IContentAssistContext; +import org.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider; import org.eclipse.xtext.util.Strings; import org.eclipse.xtext.util.XtextSwitch; /** * Represents a <b>Switch</b> for the Xtext model's inheritance hierarchy to - * callback and invoke the completion methods of <code>IProposalProvider</code> + * callback and invoke the proposal completion methods of interface <code>IProposalProvider</code> * implementations to gather and collect <code>ICompletionProposal</code> to be * displayed for Content Assist. * @@ -47,39 +51,32 @@ import org.eclipse.xtext.util.XtextSwitch; public class ProposalProviderInvokerSwitch extends XtextSwitch<List<ICompletionProposal>> { private List<ICompletionProposal> completionProposalList = new ArrayList<ICompletionProposal>(); + + private List<TemplateContextType> templateContextTypeList = new ArrayList<TemplateContextType>(); private final IProposalProvider proposalProvider; - private final IDocument document; - - private final EObject model; - - private final String prefix; - - private int offset; + private IContentAssistContext contentAssistContext; private static final Map<String, Method> methodLookupMap = new HashMap<String, Method>(); + + + /** + * @return the templateContextTypeList + */ + public List<TemplateContextType> getTemplateContextTypeList() { + return templateContextTypeList; + } /** * - * @param model the most specific model element under the cursor. - * @param document - * the document itself - * @param offset - * the position in the offset from which CA was triggered - * @param prefix - * the prefix normally consisting of the text content of the - * currentLeafNode + * @param contentAssistContext the actual contentAssistContext + * * @param proposalProvider * the proposalProvider to callback and invoke */ - public ProposalProviderInvokerSwitch(EObject model, IDocument document, int offset, String prefix, - IProposalProvider proposalProvider) { - super(); - this.model = model; - this.document = document; - this.offset = offset; - this.prefix = prefix; + public ProposalProviderInvokerSwitch(IContentAssistContext contentAssistContext, IProposalProvider proposalProvider) { + this.contentAssistContext = contentAssistContext; this.proposalProvider = proposalProvider; } @@ -93,11 +90,11 @@ public class ProposalProviderInvokerSwitch extends XtextSwitch<List<ICompletionP * <code>ICompletionProposal</code> for * @return a list of matching <code>ICompletionProposal</code> */ - public List<ICompletionProposal> collectCompletionProposalList(List<EObject> elementList) { + public List<ICompletionProposal> collectCompletionProposalList(List<AbstractElement> elementList) { completionProposalList = new ArrayList<ICompletionProposal>(); - for (Iterator<EObject> elementOrRuleIterator = elementList.iterator(); elementOrRuleIterator.hasNext();) { + for (Iterator<AbstractElement> elementOrRuleIterator = elementList.iterator(); elementOrRuleIterator.hasNext();) { EObject abstractElement = elementOrRuleIterator.next(); doSwitch(abstractElement); } @@ -106,38 +103,50 @@ public class ProposalProviderInvokerSwitch extends XtextSwitch<List<ICompletionP } + @SuppressWarnings("unchecked") @Override public List<ICompletionProposal> caseAssignment(Assignment assignment) { + ParserRule parserRule = GrammarUtil.containingParserRule(assignment); - Method method = findMethod(proposalProvider.getClass(), "complete" - + firstLetterCapitalized(parserRule.getName()) + firstLetterCapitalized(assignment.getFeature()), - Assignment.class, model==null? EObject.class : model.getClass(), String.class, document.getClass(), int.class); - - Collection<? extends ICompletionProposal> assignmentProposalList = null == method ? null : invokeMethod(method, - proposalProvider, assignment, model, prefix, document, offset); - - if (null != assignmentProposalList) { - completionProposalList.addAll(assignmentProposalList); - } - + invokeProposalProvider( + "complete"+ firstLetterCapitalized(parserRule.getName()) + firstLetterCapitalized(assignment.getFeature()), + Arrays.asList(Assignment.class, IContentAssistContext.class), + Arrays.asList(assignment, this.contentAssistContext)); + return null; } + + + @Override public List<ICompletionProposal> caseKeyword(Keyword keyword) { - completionProposalList.addAll(proposalProvider.completeKeyword(keyword, model, prefix, document,offset)); + + nullSafeAddAll(completionProposalList, proposalProvider.completeKeyword(keyword, this.contentAssistContext)); + + TemplateContextType contextType = this.proposalProvider.getTemplateContextType(keyword, + this.contentAssistContext); + + if (null != contextType) { + this.templateContextTypeList.add(contextType); + } + return null; } + @SuppressWarnings("unchecked") @Override public List<ICompletionProposal> caseRuleCall(RuleCall ruleCall) { - - List<? extends ICompletionProposal> ruleCallProposalList = this.proposalProvider.completeRuleCall(ruleCall, - model, prefix, document, offset); - if (null != ruleCallProposalList) { - completionProposalList.addAll(ruleCallProposalList); + nullSafeAddAll(completionProposalList, this.proposalProvider.completeRuleCall(ruleCall, + this.contentAssistContext)); + + TemplateContextType contextType = this.proposalProvider.getTemplateContextType(ruleCall, + this.contentAssistContext); + + if (null != contextType) { + this.templateContextTypeList.add(contextType); } AbstractRule calledRule = ruleCall.getRule(); @@ -146,19 +155,23 @@ public class ProposalProviderInvokerSwitch extends XtextSwitch<List<ICompletionP TypeRef typeRef = calledRule.getType(); - Method method = findMethod(proposalProvider.getClass(), "complete" - + firstLetterCapitalized(typeRef.getMetamodel().getAlias()) + firstLetterCapitalized(typeRef.getType().getName()), - RuleCall.class, model==null? EObject.class : model.getClass(), String.class, document.getClass(), int.class); + invokeProposalProvider( + "complete"+ firstLetterCapitalized(typeRef.getMetamodel().getAlias())+ firstLetterCapitalized(typeRef.getType().getName()), + Arrays.asList(RuleCall.class, this.contentAssistContext.getModel() == null ? EObject.class : this.contentAssistContext.getModel().getClass(),IContentAssistContext.class), + Arrays.asList(ruleCall, this.contentAssistContext.getModel(),this.contentAssistContext)); + } + return null; + } - Collection<? extends ICompletionProposal> proposalList = null == method ? null : invokeMethod(method, - proposalProvider, ruleCall, model, prefix, document, offset); + private void invokeProposalProvider(String methodName,List<Class<?>> parameterTypes,List<?> parameterValues) { + + Method method = findMethod(proposalProvider.getClass(),methodName,parameterTypes.toArray(new Class[]{})); - if (null != proposalList) { - completionProposalList.addAll(proposalList); - } + Collection<? extends ICompletionProposal> assignmentProposalList = null == method ? null : invokeMethod(method, + proposalProvider, parameterValues.toArray(new Object[]{})); - } - return null; + nullSafeAddAll(completionProposalList, assignmentProposalList); + } private final Method findMethod(Class<?> clazz, String name, Class<?>... paramTypes) { @@ -258,4 +271,10 @@ public class ProposalProviderInvokerSwitch extends XtextSwitch<List<ICompletionP return Strings.toFirstUpper(name); } + private void nullSafeAddAll(List<ICompletionProposal> source, Collection<? extends ICompletionProposal> list) { + if (null != list) { + source.addAll(list); + } + } + } 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/impl/XtextCompletionProposal.java index 1e3228a..7bab759 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/impl/XtextCompletionProposal.java @@ -1,9 +1,7 @@ -package org.eclipse.xtext.ui.common.editor.codecompletion; +package org.eclipse.xtext.ui.common.editor.codecompletion.impl; import org.apache.log4j.Logger; -import org.eclipse.core.runtime.Assert; import org.eclipse.emf.ecore.EObject; -import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.DocumentEvent; @@ -22,9 +20,11 @@ import org.eclipse.xtext.Assignment; import org.eclipse.xtext.CrossReference; import org.eclipse.xtext.GrammarUtil; import org.eclipse.xtext.Keyword; +import org.eclipse.xtext.ParserRule; import org.eclipse.xtext.RuleCall; import org.eclipse.xtext.parsetree.AbstractNode; import org.eclipse.xtext.parsetree.LeafNode; +import org.eclipse.xtext.ui.common.editor.codecompletion.IContentAssistContext; /** * Default Xtext implementation of interface <code>ICompletionProposal</code>. @@ -41,113 +41,28 @@ public class XtextCompletionProposal implements ICompletionProposal, protected final Logger logger = Logger.getLogger(XtextCompletionProposal.class); - private EObject model; private AbstractElement abstractElement; private String text; private String description; private Image image; private final StyledString label; - private final int offset; private String pluginIdentifier; + private IContentAssistContext contentAssistContext; - /** - * @param element - * the element for which this CompletionProposal is created for - * @param model the last semtantically complete object - * @param text the text value to be replaced/inserted - * @param label the label to be displayed - * @param description some additional description for the tooltip - * @param imageFilePath the relative path of the image file, relative to the root of - * the plug-in; the path must be legal - * @param pluginId the id of the plug-in containing the image file; - * @param offset the offset of the text - */ - public XtextCompletionProposal(AbstractElement element,EObject model,String text, StyledString label, - String description, String imageFilePath, String pluginIdentifier, - int offset) { - Assert.isNotNull(text, "parameter 'text' must not be null"); - Assert.isNotNull(pluginIdentifier, - "pluginIdentifier 'text' must not be null"); - this.abstractElement = element; - this.model = model; - this.text = text; - this.description = description; - this.offset = offset; - this.pluginIdentifier = pluginIdentifier; - - if (label != null) { - this.label = label; - } else { - this.label = new StyledString(this.text); - } - if (imageFilePath != null) { - initializeImage(imageFilePath); - } - } - /** - * - * Getter for model property. - * - * @return the associated model object - */ - public EObject getModel() { - return model; - } - - /** - * Setter for model property. - * - * @param model to set - */ - public void setModel(EObject model) { - this.model = model; - } - - - /** - * Getter for abstractElement property. - * - * @return the associated element - */ - public AbstractElement getAbstractElement() { - return abstractElement; - } - - - /** - * Setter for abstractElement property. - * @param abstractElement to set - */ - public void setAbstractElement(AbstractElement abstractElement) { + public XtextCompletionProposal(AbstractElement abstractElement, String displayString, + IContentAssistContext contentAssistContext) { this.abstractElement = abstractElement; + this.text = displayString; + this.description = displayString; + this.label = new StyledString(displayString); + this.contentAssistContext = contentAssistContext; } - /** - * 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) - * - * @see - * org.eclipse.jface.text.contentassist.ICompletionProposal#apply(org.eclipse - * .jface.text.IDocument) + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#apply(org.eclipse.jface.text.IDocument) */ public void apply(IDocument document) { @@ -155,9 +70,7 @@ public class XtextCompletionProposal implements ICompletionProposal, /* * (non-Javadoc) - * - * @seeorg.eclipse.jface.text.contentassist.ICompletionProposal# - * getAdditionalProposalInfo() + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getAdditionalProposalInfo() */ public String getAdditionalProposalInfo() { return this.description == null ? null : this.description @@ -166,9 +79,7 @@ public class XtextCompletionProposal implements ICompletionProposal, /* * (non-Javadoc) - * - * @seeorg.eclipse.jface.text.contentassist.ICompletionProposal# - * getContextInformation() + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getContextInformation() */ public IContextInformation getContextInformation() { if (this.description != null) @@ -179,10 +90,7 @@ public class XtextCompletionProposal implements ICompletionProposal, /* * (non-Javadoc) - * - * @see - * org.eclipse.jface.text.contentassist.ICompletionProposal#getDisplayString - * () + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getDisplayString() */ public String getDisplayString() { return this.label.getString(); @@ -199,10 +107,7 @@ public class XtextCompletionProposal implements ICompletionProposal, /* * (non-Javadoc) - * - * @see - * org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#apply - * (org.eclipse.jface.text.ITextViewer, char, int, int) + * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#apply(org.eclipse.jface.text.ITextViewer, char, int, int) */ public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) { @@ -211,38 +116,37 @@ public class XtextCompletionProposal implements ICompletionProposal, IDocument document = viewer.getDocument(); - if (model != null) { + if (this.contentAssistContext.getModel() != null) { - ContentAssistContextAdapter contentAssistContextAdapter = getContextAdapater(); - AbstractNode abstractNode = contentAssistContextAdapter.getCurrentNode(); + AbstractNode abstractNode = this.contentAssistContext.getNode(); if (abstractNode instanceof LeafNode) { LeafNode currentLeafNode = (LeafNode) abstractNode; if (getDisplayString().toUpperCase().startsWith(currentLeafNode.getText().toUpperCase())) { - setText(getText().substring(this.offset - currentLeafNode.getTotalOffset())); - } else if (contentAssistContextAdapter.isCusorAtEndOfLastCompleteNode()) { + this.text = this.text.substring(this.contentAssistContext.getOffSet() - currentLeafNode.getTotalOffset()); + } else if (isCusorAtEndOfLastCompleteNode()) { if (currentLeafNode.getGrammarElement() instanceof CrossReference && abstractElement instanceof CrossReference) { - setText(" " + getText()); + this.text = " " + this.text; } else if (currentLeafNode.getGrammarElement() instanceof RuleCall && currentLeafNode.getGrammarElement().eContainer() instanceof Assignment && abstractElement instanceof Assignment) { - setText(" " + getText()); + this.text = " " + this.text; } else if (!GrammarUtil.containingParserRule(abstractElement).equals( GrammarUtil.containingParserRule(currentLeafNode.getGrammarElement()))) { - setText(" " + getText()); + this.text = " " + this.text; } } } } - document.replace(this.offset, document.getLength()<(this.offset+getText().length()) ? 0:getText().length() , getText()); + document.replace(this.contentAssistContext.getOffSet(), 0, this.text); } catch (BadLocationException e) { logger.error(e); @@ -251,36 +155,26 @@ public class XtextCompletionProposal implements ICompletionProposal, /* * (non-Javadoc) - * - * @see - * org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#selected - * (org.eclipse.jface.text.ITextViewer, boolean) + * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#selected(org.eclipse.jface.text.ITextViewer, boolean) */ public void selected(ITextViewer viewer, boolean smartToggle) { } /* * (non-Javadoc) - * - * @see - * org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#unselected - * (org.eclipse.jface.text.ITextViewer) + * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#unselected(org.eclipse.jface.text.ITextViewer) */ public void unselected(ITextViewer viewer) { } /* * (non-Javadoc) - * - * @see - * org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#validate - * (org.eclipse.jface.text.IDocument, int, - * org.eclipse.jface.text.DocumentEvent) + * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#validate(org.eclipse.jface.text.IDocument, int, org.eclipse.jface.text.DocumentEvent) */ public boolean validate(IDocument document, int offset, DocumentEvent event) { boolean startsWith = false; try { - String prefix = document.get(this.offset, offset - this.offset); + String prefix = document.get(this.contentAssistContext.getOffSet(), offset - this.contentAssistContext.getOffSet()); startsWith = getDisplayString().toLowerCase().startsWith( prefix.toLowerCase()); } catch (BadLocationException e) { @@ -301,51 +195,46 @@ public class XtextCompletionProposal implements ICompletionProposal, /* * (non-Javadoc) - * - * @see - * org.eclipse.jface.text.contentassist.ICompletionProposal#getSelection - * (org.eclipse.jface.text.IDocument) + * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getSelection(org.eclipse.jface.text.IDocument) */ public Point getSelection(IDocument document) { - return new Point(offset + this.text.length(), 0); + return new Point(this.contentAssistContext.getOffSet() + this.text.length(), 0); } /** * - * @param prefix to match * @return true or false whether the given prefix matches the text of this completion proposal */ - public boolean matches(String prefix) { + public boolean matches() { boolean matches = true; - if (model != null) { + if (this.contentAssistContext.getModel() != null) { AbstractElement abstractElement = null; - if (getAbstractElement() instanceof Keyword || - getAbstractElement() instanceof CrossReference) { - abstractElement = GrammarUtil.containingAssignment(getAbstractElement()); + if (this.abstractElement instanceof Keyword || + this.abstractElement instanceof CrossReference) { + abstractElement = GrammarUtil.containingAssignment(this.abstractElement); } if (null==abstractElement) { - abstractElement = getAbstractElement(); + abstractElement = this.abstractElement; } - ContentAssistContextAdapter contentAssistContextAdapter = getContextAdapater(); 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 (contentAssistContextAdapter.isCusorAtEndOfLastCompleteNode() && - abstractElement.equals(contentAssistContextAdapter.getCurrentGrammarElement())) { + if (isCusorAtEndOfLastCompleteNode() && + abstractElement.equals(getCurrentGrammarElement())) { candidateToCompare = true; - } else if (!contentAssistContextAdapter.isCusorAtEndOfLastCompleteNode() ) { + } else if (!isCusorAtEndOfLastCompleteNode() ) { candidateToCompare = true; } - if ( candidateToCompare && (!"".equals(prefix.trim()) && - !getDisplayString().toUpperCase().trim().startsWith(prefix.toUpperCase().trim()))) { + if ( candidateToCompare && (!"".equals(this.contentAssistContext.getMatchString().trim()) && + !getDisplayString().toUpperCase().trim().startsWith(this.contentAssistContext.getMatchString().toUpperCase().trim()))) { matches = false; } } @@ -356,7 +245,7 @@ public class XtextCompletionProposal implements ICompletionProposal, @Override public String toString() { - return "XtextCompletionPoposal[text='"+getText()+"']"; + return "XtextCompletionPoposal[text='"+this.text+"']"; } private void initializeImage(String imageName) { @@ -374,9 +263,26 @@ public class XtextCompletionProposal implements ICompletionProposal, this.image = newImage; } - private ContentAssistContextAdapter getContextAdapater() { - ContentAssistContextAdapter contentAssistContextAdapter = (ContentAssistContextAdapter) - EcoreUtil.getAdapter(model.eAdapters(), ContentAssistContextAdapter.class); - return contentAssistContextAdapter; + + /** + * @return true or false wheter the cursor is at the the last complete node + */ + public boolean isCusorAtEndOfLastCompleteNode() { + return this.contentAssistContext.getNode() == this.contentAssistContext.getReferenceNode(); + } + + /** + * @return the grammar element of the current node + */ + public EObject getCurrentGrammarElement() { + + EObject grammarElement = GrammarUtil.containingAssignment(this.contentAssistContext.getNode().getGrammarElement()); + + if (null == grammarElement) { + grammarElement = (this.contentAssistContext.getNode().getGrammarElement() instanceof ParserRule ? ((ParserRule) this.contentAssistContext.getNode() + .getGrammarElement()).getAlternatives() : this.contentAssistContext.getNode().getGrammarElement()); + } + + return grammarElement; } } diff --git a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/impl/XtextTemplateContext.java b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/impl/XtextTemplateContext.java new file mode 100644 index 0000000..1c6ffa5 --- a/dev/null +++ b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/impl/XtextTemplateContext.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright (c) 2008 itemis AG (http://www.itemis.eu) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ +package org.eclipse.xtext.ui.common.editor.codecompletion.impl; + +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.templates.DocumentTemplateContext; +import org.eclipse.jface.text.templates.TemplateContextType; +import org.eclipse.xtext.IMetamodelAccess; +import org.eclipse.xtext.ui.common.editor.codecompletion.IContentAssistContext; +import org.eclipse.xtext.ui.common.editor.codecompletion.ILinkingCandidatesService; + +/** + * Represents an extended version of class {@link DocumentTemplateContext} to provide additional Xtext related + * information and services for resolving a <code>Template</code>. + * + * @author Michael Clay - Initial contribution and API + */ +public class XtextTemplateContext extends DocumentTemplateContext { + + private IContentAssistContext contentAssistContext; + + private ILinkingCandidatesService linkingCandidatesService; + + private IMetamodelAccess metamodelAccess; + + public XtextTemplateContext(TemplateContextType type, IDocument document, Position position, + IContentAssistContext contentAssistContext, ILinkingCandidatesService linkingCandidatesService, + IMetamodelAccess metamodelAccess) { + super(type, document, position); + this.contentAssistContext = contentAssistContext; + this.linkingCandidatesService = linkingCandidatesService; + this.metamodelAccess = metamodelAccess; + } + + /** + * @return the contentAssistContext + */ + public IContentAssistContext getContentAssistContext() { + return contentAssistContext; + } + + /** + * @return the linkingCandidatesService + */ + public ILinkingCandidatesService getLinkingCandidatesService() { + return linkingCandidatesService; + } + + /** + * @return the metamodelAccess + */ + public IMetamodelAccess getMetamodelAccess() { + return metamodelAccess; + } + +}
\ No newline at end of file diff --git a/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/impl/XtextTemplateContextType.java b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/impl/XtextTemplateContextType.java new file mode 100644 index 0000000..1ae6691 --- a/dev/null +++ b/plugins/org.eclipse.xtext.ui.common/src/org/eclipse/xtext/ui/common/editor/codecompletion/impl/XtextTemplateContextType.java @@ -0,0 +1,97 @@ +/******************************************************************************* + * Copyright (c) 2008 itemis AG (http://www.itemis.eu) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + *******************************************************************************/ +package org.eclipse.xtext.ui.common.editor.codecompletion.impl; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.jface.text.templates.GlobalTemplateVariables; +import org.eclipse.jface.text.templates.TemplateContext; +import org.eclipse.jface.text.templates.TemplateContextType; +import org.eclipse.jface.text.templates.TemplateVariable; +import org.eclipse.jface.text.templates.TemplateVariableResolver; +import org.eclipse.xtext.IMetamodelAccess; +import org.eclipse.xtext.crossref.IScopedElement; +import org.eclipse.xtext.ui.common.editor.codecompletion.impl.XtextTemplateContext; + +/** + * Provides a convenience base type for <code>TemplateContextType's</code> preconfigured with several handy + * Xtext <code>TemplateVariableResolver</code> . + * + * @author Michael Clay - Initial contribution and API + */ +public class XtextTemplateContextType extends TemplateContextType { + + public XtextTemplateContextType() { + addResolver(new CrossReferenceTemplateVariableResolver()); + addResolver(new GlobalTemplateVariables.WordSelection()); + addResolver(new GlobalTemplateVariables.LineSelection()); + addResolver(new GlobalTemplateVariables.Date()); + addResolver(new GlobalTemplateVariables.Year()); + addResolver(new GlobalTemplateVariables.Time()); + addResolver(new GlobalTemplateVariables.Dollar()); + addResolver(new GlobalTemplateVariables.User()); + addResolver(new GlobalTemplateVariables.Cursor()); + } + + public static class CrossReferenceTemplateVariableResolver extends TemplateVariableResolver { + + public CrossReferenceTemplateVariableResolver() { + super("CrossReference", "TemplateVariableResolver for CrossReferences"); + } + + public void resolve(TemplateVariable variable, TemplateContext context) { + + XtextTemplateContext xtextTemplateContext = (XtextTemplateContext) context; + + String abbreviatedCrossReference = (String) variable.getVariableType().getParams().iterator().next(); + + String[] classReferencePair = abbreviatedCrossReference.split("\\."); + + EReference reference = getReference(classReferencePair[0], classReferencePair[1], xtextTemplateContext + .getMetamodelAccess()); + + Iterable<IScopedElement> linkingCandidates = xtextTemplateContext.getLinkingCandidatesService() + .getLinkingCandidates(xtextTemplateContext.getContentAssistContext().getModel(), reference); + + List<String> names = new ArrayList<String>(); + + for (IScopedElement scopedElement : linkingCandidates) { + names.add(scopedElement.name()); + } + + String[] bindings = (String[]) names.toArray(new String[] {}); + + if (bindings.length != 0) + variable.setValues(bindings); + if (bindings.length > 1) + variable.setUnambiguous(false); + else + variable.setUnambiguous(isUnambiguous(context)); + + variable.setResolved(true); + } + + private EReference getReference(String eClassName, String eReferenceName, IMetamodelAccess metamodelAccess) { + EPackage[] allEPackages = metamodelAccess.getAllEPackages(); + for (int i = 0; i < allEPackages.length; i++) { + EPackage ePackage = allEPackages[i]; + EClass eClass = (EClass) ePackage.getEClassifier(eClassName); + if (eClass != null) { + return (EReference) eClass.getEStructuralFeature(eReferenceName); + } + } + return null; + } + } + +} diff --git a/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/IXtextSourceViewer.java b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/IXtextSourceViewer.java new file mode 100644 index 0000000..99b2fac --- a/dev/null +++ b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/IXtextSourceViewer.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2008 itemis AG (http://www.itemis.eu) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + *******************************************************************************/ +package org.eclipse.xtext.ui.core.editor; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.xtext.parsetree.AbstractNode; +import org.eclipse.xtext.parsetree.CompositeNode; + +/** + * Source viewer interface with a 'node-centric' view of the underlying document. + * + * @author Michael Clay - Initial contribution and API + */ +public interface IXtextSourceViewer { + + /** + * @return the root node of the underlying document + */ + CompositeNode getRootNode(); + + /** + * @param offset + * matching position for the reference node + * @return the nearest node with an existing grammar element set (i.e. valid + * according to the underlying grammar) + */ + AbstractNode getReferenceNode(int offset); + + /** + * @param offset + * matching position for the node + * @return the last node (on a none hidden channel) that starts at or spans + * across the given offset position + */ + AbstractNode getNode(int offset); + + /** + * @param offset + * matching position for the model + * @return the most specific model element for the given offset position + */ + EObject getModel(int offset); + +} diff --git a/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/XtextEditor.java b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/XtextEditor.java index 332820f..0a02e7d 100644 --- a/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/XtextEditor.java +++ b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/XtextEditor.java @@ -175,7 +175,7 @@ public class XtextEditor extends TextEditor implements IExecutableExtension { // overwrite superclass implementation to allow folding fAnnotationAccess = createAnnotationAccess(); fOverviewRuler = createOverviewRuler(getSharedColors()); - ISourceViewer projectionViewer = new ProjectionViewer(parent, ruler, getOverviewRuler(), + ISourceViewer projectionViewer = new XtextSourceViewer(parent, ruler, getOverviewRuler(), isOverviewRulerVisible(), styles); getSourceViewerDecorationSupport(projectionViewer); return projectionViewer; diff --git a/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/XtextSourceViewer.java b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/XtextSourceViewer.java new file mode 100644 index 0000000..122ddde --- a/dev/null +++ b/plugins/org.eclipse.xtext.ui.core/src/org/eclipse/xtext/ui/core/editor/XtextSourceViewer.java @@ -0,0 +1,164 @@ +/******************************************************************************* + * Copyright (c) 2008 itemis AG (http://www.itemis.eu) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + *******************************************************************************/ +package org.eclipse.xtext.ui.core.editor; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.source.IAnnotationModel; +import org.eclipse.jface.text.source.IOverviewRuler; +import org.eclipse.jface.text.source.IVerticalRuler; +import org.eclipse.jface.text.source.projection.ProjectionViewer; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.xtext.parser.IParseResult; +import org.eclipse.xtext.parsetree.AbstractNode; +import org.eclipse.xtext.parsetree.CompositeNode; +import org.eclipse.xtext.parsetree.NodeUtil; +import org.eclipse.xtext.parsetree.ParseTreeUtil; +import org.eclipse.xtext.resource.XtextResource; +import org.eclipse.xtext.ui.core.editor.model.IXtextDocument; +import org.eclipse.xtext.ui.core.editor.model.IXtextModelListener; +import org.eclipse.xtext.ui.core.editor.model.UnitOfWork; +import org.eclipse.xtext.util.Function; +import org.eclipse.xtext.util.SimpleCache; + +/** + * Provides a default implementation of interface <code>IXtextSourceViewer</code>. + * + * @author Michael Clay - Initial contribution and API + * + * @see IXtextSourceViewer + */ +public class XtextSourceViewer extends ProjectionViewer implements IXtextSourceViewer, IXtextModelListener { + + private CompositeNode rootNode; + + private SimpleCache<Integer, AbstractNode> referenceNodeCache; + + private SimpleCache<Integer, AbstractNode> nodeCache; + + public XtextSourceViewer(Composite parent, IVerticalRuler ruler, IOverviewRuler overviewRuler, + boolean showsAnnotationOverview, int styles) { + super(parent, ruler, overviewRuler, showsAnnotationOverview, styles); + init(); + } + + @Override + protected void createControl(Composite parent, int styles) { + // required for 'headless' standalone unit tests + if (parent != null) { + super.createControl(parent, styles); + } + } + + @Override + public void setDocument(IDocument document, IAnnotationModel annotationModel) { + super.setDocument(document, annotationModel); + ((IXtextDocument) getDocument()).addModelListener(this); + } + + @Override + public void setDocument(IDocument document, IAnnotationModel annotationModel, int modelRangeOffset, + int modelRangeLength) { + super.setDocument(document, annotationModel, modelRangeOffset, modelRangeLength); + ((IXtextDocument) getDocument()).addModelListener(this); + } + + @Override + public void setDocument(IDocument document, int visibleRegionOffset, int visibleRegionLength) { + super.setDocument(document, visibleRegionOffset, visibleRegionLength); + ((IXtextDocument) getDocument()).addModelListener(this); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.xtext.ui.core.editor.IXtextSourceViewer#getRootNode() + */ + public CompositeNode getRootNode() { + + if (null == rootNode) { + + IXtextDocument xtextDocument = (IXtextDocument) getDocument(); + + this.rootNode = xtextDocument.readOnly(new UnitOfWork<CompositeNode>() { + public CompositeNode exec(XtextResource resource) throws Exception { + IParseResult parseResult = resource.getParseResult(); + Assert.isNotNull(parseResult); + return parseResult.getRootNode(); + } + }); + } + return rootNode; + } + + /* + * (non-Javadoc) + * @see org.eclipse.xtext.ui.core.editor.model.IXtextModelListener#modelChanged(org.eclipse.xtext.resource.XtextResource) + */ + public void modelChanged(XtextResource resource) { + init(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.xtext.ui.core.editor.IXtextSourceViewer#getReferenceNode(int) + */ + public AbstractNode getReferenceNode(int offset) { + return this.referenceNodeCache.get(offset); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.xtext.ui.core.editor.IXtextSourceViewer#getNode(int) + */ + public AbstractNode getNode(int offset) { + return this.nodeCache.get(offset); + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.xtext.ui.core.editor.IXtextSourceViewer#getModel(int) + */ + public EObject getModel(int offset) { + AbstractNode lastCompleteNode = getReferenceNode(offset); + + return lastCompleteNode instanceof AbstractNode ? NodeUtil + .getNearestSemanticObject((AbstractNode) lastCompleteNode) : lastCompleteNode; + } + + private SimpleCache<Integer, AbstractNode> createReferenceNodeCache() { + return new SimpleCache<Integer, AbstractNode>(new Function<Integer, AbstractNode>() { + + public AbstractNode exec(Integer offset) { + return ParseTreeUtil.getLastCompleteNodeByOffset(getRootNode(), offset); + } + + }); + } + + private SimpleCache<Integer, AbstractNode> createNodeCache() { + return new SimpleCache<Integer, AbstractNode>(new Function<Integer, AbstractNode>() { + + public AbstractNode exec(Integer offset) { + return ParseTreeUtil.getCurrentOrFollowingNodeByOffset(getRootNode(), offset); + } + + }); + } + + private void init() { + referenceNodeCache = createReferenceNodeCache(); + nodeCache = createNodeCache(); + this.rootNode = null; + } + +} diff --git a/tests/org.eclipse.xtext.ui.common.tests/src-gen/org/eclipse/xtext/XtextGrammarTestLanguageGenProposalProvider.java b/tests/org.eclipse.xtext.ui.common.tests/src-gen/org/eclipse/xtext/XtextGrammarTestLanguageGenProposalProvider.java index be0c8f7..c251b3f 100644 --- a/tests/org.eclipse.xtext.ui.common.tests/src-gen/org/eclipse/xtext/XtextGrammarTestLanguageGenProposalProvider.java +++ b/tests/org.eclipse.xtext.ui.common.tests/src-gen/org/eclipse/xtext/XtextGrammarTestLanguageGenProposalProvider.java @@ -14,317 +14,297 @@ import org.eclipse.xtext.CrossReference; import org.eclipse.xtext.RuleCall; import org.eclipse.xtext.ui.common.editor.codecompletion.AbstractProposalProvider; import org.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider; +import org.eclipse.xtext.ui.common.editor.codecompletion.IContentAssistContext; /** * Represents a generated, default implementation of interface {@link IProposalProvider}. * - * In addition to the declared methods, the framework tries to call grammar dependent methods for assignments using reflection. - * The signature of such methods invoked reflectively follows the following pattern: - * - * public List<ICompletionProposal> complete[Typename][featureName](Assignment ele, EObject model, String prefix) - * - * <b>Example</b> - * Given the following grammar : - * <code> - * RuleA returns MyType : - * "myType" name=ID; - * </code> - * - * One could provide the following method in an implementation of this interface: - * <code> - * public List<ICompletionProposal> completeMyTypeName(Assignment ele, EObject model, String prefix, IDocument doc) {...} - * </code> - * Note that if you have generated Java classes for your domain model (meta model) you can alternatively declare the second parameter using - * a specific type: - * <code> - * public List<ICompletionProposal> completeMyTypeName(Assignment ele, MyType model, String prefix, IDocument doc) {...} - * </code> - * + * @see org.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider */ public class XtextGrammarTestLanguageGenProposalProvider extends AbstractProposalProvider { // constants private static final String UI_PLUGIN_ID = "."; - public List<? extends ICompletionProposal> completeGrammarAbstract(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeGrammarAbstract(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeGrammarAbstract feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeGrammarIdElements(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeGrammarIdElements(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeGrammarIdElements feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"GrammarIdElements", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "GrammarIdElements", contentAssistContext)); } - public List<? extends ICompletionProposal> completeGrammarSuperGrammarIdElements(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeGrammarSuperGrammarIdElements(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeGrammarSuperGrammarIdElements feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"GrammarSuperGrammarIdElements", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "GrammarSuperGrammarIdElements", contentAssistContext)); } - public List<? extends ICompletionProposal> completeGrammarMetamodelDeclarations(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeGrammarMetamodelDeclarations(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeGrammarMetamodelDeclarations feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeGrammarRules(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeGrammarRules(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeGrammarRules feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeGeneratedMetamodelName(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeGeneratedMetamodelName(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeGeneratedMetamodelName feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"GeneratedMetamodelName", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "GeneratedMetamodelName", contentAssistContext)); } - public List<? extends ICompletionProposal> completeGeneratedMetamodelNsURI(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeGeneratedMetamodelNsURI(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeGeneratedMetamodelNsURI feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"\"GeneratedMetamodelNsURI\"", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "\"GeneratedMetamodelNsURI\"", contentAssistContext)); } - public List<? extends ICompletionProposal> completeGeneratedMetamodelAlias(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeGeneratedMetamodelAlias(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeGeneratedMetamodelAlias feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"GeneratedMetamodelAlias", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "GeneratedMetamodelAlias", contentAssistContext)); } - public List<? extends ICompletionProposal> completeReferencedMetamodelUri(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeReferencedMetamodelUri(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeReferencedMetamodelUri feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"\"ReferencedMetamodelUri\"", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "\"ReferencedMetamodelUri\"", contentAssistContext)); } - public List<? extends ICompletionProposal> completeReferencedMetamodelAlias(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeReferencedMetamodelAlias(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeReferencedMetamodelAlias feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"ReferencedMetamodelAlias", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "ReferencedMetamodelAlias", contentAssistContext)); } - public List<? extends ICompletionProposal> completeLexerRuleName(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeLexerRuleName(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeLexerRuleName feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"LexerRuleName", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "LexerRuleName", contentAssistContext)); } - public List<? extends ICompletionProposal> completeLexerRuleType(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeLexerRuleType(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeLexerRuleType feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeLexerRuleBody(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeLexerRuleBody(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeLexerRuleBody feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"\"LexerRuleBody\"", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "\"LexerRuleBody\"", contentAssistContext)); } - public List<? extends ICompletionProposal> completeParserRuleName(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeParserRuleName(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeParserRuleName feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"ParserRuleName", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "ParserRuleName", contentAssistContext)); } - public List<? extends ICompletionProposal> completeParserRuleType(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeParserRuleType(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeParserRuleType feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeParserRuleAlternatives(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeParserRuleAlternatives(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeParserRuleAlternatives feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeTypeRefMetamodel(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeTypeRefMetamodel(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeTypeRefMetamodel feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return lookupCrossReference(((CrossReference)assignment.getTerminal()), model, prefix, offset); + return lookupCrossReference(((CrossReference)assignment.getTerminal()), contentAssistContext); } - public List<? extends ICompletionProposal> completeTypeRefType(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeTypeRefType(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeTypeRefType feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return lookupCrossReference(((CrossReference)assignment.getTerminal()), model, prefix, offset); + return lookupCrossReference(((CrossReference)assignment.getTerminal()), contentAssistContext); } - public List<? extends ICompletionProposal> completeAlternativesGroups(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeAlternativesGroups(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeAlternativesGroups feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeGroupAbstractTokens(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeGroupAbstractTokens(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeGroupAbstractTokens feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeAbstractTokenCardinality(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeAbstractTokenCardinality(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeAbstractTokenCardinality feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeAssignmentFeature(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeAssignmentFeature(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeAssignmentFeature feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"AssignmentFeature", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "AssignmentFeature", contentAssistContext)); } - public List<? extends ICompletionProposal> completeAssignmentOperator(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeAssignmentOperator(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeAssignmentOperator feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeAssignmentTerminal(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeAssignmentTerminal(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeAssignmentTerminal feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeActionTypeName(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeActionTypeName(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeActionTypeName feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeActionFeature(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeActionFeature(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeActionFeature feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"ActionFeature", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "ActionFeature", contentAssistContext)); } - public List<? extends ICompletionProposal> completeActionOperator(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeActionOperator(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeActionOperator feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeCrossReferenceType(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeCrossReferenceType(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeCrossReferenceType feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeCrossReferenceRule(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeCrossReferenceRule(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeCrossReferenceRule feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return lookupCrossReference(((CrossReference)assignment.getTerminal()), model, prefix, offset); + return lookupCrossReference(((CrossReference)assignment.getTerminal()), contentAssistContext); } - public List<? extends ICompletionProposal> completeKeywordValue(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeKeywordValue(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeKeywordValue feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"\"KeywordValue\"", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "\"KeywordValue\"", contentAssistContext)); } - public List<? extends ICompletionProposal> completeRuleCallRule(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeRuleCallRule(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeRuleCallRule feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return lookupCrossReference(((CrossReference)assignment.getTerminal()), model, prefix, offset); + return lookupCrossReference(((CrossReference)assignment.getTerminal()), contentAssistContext); } diff --git a/tests/org.eclipse.xtext.ui.common.tests/src-gen/org/eclipse/xtext/testlanguages/ContentAssistTestLanguageGenProposalProvider.java b/tests/org.eclipse.xtext.ui.common.tests/src-gen/org/eclipse/xtext/testlanguages/ContentAssistTestLanguageGenProposalProvider.java index 49e8efd..3b7e773 100644 --- a/tests/org.eclipse.xtext.ui.common.tests/src-gen/org/eclipse/xtext/testlanguages/ContentAssistTestLanguageGenProposalProvider.java +++ b/tests/org.eclipse.xtext.ui.common.tests/src-gen/org/eclipse/xtext/testlanguages/ContentAssistTestLanguageGenProposalProvider.java @@ -14,90 +14,70 @@ import org.eclipse.xtext.CrossReference; import org.eclipse.xtext.RuleCall; import org.eclipse.xtext.ui.common.editor.codecompletion.AbstractProposalProvider; import org.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider; +import org.eclipse.xtext.ui.common.editor.codecompletion.IContentAssistContext; /** * Represents a generated, default implementation of interface {@link IProposalProvider}. * - * In addition to the declared methods, the framework tries to call grammar dependent methods for assignments using reflection. - * The signature of such methods invoked reflectively follows the following pattern: - * - * public List<ICompletionProposal> complete[Typename][featureName](Assignment ele, EObject model, String prefix) - * - * <b>Example</b> - * Given the following grammar : - * <code> - * RuleA returns MyType : - * "myType" name=ID; - * </code> - * - * One could provide the following method in an implementation of this interface: - * <code> - * public List<ICompletionProposal> completeMyTypeName(Assignment ele, EObject model, String prefix, IDocument doc) {...} - * </code> - * Note that if you have generated Java classes for your domain model (meta model) you can alternatively declare the second parameter using - * a specific type: - * <code> - * public List<ICompletionProposal> completeMyTypeName(Assignment ele, MyType model, String prefix, IDocument doc) {...} - * </code> - * + * @see org.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider */ public class ContentAssistTestLanguageGenProposalProvider extends AbstractProposalProvider { // constants private static final String UI_PLUGIN_ID = "."; - public List<? extends ICompletionProposal> completeStartRules(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeStartRules(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeStartRules feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeFirstAbstractRuleChildName(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeFirstAbstractRuleChildName(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeFirstAbstractRuleChildName feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"FirstAbstractRuleChildName", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "FirstAbstractRuleChildName", contentAssistContext)); } - public List<? extends ICompletionProposal> completeFirstAbstractRuleChildElements(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeFirstAbstractRuleChildElements(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeFirstAbstractRuleChildElements feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeSecondAbstractRuleChildName(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeSecondAbstractRuleChildName(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeSecondAbstractRuleChildName feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"SecondAbstractRuleChildName", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "SecondAbstractRuleChildName", contentAssistContext)); } - public List<? extends ICompletionProposal> completeSecondAbstractRuleChildRule(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeSecondAbstractRuleChildRule(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeSecondAbstractRuleChildRule feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeAbstractRuleCallRule(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeAbstractRuleCallRule(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeAbstractRuleCallRule feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return lookupCrossReference(((CrossReference)assignment.getTerminal()), model, prefix, offset); + return lookupCrossReference(((CrossReference)assignment.getTerminal()), contentAssistContext); } diff --git a/tests/org.eclipse.xtext.ui.common.tests/src-gen/org/eclipse/xtext/testlanguages/ReferenceGrammarTestLanguageGenProposalProvider.java b/tests/org.eclipse.xtext.ui.common.tests/src-gen/org/eclipse/xtext/testlanguages/ReferenceGrammarTestLanguageGenProposalProvider.java index 36cd59d..6868a90 100644 --- a/tests/org.eclipse.xtext.ui.common.tests/src-gen/org/eclipse/xtext/testlanguages/ReferenceGrammarTestLanguageGenProposalProvider.java +++ b/tests/org.eclipse.xtext.ui.common.tests/src-gen/org/eclipse/xtext/testlanguages/ReferenceGrammarTestLanguageGenProposalProvider.java @@ -14,189 +14,168 @@ import org.eclipse.xtext.CrossReference; import org.eclipse.xtext.RuleCall; import org.eclipse.xtext.ui.common.editor.codecompletion.AbstractProposalProvider; import org.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider; +import org.eclipse.xtext.ui.common.editor.codecompletion.IContentAssistContext; /** * Represents a generated, default implementation of interface {@link IProposalProvider}. * - * In addition to the declared methods, the framework tries to call grammar dependent methods for assignments using reflection. - * The signature of such methods invoked reflectively follows the following pattern: - * - * public List<ICompletionProposal> complete[Typename][featureName](Assignment ele, EObject model, String prefix) - * - * <b>Example</b> - * Given the following grammar : - * <code> - * RuleA returns MyType : - * "myType" name=ID; - * </code> - * - * One could provide the following method in an implementation of this interface: - * <code> - * public List<ICompletionProposal> completeMyTypeName(Assignment ele, EObject model, String prefix, IDocument doc) {...} - * </code> - * Note that if you have generated Java classes for your domain model (meta model) you can alternatively declare the second parameter using - * a specific type: - * <code> - * public List<ICompletionProposal> completeMyTypeName(Assignment ele, MyType model, String prefix, IDocument doc) {...} - * </code> - * + * @see org.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider */ public class ReferenceGrammarTestLanguageGenProposalProvider extends AbstractProposalProvider { // constants private static final String UI_PLUGIN_ID = "."; - public List<? extends ICompletionProposal> completeSpielplatzGroesse(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeSpielplatzGroesse(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeSpielplatzGroesse feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"1", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "1", contentAssistContext)); } - public List<? extends ICompletionProposal> completeSpielplatzBeschreibung(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeSpielplatzBeschreibung(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeSpielplatzBeschreibung feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"\"SpielplatzBeschreibung\"", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "\"SpielplatzBeschreibung\"", contentAssistContext)); } - public List<? extends ICompletionProposal> completeSpielplatzKinder(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeSpielplatzKinder(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeSpielplatzKinder feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeSpielplatzErzieher(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeSpielplatzErzieher(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeSpielplatzErzieher feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeSpielplatzSpielzeuge(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeSpielplatzSpielzeuge(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeSpielplatzSpielzeuge feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeSpielplatzFamilie(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeSpielplatzFamilie(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeSpielplatzFamilie feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeKindName(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeKindName(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeKindName feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"KindName", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "KindName", contentAssistContext)); } - public List<? extends ICompletionProposal> completeKindAge(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeKindAge(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeKindAge feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"1", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "1", contentAssistContext)); } - public List<? extends ICompletionProposal> completeErwachsenerName(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeErwachsenerName(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeErwachsenerName feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"ErwachsenerName", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "ErwachsenerName", contentAssistContext)); } - public List<? extends ICompletionProposal> completeErwachsenerAge(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeErwachsenerAge(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeErwachsenerAge feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"1", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "1", contentAssistContext)); } - public List<? extends ICompletionProposal> completeSpielzeugName(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeSpielzeugName(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeSpielzeugName feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"SpielzeugName", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "SpielzeugName", contentAssistContext)); } - public List<? extends ICompletionProposal> completeSpielzeugFarbe(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeSpielzeugFarbe(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeSpielzeugFarbe feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeFamilieName(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeFamilieName(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeFamilieName feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeFamilieMutter(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeFamilieMutter(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeFamilieMutter feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return lookupCrossReference(((CrossReference)assignment.getTerminal()), model, prefix, offset); + return lookupCrossReference(((CrossReference)assignment.getTerminal()), contentAssistContext); } - public List<? extends ICompletionProposal> completeFamilieVater(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeFamilieVater(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeFamilieVater feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return lookupCrossReference(((CrossReference)assignment.getTerminal()), model, prefix, offset); + return lookupCrossReference(((CrossReference)assignment.getTerminal()), contentAssistContext); } - public List<? extends ICompletionProposal> completeFamilieKinder(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeFamilieKinder(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeFamilieKinder feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return lookupCrossReference(((CrossReference)assignment.getTerminal()), model, prefix, offset); + return lookupCrossReference(((CrossReference)assignment.getTerminal()), contentAssistContext); } - public List<? extends ICompletionProposal> complete(RuleCall ruleCall, EObject model, String prefix, - IDocument doc, int offset) { + public List<? extends ICompletionProposal> complete(RuleCall ruleCall, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("complete '" + ruleCall.getRule().getName() + "' cardinality '" + ruleCall.getCardinality() - + "' for model '" + model + "' and prefix '" + prefix.trim() + "'"); + + "' for model '" + contentAssistContext.getModel() + "' and prefix '" + contentAssistContext.getMatchString() + "'"); } return Collections.emptyList(); } diff --git a/tests/org.eclipse.xtext.ui.common.tests/src-gen/org/eclipse/xtext/testlanguages/TreeTestLanguageGenProposalProvider.java b/tests/org.eclipse.xtext.ui.common.tests/src-gen/org/eclipse/xtext/testlanguages/TreeTestLanguageGenProposalProvider.java index 8f6732c..b7704da 100644 --- a/tests/org.eclipse.xtext.ui.common.tests/src-gen/org/eclipse/xtext/testlanguages/TreeTestLanguageGenProposalProvider.java +++ b/tests/org.eclipse.xtext.ui.common.tests/src-gen/org/eclipse/xtext/testlanguages/TreeTestLanguageGenProposalProvider.java @@ -14,70 +14,50 @@ import org.eclipse.xtext.CrossReference; import org.eclipse.xtext.RuleCall; import org.eclipse.xtext.ui.common.editor.codecompletion.AbstractProposalProvider; import org.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider; +import org.eclipse.xtext.ui.common.editor.codecompletion.IContentAssistContext; /** * Represents a generated, default implementation of interface {@link IProposalProvider}. * - * In addition to the declared methods, the framework tries to call grammar dependent methods for assignments using reflection. - * The signature of such methods invoked reflectively follows the following pattern: - * - * public List<ICompletionProposal> complete[Typename][featureName](Assignment ele, EObject model, String prefix) - * - * <b>Example</b> - * Given the following grammar : - * <code> - * RuleA returns MyType : - * "myType" name=ID; - * </code> - * - * One could provide the following method in an implementation of this interface: - * <code> - * public List<ICompletionProposal> completeMyTypeName(Assignment ele, EObject model, String prefix, IDocument doc) {...} - * </code> - * Note that if you have generated Java classes for your domain model (meta model) you can alternatively declare the second parameter using - * a specific type: - * <code> - * public List<ICompletionProposal> completeMyTypeName(Assignment ele, MyType model, String prefix, IDocument doc) {...} - * </code> - * + * @see org.eclipse.xtext.ui.common.editor.codecompletion.IProposalProvider */ public class TreeTestLanguageGenProposalProvider extends AbstractProposalProvider { // constants private static final String UI_PLUGIN_ID = "."; - public List<? extends ICompletionProposal> completeModelChildren(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeModelChildren(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeModelChildren feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } - public List<? extends ICompletionProposal> completeNodeName(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeNodeName(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeNodeName feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"NodeName", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "NodeName", contentAssistContext)); } - public List<? extends ICompletionProposal> completeNodeAttrib(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeNodeAttrib(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeNodeAttrib feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } - return Collections.singletonList(createCompletionProposal(assignment,model,"\"NodeAttrib\"", offset)); + return Collections.singletonList(createCompletionProposal(assignment, "\"NodeAttrib\"", contentAssistContext)); } - public List<? extends ICompletionProposal> completeNodeChildren(Assignment assignment, EObject model, String prefix, IDocument doc,int offset) { + public List<? extends ICompletionProposal> completeNodeChildren(Assignment assignment, IContentAssistContext contentAssistContext) { if (logger.isDebugEnabled()) { logger.debug("completeNodeChildren feature '" + assignment.getFeature() + "' terminal '" + assignment.getTerminal() + "' cardinality '" + assignment.getCardinality() + "' and prefix '" - + prefix.trim() + "'"); + + contentAssistContext.getMatchString().trim() + "'"); } return Collections.emptyList(); } diff --git a/tests/org.eclipse.xtext.ui.common.tests/src/org/eclipse/xtext/ui/common/editor/codecompletion/ContentAssistProcessorTestBuilder.java b/tests/org.eclipse.xtext.ui.common.tests/src/org/eclipse/xtext/ui/common/editor/codecompletion/ContentAssistProcessorTestBuilder.java index 1f6d416..cb1d1bc 100644 --- a/tests/org.eclipse.xtext.ui.common.tests/src/org/eclipse/xtext/ui/common/editor/codecompletion/ContentAssistProcessorTestBuilder.java +++ b/tests/org.eclipse.xtext.ui.common.tests/src/org/eclipse/xtext/ui/common/editor/codecompletion/ContentAssistProcessorTestBuilder.java @@ -27,6 +27,7 @@ import java.util.List; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.resource.ResourceSet; +import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.contentassist.ICompletionProposal; import org.eclipse.jface.text.contentassist.IContentAssistProcessor; @@ -39,6 +40,7 @@ import org.eclipse.xtext.resource.XtextResource; import org.eclipse.xtext.resource.XtextResourceSet; import org.eclipse.xtext.service.IServiceScope; import org.eclipse.xtext.service.ServiceRegistry; +import org.eclipse.xtext.ui.core.editor.XtextSourceViewer; import org.eclipse.xtext.ui.core.editor.model.IXtextDocument; import org.eclipse.xtext.ui.core.editor.model.UnitOfWork; import org.eclipse.xtext.util.StringInputStream; @@ -178,20 +180,31 @@ public class ContentAssistProcessorTestBuilder { return this; } - public ICompletionProposal[] computeCompletionProposals(String currentModelToParse, int cursorPosition) + public ICompletionProposal[] computeCompletionProposals(final String currentModelToParse, int cursorPosition) throws Exception { CompositeNode rootNode = getRootNode(currentModelToParse); org.easymock.EasyMock.reset(textViewerMock, xtextDocumentMock, textViewerMock); - expect(textViewerMock.getDocument()).andReturn(xtextDocumentMock); + //expect(textViewerMock.getDocument()).andReturn(xtextDocumentMock); expect(xtextDocumentMock.readOnly((UnitOfWork<CompositeNode>) anyObject())).andReturn(rootNode); - expect(textViewerMock.getTextWidget()).andReturn(newStyledTextWidgetMock(currentModelToParse)); + //expect(textViewerMock.getTextWidget()).andReturn(newStyledTextWidgetMock(currentModelToParse)); - replay(textViewerMock, xtextDocumentMock); + replay(xtextDocumentMock); ICompletionProposal[] computeCompletionProposals = this.contentAssistProcessor.computeCompletionProposals( - textViewerMock, cursorPosition); + new XtextSourceViewer(null,null,null,false,0) { + @Override + public IDocument getDocument() { + return xtextDocumentMock; + } + + @Override + public StyledText getTextWidget() { + return newStyledTextWidgetMock(currentModelToParse); + } + + }, cursorPosition); return computeCompletionProposals; } |

