Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephan Wahlbrink2019-12-02 14:31:12 +0000
committerMickael Istria2019-12-03 16:34:17 +0000
commitba8184ce0177f0bd80b2c7c049df6b5eb2ff91c6 (patch)
tree27efc955c66875af9b30cb74fecab52980ba4427
parent6b2a33e6a69a6661649601cc07e72e2ceb494ca7 (diff)
downloadeclipse.platform.text-ba8184ce0177f0bd80b2c7c049df6b5eb2ff91c6.tar.gz
eclipse.platform.text-ba8184ce0177f0bd80b2c7c049df6b5eb2ff91c6.tar.xz
eclipse.platform.text-ba8184ce0177f0bd80b2c7c049df6b5eb2ff91c6.zip
Bug 553622: Add tests for context information to jface.text.tests
Change-Id: I35d5ee744a0df394dfa8288b40e6d5b8a3c633fb Signed-off-by: Stephan Wahlbrink <sw@wahlbrink.eu>
-rw-r--r--org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/JFaceTextTestSuite.java4
-rw-r--r--org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/contentassist/AbstractContentAssistTest.java173
-rw-r--r--org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/contentassist/BarContentAssistProcessor.java181
-rw-r--r--org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/contentassist/ContextInformationPresenterTest.java127
-rw-r--r--org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/contentassist/ContextInformationTest.java106
5 files changed, 591 insertions, 0 deletions
diff --git a/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/JFaceTextTestSuite.java b/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/JFaceTextTestSuite.java
index 1a315f14078..08104d53c8b 100644
--- a/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/JFaceTextTestSuite.java
+++ b/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/JFaceTextTestSuite.java
@@ -20,6 +20,8 @@ import org.junit.runners.Suite.SuiteClasses;
import org.eclipse.jface.text.tests.codemining.CodeMiningProjectionViewerTest;
import org.eclipse.jface.text.tests.codemining.CodeMiningTest;
import org.eclipse.jface.text.tests.contentassist.AsyncContentAssistTest;
+import org.eclipse.jface.text.tests.contentassist.ContextInformationPresenterTest;
+import org.eclipse.jface.text.tests.contentassist.ContextInformationTest;
import org.eclipse.jface.text.tests.contentassist.FilteringAsyncContentAssistTests;
import org.eclipse.jface.text.tests.reconciler.AbstractReconcilerTest;
import org.eclipse.jface.text.tests.rules.DefaultPartitionerTest;
@@ -51,6 +53,8 @@ import org.eclipse.jface.text.tests.templates.persistence.TemplatePersistenceDat
DefaultPairMatcherTest2.class,
AsyncContentAssistTest.class,
FilteringAsyncContentAssistTests.class,
+ ContextInformationTest.class,
+ ContextInformationPresenterTest.class,
AbstractReconcilerTest.class,
diff --git a/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/contentassist/AbstractContentAssistTest.java b/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/contentassist/AbstractContentAssistTest.java
new file mode 100644
index 00000000000..c6692817b12
--- /dev/null
+++ b/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/contentassist/AbstractContentAssistTest.java
@@ -0,0 +1,173 @@
+/*******************************************************************************
+ * Copyright (c) 2019 Stephan Wahlbrink and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Stephan Wahlbrink <sw@wahlbrink.eu>
+ *******************************************************************************/
+
+package org.eclipse.jface.text.tests.contentassist;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.junit.After;
+import org.junit.Assert;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Shell;
+
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.ITextOperationTarget;
+import org.eclipse.jface.text.contentassist.ContentAssistant;
+import org.eclipse.jface.text.contentassist.IContentAssistant;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.SourceViewer;
+import org.eclipse.jface.text.source.SourceViewerConfiguration;
+import org.eclipse.jface.text.tests.util.DisplayHelper;
+
+
+public class AbstractContentAssistTest {
+
+
+ private Shell shell;
+ private SourceViewer viewer;
+ private ContentAssistant assistant;
+ private Document document;
+
+
+ public AbstractContentAssistTest() {
+ }
+
+
+ @After
+ public void close() {
+ if (shell != null && !shell.isDisposed()) {
+ shell.close();
+ }
+ }
+
+
+ protected void setupSourceViewer(ContentAssistant contentAssistant, String initialText) {
+ shell= new Shell();
+ shell.setSize(500, 240);
+ shell.setLayout(new FillLayout());
+
+ viewer= new SourceViewer(shell, null, SWT.NONE);
+ assistant= contentAssistant;
+ viewer.configure(createSourceViewerConfiguration());
+
+ document= new Document();
+ if (initialText != null) {
+ document.set(initialText);
+ }
+ viewer.setDocument(document);
+
+ shell.open();
+ Assert.assertTrue(new DisplayHelper() {
+ @Override
+ protected boolean condition() {
+ return viewer.getTextWidget().isVisible();
+ }
+ }.waitForCondition(shell.getDisplay(), 3000));
+ }
+
+ protected SourceViewerConfiguration createSourceViewerConfiguration() {
+ return new SourceViewerConfiguration() {
+ @Override
+ public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) {
+ return AbstractContentAssistTest.this.getContentAssistant();
+ }
+ };
+ }
+
+ protected SourceViewer getSourceViewer() {
+ return viewer;
+ }
+
+ protected Document getDocument() {
+ return document;
+ }
+
+ protected ContentAssistant getContentAssistant() {
+ return assistant;
+ }
+
+ protected void selectAndReveal(int selectionStart, int selectionLength) {
+ StyledText widget= viewer.getTextWidget();
+ widget.setRedraw(false);
+
+ viewer.revealRange(selectionStart, selectionLength);
+ viewer.setSelectedRange(selectionStart, selectionLength);
+
+ widget.setRedraw(true);
+ }
+
+ protected void postSourceViewerKeyEvent(int keyCode, int stateMask, int type) {
+ processEvents();
+ Event event= new Event();
+ event.type= type;
+ event.widget= viewer.getTextWidget();
+ event.display= viewer.getTextWidget().getDisplay();
+ event.keyCode= keyCode;
+ event.stateMask= stateMask;
+ event.doit= true;
+ viewer.getTextWidget().notifyListeners(type, event);
+ processEvents();
+ }
+
+ protected void runTextOperation(int operation) {
+ ITextOperationTarget textOperationTarget= viewer.getTextOperationTarget();
+
+ assertTrue(textOperationTarget.canDoOperation(operation));
+ textOperationTarget.doOperation(operation);
+ }
+
+ protected void triggerContextInformation() {
+ runTextOperation(ISourceViewer.CONTENTASSIST_CONTEXT_INFORMATION);
+ }
+
+
+ protected void processEvents() {
+ DisplayHelper.driveEventQueue(shell.getDisplay());
+ }
+
+ protected List<Shell> getCurrentShells() {
+ return Arrays.stream(shell.getDisplay().getShells())
+ .filter(Shell::isVisible)
+ .collect(Collectors.toList());
+ }
+
+ protected List<Shell> findNewShells(Collection<Shell> beforeShells) {
+ return Arrays.stream(shell.getDisplay().getShells())
+ .filter(Shell::isVisible)
+ .filter(shell -> !beforeShells.contains(shell))
+ .collect(Collectors.toList());
+ }
+
+ protected Shell findNewShell(Collection<Shell> beforeShells) {
+ DisplayHelper.sleep(shell.getDisplay(), 100);
+ List<Shell> afterShells= findNewShells(beforeShells);
+ if (afterShells.isEmpty()) {
+ DisplayHelper.sleep(shell.getDisplay(), 1000);
+ }
+ afterShells= findNewShells(beforeShells);
+ assertEquals("No new shell found", 1, afterShells.size());
+ return afterShells.get(0);
+ }
+
+}
diff --git a/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/contentassist/BarContentAssistProcessor.java b/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/contentassist/BarContentAssistProcessor.java
new file mode 100644
index 00000000000..0cced65d683
--- /dev/null
+++ b/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/contentassist/BarContentAssistProcessor.java
@@ -0,0 +1,181 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2019 Red Hat Inc. and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Mickael Istria (Red Hat Inc.)
+ * Stephan Wahlbrink <sw@wahlbrink.eu> - Bug 512251 - Fix IllegalArgumentException in ContextInformationPopup
+ *******************************************************************************/
+
+package org.eclipse.jface.text.tests.contentassist;
+
+import java.util.Arrays;
+
+import org.eclipse.swt.graphics.Image;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+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.IContextInformationExtension;
+import org.eclipse.jface.text.contentassist.IContextInformationValidator;
+
+
+public class BarContentAssistProcessor implements IContentAssistProcessor {
+
+ public static final String PROPOSAL= "bars are good for a beer.";
+
+ protected static class BarContextInformation implements IContextInformation, IContextInformationExtension {
+
+ private String contextDisplayString;
+
+ private String informationDisplayString;
+
+ private int offset;
+
+ public BarContextInformation(String contextDisplayString, String informationDisplayString, int offset) {
+ this.contextDisplayString= contextDisplayString;
+ this.informationDisplayString= informationDisplayString;
+ this.offset= offset;
+ }
+
+ @Override
+ public String getContextDisplayString() {
+ return contextDisplayString;
+ }
+
+ @Override
+ public Image getImage() {
+ return null;
+ }
+
+ @Override
+ public String getInformationDisplayString() {
+ return informationDisplayString;
+ }
+
+ @Override
+ public int getContextInformationPosition() {
+ return offset;
+ }
+
+ }
+
+ protected static class ContextInformationValidator implements IContextInformationValidator {
+
+ protected BarContextInformation info;
+
+ protected ITextViewer viewer;
+
+ protected int offset;
+
+ @Override
+ public void install(IContextInformation info, ITextViewer viewer, int offset) {
+ if (info instanceof BarContextInformation) {
+ this.info= (BarContextInformation) info;
+ }
+ this.viewer= viewer;
+ this.offset= offset;
+ }
+
+ @Override
+ public boolean isContextInformationValid(int offset) {
+ if (this.info == null) {
+ return false;
+ }
+ try {
+ IDocument document= viewer.getDocument();
+ IRegion line= document.getLineInformationOfOffset(this.offset);
+ int end= line.getOffset() + line.getLength();
+ return (offset >= this.offset && offset < end);
+ } catch (BadLocationException e) {
+ return false;
+ }
+ }
+ }
+
+
+ private final String completeString;
+
+ public BarContentAssistProcessor() {
+ this(PROPOSAL);
+ }
+
+ public BarContentAssistProcessor(String completeString) {
+ this.completeString= completeString;
+ }
+
+ @Override
+ public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
+ 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];
+ }
+
+ @Override
+ public char[] getCompletionProposalAutoActivationCharacters() {
+ return null;
+ }
+
+ @Override
+ public char[] getContextInformationAutoActivationCharacters() {
+ return null;
+ }
+
+ /**
+ * Creates context info "idx= <word index in #PROPOSAL>" at the end of a word.
+ **/
+ @Override
+ public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) {
+ try {
+ IDocument document= viewer.getDocument();
+ int wordBegin= offset;
+ while (wordBegin > 0 && Character.isLetterOrDigit(document.getChar(wordBegin - 1))) {
+ wordBegin--;
+ }
+ if (wordBegin < offset) {
+ String word= document.get(wordBegin, offset - wordBegin);
+ int wordIdx= Arrays.asList(completeString.split("\\W")).indexOf(word);
+ if (wordIdx >= 0) {
+ return new IContextInformation[] {
+ new BarContextInformation(word, "idx= " + wordIdx, wordBegin)
+ };
+ }
+ }
+ } catch (BadLocationException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ @Override
+ public IContextInformationValidator getContextInformationValidator() {
+ return new ContextInformationValidator();
+ }
+
+ @Override
+ public String getErrorMessage() {
+ return null;
+ }
+
+}
diff --git a/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/contentassist/ContextInformationPresenterTest.java b/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/contentassist/ContextInformationPresenterTest.java
new file mode 100644
index 00000000000..80b8cefc0d1
--- /dev/null
+++ b/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/contentassist/ContextInformationPresenterTest.java
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (c) 2017, 2019 Stephan Wahlbrink and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Stephan Wahlbrink <sw@wahlbrink.eu>
+ *******************************************************************************/
+package org.eclipse.jface.text.tests.contentassist;
+
+import static org.eclipse.jface.text.tests.contentassist.ContextInformationTest.getInfoText;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+
+import org.junit.Test;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyleRange;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.TextPresentation;
+import org.eclipse.jface.text.contentassist.ContentAssistant;
+import org.eclipse.jface.text.contentassist.IContextInformationPresenter;
+import org.eclipse.jface.text.contentassist.IContextInformationValidator;
+
+
+public class ContextInformationPresenterTest extends AbstractContentAssistTest {
+
+ private static class ValidatorWithPresenter extends BarContentAssistProcessor.ContextInformationValidator
+ implements IContextInformationPresenter {
+
+ private boolean isStyled;
+
+ /**
+ * Hightlight (bold) "idx" if caret is inside the word (including end)
+ */
+ @Override
+ public boolean updatePresentation(int offset, TextPresentation presentation) {
+ if (info == null) { // Ignore unknown information
+ return false;
+ }
+
+ int begin= info.getContextInformationPosition();
+ int end= begin + info.getContextDisplayString().length();
+ boolean style= (offset >= begin && offset <= end);
+ if (style == isStyled) {
+ return false;
+ }
+ if (style) {
+ presentation.clear();
+ presentation.addStyleRange(new StyleRange(0, 3, null, null, SWT.BOLD));
+ } else {
+ presentation.clear();
+ }
+ isStyled= style;
+ return true;
+ }
+
+ }
+
+
+ private Shell infoShell;
+
+
+ private ContentAssistant createBarContentAssist() {
+ ContentAssistant contentAssistant= new ContentAssistant();
+ contentAssistant.setContentAssistProcessor(new BarContentAssistProcessor() {
+ @Override
+ public IContextInformationValidator getContextInformationValidator() {
+ return new ValidatorWithPresenter();
+ }
+ }, IDocument.DEFAULT_CONTENT_TYPE);
+ return contentAssistant;
+ }
+
+ @Test
+ public void testContextInfo_withStyledTextPresentation() throws Exception {
+ setupSourceViewer(createBarContentAssist(), BarContentAssistProcessor.PROPOSAL);
+
+ final List<Shell> beforeShells= getCurrentShells();
+
+ postSourceViewerKeyEvent(SWT.ARROW_RIGHT, 0, SWT.KeyDown);
+ selectAndReveal(4, 0);
+ processEvents();
+
+ triggerContextInformation();
+ this.infoShell= findNewShell(beforeShells);
+ assertEquals("idx= 0", getInfoText(this.infoShell));
+ assertArrayEquals(new StyleRange[] {
+ new StyleRange(0, 3, null, null, SWT.BOLD)
+ }, getInfoStyleRanges(this.infoShell));
+
+ postSourceViewerKeyEvent(SWT.ARROW_RIGHT, 0, SWT.KeyDown);
+
+ assertEquals("idx= 0", getInfoText(this.infoShell));
+ assertArrayEquals(new StyleRange[] {
+ }, getInfoStyleRanges(this.infoShell));
+ }
+
+
+ static StyleRange[] getInfoStyleRanges(final Shell shell) {
+ assertTrue(shell.isVisible());
+ Control[] children= shell.getChildren();
+ for (Control child : children) {
+ if (child instanceof Text) {
+ return null;
+ }
+ if (child instanceof StyledText) {
+ return ((StyledText) child).getStyleRanges();
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/contentassist/ContextInformationTest.java b/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/contentassist/ContextInformationTest.java
new file mode 100644
index 00000000000..1d5d6afa85e
--- /dev/null
+++ b/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/contentassist/ContextInformationTest.java
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (c) 2017, 2019 Stephan Wahlbrink and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Stephan Wahlbrink <sw@wahlbrink.eu>
+ *******************************************************************************/
+package org.eclipse.jface.text.tests.contentassist;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+
+import org.junit.Test;
+
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+import org.eclipse.text.tests.Accessor;
+
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.contentassist.ContentAssistant;
+
+
+public class ContextInformationTest extends AbstractContentAssistTest {
+
+
+ private Shell infoShell;
+
+
+ private ContentAssistant createBarContentAssist() {
+ ContentAssistant contentAssistant= new ContentAssistant();
+ contentAssistant.setContentAssistProcessor(new BarContentAssistProcessor(), IDocument.DEFAULT_CONTENT_TYPE);
+ return contentAssistant;
+ }
+
+ @Test
+ public void testContextInfo() throws Exception {
+ setupSourceViewer(createBarContentAssist(), BarContentAssistProcessor.PROPOSAL);
+
+ final List<Shell> beforeShells= getCurrentShells();
+
+ selectAndReveal(4, 0);
+ processEvents();
+
+ triggerContextInformation();
+ this.infoShell= findNewShell(beforeShells);
+ assertEquals("idx= 0", getInfoText(this.infoShell));
+
+ selectAndReveal(8, 0);
+ processEvents();
+
+ triggerContextInformation();
+ this.infoShell= findNewShell(beforeShells);
+ assertEquals("idx= 1", getInfoText(this.infoShell));
+ }
+
+ @Test
+ public void testContextInfo_hide_Bug512251() throws Exception {
+ setupSourceViewer(createBarContentAssist(), BarContentAssistProcessor.PROPOSAL);
+
+ final List<Shell> beforeShells= getCurrentShells();
+
+ selectAndReveal(4, 0);
+ processEvents();
+
+ triggerContextInformation();
+ this.infoShell= findNewShell(beforeShells);
+
+ selectAndReveal(8, 0);
+ processEvents();
+
+ triggerContextInformation();
+ this.infoShell= findNewShell(beforeShells);
+
+ // ITextEditorActionConstants.DELETE_LINE
+ getDocument().set("");
+
+ new Accessor(getContentAssistant(), ContentAssistant.class).invoke("hide", new Object[0]);
+ }
+
+
+ static String getInfoText(final Shell shell) {
+ assertTrue(shell.isVisible());
+ Control[] children= shell.getChildren();
+ for (Control child : children) {
+ if (child instanceof Text) {
+ return ((Text) child).getText();
+ }
+ if (child instanceof StyledText) {
+ return ((StyledText) child).getText();
+ }
+ }
+ return null;
+ }
+
+}

Back to the top