Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Pazderski2019-03-20 21:07:30 +0000
committerPaul Pazderski2019-09-19 10:42:59 +0000
commit8ccad171e66800e09d381954ae51d4c05fd07fa3 (patch)
tree929806c289bbcfe582dd044b7ad479d7c4be2632
parent7445b64b4c3a7f8c5a11a51d276d50dfc6f1f1fe (diff)
downloadeclipse.platform.debug-8ccad171e66800e09d381954ae51d4c05fd07fa3.tar.gz
eclipse.platform.debug-8ccad171e66800e09d381954ae51d4c05fd07fa3.tar.xz
eclipse.platform.debug-8ccad171e66800e09d381954ae51d4c05fd07fa3.zip
Bug 550621 - [console] Add IConsoleDocumentPartitionerExtension
Used to better test for read-only parts of console document. Change-Id: I1d8e3b2655080a8b435e8aaf296c40823239cc93 Signed-off-by: Paul Pazderski <paul-eclipse@ppazderski.de>
-rw-r--r--org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/IOConsoleTests.java51
-rw-r--r--org.eclipse.ui.console/src/org/eclipse/ui/console/IConsoleDocumentPartitioner.java16
-rw-r--r--org.eclipse.ui.console/src/org/eclipse/ui/console/IConsoleDocumentPartitionerExtension.java120
-rw-r--r--org.eclipse.ui.console/src/org/eclipse/ui/internal/console/IOConsolePartitioner.java102
4 files changed, 285 insertions, 4 deletions
diff --git a/org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/IOConsoleTests.java b/org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/IOConsoleTests.java
index 213f1aefa..33811030e 100644
--- a/org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/IOConsoleTests.java
+++ b/org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/IOConsoleTests.java
@@ -42,6 +42,7 @@ import org.eclipse.ui.console.ConsolePlugin;
import org.eclipse.ui.console.IConsole;
import org.eclipse.ui.console.IConsoleConstants;
import org.eclipse.ui.console.IConsoleDocumentPartitioner;
+import org.eclipse.ui.console.IConsoleDocumentPartitionerExtension;
import org.eclipse.ui.console.IConsoleManager;
import org.eclipse.ui.console.IOConsole;
import org.eclipse.ui.console.IOConsoleOutputStream;
@@ -484,6 +485,56 @@ public class IOConsoleTests extends AbstractDebugTest {
assertTrue("Offset should be read-only.", c.getPartitioner().isReadOnly(loremEnd + 3));
assertTrue("Offset should be read-only.", c.getPartitioner().isReadOnly(loremEnd + 4));
assertTrue("Offset should be read-only.", c.getPartitioner().isReadOnly(loremEnd + 5));
+
+ if (c.getPartitioner() instanceof IConsoleDocumentPartitionerExtension) {
+ final IConsoleDocumentPartitionerExtension extension = (IConsoleDocumentPartitionerExtension) c.getPartitioner();
+ assertFalse("Writable parts not recognized.", extension.isReadOnly(0, c.getContentLength()));
+ assertTrue("Read-only parts not recognized.", extension.containsReadOnly(0, c.getContentLength()));
+ assertFalse("Writable parts not recognized.", extension.isReadOnly(0, 3));
+ assertTrue("Read-only parts not recognized.", extension.containsReadOnly(0, 3));
+ assertFalse("Area should be writable.", extension.isReadOnly(loremEnd, 3));
+ assertFalse("Area should be writable.", extension.containsReadOnly(loremEnd, 3));
+ assertTrue("Area should be read-only.", extension.isReadOnly(6, 105));
+ assertTrue("Area should be read-only.", extension.containsReadOnly(8, 111));
+
+ assertTrue("Read-only parts not found.", extension.computeReadOnlyPartitions().length > 0);
+ assertTrue("Writable parts not found.", extension.computeWritablePartitions().length > 0);
+ assertTrue("Read-only parts not found.", extension.computeReadOnlyPartitions(loremEnd - 5, 7).length > 0);
+ assertTrue("Writable parts not found.", extension.computeWritablePartitions(loremEnd - 5, 7).length > 0);
+ assertTrue("Area should be read-only.", extension.computeReadOnlyPartitions(5, 100).length > 0);
+ assertEquals("Area should be read-only.", 0, extension.computeWritablePartitions(5, 100).length);
+ assertEquals("Area should be writable.", 0, extension.computeReadOnlyPartitions(loremEnd, 2).length);
+ assertTrue("Area should be writable.", extension.computeWritablePartitions(loremEnd, 2).length > 0);
+
+ assertEquals("Got wrong offset.", 0, extension.getNextOffsetByState(0, false));
+ assertEquals("Got wrong offset.", 2, extension.getNextOffsetByState(0, true));
+ assertEquals("Got wrong offset.", 0, extension.getPreviousOffsetByState(0, false));
+ assertEquals("Got wrong offset.", -1, extension.getPreviousOffsetByState(0, true));
+ assertEquals("Got wrong offset.", 1, extension.getNextOffsetByState(1, false));
+ assertEquals("Got wrong offset.", 2, extension.getNextOffsetByState(1, true));
+ assertEquals("Got wrong offset.", 1, extension.getPreviousOffsetByState(1, false));
+ assertEquals("Got wrong offset.", -1, extension.getPreviousOffsetByState(1, true));
+ assertEquals("Got wrong offset.", 3, extension.getNextOffsetByState(2, false));
+ assertEquals("Got wrong offset.", 2, extension.getNextOffsetByState(2, true));
+ assertEquals("Got wrong offset.", 1, extension.getPreviousOffsetByState(2, false));
+ assertEquals("Got wrong offset.", 2, extension.getPreviousOffsetByState(2, true));
+ for (int i = 3; i < loremEnd; i++) {
+ assertEquals("Got wrong offset.", i, extension.getNextOffsetByState(i, false));
+ assertEquals("Got wrong offset.", loremEnd, extension.getNextOffsetByState(i, true));
+ assertEquals("Got wrong offset.", i, extension.getPreviousOffsetByState(i, false));
+ assertEquals("Got wrong offset.", 2, extension.getPreviousOffsetByState(i, true));
+ }
+ assertEquals("Got wrong offset.", loremEnd + 3, extension.getNextOffsetByState(loremEnd, false));
+ assertEquals("Got wrong offset.", loremEnd, extension.getNextOffsetByState(loremEnd, true));
+ assertEquals("Got wrong offset.", loremEnd - 1, extension.getPreviousOffsetByState(loremEnd, false));
+ assertEquals("Got wrong offset.", loremEnd, extension.getPreviousOffsetByState(loremEnd, true));
+ assertEquals("Got wrong offset.", loremEnd + 3, extension.getNextOffsetByState(loremEnd + 2, false));
+ assertEquals("Got wrong offset.", loremEnd + 2, extension.getNextOffsetByState(loremEnd + 2, true));
+ assertEquals("Got wrong offset.", loremEnd - 1, extension.getPreviousOffsetByState(loremEnd + 2, false));
+ assertEquals("Got wrong offset.", loremEnd + 2, extension.getPreviousOffsetByState(loremEnd + 2, true));
+ } else {
+ TestUtil.log(IStatus.INFO, TestsPlugin.PLUGIN_ID, "IOConsole partitioner does not implement " + IConsoleDocumentPartitionerExtension.class.getName() + ". Skip those tests.");
+ }
}
c.verifyPartitions();
closeConsole(c, "#");
diff --git a/org.eclipse.ui.console/src/org/eclipse/ui/console/IConsoleDocumentPartitioner.java b/org.eclipse.ui.console/src/org/eclipse/ui/console/IConsoleDocumentPartitioner.java
index 87d3c3785..c92b878e7 100644
--- a/org.eclipse.ui.console/src/org/eclipse/ui/console/IConsoleDocumentPartitioner.java
+++ b/org.eclipse.ui.console/src/org/eclipse/ui/console/IConsoleDocumentPartitioner.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2006 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
@@ -21,12 +21,24 @@ import org.eclipse.swt.custom.StyleRange;
* A document partitioner for a text console.
* <p>
* In addition to regular partitioner duties, a console document partitioner
- * dictates which regions in its document are read-only and provides style ranges.
+ * dictates which regions in its document are read-only and provides style
+ * ranges.
* </p>
* <p>
* Clients may implement this interface.
* </p>
+ * <p>
+ * In order to provided backward compatibility for clients of
+ * <code>IConsoleDocumentPartitioner</code>, extension interfaces are used to
+ * provide a means of evolution. The following extension interfaces exist:
+ * <ul>
+ * <li>{@link org.eclipse.ui.console.IConsoleDocumentPartitionerExtension} since
+ * version 3.9 adding more possibilities to query read-only regions.</li>
+ * </ul>
+ * </p>
+ *
* @see org.eclipse.ui.console.TextConsole
+ * @see org.eclipse.ui.console.IConsoleDocumentPartitionerExtension
* @since 3.1
*/
public interface IConsoleDocumentPartitioner extends IDocumentPartitioner {
diff --git a/org.eclipse.ui.console/src/org/eclipse/ui/console/IConsoleDocumentPartitionerExtension.java b/org.eclipse.ui.console/src/org/eclipse/ui/console/IConsoleDocumentPartitionerExtension.java
new file mode 100644
index 000000000..e03418ddc
--- /dev/null
+++ b/org.eclipse.ui.console/src/org/eclipse/ui/console/IConsoleDocumentPartitionerExtension.java
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * 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.ui.console;
+
+import org.eclipse.jface.text.ITypedRegion;
+
+/**
+ * Extension interface for {@link IConsoleDocumentPartitioner}.
+ * <p>
+ * It adds more possibilities to query read-only regions of the partitioned
+ * document.
+ * </p>
+ *
+ * @see org.eclipse.ui.console.IConsoleDocumentPartitioner
+ * @since 3.9
+ */
+public interface IConsoleDocumentPartitionerExtension {
+
+ /**
+ * Returns all partitions which are read-only.
+ *
+ * @return all read-only partitions. Ordered by offset and never
+ * <code>null</code>.
+ */
+ ITypedRegion[] computeReadOnlyPartitions();
+
+ /**
+ * Returns all read-only partitions in given range.
+ *
+ * @param offset the offset of the range of interest
+ * @param length the length of the range of interest
+ * @return read-only partitions in given range. Ordered by offset and never
+ * <code>null</code>. Returned regions may start and/or end outside
+ * given range.
+ */
+ ITypedRegion[] computeReadOnlyPartitions(int offset, int length);
+
+ /**
+ * Returns all partitions which are writable.
+ *
+ * @return all writable partitions. Ordered by offset and never
+ * <code>null</code>.
+ */
+ ITypedRegion[] computeWritablePartitions();
+
+ /**
+ * Returns all writable partitions in given range.
+ *
+ * @param offset the offset of the range of interest
+ * @param length the length of the range of interest
+ * @return writable partitions in given range. Ordered by offset and never
+ * <code>null</code>. Returned regions may start and/or end outside
+ * given range.
+ */
+ ITypedRegion[] computeWritablePartitions(int offset, int length);
+
+ /**
+ * Returns whether this partitioner's document is read-only in the specified
+ * range. Only returns <code>true</code> if the whole range is read-only.
+ *
+ * @param offset document offset
+ * @param length range length
+ * @return whether this partitioner's document is read-only in the specific
+ * range
+ */
+ boolean isReadOnly(int offset, int length);
+
+ /**
+ * Returns whether this partitioner's document is read-only at any point in the
+ * specified range.
+ *
+ * @param offset document offset
+ * @param length range length
+ * @return returns <code>true</code> if any offset in the given range is
+ * read-only
+ */
+ boolean containsReadOnly(int offset, int length);
+
+ /**
+ * Get this offset or the nearest offset before which is, depending on argument,
+ * writable or read-only.
+ *
+ * @param offset the offset of interest
+ * @param searchWritable if <code>true</code> return the nearest writable
+ * offset. If <code>false</code> return the nearest
+ * read-only offset.
+ * @return the given offset if it has the requested read-only/writable state or
+ * the nearest offset before with requested state. Returns
+ * <code>-1</code> if there is no offset with requested state before
+ * requested offset.
+ */
+ int getPreviousOffsetByState(int offset, boolean searchWritable);
+
+ /**
+ * Get this offset or the nearest offset after which is, depending on argument,
+ * writable or read-only.
+ *
+ * @param offset the offset of interest
+ * @param searchWritable if <code>true</code> return the nearest writable
+ * offset. If <code>false</code> return the nearest
+ * read-only offset.
+ * @return the given offset if it has the requested read-only/writable state or
+ * the nearest offset after with requested state. Returns the document
+ * length if there is no offset with requested state after requested
+ * offset.
+ */
+ int getNextOffsetByState(int offset, boolean searchWritable);
+}
diff --git a/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/IOConsolePartitioner.java b/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/IOConsolePartitioner.java
index 67e7b8e1c..fcf3937f1 100644
--- a/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/IOConsolePartitioner.java
+++ b/org.eclipse.ui.console/src/org/eclipse/ui/internal/console/IOConsolePartitioner.java
@@ -14,6 +14,7 @@
* Bug 547064: use binary search for getPartition
* Bug 548356: fixed user input handling
* Bug 550618: getStyleRanges produced invalid overlapping styles
+ * Bug 550621: Implementation of IConsoleDocumentPartitionerExtension
*******************************************************************************/
package org.eclipse.ui.internal.console;
@@ -42,6 +43,7 @@ import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.console.ConsolePlugin;
import org.eclipse.ui.console.IConsoleDocumentPartitioner;
+import org.eclipse.ui.console.IConsoleDocumentPartitionerExtension;
import org.eclipse.ui.console.IOConsole;
import org.eclipse.ui.console.IOConsoleInputStream;
import org.eclipse.ui.console.IOConsoleOutputStream;
@@ -53,7 +55,8 @@ import org.eclipse.ui.progress.WorkbenchJob;
*
* @since 3.1
*/
-public class IOConsolePartitioner implements IConsoleDocumentPartitioner, IDocumentPartitionerExtension {
+public class IOConsolePartitioner
+ implements IConsoleDocumentPartitioner, IConsoleDocumentPartitionerExtension, IDocumentPartitionerExtension {
/**
* If true validate partitioning after changes and do other additional
* assertions. Useful for developing/debugging.
@@ -221,6 +224,21 @@ public class IOConsolePartitioner implements IConsoleDocumentPartitioner, IDocum
* @return the partitioning of the requested range (never <code>null</code>)
*/
private IOConsolePartition[] computeIOPartitioning(int offset, int length) {
+ return computePartitioning(offset, length, true, true);
+ }
+
+ /**
+ * Get partitioning for a given range with possibility to filter partitions by
+ * their read-only property.
+ *
+ * @param offset the offset of the range of interest
+ * @param length the length of the range of interest
+ * @param includeWritable if false writable partitions are skipped
+ * @param includeReadOnly if false read-only partitions are skipped
+ * @return the partitioning of the requested range (never <code>null</code>)
+ */
+ private IOConsolePartition[] computePartitioning(int offset, int length, boolean includeWritable,
+ boolean includeReadOnly) {
final List<IOConsolePartition> result = new ArrayList<>();
synchronized (partitions) {
int index = findPartitionCandidate(offset);
@@ -234,7 +252,9 @@ public class IOConsolePartitioner implements IConsoleDocumentPartitioner, IDocum
if (partition.getOffset() >= end) {
break;
}
- result.add(partition);
+ if ((includeWritable && !partition.isReadOnly()) || (includeReadOnly && partition.isReadOnly())) {
+ result.add(partition);
+ }
}
}
return result.toArray(new IOConsolePartition[0]);
@@ -795,6 +815,84 @@ public class IOConsolePartitioner implements IConsoleDocumentPartitioner, IDocum
return styles;
}
+ @Override
+ public ITypedRegion[] computeReadOnlyPartitions() {
+ if (document == null) {
+ return new IOConsolePartition[0];
+ }
+ return computeReadOnlyPartitions(0, document.getLength());
+ }
+
+ @Override
+ public ITypedRegion[] computeReadOnlyPartitions(int offset, int length) {
+ return computePartitioning(offset, length, false, true);
+ }
+
+ @Override
+ public ITypedRegion[] computeWritablePartitions() {
+ if (document == null) {
+ return new IOConsolePartition[0];
+ }
+ return computeWritablePartitions(0, document.getLength());
+ }
+
+ @Override
+ public ITypedRegion[] computeWritablePartitions(int offset, int length) {
+ return computePartitioning(offset, length, true, false);
+ }
+
+ @Override
+ public boolean isReadOnly(int offset, int length) {
+ final ITypedRegion[] readOnlyRegions = computeReadOnlyPartitions(offset, length);
+ int o = offset;
+ int end = offset + length;
+ for (ITypedRegion readOnlyRegion : readOnlyRegions) {
+ if (o < readOnlyRegion.getOffset()) {
+ return false;
+ }
+ o += readOnlyRegion.getLength();
+ if (o >= end) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean containsReadOnly(int offset, int length) {
+ return computeReadOnlyPartitions(offset, length).length > 0;
+ }
+
+ @Override
+ public int getPreviousOffsetByState(int offset, boolean searchWritable) {
+ if (partitions != null) {
+ int partitionIndex = findPartitionCandidate(offset);
+ for (; partitionIndex >= 0; partitionIndex--) {
+ final IOConsolePartition partition = partitions.get(partitionIndex);
+ if (partition.isReadOnly() != searchWritable) {
+ return Math.min(partition.getOffset() + partition.getLength() - 1, offset);
+ }
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public int getNextOffsetByState(int offset, boolean searchWritable) {
+ if (partitions != null) {
+ int partitionIndex = findPartitionCandidate(offset);
+ if (partitionIndex >= 0) {
+ for (; partitionIndex < partitions.size(); partitionIndex++) {
+ final IOConsolePartition partition = partitions.get(partitionIndex);
+ if (partition.isReadOnly() != searchWritable) {
+ return Math.max(partition.getOffset(), offset);
+ }
+ }
+ }
+ }
+ return document != null ? document.getLength() : 0;
+ }
+
/**
* Get a partition by its index. Safe from out of bounds exceptions.
*

Back to the top