diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/PairMatcherTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/PairMatcherTest.java new file mode 100644 index 00000000000..332b2511271 --- /dev/null +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/PairMatcherTest.java @@ -0,0 +1,157 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Anton Leherbauer (Wind River Systems) - Adapted for CDT + *******************************************************************************/ +package org.eclipse.cdt.ui.tests.text; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.rules.FastPartitioner; + +import org.eclipse.cdt.ui.text.ICPartitions; + +import org.eclipse.cdt.internal.ui.text.CPairMatcher; +import org.eclipse.cdt.internal.ui.text.FastCPartitionScanner; + +public class PairMatcherTest extends TestCase { + + private static boolean BEFORE_MATCHES_DISABLED= true; + + protected IDocument fDocument; + protected CPairMatcher fPairMatcher; + + + public PairMatcherTest(String name) { + super(name); + } + + protected void setUp() { + Document document= new Document("xx(yy(xx)yy)xx"); + String[] types= new String[] { + ICPartitions.C_MULTI_LINE_COMMENT, + ICPartitions.C_SINGLE_LINE_COMMENT, + ICPartitions.C_STRING, + ICPartitions.C_CHARACTER, + IDocument.DEFAULT_CONTENT_TYPE + }; + FastPartitioner partitioner= new FastPartitioner(new FastCPartitionScanner(), types); + partitioner.connect(document); + document.setDocumentPartitioner(ICPartitions.C_PARTITIONING, partitioner); + + fDocument= document; + fPairMatcher= new CPairMatcher(new char[] { '(', ')' }); + } + + public static Test suite() { + return new TestSuite(PairMatcherTest.class); + } + + protected void tearDown () { + fDocument= null; + fPairMatcher= null; + } + + public void testBeforeOpeningMatch() { + IRegion match= fPairMatcher.match(fDocument, 2); + if (BEFORE_MATCHES_DISABLED) { + assertNull(match); + } else { + assertNotNull(match); + assertTrue(match.getOffset() == 2 && match.getLength() == 10); + } + + match= fPairMatcher.match(fDocument, 5); + if (BEFORE_MATCHES_DISABLED) { + assertNull(match); + } else { + assertNotNull(match); + assertTrue(match.getOffset() == 5 && match.getLength() == 4); + } + } + + public void testAfterOpeningMatch() { + IRegion match= fPairMatcher.match(fDocument, 3); + assertNotNull(match); + assertTrue(match.getOffset() == 2 && match.getLength() == 10); + + match= fPairMatcher.match(fDocument, 6); + assertNotNull(match); + assertTrue(match.getOffset() == 5 && match.getLength() == 4); + } + + public void testBeforeClosingMatch() { + IRegion match= fPairMatcher.match(fDocument, 11); + if (BEFORE_MATCHES_DISABLED) { + assertNull(match); + } else { + assertNotNull(match); + assertTrue(match.getOffset() == 2 && match.getLength() == 10); + } + + match= fPairMatcher.match(fDocument, 8); + if (BEFORE_MATCHES_DISABLED) { + assertNull(match); + } else { + assertNotNull(match); + assertTrue(match.getOffset() == 5 && match.getLength() == 4); + } + } + + public void testAfterClosingMatch() { + IRegion match= fPairMatcher.match(fDocument, 12); + assertNotNull(match); + assertTrue(match.getOffset() == 2 && match.getLength() == 10); + + match= fPairMatcher.match(fDocument, 9); + assertNotNull(match); + assertTrue(match.getOffset() == 5 && match.getLength() == 4); + } + + public void testBeforeClosingMatchWithNL() { + fDocument.set("x(y\ny)x"); + IRegion match= fPairMatcher.match(fDocument, 5); + if (BEFORE_MATCHES_DISABLED) { + assertNull(match); + } else { + assertNotNull(match); + assertTrue(match.getOffset() == 1 && match.getLength() == 5); + } + } + + public void testAfterClosingMatchWithNL() { + fDocument.set("x(y\ny)x"); + IRegion match= fPairMatcher.match(fDocument, 6); + assertNotNull(match); + assertTrue(match.getOffset() == 1 && match.getLength() == 5); + } + + public void testBeforeClosingMatchWithNLAndSingleLineComment() { + fDocument.set("x\nx(y\nx //(x\ny)x"); + IRegion match= fPairMatcher.match(fDocument, 14); + if (BEFORE_MATCHES_DISABLED) { + assertNull(match); + } else { + assertNotNull(match); + assertTrue(match.getOffset() == 3 && match.getLength() == 12); + } + } + + public void testAfterClosingMatchWithNLAndSingleLineComment() { + fDocument.set("x\nx(y\nx //(x\ny)x"); + IRegion match= fPairMatcher.match(fDocument, 15); + assertNotNull(match); + assertTrue(match.getOffset() == 3 && match.getLength() == 12); + } +} diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/TextTestSuite.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/TextTestSuite.java index 5202dcc6195..0547540c4c7 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/TextTestSuite.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/TextTestSuite.java @@ -20,13 +20,13 @@ public class TextTestSuite extends TestSuite { } public TextTestSuite() { - super("Tests in package org.eclipse.cdt.ui.tests.text.text"); + super("Tests in package org.eclipse.cdt.ui.tests.text"); - // Success Tests //addTest(PartitionTokenScannerTest.suite()); addTest(NumberRuleTest.suite()); addTest(CAutoIndentTest.suite()); addTest(CPartitionerTest.suite()); + addTest(PairMatcherTest.suite()); // Break iterator tests. addTest(CBreakIteratorTest.suite()); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CDoubleClickSelector.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CDoubleClickSelector.java index f508a02cfcf..d7e37c17e37 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CDoubleClickSelector.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CDoubleClickSelector.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000 2005 IBM Corporation and others. + * Copyright (c) 2000 2006 IBM Corporation 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 @@ -8,11 +8,13 @@ * Contributors: * IBM Corporation - initial API and implementation * QNX Software System + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui.text; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextDoubleClickStrategy; import org.eclipse.jface.text.ITextViewer; @@ -25,12 +27,14 @@ public class CDoubleClickSelector implements ITextDoubleClickStrategy { protected int fPos; protected int fStartPos; protected int fEndPos; + private CPairMatcher fPairMatcher; protected static char[] fgBrackets= {'{', '}', '(', ')', '[', ']', '"', '"'}; public CDoubleClickSelector() { super(); + fPairMatcher= new CPairMatcher(fgBrackets); } @@ -50,60 +54,18 @@ public class CDoubleClickSelector implements ITextDoubleClickStrategy { if (!selectBracketBlock()) selectWord(); + + fText= null; } protected boolean matchBracketsAt() { - char prevChar, nextChar; - - - int i; - int bracketIndex1= fgBrackets.length; - int bracketIndex2= fgBrackets.length; - - - fStartPos= -1; - fEndPos= -1; - - // get the chars preceding and following the start position - try { - IDocument doc= fText.getDocument(); - - - prevChar= doc.getChar(fPos - 1); - nextChar= doc.getChar(fPos); - - - // is the char either an open or close bracket? - for (i= 0; i < fgBrackets.length; i= i + 2) { - if (prevChar == fgBrackets[i]) { - fStartPos= fPos - 1; - bracketIndex1= i; - } - } - for (i= 1; i < fgBrackets.length; i= i + 2) { - if (nextChar == fgBrackets[i]) { - fEndPos= fPos; - bracketIndex2= i; - } - } - - - if (fStartPos > -1 && bracketIndex1 < bracketIndex2) { - fEndPos= searchForClosingBracket(fStartPos, prevChar, fgBrackets[bracketIndex1 + 1], doc); - if (fEndPos > -1) - return true; - fStartPos= -1; - } else if (fEndPos > -1) { - fStartPos= searchForOpenBracket(fEndPos, fgBrackets[bracketIndex2 - 1], nextChar, doc); - if (fStartPos > -1) - return true; - fEndPos= -1; - } - } catch (BadLocationException x) { + IRegion region= fPairMatcher.match(fText.getDocument(), fPos); + if (region != null && region.getLength() > 0) { + fStartPos= region.getOffset(); + fEndPos= fStartPos + region.getLength() - 1; + return true; } - - return false; } @@ -146,50 +108,6 @@ public class CDoubleClickSelector implements ITextDoubleClickStrategy { } - protected int searchForClosingBracket(int startPos, char openBracket, char closeBracket, IDocument doc) throws BadLocationException { - int stack= 1; - int closePos= startPos + 1; - int length= doc.getLength(); - char nextChar; - - - while (closePos < length && stack > 0) { - nextChar= doc.getChar(closePos); - if (nextChar == openBracket && nextChar != closeBracket) - stack++; - else if (nextChar == closeBracket) - stack--; - closePos++; - } - - - if (stack == 0) - return closePos - 1; - return -1; - } - - - protected int searchForOpenBracket(int startPos, char openBracket, char closeBracket, IDocument doc) throws BadLocationException { - int stack= 1; - int openPos= startPos - 1; - char nextChar; - - while (openPos >= 0 && stack > 0) { - nextChar= doc.getChar(openPos); - if (nextChar == closeBracket && nextChar != openBracket) - stack++; - else if (nextChar == openBracket) - stack--; - openPos--; - } - - - if (stack == 0) - return openPos + 1; - return -1; - } - - protected boolean selectBracketBlock() { if (matchBracketsAt()) { if (fStartPos == fEndPos) diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CPairMatcher.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CPairMatcher.java index eb5f65e1f68..cecf3e03c84 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CPairMatcher.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CPairMatcher.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000 2005 IBM Corporation and others. + * Copyright (c) 2000 2006 IBM Corporation 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 @@ -8,17 +8,19 @@ * Contributors: * IBM Corporation - initial API and implementation * QNX Software System + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.ui.text; -import java.io.IOException; - import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.Region; +import org.eclipse.jface.text.TextUtilities; import org.eclipse.jface.text.source.ICharacterPairMatcher; +import org.eclipse.cdt.ui.text.ICPartitions; + /** * Helper class for match pairs of characters. */ @@ -32,12 +34,13 @@ public class CPairMatcher implements ICharacterPairMatcher { protected int fEndPos; protected int fAnchor; - protected CCodeReader fReader = new CCodeReader(); - public CPairMatcher(char[] pairs) { fPairs = pairs; } + /* + * @see org.eclipse.jface.text.source.ICharacterPairMatcher#match(org.eclipse.jface.text.IDocument, int) + */ public IRegion match(IDocument document, int offset) { fOffset = offset; @@ -53,28 +56,27 @@ public class CPairMatcher implements ICharacterPairMatcher { return null; } + /* + * @see org.eclipse.jface.text.source.ICharacterPairMatcher#getAnchor() + */ public int getAnchor() { return fAnchor; } /* - * @see org.eclipse.jface.text.source.ICharacterPairMatcher#clear() - */ + * @see org.eclipse.jface.text.source.ICharacterPairMatcher#clear() + */ public void clear() { - if (fReader != null) { - try { - fReader.close(); - } catch (IOException x) { - // ignore - } - } } + /* + * @see org.eclipse.jface.text.source.ICharacterPairMatcher#dispose() + */ public void dispose() { clear(); fDocument = null; - fReader = null; } + protected boolean matchPairsAt() { int i; @@ -88,15 +90,9 @@ public class CPairMatcher implements ICharacterPairMatcher { try { char prevChar= fDocument.getChar(Math.max(fOffset - 1, 0)); -// modified behavior for http://dev.eclipse.org/bugs/show_bug.cgi?id=16879 -// char nextChar= fDocument.getChar(fOffset); // search for opening peer character next to the activation point for (i= 0; i < fPairs.length; i= i + 2) { -// if (nextChar == fPairs[i]) { -// fStartPos= fOffset; -// pairIndex1= i; -// } else if (prevChar == fPairs[i]) { fStartPos= fOffset - 1; pairIndex1= i; @@ -109,10 +105,6 @@ public class CPairMatcher implements ICharacterPairMatcher { fEndPos= fOffset - 1; pairIndex2= i; } -// else if (nextChar == fPairs[i]) { -// fEndPos= fOffset; -// pairIndex2= i; -// } } if (fEndPos > -1) { @@ -130,118 +122,22 @@ public class CPairMatcher implements ICharacterPairMatcher { } } catch (BadLocationException x) { - } catch (IOException x) { } return false; } - -// protected boolean matchPairsAt() { -// -// int i; -// int pairIndex1 = fPairs.length; -// int pairIndex2 = fPairs.length; -// -// fStartPos = -1; -// fEndPos = -1; -// -// // get the chars preceding and following the start position -// try { -// -// /* -// A quick hack to get around the fact that we can't bracket -// match on the very first element of a document. We make the -// character to match a null character which is unlikely to match. -// */ -// char prevChar = (fOffset > 0) ? fDocument.getChar(fOffset - 1) : '\0'; -// char nextChar = fDocument.getChar(fOffset); -// -// // search for opening peer character next to the activation point -// for (i = 0; i < fPairs.length; i = i + 2) { -// if (nextChar == fPairs[i]) { -// fStartPos = fOffset; -// pairIndex1 = i; -// } else if (prevChar == fPairs[i]) { -// fStartPos = fOffset - 1; -// pairIndex1 = i; -// } -// } -// -// // search for closing peer character next to the activation point -// for (i = 1; i < fPairs.length; i = i + 2) { -// if (prevChar == fPairs[i]) { -// fEndPos = fOffset - 1; -// pairIndex2 = i; -// } else if (nextChar == fPairs[i]) { -// fEndPos = fOffset; -// pairIndex2 = i; -// } -// } -// -// if (fEndPos > -1) { -// fAnchor = RIGHT; -// fStartPos = searchForOpeningPeer(fEndPos, fPairs[pairIndex2 - 1], fPairs[pairIndex2], fDocument); -// if (fStartPos > -1) -// return true; -// else -// fEndPos = -1; -// } else if (fStartPos > -1) { -// fAnchor = LEFT; -// fEndPos = searchForClosingPeer(fStartPos, fPairs[pairIndex1], fPairs[pairIndex1 + 1], fDocument); -// if (fEndPos > -1) -// return true; -// else -// fStartPos = -1; -// } -// -// } catch (BadLocationException x) { -// } catch (IOException x) { -// } -// -// return false; -// } - - protected int searchForClosingPeer(int offset, int openingPeer, int closingPeer, IDocument document) throws IOException { - - fReader.configureForwardReader(document, offset + 1, document.getLength(), true, true); - - int stack = 1; - int c = fReader.read(); - while (c != CCodeReader.EOF) { - if (c == openingPeer && c != closingPeer) - stack++; - else if (c == closingPeer) - stack--; - - if (stack == 0) - return fReader.getOffset(); - - c = fReader.read(); - } - - return -1; + protected int searchForClosingPeer(int offset, char openingPeer, char closingPeer, IDocument document) throws BadLocationException { + CHeuristicScanner scanner= new CHeuristicScanner(document, ICPartitions.C_PARTITIONING, TextUtilities.getContentType(document, ICPartitions.C_PARTITIONING, offset, false)); + return scanner.findClosingPeer(offset + 1, openingPeer, closingPeer); } - protected int searchForOpeningPeer(int offset, int openingPeer, int closingPeer, IDocument document) throws IOException { - - fReader.configureBackwardReader(document, offset, true, true); - - int stack = 1; - int c = fReader.read(); - while (c != CCodeReader.EOF) { - if (c == closingPeer && c != openingPeer) - stack++; - else if (c == openingPeer) - stack--; - - if (stack == 0) - return fReader.getOffset(); - - c = fReader.read(); - } - - return -1; + protected int searchForOpeningPeer(int offset, char openingPeer, char closingPeer, IDocument document) throws BadLocationException { + CHeuristicScanner scanner= new CHeuristicScanner(document, ICPartitions.C_PARTITIONING, TextUtilities.getContentType(document, ICPartitions.C_PARTITIONING, offset, false)); + int peer= scanner.findOpeningPeer(offset - 1, openingPeer, closingPeer); + if (peer == CHeuristicScanner.NOT_FOUND) + return -1; + return peer; } -} \ No newline at end of file +}