Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDeepak Azad2012-02-26 08:17:36 +0000
committerDani Megert2012-02-26 08:17:36 +0000
commit1942dbddd460925c0dd3cbed02bad82b548af896 (patch)
tree5259505fe4170d94bc068e75106dca5153a41440
parentdb449c047ea409b35e73b1cf7094d38610826800 (diff)
downloadeclipse.platform.text-1942dbddd460925c0dd3cbed02bad82b548af896.tar.gz
eclipse.platform.text-1942dbddd460925c0dd3cbed02bad82b548af896.tar.xz
eclipse.platform.text-1942dbddd460925c0dd3cbed02bad82b548af896.zip
Fixed bug 40580: [navigation] Matching brace (Ctrl+Shift+P) should workv20120226-0817
anywhere in the file
-rw-r--r--org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/AbstractPairMatcherTest.java126
-rw-r--r--org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/JFaceTextTestSuite.java1
-rw-r--r--org.eclipse.jface.text/src/org/eclipse/jface/text/source/DefaultCharacterPairMatcher.java87
-rw-r--r--org.eclipse.jface.text/src/org/eclipse/jface/text/source/ICharacterPairMatcher.java16
-rw-r--r--org.eclipse.jface.text/src/org/eclipse/jface/text/source/ICharacterPairMatcherExtension.java25
-rw-r--r--org.eclipse.jface.text/src/org/eclipse/jface/text/source/MatchingCharacterPainter.java50
6 files changed, 252 insertions, 53 deletions
diff --git a/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/AbstractPairMatcherTest.java b/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/AbstractPairMatcherTest.java
index 474363f2db1..00166bc67cc 100644
--- a/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/AbstractPairMatcherTest.java
+++ b/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/AbstractPairMatcherTest.java
@@ -85,10 +85,21 @@ public abstract class AbstractPairMatcherTest extends TestCase {
performMatch(matcher, "[% ]#");
performMatch(matcher, "{% }#");
+ performMatch(matcher, "#( %)%");
+ performMatch(matcher, "#[ %]%");
+ performMatch(matcher, "#{ %}%");
+ performMatch(matcher, "%(% )#");
+ performMatch(matcher, "%[% ]#");
+ performMatch(matcher, "%{% }#");
+
performMatch(matcher, "#( % )#");
performMatch(matcher, "#[ % ]#");
performMatch(matcher, "#{ % }#");
+ performMatch(matcher, "#( % % )#");
+ performMatch(matcher, "#[ % % ]#");
+ performMatch(matcher, "#{ % % }#");
+
matcher.dispose();
}
@@ -122,9 +133,17 @@ public abstract class AbstractPairMatcherTest extends TestCase {
performMatch(matcher, "(%())#");
performMatch(matcher, "((%)#)");
+ performMatch(matcher, "%(%)#");
+ performMatch(matcher, "#(()%)%");
+ performMatch(matcher, "%(%())#");
+ performMatch(matcher, "(%(%)#)");
+
performMatch(matcher, "#(%)#");
performMatch(matcher, "#(%())#");
+ performMatch(matcher, "#(% %)#");
+ performMatch(matcher, "#(% %())#");
+
matcher.dispose();
}
@@ -167,6 +186,13 @@ public abstract class AbstractPairMatcherTest extends TestCase {
performMatch(matcher, "|c #( c| ) ( |c % )# c|");
performMatch(matcher, "#( % |a ) a| |b ) b| |c ) c| )#");
+ performMatch(matcher, "#( % % |a a| )#");
+ performMatch(matcher, "|b #( % % )# b|");
+ performMatch(matcher, "|c #( % % c| ) ( |c )# c|");
+ performMatch(matcher, "|c #( c| ) ( |c % % )# c|");
+ performMatch(matcher, "#( % % |a ) a| |b ) b| |c ) c| )#");
+// performMatch(matcher, " #( |c ( c| % % |c ) c| )#");
+
matcher.dispose();
}
@@ -259,7 +285,7 @@ public abstract class AbstractPairMatcherTest extends TestCase {
*/
protected void performReaderTest(String testString, int expectedPos, int expectedMatch, String expectedString) {
TestCase t0= createTestCase(testString);
- assertEquals(expectedPos, t0.fPos);
+ assertEquals(expectedPos, t0.fPos1);
assertEquals(expectedMatch, t0.fMatch2);
assertEquals(expectedString, t0.fString);
}
@@ -275,12 +301,22 @@ public abstract class AbstractPairMatcherTest extends TestCase {
matcher.clear();
final IRegion region;
- if (test.isEnclosingTestCase()) {
+ if (test.isSelectionTestCase()) {
assertTrue((matcher instanceof ICharacterPairMatcherExtension));
ICharacterPairMatcherExtension matcherExtension= (ICharacterPairMatcherExtension)matcher;
- region= matcherExtension.findEnclosingPeerCharacters(test.getDocument(), test.fPos);
+ if (test.isEnclosingTestCase()) {
+ region= matcherExtension.findEnclosingPeerCharacters(test.getDocument(), test.fPos1, test.fPos2 - test.fPos1);
+ } else {
+ region= matcherExtension.match(test.getDocument(), test.fPos1, test.fPos2 - test.fPos1);
+ }
} else {
- region= matcher.match(test.getDocument(), test.fPos);
+ if (test.isEnclosingTestCase()) {
+ assertTrue((matcher instanceof ICharacterPairMatcherExtension));
+ ICharacterPairMatcherExtension matcherExtension= (ICharacterPairMatcherExtension)matcher;
+ region= matcherExtension.findEnclosingPeerCharacters(test.getDocument(), test.fPos1, test.fPos2 - test.fPos1);
+ } else {
+ region= matcher.match(test.getDocument(), test.fPos1);
+ }
}
if (test.fMatch2 == -1) {
@@ -289,11 +325,13 @@ public abstract class AbstractPairMatcherTest extends TestCase {
assertNull(region);
} else {
assertNotNull(region);
- final boolean isForward= test.isEnclosingTestCase() ? false : test.fPos > test.fMatch2;
+ final boolean isForward= test.isEnclosingTestCase() ? false : test.fPos1 > test.fMatch2;
assertEquals(isForward, matcher.getAnchor() == ICharacterPairMatcher.RIGHT);
final int offset= (isForward || test.isEnclosingTestCase()) ? test.getOffset() : test.getOffset() - 1;
- final int length= ((isForward && !fCaretInsideMatchedPair) || test.isEnclosingTestCase()) ? test.getLength() : test.getLength() + 1;
+ final int length= ((isForward && (!fCaretInsideMatchedPair || test.isSelectionTestCase())) || test.isEnclosingTestCase())
+ ? test.getLength()
+ : test.getLength() + 1;
assertEquals(length, region.getLength());
assertEquals(offset, region.getOffset());
}
@@ -313,49 +351,77 @@ public abstract class AbstractPairMatcherTest extends TestCase {
* @return the created test case
*/
public TestCase createTestCase(String str) {
- int pos= str.indexOf("%");
- assertFalse(pos == -1);
+ int pos1= str.indexOf("%");
+ assertFalse(pos1 == -1);
+ int pos2= str.lastIndexOf("%");
+ boolean selectionTest= pos1 != pos2;
+
int match1= str.indexOf("#");
int match2= str.lastIndexOf("#");
boolean enclosingTest= match1 != match2;
- if (fCaretInsideMatchedPair) {
- if (pos - 1 >= 0) {
- char ch= str.charAt(pos - 1);
+
+ if (!selectionTest && fCaretInsideMatchedPair) {
+ if (pos1 - 1 >= 0) {
+ char ch= str.charAt(pos1 - 1);
if ("()[]{}<>".indexOf(ch) % 2 == 1) {
- pos-= 1;
+ pos1-= 1;
}
}
}
// account for the length of marker characters
- if (!enclosingTest) {
- if (match1 != -1 && match1 < pos)
- pos-= 1;
- if (pos < match1)
- match1-= 1;
+ if (selectionTest) {
+ if (!enclosingTest) {
+ assertTrue(pos2 - pos1 == 2);
+ if (match1 != -1 && match1 < pos1) {
+ pos1-= 1;
+ pos2-= 2;
+ }
+ if (pos1 < match1) {
+ pos2-= 1;
+ match1-= 2;
+ }
+ } else {
+ pos1-= 1;
+ pos2-= 2;
+ match2-= 3;
+ }
} else {
- pos-= 1;
- match2-= 2;
+ if (!enclosingTest) {
+ if (match1 != -1 && match1 < pos1)
+ pos1-= 1;
+ if (pos1 < match1)
+ match1-= 1;
+ } else {
+ pos1-= 1;
+ match2-= 2;
+ }
+ pos2= pos1;
}
final String stripped= str.replaceAll("%", "").replaceAll("#", "");
- return enclosingTest ? new TestCase(stripped, pos, match1, match2) : new TestCase(stripped, pos, match1);
+
+ if (enclosingTest)
+ return new TestCase(stripped, pos1, pos2, match1, match2);
+ else {
+ if (selectionTest)
+ return new TestCase(stripped, pos1, pos2, pos2, match1);
+ else
+ return new TestCase(stripped, pos1, pos2, pos1, match1);
+ }
}
private class TestCase {
public final String fString;
- public final int fPos, fMatch1, fMatch2;
+ public final int fPos1, fPos2, fMatch1, fMatch2;
- public TestCase(String string, int pos, int match) {
- this(string, pos, pos, match);
- }
-
- public TestCase(String string, int pos, int match1, int match2) {
+ public TestCase(String string, int pos1, int pos2, int match1, int match2) {
fString= string;
- fPos= pos;
+ fPos1= pos1;
+ fPos2= pos2;
fMatch1= match1;
fMatch2= match2;
}
@@ -375,7 +441,11 @@ public abstract class AbstractPairMatcherTest extends TestCase {
}
public boolean isEnclosingTestCase() {
- return fPos != fMatch1;
+ return fPos1 != fMatch1 && fPos2 != fMatch1;
+ }
+
+ public boolean isSelectionTestCase() {
+ return fPos1 != fPos2;
}
}
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 40f17217f61..e8dae5280fb 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
@@ -34,6 +34,7 @@ public class JFaceTextTestSuite extends TestSuite {
suite.addTest(RulesTestSuite.suite());
suite.addTest(ReconcilerTestSuite.suite());
suite.addTest(DefaultPairMatcherTest.suite());
+ suite.addTest(DefaultPairMatcherTest2.suite());
return suite;
}
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/DefaultCharacterPairMatcher.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/DefaultCharacterPairMatcher.java
index 64bd558085b..1327c8a0340 100644
--- a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/DefaultCharacterPairMatcher.java
+++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/DefaultCharacterPairMatcher.java
@@ -108,21 +108,53 @@ public class DefaultCharacterPairMatcher implements ICharacterPairMatcher, IChar
}
/**
- * @see org.eclipse.jface.text.source.ICharacterPairMatcherExtension#findEnclosingPeerCharacters(org.eclipse.jface.text.IDocument, int)
+ * @see org.eclipse.jface.text.source.ICharacterPairMatcherExtension#match(org.eclipse.jface.text.IDocument,
+ * int, int)
* @since 3.8
*/
- public IRegion findEnclosingPeerCharacters(IDocument document, int offset) {
+ public IRegion match(IDocument document, int offset, int length) {
+ if (document == null || offset < 0 || offset > document.getLength() || Math.abs(length) > 1)
+ return null;
+
+ int sourceCaretOffset= offset + length;
+ int adjustment= getOffsetAdjustment(document, sourceCaretOffset, length);
+ sourceCaretOffset+= adjustment;
+
+ return match(document, sourceCaretOffset);
+ }
+
+ /**
+ * @see org.eclipse.jface.text.source.ICharacterPairMatcherExtension#findEnclosingPeerCharacters(org.eclipse.jface.text.IDocument,
+ * int, int)
+ * @since 3.8
+ */
+ public IRegion findEnclosingPeerCharacters(IDocument document, int offset, int length) {
if (document == null || offset < 0 || offset > document.getLength())
return null;
+
+ int start;
+ int end;
+ if (length >= 0) {
+ start= offset;
+ end= offset + length;
+ } else {
+ end= offset;
+ start= offset + length;
+ }
+
+ int sourceCaretOffset= offset + length;
+ int adjustment= getOffsetAdjustment(document, sourceCaretOffset, length);
+ sourceCaretOffset+= adjustment;
+
try {
- for (int offset1= offset; offset1 >= 0; offset1--) {
+ for (int offset1= sourceCaretOffset; offset1 >= 0; offset1--) {
char prevChar= document.getChar(Math.max(offset1 - 1, 0));
if (fPairs.contains(prevChar) && fPairs.isStartCharacter(prevChar)) {
IRegion match= performMatch(document, offset1);
if (match != null) {
int matchOffset= match.getOffset();
int matchLength= match.getLength();
- if ((matchOffset <= offset) && (matchOffset + matchLength > offset)) {
+ if ((matchOffset <= start) && (matchOffset + matchLength > start) && (matchOffset < end) && (matchOffset + matchLength >= end)) {
return match;
}
}
@@ -134,6 +166,36 @@ public class DefaultCharacterPairMatcher implements ICharacterPairMatcher, IChar
return null;
}
+ /**
+ * Computes the adjustment in the start offset for the purpose of finding a matching peer. The
+ * adjustment is non-zero only when the selection length is one and the selection covers a
+ * character matched by the matcher.
+ *
+ * @param document the document to work on
+ * @param offset the start offset
+ * @param length the selection length
+ * @return the start offset adjustment
+ * @since 3.8
+ */
+ private int getOffsetAdjustment(IDocument document, int offset, int length) {
+ if (length == 0 || Math.abs(length) > 1)
+ return 0;
+ try {
+ if (length < 0) {
+ if (fPairs.isStartCharacter(document.getChar(offset))) {
+ return 1;
+ }
+ } else {
+ if (fCaretInsideMatchedPair && fPairs.isEndCharacter(document.getChar(offset - 1))) {
+ return -1;
+ }
+ }
+ } catch (BadLocationException e) {
+ //do nothing
+ }
+ return 0;
+ }
+
/*
* Performs the actual work of matching for #match(IDocument, int).
*/
@@ -385,8 +447,8 @@ public class DefaultCharacterPairMatcher implements ICharacterPairMatcher, IChar
}
/**
- * Returns true of the specified character is a start character.
- *
+ * Returns true if the specified character is a start character.
+ *
* @param c a character
* @return true exactly if the character is a start character
*/
@@ -395,8 +457,19 @@ public class DefaultCharacterPairMatcher implements ICharacterPairMatcher, IChar
}
/**
+ * Returns true if the specified character is an end character.
+ *
+ * @param c a character
+ * @return true exactly if the character is an end character
+ * @since 3.8
+ */
+ public boolean isEndCharacter(char c) {
+ return this.isOpeningCharacter(c, false);
+ }
+
+ /**
* Returns the matching character for the specified character.
- *
+ *
* @param c a character occurring in a character pair
* @return the matching character
*/
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/ICharacterPairMatcher.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/ICharacterPairMatcher.java
index 6a7e8d9202a..5e09b636e29 100644
--- a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/ICharacterPairMatcher.java
+++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/ICharacterPairMatcher.java
@@ -28,7 +28,8 @@ import org.eclipse.jface.text.IRegion;
* exists:
* <ul>
* <li>{@link org.eclipse.jface.text.source.ICharacterPairMatcherExtension} since version 3.8
- * introducing the concept of enclosing peer characters at a caret offset.</li>
+ * introducing the concept of matching peer character and enclosing peer characters for a given
+ * selection.</li>
* </ul>
* </p>
* <p>
@@ -66,13 +67,18 @@ public interface ICharacterPairMatcher {
/**
* Starting at the given offset, the matcher chooses a character close to this offset. The
* matcher then searches for the matching peer character of the chosen character and if it finds
- * one, returns the minimal region of the document that contains both characters. It returns
- * <code>null</code> if there is no peer character.
+ * one, returns the minimal region of the document that contains both characters.
+ *
+ * <p>
+ * Since version 3.8 the recommended way for finding matching peers is to use
+ * {@link org.eclipse.jface.text.source.ICharacterPairMatcherExtension#match(IDocument, int, int)}
+ * .
+ * </p>
*
* @param document the document to work on
* @param offset the start offset
- * @return the minimal region containing the peer characters and <code>null</code> if there is
- * no peer character.
+ * @return the minimal region containing the peer characters or <code>null</code> if there is no
+ * peer character.
*/
IRegion match(IDocument document, int offset);
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/ICharacterPairMatcherExtension.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/ICharacterPairMatcherExtension.java
index 1c03e232317..32ceac7fe9d 100644
--- a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/ICharacterPairMatcherExtension.java
+++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/ICharacterPairMatcherExtension.java
@@ -16,8 +16,8 @@ import org.eclipse.jface.text.IRegion;
/**
* Extension interface {@link org.eclipse.jface.text.source.ICharacterPairMatcher}.
* <p>
- * Extends the character pair matcher with the concept of enclosing peer characters at a caret
- * offset.
+ * Extends the character pair matcher with the concept of matching peer character and enclosing peer
+ * characters for a given selection.
*
* @see org.eclipse.jface.text.source.ICharacterPairMatcher
* @since 3.8
@@ -25,13 +25,30 @@ import org.eclipse.jface.text.IRegion;
public interface ICharacterPairMatcherExtension {
/**
- * Starting at the given offset, the matcher searches for a pair of enclosing peer characters
+ * Starting with the selected character or a character close to the given <code>offset</code>,
+ * the matcher searches for the matching peer character and if it finds one, returns the minimal
+ * region of the document that contains both characters.
+ *
+ * @param document the document to work on
+ * @param offset the start offset
+ * @param length the selection length. The length can be negative indicating right-to-left
+ * selection.
+ * @return the minimal region containing the peer characters or <code>null</code> if there is no
+ * peer character.
+ */
+ IRegion match(IDocument document, int offset, int length);
+
+
+ /**
+ * Starting at the given selection, the matcher searches for a pair of enclosing peer characters
* and if it finds one, returns the minimal region of the document that contains the pair.
*
* @param document the document to work on
* @param offset the start offset
+ * @param length the selection length. The length can be negative indicating right-to-left
+ * selection.
* @return the minimal region containing the peer characters or <code>null</code> if there is no
* enclosing pair
*/
- IRegion findEnclosingPeerCharacters(IDocument document, int offset);
+ IRegion findEnclosingPeerCharacters(IDocument document, int offset, int length);
}
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/MatchingCharacterPainter.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/MatchingCharacterPainter.java
index 783bd0699e7..f32f1a0b7fc 100644
--- a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/MatchingCharacterPainter.java
+++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/MatchingCharacterPainter.java
@@ -232,6 +232,31 @@ public final class MatchingCharacterPainter implements IPainter, PaintListener {
}
}
+ /**
+ * Returns the signed current selection. The length will be negative if the resulting selection
+ * is right-to-left.
+ * <p>
+ * The selection offset is model based.
+ * </p>
+ *
+ * @param sourceViewer the source viewer
+ * @return a region denoting the current signed selection, for a resulting RtoL selections
+ * length is < 0
+ * @since 3.8
+ */
+ private static final IRegion getSignedSelection(ISourceViewer sourceViewer) {
+ Point viewerSelection= sourceViewer.getSelectedRange();
+
+ StyledText text= sourceViewer.getTextWidget();
+ Point selection= text.getSelectionRange();
+ if (text.getCaretOffset() == selection.x) {
+ viewerSelection.x= viewerSelection.x + viewerSelection.y;
+ viewerSelection.y= -viewerSelection.y;
+ }
+
+ return new Region(viewerSelection.x, viewerSelection.y);
+ }
+
/*
* @see org.eclipse.jface.text.IPainter#paint(int)
*/
@@ -243,17 +268,24 @@ public final class MatchingCharacterPainter implements IPainter, PaintListener {
return;
}
- Point selection= fSourceViewer.getSelectedRange();
- if (selection.y > 0) {
- deactivate(true);
- return;
- }
+ IRegion selection= getSignedSelection(fSourceViewer);
+ IRegion pair;
+ boolean characterPresentAtCaretLocation;
- IRegion pair= fMatcher.match(document, selection.x);
- boolean characterPresentAtCaretLocation= (pair != null);
- if (pair == null && fHighlightEnclosingPeerCharcters && fMatcher instanceof ICharacterPairMatcherExtension) {
+ if (fMatcher instanceof ICharacterPairMatcherExtension) {
ICharacterPairMatcherExtension matcher= (ICharacterPairMatcherExtension)fMatcher;
- pair= matcher.findEnclosingPeerCharacters(document, selection.x);
+ pair= matcher.match(document, selection.getOffset(), selection.getLength());
+ characterPresentAtCaretLocation= (pair != null);
+ if (pair == null && fHighlightEnclosingPeerCharcters) {
+ pair= matcher.findEnclosingPeerCharacters(document, selection.getOffset(), selection.getLength());
+ }
+ } else {
+ if (Math.abs(selection.getLength()) > 0) {
+ deactivate(true);
+ return;
+ }
+ pair= fMatcher.match(document, selection.getOffset());
+ characterPresentAtCaretLocation= (pair != null);
}
if (pair == null) {

Back to the top