Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMickael Istria2017-09-13 16:51:46 +0000
committerMickael Istria2017-09-24 20:24:25 +0000
commitd9b4c1b5fa395ecc797e2b66c23885ca6e88f31d (patch)
tree371a3f8f50c588ff4e0dc13c469b936841d033ac
parenta094046b191efc72bef93d227499cb75bc532e87 (diff)
downloadeclipse.platform.text-d9b4c1b5fa395ecc797e2b66c23885ca6e88f31d.tar.gz
eclipse.platform.text-d9b4c1b5fa395ecc797e2b66c23885ca6e88f31d.tar.xz
eclipse.platform.text-d9b4c1b5fa395ecc797e2b66c23885ca6e88f31d.zip
Bug 522255 - Filter/restart completion session only uses 1st processorI20170927-2000I20170927-0420I20170926-2000I20170925-2000
Change-Id: Ie5697da68555f80569c870c6d54ea7f0ec94370a Signed-off-by: Mickael Istria <mistria@redhat.com>
-rw-r--r--org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/ContentAssistant.java196
-rw-r--r--org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/CompletionTest.java102
-rw-r--r--org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/contributions/BarContentAssistProcessor.java28
-rw-r--r--org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/contributions/LongRunningBarContentAssistProcessor.java46
4 files changed, 219 insertions, 153 deletions
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/ContentAssistant.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/ContentAssistant.java
index 72c62e98716..838eba116f1 100644
--- a/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/ContentAssistant.java
+++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/contentassist/ContentAssistant.java
@@ -15,11 +15,17 @@
*******************************************************************************/
package org.eclipse.jface.text.contentassist;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
+import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
+import java.util.function.Function;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTError;
@@ -1909,16 +1915,16 @@ public class ContentAssistant implements IContentAssistant, IContentAssistantExt
*
* @param viewer the text viewer
* @param offset a offset within the document
- * @return a content-assist processor or <code>null</code> if none exists
- * @since 3.0
+ * @return the content-assist processors or <code>null</code> if none exists
+ * @since 3.13
*/
- private IContentAssistProcessor getProcessor(ITextViewer viewer, int offset) {
+ private Set<IContentAssistProcessor> getProcessors(ITextViewer viewer, int offset) {
try {
IDocument document= viewer.getDocument();
String type= TextUtilities.getContentType(document, getDocumentPartitioning(), offset, true);
- return getContentAssistProcessor(type);
+ return getContentAssistProcessors(type);
} catch (BadLocationException x) {
}
@@ -1927,14 +1933,14 @@ public class ContentAssistant implements IContentAssistant, IContentAssistantExt
}
/**
- * Returns the content assist processor for the content type of the specified document position.
+ * Returns the content assist processors for the content type of the specified document position.
*
* @param contentAssistSubjectControl the content assist subject control
* @param offset a offset within the document
- * @return a content-assist processor or <code>null</code> if none exists
- * @since 3.0
+ * @return the content-assist processors or <code>null</code> if none exists
+ * @since 3.13
*/
- private IContentAssistProcessor getProcessor(IContentAssistSubjectControl contentAssistSubjectControl, int offset) {
+ private Set<IContentAssistProcessor> getProcessors(IContentAssistSubjectControl contentAssistSubjectControl, int offset) {
try {
IDocument document= contentAssistSubjectControl.getDocument();
@@ -1944,7 +1950,7 @@ public class ContentAssistant implements IContentAssistant, IContentAssistantExt
else
type= IDocument.DEFAULT_CONTENT_TYPE;
- return getContentAssistProcessor(type);
+ return getContentAssistProcessors(type);
} catch (BadLocationException x) {
}
@@ -1966,22 +1972,25 @@ public class ContentAssistant implements IContentAssistant, IContentAssistantExt
final IContentAssistSubjectControl contentAssistSubjectControl, final int offset) {
fLastErrorMessage= null;
- final ICompletionProposal[][] result= { null };
-
- final IContentAssistProcessor p= getProcessor(contentAssistSubjectControl, offset);
- if (p instanceof ISubjectControlContentAssistProcessor) {
- // Ensure that the assist session ends cleanly even if the processor throws an exception.
- SafeRunner.run(new ExceptionLoggingSafeRunnable(COMPLETION_ERROR_MESSAGE_KEY) {
- @Override
- public void run() throws Exception {
- result[0]= ((ISubjectControlContentAssistProcessor) p)
- .computeCompletionProposals(contentAssistSubjectControl, offset);
- fLastErrorMessage= p.getErrorMessage();
+ final List<ICompletionProposal> result= new ArrayList<>();
+ final Set<IContentAssistProcessor> processors= getProcessors(contentAssistSubjectControl, offset);
+ if (processors != null) {
+ processors.forEach(p -> {
+ if (p instanceof ISubjectControlContentAssistProcessor) {
+ // Ensure that the assist session ends cleanly even if the processor throws an exception.
+ SafeRunner.run(new ExceptionLoggingSafeRunnable(COMPLETION_ERROR_MESSAGE_KEY) {
+ @Override
+ public void run() throws Exception {
+ result.addAll(Arrays.asList( ((ISubjectControlContentAssistProcessor) p)
+ .computeCompletionProposals(contentAssistSubjectControl, offset)));
+ fLastErrorMessage= p.getErrorMessage();
+ }
+ });
}
});
}
- return result[0];
+ return result.isEmpty() ? null : result.toArray(new ICompletionProposal[result.size()]);
}
/**
@@ -1996,21 +2005,22 @@ public class ContentAssistant implements IContentAssistant, IContentAssistantExt
ICompletionProposal[] computeCompletionProposals(final ITextViewer viewer, final int offset) {
fLastErrorMessage= null;
- final ICompletionProposal[][] result= { null };
-
- final IContentAssistProcessor p= getProcessor(viewer, offset);
- if (p != null) {
+ final Set<IContentAssistProcessor> processors= getProcessors(viewer, offset);
+ final List<ICompletionProposal> res = new ArrayList<>();
+ if (processors != null && !processors.isEmpty()) {
// Ensure that the assist session ends cleanly even if the processor throws an exception.
SafeRunner.run(new ExceptionLoggingSafeRunnable(COMPLETION_ERROR_MESSAGE_KEY) {
@Override
public void run() throws Exception {
- result[0]= p.computeCompletionProposals(viewer, offset);
- fLastErrorMessage= p.getErrorMessage();
+ processors.forEach(p -> {
+ res.addAll(Arrays.asList(p.computeCompletionProposals(viewer, offset)));
+ fLastErrorMessage= p.getErrorMessage();
+ });
}
});
}
- return result[0];
+ return res.isEmpty() ? null : res.toArray(new ICompletionProposal[res.size()]);
}
/**
@@ -2026,21 +2036,22 @@ public class ContentAssistant implements IContentAssistant, IContentAssistantExt
IContextInformation[] computeContextInformation(final ITextViewer viewer, final int offset) {
fLastErrorMessage= null;
- final IContextInformation[][] result= { null };
-
- final IContentAssistProcessor p= getProcessor(viewer, offset);
- if (p != null) {
+ final List<IContextInformation> result= new ArrayList<>();
+ final Set<IContentAssistProcessor> processors= getProcessors(viewer, offset);
+ if (processors != null && !processors.isEmpty()) {
// Ensure that the assist session ends cleanly even if the processor throws an exception.
SafeRunner.run(new ExceptionLoggingSafeRunnable(CONTEXT_ERROR_MESSAGE_KEY) {
@Override
public void run() throws Exception {
- result[0]= p.computeContextInformation(viewer, offset);
- fLastErrorMessage= p.getErrorMessage();
+ processors.forEach(p -> {
+ result.addAll(Arrays.asList(p.computeContextInformation(viewer, offset)));
+ fLastErrorMessage= p.getErrorMessage();
+ });
}
});
}
- return result[0];
+ return result.isEmpty() ? null : result.toArray(new IContextInformation[result.size()]);
}
/**
@@ -2058,22 +2069,25 @@ public class ContentAssistant implements IContentAssistant, IContentAssistantExt
final IContentAssistSubjectControl contentAssistSubjectControl, final int offset) {
fLastErrorMessage= null;
- final IContextInformation[][] result= { null };
-
- final IContentAssistProcessor p= getProcessor(contentAssistSubjectControl, offset);
- if (p instanceof ISubjectControlContentAssistProcessor) {
- // Ensure that the assist session ends cleanly even if the processor throws an exception.
- SafeRunner.run(new ExceptionLoggingSafeRunnable(CONTEXT_ERROR_MESSAGE_KEY) {
- @Override
- public void run() throws Exception {
- result[0]= ((ISubjectControlContentAssistProcessor) p)
- .computeContextInformation(contentAssistSubjectControl, offset);
- fLastErrorMessage= p.getErrorMessage();
+ final List<IContextInformation> result= new ArrayList<>();
+ final Set<IContentAssistProcessor> processors = getProcessors(contentAssistSubjectControl, offset);
+ if (processors != null) {
+ processors.forEach(p -> {
+ if (p instanceof ISubjectControlContentAssistProcessor) {
+ // Ensure that the assist session ends cleanly even if the processor throws an exception.
+ SafeRunner.run(new ExceptionLoggingSafeRunnable(CONTEXT_ERROR_MESSAGE_KEY) {
+ @Override
+ public void run() throws Exception {
+ result.addAll(Arrays.asList( ((ISubjectControlContentAssistProcessor) p)
+ .computeContextInformation(contentAssistSubjectControl, offset)));
+ fLastErrorMessage= p.getErrorMessage();
+ }
+ });
}
});
}
- return result[0];
+ return result.isEmpty() ? null : result.toArray(new IContextInformation[result.size()]);
}
/**
@@ -2088,7 +2102,12 @@ public class ContentAssistant implements IContentAssistant, IContentAssistantExt
* @since 3.0
*/
IContextInformationValidator getContextInformationValidator(ITextViewer viewer, int offset) {
- IContentAssistProcessor p= getProcessor(viewer, offset);
+ Set<IContentAssistProcessor> processors= getProcessors(viewer, offset);
+ if (processors == null || processors.isEmpty()) {
+ return null;
+ }
+ // pick first one, arbitrary
+ IContentAssistProcessor p = processors.iterator().next();
return p != null ? p.getContextInformationValidator() : null;
}
@@ -2104,7 +2123,12 @@ public class ContentAssistant implements IContentAssistant, IContentAssistantExt
* @since 3.0
*/
IContextInformationValidator getContextInformationValidator(IContentAssistSubjectControl contentAssistSubjectControl, int offset) {
- IContentAssistProcessor p= getProcessor(contentAssistSubjectControl, offset);
+ Set<IContentAssistProcessor> processors= getProcessors(contentAssistSubjectControl, offset);
+ if (processors == null || processors.isEmpty()) {
+ return null;
+ }
+ // pick first one, arbitrary
+ IContentAssistProcessor p = processors.iterator().next();
return p != null ? p.getContextInformationValidator() : null;
}
@@ -2152,8 +2176,7 @@ public class ContentAssistant implements IContentAssistant, IContentAssistantExt
* @since 3.0
*/
char[] getCompletionProposalAutoActivationCharacters(IContentAssistSubjectControl contentAssistSubjectControl, int offset) {
- IContentAssistProcessor p= getProcessor(contentAssistSubjectControl, offset);
- return p != null ? p.getCompletionProposalAutoActivationCharacters() : null;
+ return mergeResults(getProcessors(contentAssistSubjectControl, offset), IContentAssistProcessor::getCompletionProposalAutoActivationCharacters);
}
/**
@@ -2167,8 +2190,7 @@ public class ContentAssistant implements IContentAssistant, IContentAssistantExt
* @see IContentAssistProcessor#getCompletionProposalAutoActivationCharacters()
*/
char[] getCompletionProposalAutoActivationCharacters(ITextViewer viewer, int offset) {
- IContentAssistProcessor p= getProcessor(viewer, offset);
- return p != null ? p.getCompletionProposalAutoActivationCharacters() : null;
+ return mergeResults(getProcessors(viewer, offset), IContentAssistProcessor::getCompletionProposalAutoActivationCharacters);
}
/**
@@ -2183,8 +2205,7 @@ public class ContentAssistant implements IContentAssistant, IContentAssistantExt
* @since 3.0
*/
char[] getContextInformationAutoActivationCharacters(ITextViewer viewer, int offset) {
- IContentAssistProcessor p= getProcessor(viewer, offset);
- return p != null ? p.getContextInformationAutoActivationCharacters() : null;
+ return mergeResults(getProcessors(viewer, offset), IContentAssistProcessor::getContextInformationAutoActivationCharacters);
}
/**
@@ -2199,8 +2220,34 @@ public class ContentAssistant implements IContentAssistant, IContentAssistantExt
* @since 3.0
*/
char[] getContextInformationAutoActivationCharacters(IContentAssistSubjectControl contentAssistSubjectControl, int offset) {
- IContentAssistProcessor p= getProcessor(contentAssistSubjectControl, offset);
- return p != null ? p.getContextInformationAutoActivationCharacters() : null;
+ return mergeResults(getProcessors(contentAssistSubjectControl, offset), IContentAssistProcessor::getContextInformationAutoActivationCharacters);
+ }
+
+ private char[] mergeResults(Collection<IContentAssistProcessor> processors, Function<IContentAssistProcessor, char[]> f) {
+ char[][] arrays = processors.stream()
+ .map(f)
+ .filter(Objects::nonNull)
+ .filter(array -> array.length > 0)
+ .toArray(char[][]::new);
+ if (arrays.length == 0) {
+ return null;
+ } else if (arrays.length == 1) {
+ return arrays[0];
+ } else {
+ LinkedHashSet<Character> res = new LinkedHashSet<>();
+ for (char[] current : arrays) {
+ for (char c : current) {
+ res.add(Character.valueOf(c));
+ }
+ }
+ char[] array = new char[res.size()];
+ int index = 0;
+ for (Character c : res) {
+ array[index] = c.charValue();
+ index++;
+ }
+ return array;
+ }
}
@Override
@@ -2443,11 +2490,12 @@ public class ContentAssistant implements IContentAssistant, IContentAssistantExt
*/
void fireSessionBeginEvent(boolean isAutoActivated) {
if (fContentAssistSubjectControlAdapter != null && !isProposalPopupActive()) {
- IContentAssistProcessor processor= getProcessor(fContentAssistSubjectControlAdapter, fContentAssistSubjectControlAdapter.getSelectedRange().x);
- ContentAssistEvent event= new ContentAssistEvent(this, processor, isAutoActivated);
- for (ICompletionListener listener : fCompletionListeners) {
- listener.assistSessionStarted(event);
- }
+ getProcessors(fContentAssistSubjectControlAdapter, fContentAssistSubjectControlAdapter.getSelectedRange().x).forEach(processor -> {
+ ContentAssistEvent event= new ContentAssistEvent(this, processor, isAutoActivated);
+ for (ICompletionListener listener : fCompletionListeners) {
+ listener.assistSessionStarted(event);
+ }
+ });
}
}
@@ -2458,12 +2506,13 @@ public class ContentAssistant implements IContentAssistant, IContentAssistantExt
*/
void fireSessionRestartEvent() {
if (fContentAssistSubjectControlAdapter != null) {
- IContentAssistProcessor processor= getProcessor(fContentAssistSubjectControlAdapter, fContentAssistSubjectControlAdapter.getSelectedRange().x);
- ContentAssistEvent event= new ContentAssistEvent(this, processor);
- for (ICompletionListener listener : fCompletionListeners) {
- if (listener instanceof ICompletionListenerExtension)
- ((ICompletionListenerExtension)listener).assistSessionRestarted(event);
- }
+ getProcessors(fContentAssistSubjectControlAdapter, fContentAssistSubjectControlAdapter.getSelectedRange().x).forEach(processor -> {
+ ContentAssistEvent event= new ContentAssistEvent(this, processor);
+ for (ICompletionListener listener : fCompletionListeners) {
+ if (listener instanceof ICompletionListenerExtension)
+ ((ICompletionListenerExtension)listener).assistSessionRestarted(event);
+ }
+ });
}
}
@@ -2474,11 +2523,12 @@ public class ContentAssistant implements IContentAssistant, IContentAssistantExt
*/
void fireSessionEndEvent() {
if (fContentAssistSubjectControlAdapter != null) {
- IContentAssistProcessor processor= getProcessor(fContentAssistSubjectControlAdapter, fContentAssistSubjectControlAdapter.getSelectedRange().x);
- ContentAssistEvent event= new ContentAssistEvent(this, processor);
- for (ICompletionListener listener : fCompletionListeners) {
- listener.assistSessionEnded(event);
- }
+ getProcessors(fContentAssistSubjectControlAdapter, fContentAssistSubjectControlAdapter.getSelectedRange().x).forEach(processor -> {
+ ContentAssistEvent event= new ContentAssistEvent(this, processor);
+ for (ICompletionListener listener : fCompletionListeners) {
+ listener.assistSessionEnded(event);
+ }
+ });
}
}
diff --git a/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/CompletionTest.java b/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/CompletionTest.java
index 7ed46a86486..31b0543957f 100644
--- a/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/CompletionTest.java
+++ b/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/CompletionTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2016 Red Hat Inc. and others
+ * Copyright (c) 2016-2017 Red Hat Inc. 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
@@ -14,9 +14,10 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.Arrays;
-import java.util.HashSet;
import java.util.Set;
+import java.util.stream.Collectors;
+import org.junit.After;
import org.junit.Test;
import org.eclipse.swt.SWT;
@@ -24,13 +25,13 @@ import org.eclipse.swt.custom.ST;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Widget;
+import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.tests.util.DisplayHelper;
@@ -45,65 +46,78 @@ import org.eclipse.ui.texteditor.ITextEditorActionConstants;
*/
public class CompletionTest extends AbstratGenericEditorTest {
+ private Shell completionShell;
+
@Test
public void testCompletion() throws Exception {
- Set<Shell> beforeShell = new HashSet<>(Arrays.asList(Display.getDefault().getShells()));
+ final Set<Shell> beforeShells = Arrays.stream(editor.getSite().getShell().getDisplay().getShells()).filter(Shell::isVisible).collect(Collectors.toSet());
editor.selectAndReveal(3, 0);
ContentAssistAction action = (ContentAssistAction) editor.getAction(ITextEditorActionConstants.CONTENT_ASSIST);
action.update();
action.run();
waitAndDispatch(100);
- Set<Shell> afterShell = new HashSet<>(Arrays.asList(Display.getDefault().getShells()));
- afterShell.removeAll(beforeShell);
- assertEquals("No completion", 1, afterShell.size());
- Shell completionShell= afterShell.iterator().next();
+ this.completionShell= findNewShell(beforeShells);
final Table completionProposalList = findCompletionSelectionControl(completionShell);
+ checkCompletionContent(completionProposalList);
+ // TODO find a way to actually trigger completion and verify result against Editor content
+ // Assert.assertEquals("Completion didn't complete", "bars are good for a beer.", ((StyledText)editor.getAdapter(Control.class)).getText());
+ }
+
+ /**
+ * Checks that completion behaves as expected:
+ * 1. Computing is shown instantaneously
+ * 2. 1st proposal shown instantaneously
+ * 3. 2s later, 2nd proposal is shown
+ * @param completionProposalList the completion list
+ */
+ private void checkCompletionContent(final Table completionProposalList) {
// should be instantaneous, but happens to go asynchronous on CI so let's allow a wait
new DisplayHelper() {
@Override
protected boolean condition() {
return completionProposalList.getItemCount() == 2;
}
- }.waitForCondition(completionShell.getDisplay(), 200);
+ }.waitForCondition(completionProposalList.getDisplay(), 200);
assertEquals(2, completionProposalList.getItemCount());
final TableItem computingItem = completionProposalList.getItem(0);
assertTrue("Missing computing info entry", computingItem.getText().contains("Computing")); //$NON-NLS-1$ //$NON-NLS-2$
TableItem completionProposalItem = completionProposalList.getItem(1);
- ICompletionProposal completionProposal = (ICompletionProposal)completionProposalItem.getData();
- assertEquals(BarContentAssistProcessor.PROPOSAL, completionProposal .getDisplayString());
+ final ICompletionProposal selectedProposal = (ICompletionProposal)completionProposalItem.getData();
+ assertTrue("Incorrect proposal content", BarContentAssistProcessor.PROPOSAL.endsWith(selectedProposal .getDisplayString()));
completionProposalList.setSelection(completionProposalItem);
// asynchronous
new DisplayHelper() {
@Override
protected boolean condition() {
- return completionProposalList.getItem(0) != computingItem;
+ return completionProposalList.getItem(0) != computingItem && completionProposalList.getItemCount() == 2;
}
- }.waitForCondition(completionShell.getDisplay(), LongRunningBarContentAssistProcessor.DELAY + 200);
- assertEquals(2, completionProposalList.getItemCount());
+ }.waitForCondition(completionProposalList.getDisplay(), LongRunningBarContentAssistProcessor.DELAY + 200);
completionProposalItem = completionProposalList.getItem(0);
- assertEquals(BarContentAssistProcessor.PROPOSAL, ((ICompletionProposal)completionProposalItem.getData()).getDisplayString());
+ assertTrue("Proposal content seems incorrect", BarContentAssistProcessor.PROPOSAL.endsWith(((ICompletionProposal)completionProposalItem.getData()).getDisplayString()));
TableItem otherProposalItem = completionProposalList.getItem(1);
- assertEquals(LongRunningBarContentAssistProcessor.PROPOSAL, ((ICompletionProposal)otherProposalItem.getData()).getDisplayString());
- assertEquals("Addition of completion proposal should keep selection", completionProposal, completionProposalList.getSelection()[0].getData());
+ assertTrue("Proposal content seems incorrect", LongRunningBarContentAssistProcessor.PROPOSAL.endsWith(((ICompletionProposal)otherProposalItem.getData()).getDisplayString()));
+ assertEquals("Addition of completion proposal should keep selection", selectedProposal, completionProposalList.getSelection()[0].getData());
+ }
- // TODO find a way to actually trigger completion and verify result against Editor content
- // Assert.assertEquals("Completion didn't complete", "bars are good for a beer.", ((StyledText)editor.getAdapter(Control.class)).getText());
- completionShell.close();
+ private Shell findNewShell(Set<Shell> beforeShells) {
+ Shell[] afterShells = Arrays.stream(editor.getSite().getShell().getDisplay().getShells())
+ .filter(Shell::isVisible)
+ .filter(shell -> !beforeShells.contains(shell))
+ .toArray(Shell[]::new);
+ assertEquals("No new shell found", 1, afterShells.length);
+ return afterShells[0];
}
@Test
public void testCompletionFreeze_bug521484() throws Exception {
- Set<Shell> beforeShell = new HashSet<>(Arrays.asList(Display.getDefault().getShells()));
+ final Set<Shell> beforeShells = Arrays.stream(editor.getSite().getShell().getDisplay().getShells()).filter(Shell::isVisible).collect(Collectors.toSet());
editor.selectAndReveal(3, 0);
ContentAssistAction action = (ContentAssistAction) editor.getAction(ITextEditorActionConstants.CONTENT_ASSIST);
action.update();
action.run();
waitAndDispatch(100);
- Set<Shell> afterShell = new HashSet<>(Arrays.asList(Display.getDefault().getShells()));
- afterShell.removeAll(beforeShell);
- assertEquals("No completion", 1, afterShell.size());
- Shell completionShell= afterShell.iterator().next();
- final Table completionProposalList = findCompletionSelectionControl(completionShell);
+ this.completionShell= findNewShell(beforeShells);
+ final Table completionProposalList = findCompletionSelectionControl(this.completionShell);
// should be instantaneous, but happens to go asynchronous on CI so let's allow a wait
new DisplayHelper() {
@Override
@@ -116,22 +130,34 @@ public class CompletionTest extends AbstratGenericEditorTest {
assertTrue("Missing computing info entry", computingItem.getText().contains("Computing")); //$NON-NLS-1$ //$NON-NLS-2$
// Some processors are long running, moving cursor can cause freeze (bug 521484)
// asynchronous
+ long timestamp = System.currentTimeMillis();
+ emulatePressLeftArrowKey();
+ DisplayHelper.sleep(editor.getSite().getShell().getDisplay(), 200); //give time to process events
+ long processingDuration = System.currentTimeMillis() - timestamp;
+ assertTrue("UI Thread frozen for " + processingDuration + "ms", processingDuration < LongRunningBarContentAssistProcessor.DELAY);
+ }
+
+ @Test
+ public void testMoveCaretBackUsesAllProcessors_bug522255() throws Exception {
+ final Set<Shell> beforeShells = Arrays.stream(editor.getSite().getShell().getDisplay().getShells()).filter(Shell::isVisible).collect(Collectors.toSet());
+ testCompletion();
+ emulatePressLeftArrowKey();
+ DisplayHelper.sleep(editor.getSite().getShell().getDisplay(), LongRunningBarContentAssistProcessor.DELAY + 500); // adding delay is a workaround for bug521484, use only 100ms without the bug
+ this.completionShell= findNewShell(beforeShells);
+ final Table completionProposalList = findCompletionSelectionControl(this.completionShell);
+ assertEquals("Missing proposals from a Processor", 2, completionProposalList.getItemCount()); // replace with line below when #5214894 is done
+ // checkCompletionContent(completionProposalList); // use this instead of assert above when #521484 is done
+ }
+
+ private void emulatePressLeftArrowKey() {
+ editor.selectAndReveal(((ITextSelection)editor.getSelectionProvider().getSelection()).getOffset() - 1, 0);
StyledText styledText = (StyledText) editor.getAdapter(Control.class);
- styledText.setSelection(styledText.getSelectionRange().x - 1);
Event e = new Event();
e.type = ST.VerifyKey;
e.widget = styledText;
e.keyCode = SWT.ARROW_LEFT;
e.display = styledText.getDisplay();
- long timestamp = System.currentTimeMillis();
styledText.notifyListeners(ST.VerifyKey, e);
- DisplayHelper.sleep(styledText.getDisplay(), 200); //give time to process events
- long processingDuration = System.currentTimeMillis() - timestamp;
- assertTrue("UI Thread frozen for " + processingDuration + "ms", processingDuration < LongRunningBarContentAssistProcessor.DELAY);
-
- if (!completionShell.isDisposed()) {
- completionShell.close();
- }
}
private Table findCompletionSelectionControl(Widget control) {
@@ -148,4 +174,10 @@ public class CompletionTest extends AbstratGenericEditorTest {
return null;
}
+ @After
+ public void closeShell() {
+ if (this.completionShell != null && !completionShell.isDisposed()) {
+ completionShell.close();
+ }
+ }
}
diff --git a/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/contributions/BarContentAssistProcessor.java b/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/contributions/BarContentAssistProcessor.java
index 745f42dc3bf..f53da979686 100644
--- a/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/contributions/BarContentAssistProcessor.java
+++ b/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/contributions/BarContentAssistProcessor.java
@@ -10,6 +10,7 @@
*******************************************************************************/
package org.eclipse.ui.genericeditor.tests.contributions;
+import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.contentassist.CompletionProposal;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
@@ -19,15 +20,30 @@ import org.eclipse.jface.text.contentassist.IContextInformationValidator;
public class BarContentAssistProcessor implements IContentAssistProcessor {
- public static final String PROPOSAL = "s are good for a beer.";
+ public static final String PROPOSAL = "bars are good for a beer.";
+ private final String completeString;
+
+ public BarContentAssistProcessor() {
+ this(PROPOSAL);
+ }
+
+ public BarContentAssistProcessor(String completeString) {
+ this.completeString = completeString;
+ }
@Override
public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
- String text = viewer.getDocument().get();
- if (text.length() >= 3 && offset >= 3 && text.substring(offset - 3, offset).equals("bar")) {
- String message = PROPOSAL;
- CompletionProposal proposal = new CompletionProposal(message, offset, 0, message.length());
- return new ICompletionProposal[] { proposal };
+ for (int offsetInProposal = Math.min(this.completeString.length(), viewer.getDocument().getLength()); offsetInProposal > 0; offsetInProposal--) {
+ String maybeMatchingString = this.completeString.substring(0, offsetInProposal);
+ try {
+ int lastIndex = offset - offsetInProposal + this.completeString.length();
+ if (offset >= offsetInProposal && viewer.getDocument().get(offset - offsetInProposal, maybeMatchingString.length()).equals(maybeMatchingString)) {
+ CompletionProposal proposal = new CompletionProposal(this.completeString.substring(offsetInProposal), offset, 0, lastIndex);
+ return new ICompletionProposal[] { proposal };
+ }
+ } catch (BadLocationException e) {
+ e.printStackTrace();
+ }
}
return new ICompletionProposal[0];
}
diff --git a/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/contributions/LongRunningBarContentAssistProcessor.java b/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/contributions/LongRunningBarContentAssistProcessor.java
index 6f504d78053..ce0dc48cf41 100644
--- a/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/contributions/LongRunningBarContentAssistProcessor.java
+++ b/org.eclipse.ui.genericeditor.tests/src/org/eclipse/ui/genericeditor/tests/contributions/LongRunningBarContentAssistProcessor.java
@@ -11,17 +11,17 @@
package org.eclipse.ui.genericeditor.tests.contributions;
import org.eclipse.jface.text.ITextViewer;
-import org.eclipse.jface.text.contentassist.CompletionProposal;
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;
-public class LongRunningBarContentAssistProcessor implements IContentAssistProcessor {
+public class LongRunningBarContentAssistProcessor extends BarContentAssistProcessor {
- public static final String PROPOSAL = "s are also good for soft drink cocktails.";
+ public static final String PROPOSAL = "bars are also good for soft drink cocktails.";
public static final int DELAY = 2000;
+ public LongRunningBarContentAssistProcessor() {
+ super(PROPOSAL);
+ }
+
@Override
public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
try {
@@ -30,38 +30,6 @@ public class LongRunningBarContentAssistProcessor implements IContentAssistProce
// TODO Auto-generated catch block
e.printStackTrace();
}
- String text = viewer.getDocument().get();
- if (text.length() >= 3 && offset >= 3 && text.substring(offset - 3, offset).equals("bar")) {
- String message = PROPOSAL;
- CompletionProposal proposal = new CompletionProposal(message, offset, 0, message.length());
- return new ICompletionProposal[] { proposal };
- }
- return new ICompletionProposal[0];
- }
-
- @Override
- public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) {
- return null;
+ return super.computeCompletionProposals(viewer, offset);
}
-
- @Override
- public char[] getCompletionProposalAutoActivationCharacters() {
- return null;
- }
-
- @Override
- public char[] getContextInformationAutoActivationCharacters() {
- return null;
- }
-
- @Override
- public String getErrorMessage() {
- return null;
- }
-
- @Override
- public IContextInformationValidator getContextInformationValidator() {
- return null;
- }
-
}

Back to the top