/*******************************************************************************
* 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);
}
}