Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Pazderski2019-02-28 16:17:43 -0500
committerAndrey Loskutov2019-03-16 12:31:05 -0400
commitf8f69cc849b9a3bd4edea07fbafc96db4c4f1842 (patch)
tree5ed3a488ba81289a0bf043a17af347388909e928
parentda6766d3adacd89923da191bce68e3e096445e0e (diff)
downloadeclipse.platform.debug-f8f69cc849b9a3bd4edea07fbafc96db4c4f1842.tar.gz
eclipse.platform.debug-f8f69cc849b9a3bd4edea07fbafc96db4c4f1842.tar.xz
eclipse.platform.debug-f8f69cc849b9a3bd4edea07fbafc96db4c4f1842.zip
Bug 544969 - [console] ConsoleDocumentAdapter.setText does not set textI20190318-1800
Change-Id: Ib12b38b964891bb13bd933bb1f9d74fb39421471 Signed-off-by: Paul Pazderski <paul-eclipse@ppazderski.de> Signed-off-by: Andrey Loskutov <loskutov@gmx.de>
-rw-r--r--org.eclipse.debug.tests/META-INF/MANIFEST.MF4
-rw-r--r--org.eclipse.debug.tests/pom.xml4
-rw-r--r--org.eclipse.debug.tests/src/org/eclipse/debug/tests/AutomatedSuite.java4
-rw-r--r--org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/ConsoleDocumentAdapterTests.java304
-rw-r--r--org.eclipse.ui.console/META-INF/MANIFEST.MF2
-rw-r--r--org.eclipse.ui.console/pom.xml2
-rw-r--r--org.eclipse.ui.console/src/org/eclipse/ui/internal/console/ConsoleDocumentAdapter.java3
7 files changed, 315 insertions, 8 deletions
diff --git a/org.eclipse.debug.tests/META-INF/MANIFEST.MF b/org.eclipse.debug.tests/META-INF/MANIFEST.MF
index 0e97d9e66..77078da02 100644
--- a/org.eclipse.debug.tests/META-INF/MANIFEST.MF
+++ b/org.eclipse.debug.tests/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.debug.tests;singleton:=true
-Bundle-Version: 3.11.200.qualifier
+Bundle-Version: 3.11.300.qualifier
Bundle-Activator: org.eclipse.debug.tests.TestsPlugin
Bundle-Localization: plugin
Require-Bundle: org.eclipse.ui;bundle-version="[3.6.0,4.0.0)",
@@ -15,7 +15,7 @@ Require-Bundle: org.eclipse.ui;bundle-version="[3.6.0,4.0.0)",
org.eclipse.debug.core;bundle-version="[3.9.0,4.0.0)",
org.eclipse.ui.externaltools;bundle-version="[3.3.0,4.0.0)",
org.eclipse.ui.console;bundle-version="[3.7.0,4.0.0)",
- org.eclipse.text
+ org.eclipse.jface.text;bundle-version="[3.5.0,4.0.0)"
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-Vendor: %providerName
diff --git a/org.eclipse.debug.tests/pom.xml b/org.eclipse.debug.tests/pom.xml
index b99c54edf..36aa7e3cd 100644
--- a/org.eclipse.debug.tests/pom.xml
+++ b/org.eclipse.debug.tests/pom.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2012, 2018 Eclipse Foundation and others.
+ Copyright (c) 2012, 2019 Eclipse Foundation and others.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Distribution License v1.0
which accompanies this distribution, and is available at
@@ -18,7 +18,7 @@
</parent>
<groupId>org.eclipse.debug</groupId>
<artifactId>org.eclipse.debug.tests</artifactId>
- <version>3.11.200-SNAPSHOT</version>
+ <version>3.11.300-SNAPSHOT</version>
<packaging>eclipse-test-plugin</packaging>
<properties>
<code.ignoredWarnings>${tests.ignoredWarnings}</code.ignoredWarnings>
diff --git a/org.eclipse.debug.tests/src/org/eclipse/debug/tests/AutomatedSuite.java b/org.eclipse.debug.tests/src/org/eclipse/debug/tests/AutomatedSuite.java
index 497735d73..b8b816930 100644
--- a/org.eclipse.debug.tests/src/org/eclipse/debug/tests/AutomatedSuite.java
+++ b/org.eclipse.debug.tests/src/org/eclipse/debug/tests/AutomatedSuite.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2009, 2017 IBM Corporation and others.
+ * Copyright (c) 2009, 2019 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -16,6 +16,7 @@
package org.eclipse.debug.tests;
import org.eclipse.debug.tests.breakpoint.BreakpointOrderingTests;
+import org.eclipse.debug.tests.console.ConsoleDocumentAdapterTests;
import org.eclipse.debug.tests.console.ConsoleManagerTests;
import org.eclipse.debug.tests.console.ConsoleTests;
import org.eclipse.debug.tests.launching.AcceleratorSubstitutionTests;
@@ -107,6 +108,7 @@ public class AutomatedSuite extends TestSuite {
addTest(new TestSuite(StepFiltersTests.class));
// Console view
+ addTest(new TestSuite(ConsoleDocumentAdapterTests.class));
addTest(new TestSuite(ConsoleManagerTests.class));
addTest(new TestSuite(ConsoleTests.class));
diff --git a/org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/ConsoleDocumentAdapterTests.java b/org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/ConsoleDocumentAdapterTests.java
new file mode 100644
index 000000000..8292afd83
--- /dev/null
+++ b/org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/ConsoleDocumentAdapterTests.java
@@ -0,0 +1,304 @@
+/*******************************************************************************
+ * Copyright (c) 2019 Paul Pazderski 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:
+ * Paul Pazderski - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.debug.tests.console;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+import java.util.Random;
+import org.eclipse.debug.tests.AbstractDebugTest;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentAdapter;
+import org.eclipse.swt.custom.TextChangeListener;
+import org.eclipse.swt.custom.TextChangedEvent;
+import org.eclipse.swt.custom.TextChangingEvent;
+import org.eclipse.ui.internal.console.ConsoleDocumentAdapter;
+
+/**
+ * Tests {@link ConsoleDocumentAdapter}.
+ */
+@SuppressWarnings("restriction")
+public class ConsoleDocumentAdapterTests extends AbstractDebugTest {
+
+ public ConsoleDocumentAdapterTests() {
+ super(ConsoleDocumentAdapterTests.class.getSimpleName());
+ }
+
+ public ConsoleDocumentAdapterTests(String name) {
+ super(name);
+ }
+
+ /**
+ * Test {@link ConsoleDocumentAdapter#setText(String)}.
+ */
+ public void testSetText() {
+ final ExpectingTextChangeListener eventListener = new ExpectingTextChangeListener(true, null);
+ final IDocumentAdapter docAdapter = new ConsoleDocumentAdapter(-1);
+ docAdapter.setDocument(new Document());
+ docAdapter.addTextChangeListener(eventListener);
+
+ final String text = "123456";
+ eventListener.addExpectation(new TextEventExpectation(TextChangeEventType.SET));
+ docAdapter.setText(text);
+ assertContent(docAdapter, text);
+ assertNumberOfLines(docAdapter, 1);
+ checkLineMapping(docAdapter, null);
+
+ for (String s : new String[] { "", null }) {
+ docAdapter.setText(s);
+ assertContent(docAdapter, "");
+ assertNumberOfLines(docAdapter, 1);
+ checkLineMapping(docAdapter, null);
+ }
+ }
+
+ /**
+ * Test
+ * {@link IDocumentAdapter#setDocument(org.eclipse.jface.text.IDocument)}
+ * and ensure old document is indeed disconnected and not notified anymore.
+ */
+ public void testChangeDocument() {
+ final IDocumentAdapter docAdapter = new ConsoleDocumentAdapter(-1);
+ final IDocument doc1 = new Document();
+ final IDocument doc2 = new Document();
+ final String text1 = "foo";
+ final String text2 = "bar";
+
+ docAdapter.setDocument(doc1);
+ docAdapter.setText(text1);
+ assertContent(docAdapter, text1);
+
+ final String doc1Text = doc1.get();
+ docAdapter.setDocument(doc2);
+ docAdapter.setText(text2);
+ assertContent(docAdapter, text2);
+ assertEquals("Document was changed after disconnect.", doc1Text, doc1.get());
+
+ docAdapter.setDocument(null);
+ }
+
+ private static void assertContent(IDocumentAdapter docAdapter, String content) {
+ assertEquals("Adapter returned wrong content.", content, docAdapter.getTextRange(0, docAdapter.getCharCount()));
+ }
+
+ private static void assertNumberOfLines(IDocumentAdapter docAdapter, int expectedLines) {
+ assertEquals("Adapter has wrong line count.", expectedLines, docAdapter.getLineCount());
+ }
+
+ /**
+ * Goes through every line in adapted document and checks if value of
+ * {@link IDocumentAdapter#getOffsetAtLine(int)} for a line returns the same
+ * line again if put into {@link IDocumentAdapter#getLineAtOffset(int)}.
+ * <p>
+ * If random source is provided test is more intensive and to some extend
+ * tests {@link IDocumentAdapter#getLine(int)}.
+ * </p>
+ *
+ * @param docAdapter document adapter to test
+ * @param rand Optional. If provided will request line from random offset of
+ * this line instead of first and check lines in random order.
+ */
+ private static void checkLineMapping(IDocumentAdapter docAdapter, Random rand) {
+ final int n = docAdapter.getLineCount();
+ final List<Integer> lines = new ArrayList<>(n);
+ for (int i = 0; i < n; i++) {
+ lines.add(i);
+ }
+ if (rand != null) {
+ Collections.shuffle(lines, rand);
+ }
+ for (int lineIndex : lines) {
+ int offset = docAdapter.getOffsetAtLine(lineIndex);
+ if (rand != null) {
+ int lineLength = docAdapter.getLine(lineIndex).length();
+ if (lineLength > 0) {
+ offset += rand.nextInt(lineLength);
+ }
+ }
+ final int testLineIndex = docAdapter.getLineAtOffset(offset);
+ assertEquals("Got wrong line with offset " + offset + ".", lineIndex, testLineIndex);
+ }
+ }
+
+ private static class TextEventExpectation {
+ // common attributes
+ /** Expected text change event type. */
+ public final TextChangeEventType type;
+
+ // text changing only attributes
+ /**
+ * Expected value of {@link TextChangingEvent#start} or
+ * <code>null</code> to ignore.
+ */
+ public final Integer start;
+ /**
+ * Expected value of {@link TextChangingEvent#newText} or
+ * <code>null</code> to ignore.
+ */
+ public final String newText;
+ /**
+ * Expected value of {@link TextChangingEvent#replaceCharCount} or
+ * <code>null</code> to ignore.
+ */
+ public final Integer replaceCharCount;
+ /**
+ * Expected value of {@link TextChangingEvent#newCharCount} or
+ * <code>null</code> to ignore.
+ */
+ public final Integer newCharCount;
+ /**
+ * Expected value of {@link TextChangingEvent#replaceLineCount} or
+ * <code>null</code> to ignore.
+ */
+ public final Integer replaceLineCount;
+ /**
+ * Expected value of {@link TextChangingEvent#newLineCount} or
+ * <code>null</code> to ignore.
+ */
+ public final Integer newLineCount;
+
+ public TextEventExpectation(TextChangeEventType type) {
+ this(type, null, null, null, null, null, null);
+ }
+
+ public TextEventExpectation(TextChangeEventType type, Integer start, String newText, Integer replaceCharCount, Integer newCharCount, Integer replaceLineCount, Integer newLineCount) {
+ super();
+ this.type = type;
+ this.start = start;
+ this.newText = newText;
+ this.replaceCharCount = replaceCharCount;
+ this.newCharCount = newCharCount;
+ this.replaceLineCount = replaceLineCount;
+ this.newLineCount = newLineCount;
+ }
+ }
+
+ /**
+ * A {@link TextChangeListener} which has some expectations about generated
+ * text change events and is not gladly disappointed.
+ */
+ private static class ExpectingTextChangeListener implements TextChangeListener {
+
+ final Queue<TextEventExpectation> expectations = new LinkedList<>();
+ final boolean allowUnexpectedEvents;
+ /**
+ * The {@link IDocumentAdapter} generating the events. If set some
+ * additional checks are performed.
+ */
+ final IDocumentAdapter docAdapter;
+ /**
+ * If all events are checked ({@link #allowUnexpectedEvents} = false)
+ * and {@link #docAdapter} is set do some additional validations.
+ */
+ TextChangingEvent lastEvent;
+ int linesBeforeReplace = -1;
+ int lengthBeforeReplace = -1;
+
+ public ExpectingTextChangeListener(boolean allowUnexpectedEvents, IDocumentAdapter docAdapter) {
+ super();
+ this.allowUnexpectedEvents = allowUnexpectedEvents;
+ this.docAdapter = docAdapter;
+ }
+
+ public void addExpectation(TextEventExpectation expectation) {
+ expectations.add(expectation);
+ }
+
+ @Override
+ public void textChanging(TextChangingEvent event) {
+ final TextEventExpectation expectation = checkCommon(TextChangeEventType.CHANGING);
+ if (expectation == null) {
+ return;
+ }
+
+ if (expectation.start != null) {
+ assertEquals("event.start", (int) expectation.start, event.start);
+ }
+ if (expectation.newText != null) {
+ assertEquals("event.newText", expectation.newText, event.newText);
+ }
+ if (expectation.replaceCharCount != null) {
+ assertEquals("event.replaceCharCount", (int) expectation.replaceCharCount, event.replaceCharCount);
+ }
+ if (expectation.newCharCount != null) {
+ assertEquals("event.newCharCount", (int) expectation.newCharCount, event.newCharCount);
+ }
+ if (expectation.replaceLineCount != null) {
+ assertEquals("event.replaceLineCount", (int) expectation.replaceLineCount, event.replaceLineCount);
+ }
+ if (expectation.newLineCount != null) {
+ assertEquals("event.newLineCount", (int) expectation.newLineCount, event.newLineCount);
+ }
+
+ if (!allowUnexpectedEvents && docAdapter != null) {
+ lastEvent = event;
+ linesBeforeReplace = docAdapter.getLineCount();
+ lengthBeforeReplace = docAdapter.getCharCount();
+
+ final int charactersBehindEventStart = docAdapter.getCharCount() - event.start;
+ assertTrue("Tried to remove more characters than available.", event.replaceCharCount <= charactersBehindEventStart);
+
+ final int linesBehindEvent = docAdapter.getLineCount() - docAdapter.getLineAtOffset(event.start);
+ assertTrue("Tried to remove more lines than available.", event.replaceLineCount <= linesBehindEvent);
+ }
+ }
+
+ @Override
+ public void textChanged(TextChangedEvent event) {
+ checkCommon(TextChangeEventType.CHANGED);
+
+ if (docAdapter != null && lastEvent != null) {
+ final int lastEventOffset = lastEvent.start;
+ final int lastEventLineIndex = docAdapter.getLineAtOffset(lastEventOffset);
+ assertEquals("Line of offset " + lastEventOffset + " has changed after text change.", lastEventLineIndex, docAdapter.getLineAtOffset(lastEventOffset));
+
+ // check if predicted changes are correct
+ final int predictedDocLength = lengthBeforeReplace - lastEvent.replaceCharCount + lastEvent.newCharCount;
+ assertEquals("New widget length not as announce by changing event.", predictedDocLength, docAdapter.getCharCount());
+ final int predictedDocLines = linesBeforeReplace - lastEvent.replaceLineCount + lastEvent.newLineCount;
+ assertEquals("New widget line number not as announce by changing event.", predictedDocLines, docAdapter.getLineCount());
+ assertEquals("Inserted text not found in document.", lastEvent.newText, docAdapter.getTextRange(lastEvent.start, lastEvent.newText.length()));
+ }
+ }
+
+ @Override
+ public void textSet(TextChangedEvent event) {
+ checkCommon(TextChangeEventType.SET);
+ }
+
+ private TextEventExpectation checkCommon(TextChangeEventType eventType) {
+ final TextEventExpectation expectation = expectations.poll();
+ if (expectation == null && allowUnexpectedEvents) {
+ return null;
+ }
+ assertNotNull("Unexpected event.", expectation);
+ if (expectation == null) {
+ // prevents wrong compiler warning 'expectation may be null'
+ return null;
+ }
+ if (expectation.type != eventType && allowUnexpectedEvents) {
+ return null;
+ }
+ assertEquals("Wrong event type.", expectation.type, eventType);
+ return expectation;
+ }
+ }
+
+ public enum TextChangeEventType {
+ CHANGING, CHANGED, SET,
+ }
+}
diff --git a/org.eclipse.ui.console/META-INF/MANIFEST.MF b/org.eclipse.ui.console/META-INF/MANIFEST.MF
index b663e90c0..df2b6082b 100644
--- a/org.eclipse.ui.console/META-INF/MANIFEST.MF
+++ b/org.eclipse.ui.console/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.ui.console; singleton:=true
-Bundle-Version: 3.8.400.qualifier
+Bundle-Version: 3.8.500.qualifier
Bundle-Activator: org.eclipse.ui.console.ConsolePlugin
Bundle-Vendor: %providerName
Bundle-Localization: plugin
diff --git a/org.eclipse.ui.console/pom.xml b/org.eclipse.ui.console/pom.xml
index 32a95983b..8c8eed6bc 100644
--- a/org.eclipse.ui.console/pom.xml
+++ b/org.eclipse.ui.console/pom.xml
@@ -18,6 +18,6 @@
</parent>
<groupId>org.eclipse.ui</groupId>
<artifactId>org.eclipse.ui.console</artifactId>
- <version>3.8.400-SNAPSHOT</version>
+ <version>3.8.500-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
</project>
diff --git a/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/ConsoleDocumentAdapter.java b/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/ConsoleDocumentAdapter.java
index 0d90b45cd..f8f0df6f5 100644
--- a/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/ConsoleDocumentAdapter.java
+++ b/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/ConsoleDocumentAdapter.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2018 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -240,6 +240,7 @@ public class ConsoleDocumentAdapter implements IDocumentAdapter, IDocumentListen
@Override
public synchronized void setText(String text) {
+ document.set(text == null ? "" : text); //$NON-NLS-1$
TextChangedEvent changeEvent = new TextChangedEvent(this);
for (TextChangeListener listener : textChangeListeners) {
listener.textSet(changeEvent);

Back to the top