/******************************************************************************* * Copyright (c) 2010, 2011 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: * Bruno Medeiros - initial API and implementation *******************************************************************************/ package melnorme.lang.ide.core_text; import static melnorme.utilbox.core.Assert.AssertNamespace.assertNotNull; import static melnorme.utilbox.core.Assert.AssertNamespace.assertTrue; import melnorme.lang.ide.core.text.AbstractDocumentScanner; import melnorme.lang.ide.core.text.BlockHeuristicsScannner; import melnorme.lang.ide.core.text.TextSourceUtils; import melnorme.lang.ide.core.text.BlockHeuristicsScannner.BlockTokenRule; import org.eclipse.jface.text.BadLocationException; import org.junit.Test; public class BlockHeuristicsScannnerTest extends Scanner_BaseTest { public static BlockTokenRule[] SAMPLE_BLOCK_TOKENS = new BlockTokenRule[] { new BlockTokenRule('{', '}'), new BlockTokenRule('(', ')') }; public static final boolean LEFT_INVALID = true; protected BlockHeuristicsScannner setupSource(String source) { getDocument().set(source); return setupScanner(); } public BlockHeuristicsScannner setupScanner() { return new BlockHeuristicsScannner(getDocument(), null, null, SAMPLE_BLOCK_TOKENS); } @Test public void testBasic() throws Exception { testBasic$(); } public void testBasic$() throws Exception { testScanToBlockStart("", "{blah", "}", 0); testScanToBlockStart("", "blah", "}", 1); testScanToBlockStart("", "(blah", ")", 0); testScanToBlockStart("", "blah", ")", 1); testScanToBlockStart("", "{", "}", 0); testScanToBlockStart("", "", "}", 1); } protected void testScanToBlockStart(String srcPre, String scrBlock, String srcAfter, int expecBalance) throws BadLocationException { testScanToBlockStart(srcPre, scrBlock, srcAfter, expecBalance, false); } protected void testScanToBlockStart(String srcPre, String srcBlock, String srcAfter, int expecBalance, boolean expecInvalidLeft) throws BadLocationException { String srcBefore = srcPre + srcBlock; BlockHeuristicsScannner scanner = setupSource(srcBefore + srcAfter); char closeChar = srcAfter.charAt(0); assertNotNull(scanner.getOpeningPeer(closeChar)); int balance = scanner.scanToBlockStart(srcBefore.length()); assertTrue(balance == expecBalance); assertTrue(scanner.getPosition() == srcPre.length()); assertTrue((scanner.getLastToken() == AbstractDocumentScanner.TOKEN_INVALID) == expecInvalidLeft); if(balance == 0) { int blockEndOffset = srcBefore.length(); if (scanner.getLastToken() != AbstractDocumentScanner.TOKEN_INVALID) { balance = scanner.scanToBlockEnd(scanner.getPosition()); assertTrue(balance == 0); assertEquals(scanner.getPosition()-1, blockEndOffset); } else { // There must be a brace next to where the scanner stopped scanner.scanToBlockEnd(scanner.getPosition()-1); assertTrue(scanner.getPosition() == document.getLength() || scanner.getPosition() > blockEndOffset); } } // Now let's try a reverted test case, which should yield the same result String srcBeforeR = reverse(srcAfter); String srcAfterR = reverse(srcBefore); scanner = setupSource(srcBeforeR + srcAfterR); balance = scanner.scanToBlockEnd(srcBeforeR.length()-1); assertTrue(balance == expecBalance); assertTrue(scanner.getPosition() == reversePosition(srcPre.length())); assertTrue((scanner.getLastToken() == AbstractDocumentScanner.TOKEN_INVALID) == expecInvalidLeft); } protected String reverse(String string) { StringBuffer buffer = new StringBuffer(); for (int i = string.length()-1; i >= 0; i--) { char ch = string.charAt(i); char revertedCh = TextSourceUtils.getBracePair(ch); buffer.append(revertedCh); } return buffer.toString(); } protected int reversePosition(int position) { return document.getLength() - position; } @Test public void testScanToBlockStart() throws Exception { testScanToBlockStart$(); } public void testScanToBlockStart$() throws Exception { testScanToBlockStart("{{", "{blah", "}", 0); testScanToBlockStart("}}", "{blah", "} {}", 0); testScanToBlockStart("", "}}aaaa", "}" +NEUTRAL_SRC1, 3); testScanToBlockStart("", "} {abc(foo) blah;} }} aaaa", "}" +NEUTRAL_SRC2, 4); testScanToBlockStart("", "} (abc{foo} blah;) }} aaaa", "}" +NEUTRAL_SRC2, 4); testScanToBlockStart(NEUTRAL_SRC1+"{{() ({", "{blah(aaa)", "}", 0); testScanToBlockStart(NEUTRAL_SRC2+"{{() ({", "{blah((aaa { (asd) } ))", "}", 0); // Now some syntax errors: testScanToBlockStart(NEUTRAL_SRC1+"{(", "{ )", "}", 0); testScanToBlockStart(NEUTRAL_SRC1+"{(", "{ (", "}", 0); testScanToBlockStart(NEUTRAL_SRC2+"{(", "( {( }", ")", 0); testScanToBlockStart(NEUTRAL_SRC2+"{", "", ")", 0, LEFT_INVALID); testScanToBlockStart(NEUTRAL_SRC2+"{", " ", ")", 0, LEFT_INVALID); testScanToBlockStart(NEUTRAL_SRC2+"{", " ))", ")", 0, LEFT_INVALID); testScanToBlockStart("", " ()", "}", 1); testScanToBlockStart("", " ) (", "}", 2); testScanToBlockStart("(({", " ()", ")", 0, LEFT_INVALID); testScanToBlockStart("(({", " ) [", ")", 0, LEFT_INVALID); testScanToBlockStart(NEUTRAL_SRC1+"(", "(({)) ))})", ")", 0); testScanToBlockStart(NEUTRAL_SRC1+"(", "( {(( ((} ", ")", 0); testScanToBlockStart(NEUTRAL_SRC1+"(({", " {} {()} ) {(( ((} ", ")", 0, LEFT_INVALID); } }