From f2738e0936e3ad197749460a18da65cdcdf1d8e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Sp=C3=B6nemann?= Date: Thu, 12 Nov 2015 18:36:48 +0100 Subject: [PATCH] [web] Extended hover service so it can compute hovers for selected content assist entries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miro Spönemann --- .../contentassist/ContentAssistEntry.xtend | 6 +++ .../IdeContentProposalProvider.xtend | 46 ++++++++++++------- .../IdeCrossrefProposalProvider.xtend | 4 ++ .../xtext/ide/labels/INameLabelProvider.xtend | 2 +- 4 files changed, 40 insertions(+), 18 deletions(-) diff --git a/plugins/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/editor/contentassist/ContentAssistEntry.xtend b/plugins/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/editor/contentassist/ContentAssistEntry.xtend index a59ffcb9c..b003af7a9 100644 --- a/plugins/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/editor/contentassist/ContentAssistEntry.xtend +++ b/plugins/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/editor/contentassist/ContentAssistEntry.xtend @@ -64,4 +64,10 @@ class ContentAssistEntry { */ val editPositions = new ArrayList + /** + * The EObject or IEObjectDescription for which this entry has been created, if any. + * This field is not serialized when the entry is sent over a communication channel. + */ + transient Object source + } \ No newline at end of file diff --git a/plugins/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/editor/contentassist/IdeContentProposalProvider.xtend b/plugins/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/editor/contentassist/IdeContentProposalProvider.xtend index 3f8cf4bef..87d9441da 100644 --- a/plugins/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/editor/contentassist/IdeContentProposalProvider.xtend +++ b/plugins/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/editor/contentassist/IdeContentProposalProvider.xtend @@ -7,9 +7,10 @@ *******************************************************************************/ package org.eclipse.xtext.ide.editor.contentassist +import com.google.common.base.Predicate import com.google.common.base.Predicates import com.google.inject.Inject -import java.util.List +import java.util.Collection import org.eclipse.emf.ecore.EClass import org.eclipse.xtend.lib.annotations.Accessors import org.eclipse.xtext.AbstractElement @@ -19,9 +20,8 @@ import org.eclipse.xtext.GrammarUtil import org.eclipse.xtext.Keyword import org.eclipse.xtext.RuleCall import org.eclipse.xtext.TerminalRule -import org.eclipse.xtext.ide.editor.contentassist.ContentAssistContext -import org.eclipse.xtext.ide.editor.contentassist.ContentAssistEntry import org.eclipse.xtext.naming.IQualifiedNameConverter +import org.eclipse.xtext.resource.IEObjectDescription import org.eclipse.xtext.scoping.IScopeProvider import org.eclipse.xtext.util.TextRegion import org.eclipse.xtext.xtext.CurrentTypeFinder @@ -51,7 +51,18 @@ class IdeContentProposalProvider { /** * Create content assist proposals and pass them to the given acceptor. */ - def void createProposals(List contexts, IIdeContentProposalAcceptor acceptor) { + def void createProposals(Collection contexts, IIdeContentProposalAcceptor acceptor) { + for (context : getFilteredContexts(contexts)) { + for (element : context.firstSetGrammarElements) { + if (!acceptor.canAcceptMoreProposals) { + return + } + createProposals(element, context, acceptor) + } + } + } + + protected def Iterable getFilteredContexts(Collection contexts) { var ContentAssistContext selectedContext for (context : contexts) { if (selectedContext === null || context.acceptable @@ -59,16 +70,11 @@ class IdeContentProposalProvider { selectedContext = context } } - for (context : contexts) { - if (context === selectedContext || context.prefix == selectedContext.prefix && context.acceptable) { - for (element : context.firstSetGrammarElements) { - if (!acceptor.canAcceptMoreProposals) { - return - } - createProposals(element, context, acceptor) - } - } - } + val finalSelectedContext = selectedContext + return contexts.filter[ context | + context === finalSelectedContext + || context.prefix == finalSelectedContext.prefix && context.acceptable + ] } protected def isAcceptable(ContentAssistContext context) { @@ -85,7 +91,7 @@ class IdeContentProposalProvider { IIdeContentProposalAcceptor acceptor) { val terminal = assignment.terminal if (terminal instanceof CrossReference) { - createProposals(assignment.terminal, context, acceptor) + createProposals(terminal, context, acceptor) } else if (terminal instanceof RuleCall) { val rule = terminal.rule if (rule instanceof TerminalRule && context.prefix.empty) { @@ -116,7 +122,7 @@ class IdeContentProposalProvider { } } - protected def filterKeyword(Keyword keyword, ContentAssistContext context) { + protected def boolean filterKeyword(Keyword keyword, ContentAssistContext context) { keyword.value.regionMatches(true, 0, context.prefix, 0, context.prefix.length) && keyword.value.length > context.prefix.length } @@ -133,9 +139,15 @@ class IdeContentProposalProvider { val ereference = GrammarUtil.getReference(reference, type) if (ereference !== null) { val scope = scopeProvider.getScope(context.currentModel, ereference) - crossrefProposalProvider.lookupCrossReference(scope, reference, context, acceptor, Predicates.alwaysTrue) + crossrefProposalProvider.lookupCrossReference(scope, reference, context, acceptor, + getCrossrefFilter(reference, context)) } } } + protected def Predicate getCrossrefFilter(CrossReference reference, + ContentAssistContext context) { + Predicates.alwaysTrue + } + } diff --git a/plugins/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/editor/contentassist/IdeCrossrefProposalProvider.xtend b/plugins/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/editor/contentassist/IdeCrossrefProposalProvider.xtend index d24444432..da00869ee 100644 --- a/plugins/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/editor/contentassist/IdeCrossrefProposalProvider.xtend +++ b/plugins/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/editor/contentassist/IdeCrossrefProposalProvider.xtend @@ -36,6 +36,9 @@ class IdeCrossrefProposalProvider { IIdeContentProposalAcceptor acceptor, Predicate filter) { try { for (candidate : queryScope(scope, crossReference, context)) { + if (!acceptor.canAcceptMoreProposals) { + return + } if (filter.apply(candidate)) { val entry = createProposal(candidate, crossReference, context) acceptor.accept(entry, proposalPriorities.getCrossRefPriority(candidate, entry)) @@ -72,6 +75,7 @@ class IdeCrossrefProposalProvider { protected def ContentAssistEntry createProposal(IEObjectDescription candidate, CrossReference crossRef, ContentAssistContext context) { return new ContentAssistEntry => [ + source = candidate prefix = context.prefix proposal = qualifiedNameConverter.toString(candidate.name) description = candidate.getEClass?.name diff --git a/plugins/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/labels/INameLabelProvider.xtend b/plugins/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/labels/INameLabelProvider.xtend index adba314eb..ab04f54d4 100644 --- a/plugins/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/labels/INameLabelProvider.xtend +++ b/plugins/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/labels/INameLabelProvider.xtend @@ -28,7 +28,7 @@ class SimpleNameLabelProvider implements INameLabelProvider { SimpleAttributeResolver.NAME_RESOLVER.apply(element) IEObjectDescription: element.name.lastSegment - default: + default: null } }