diff options
| author | Laurent Fasani | 2018-01-05 17:21:43 +0000 |
|---|---|---|
| committer | Pierre-Charles David | 2018-01-30 16:19:52 +0000 |
| commit | a3393ba4f56b52a4dc6b16f4119b1d84b96ba80c (patch) | |
| tree | 0330479c26212420201f00e51bfef51fc4fd4ce4 | |
| parent | 627b435006fc5793783233f2f1a419dc5c86599d (diff) | |
| download | org.eclipse.sirius-a3393ba4f56b52a4dc6b16f4119b1d84b96ba80c.tar.gz org.eclipse.sirius-a3393ba4f56b52a4dc6b16f4119b1d84b96ba80c.tar.xz org.eclipse.sirius-a3393ba4f56b52a4dc6b16f4119b1d84b96ba80c.zip | |
[484858] Fix completion in aql expression on domain types
* leverage ICompletionResult API to provide the right proposal
* distinguish PROPOSAL_REPLACE and PROPOSAL_INSERT modes in
AQLProposalProvider
* add a test in AcceleoQueryLanguageCompletionTests
Bug:484858
Change-Id: Ic90eb4f8c2170d427c63d07341408e9687b078c1
Signed-off-by: Laurent Fasani <laurent.fasani@obeo.fr>
3 files changed, 121 insertions, 14 deletions
diff --git a/plugins/org.eclipse.sirius.common.acceleo.aql.ide/src/org/eclipse/sirius/common/acceleo/aql/ide/proposal/AQLProposalProvider.java b/plugins/org.eclipse.sirius.common.acceleo.aql.ide/src/org/eclipse/sirius/common/acceleo/aql/ide/proposal/AQLProposalProvider.java index 919f0aeeb8..3efda4cb22 100644 --- a/plugins/org.eclipse.sirius.common.acceleo.aql.ide/src/org/eclipse/sirius/common/acceleo/aql/ide/proposal/AQLProposalProvider.java +++ b/plugins/org.eclipse.sirius.common.acceleo.aql.ide/src/org/eclipse/sirius/common/acceleo/aql/ide/proposal/AQLProposalProvider.java @@ -73,7 +73,8 @@ public class AQLProposalProvider implements IProposalProvider { setupInterpreter(context, aqlInterpreter); Map<String, Set<IType>> variableTypes = TypesUtil.createAQLVariableTypesFromInterpreterContext(context.getInterpreterContext(), aqlInterpreter.getQueryEnvironment()); - return ImmutableList.copyOf(getProposals(trimer, context.getPosition(), aqlInterpreter.getQueryEnvironment(), variableTypes)); + return ImmutableList.copyOf(getProposals(trimer, context.getPosition(), aqlInterpreter.getQueryEnvironment(), variableTypes, + ProposalAcceptanceStyle.PROPOSAL_INSERT)); } } return Collections.<ContentProposal> emptyList(); @@ -98,21 +99,48 @@ public class AQLProposalProvider implements IProposalProvider { } } - private Set<ContentProposal> getProposals(ExpressionTrimmer trimmer, int position, IQueryEnvironment queryEnvironment, Map<String, Set<IType>> variableTypes) { + /** + * Evaluates the content proposals for a given expression and returns the result as a list. + * + * @param trimmer + * the trimmer. + * @param position + * position of the cursor. + * @param queryEnvironment + * the IQueryEnvironment. + * @param variableTypes + * the variable Types. + * @param proposalAcceptanceStyle + * Integer that indicates how an accepted proposal should affect the global string.</br> + * The possible values are ContentProposalAdapter.PROPOSAL_INSERT or + * ContentProposalAdapter.PROPOSAL_REPLACE + * @return content proposal list. + */ + private Set<ContentProposal> getProposals(ExpressionTrimmer trimmer, int position, IQueryEnvironment queryEnvironment, Map<String, Set<IType>> variableTypes, + ProposalAcceptanceStyle proposalAcceptanceStyle) { Set<ContentProposal> proposals = new LinkedHashSet<>(); IQueryCompletionEngine engine = QueryCompletion.newEngine(queryEnvironment); final ICompletionResult completionResult = engine.getCompletion(trimmer.getExpression(), trimmer.getPositionWithinAQL(position), variableTypes); /* * completionResult.sort(new ProposalComparator()); */ - final Set<ICompletionProposal> proposal = Sets.newLinkedHashSet(completionResult.getProposals(QueryCompletion.createBasicFilter(completionResult))); + final Set<ICompletionProposal> aqlProposals = Sets.newLinkedHashSet(completionResult.getProposals(QueryCompletion.createBasicFilter(completionResult))); - for (ICompletionProposal propFromAQL : proposal) { - int offset = position - completionResult.getPrefix().length(); - int length = completionResult.getPrefix().length() + completionResult.getRemaining().length(); - - ContentProposal contentProposal = ContentProposalBuilder.proposal(propFromAQL.getProposal(), propFromAQL.toString(), propFromAQL.getDescription(), propFromAQL.getCursorOffset()) - .withReplacement(offset, length).build(); + for (ICompletionProposal propFromAQL : aqlProposals) { + int offset = trimmer.getPositionInExpression(completionResult.getReplacementOffset()); + String proposal = ""; //$NON-NLS-1$ + ContentProposal contentProposal = null; + if (proposalAcceptanceStyle.equals(ProposalAcceptanceStyle.PROPOSAL_INSERT)) { + // as the TextContentProposalProvider uses the ContentProposalAdapter.PROPOSAL_INSERT style, we remove a + // part of the proposal + proposal = propFromAQL.getProposal().substring(completionResult.getReplacementLength()); + contentProposal = ContentProposalBuilder.proposal(proposal, propFromAQL.toString(), propFromAQL.getDescription(), propFromAQL.getCursorOffset()).build(); + } else if (proposalAcceptanceStyle.equals(ProposalAcceptanceStyle.PROPOSAL_REPLACE)) { + int length = completionResult.getReplacementLength() + completionResult.getRemaining().length(); + proposal = propFromAQL.getProposal(); + contentProposal = ContentProposalBuilder.proposal(proposal, propFromAQL.toString(), propFromAQL.getDescription(), propFromAQL.getCursorOffset()).withReplacement(offset, length) + .build(); + } proposals.add(contentProposal); } return proposals; @@ -133,7 +161,8 @@ public class AQLProposalProvider implements IProposalProvider { ExpressionTrimmer trimer = new ExpressionTrimmer(context.getTextSoFar()); if (trimer.positionIsWithinAQL(context.getCursorPosition())) { - return ImmutableList.copyOf(getProposals(trimer, context.getCursorPosition(), queryEnvironment, variableTypes)); + return ImmutableList.copyOf(getProposals(trimer, context.getCursorPosition(), queryEnvironment, variableTypes, + ProposalAcceptanceStyle.PROPOSAL_REPLACE)); } } diff --git a/plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/api/contentassist/IProposalProvider.java b/plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/api/contentassist/IProposalProvider.java index 3f0007a1bd..0e5d169d3b 100644 --- a/plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/api/contentassist/IProposalProvider.java +++ b/plugins/org.eclipse.sirius.common/src/org/eclipse/sirius/common/tools/api/contentassist/IProposalProvider.java @@ -22,6 +22,29 @@ import org.eclipse.sirius.common.tools.api.interpreter.IInterpreter; public interface IProposalProvider { /** + * Indicates how an accepted proposal should affect the string being completed. These enum corresponds to + * ContentProposalAdapter.PROPOSAL_INSERT and ContentProposalAdapter.PROPOSAL_REPLACE. Default value is + * PROPOSAL_INSERT. + * + * @author lfasani + * + */ + enum ProposalAcceptanceStyle { + + /** + * If the proposal is to be inserted in a string.</br> + * Corresponds to ContentProposalAdapter.PROPOSAL_INSERT + */ + PROPOSAL_INSERT, + + /** + * If the proposal is to be replacing another string in the global string.</br> + * Corresponds to ContentProposalAdapter.PROPOSAL_REPLACE + */ + PROPOSAL_REPLACE + } + + /** * Evaluates the content proposals for a given expression and returns the * result as a list. * diff --git a/plugins/org.eclipse.sirius.tests.junit/src/org/eclipse/sirius/tests/unit/common/interpreter/acceleo/aql/AcceleoQueryLanguageCompletionTests.java b/plugins/org.eclipse.sirius.tests.junit/src/org/eclipse/sirius/tests/unit/common/interpreter/acceleo/aql/AcceleoQueryLanguageCompletionTests.java index 008cf7c131..241e2f179c 100644 --- a/plugins/org.eclipse.sirius.tests.junit/src/org/eclipse/sirius/tests/unit/common/interpreter/acceleo/aql/AcceleoQueryLanguageCompletionTests.java +++ b/plugins/org.eclipse.sirius.tests.junit/src/org/eclipse/sirius/tests/unit/common/interpreter/acceleo/aql/AcceleoQueryLanguageCompletionTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015 Obeo. + * Copyright (c) 2015, 2018 Obeo. * 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 @@ -16,6 +16,7 @@ import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EcoreFactory; import org.eclipse.sirius.common.acceleo.aql.business.internal.AQLSiriusInterpreter; import org.eclipse.sirius.common.acceleo.aql.ide.proposal.AQLProposalProvider; +import org.eclipse.sirius.common.tools.api.contentassist.ContentContext; import org.eclipse.sirius.common.tools.api.contentassist.ContentInstanceContext; import org.eclipse.sirius.common.tools.api.contentassist.ContentProposal; import org.eclipse.sirius.common.tools.api.contentassist.ContentProposalWithReplacement; @@ -83,8 +84,62 @@ public class AcceleoQueryLanguageCompletionTests extends AbstractCompletionTestC } /** - * Test the completion with replacement of a part of the expression after - * the cursor. + * Test the completion with insertion at the end of the expression where the cursor is.</br> + * The inserted string is a part of a method name. + */ + public void testAQLProposalForMethodName_ContentProposal() { + EClass c = EcoreFactory.eINSTANCE.createEClass(); + c.setName("FirstEClass"); + ContentContext contentContext = createContentContext("aql:self.na", "aql:self.na".length(), c, "EClass"); + + List<ContentProposal> proposals = getProposals(contentContext); + + assertEquals(1, proposals.size()); + + ContentProposal proposal = proposals.get(0); + assertEquals("me", proposal.getProposal()); + } + + /** + * Test the completion with replacement of a part of the expression before the cursor.</br> + * The replaced string is a part of a domain type. + */ + public void testAQLProposalWithPreviousReplacementOnDomainType() { + EClass c = EcoreFactory.eINSTANCE.createEClass(); + c.setName("FirstEClass"); + + ContentInstanceContext cic = new ContentInstanceContext(c, "aql:self.eAllContents(ecore::E)", 30); + List<ContentProposal> proposals = this.getProposals(cic); + + assertEquals(53, proposals.size()); + + if (proposals.get(0) instanceof ContentProposalWithReplacement) { + ContentProposalWithReplacement proposalWithReplacement = (ContentProposalWithReplacement) proposals.get(0); + assertEquals("ecore::EAttribute", proposalWithReplacement.getProposal()); + assertEquals(8, proposalWithReplacement.getReplacementLength()); + assertEquals(22, proposalWithReplacement.getReplacementOffset()); + } + } + + /** + * Test the completion with insertion at the end of the expression where the cursor is.</br> + * The inserted string is a part of a domain type. + */ + public void testAQLProposalForDomainType_ContentProposal() { + EClass c = EcoreFactory.eINSTANCE.createEClass(); + ContentContext contentContext = createContentContext("aql:self.eAllContents(ecore::E)", 30, c, ""); + + List<ContentProposal> proposals = getProposals(contentContext); + + assertEquals(53, proposals.size()); + + ContentProposal proposal = proposals.get(0); + assertEquals("Attribute", proposal.getProposal()); + } + + + /** + * Test the completion with replacement of a part of the expression after the cursor. */ public void testAQLWithAfterReplacement() { EClass c = EcoreFactory.eINSTANCE.createEClass(); @@ -112,7 +167,7 @@ public class AcceleoQueryLanguageCompletionTests extends AbstractCompletionTestC EClass c = EcoreFactory.eINSTANCE.createEClass(); c.setName("FirstEClass"); - ContentInstanceContext cic = new ContentInstanceContext(c, "aql:self.nam", 11); + ContentInstanceContext cic = new ContentInstanceContext(c, "aql:self.nam", "aql:self.na".length()); List<ContentProposal> proposals = this.getProposals(cic); assertEquals(1, proposals.size()); |
