1 19 20 package org.netbeans.lib.lexer.test; 21 22 import java.lang.reflect.Field ; 23 import java.util.ArrayList ; 24 import java.util.Collection ; 25 import java.util.Iterator ; 26 import java.util.List ; 27 import javax.swing.event.DocumentEvent ; 28 import javax.swing.event.DocumentListener ; 29 import javax.swing.text.BadLocationException ; 30 import javax.swing.text.Document ; 31 import junit.framework.TestCase; 32 import org.netbeans.api.lexer.Language; 33 import org.netbeans.api.lexer.Token; 34 import org.netbeans.api.lexer.TokenHierarchyEvent; 35 import org.netbeans.api.lexer.TokenHierarchyListener; 36 import org.netbeans.api.lexer.TokenHierarchy; 37 import org.netbeans.api.lexer.TokenId; 38 import org.netbeans.api.lexer.TokenSequence; 39 import org.netbeans.api.lexer.TokenUtilities; 40 import org.netbeans.junit.NbTestCase; 41 import org.netbeans.lib.lexer.TokenList; 42 import org.netbeans.lib.lexer.test.dump.TokenDumpCheck; 43 44 45 50 public final class LexerTestUtilities { 51 52 53 private static final boolean testing = Boolean.getBoolean("netbeans.debug.lexer.test"); 54 55 private static final String LAST_TOKEN_HIERARCHY = "last-token-hierarchy"; 56 57 private static Field tokenListField; 58 59 private LexerTestUtilities() { 60 } 62 63 66 public static void assertTokenEquals(TokenSequence<? extends TokenId> ts, TokenId id, String text, int offset) { 67 assertTokenEquals(null, ts, id, text, offset); 68 } 69 70 76 public static void assertTokenEquals(String message, TokenSequence<? extends TokenId> ts, TokenId id, String text, int offset) { 77 message = messagePrefix(message); 78 Token<? extends TokenId> t = ts.token(); 79 TestCase.assertNotNull("Token is null", t); 80 TokenId tId = t.id(); 81 TestCase.assertEquals(message + "Invalid token.id()", id, tId); 82 CharSequence tText = t.text(); 83 assertTextEquals(message + "Invalid token.text()", text, tText); 84 TestCase.assertEquals(message + "Invalid token.length()", text.length(), t.length()); 86 87 if (offset != -1) { 88 int tsOffset = ts.offset(); 89 TestCase.assertEquals(message + "Invalid tokenSequence.offset()", offset, tsOffset); 90 91 int tOffset = t.offset(null); 95 assertTokenOffsetMinusOneForFlyweight(t.isFlyweight(), tOffset); 96 if (!t.isFlyweight()) { 97 assertTokenOffsetsEqual(message, tOffset, offset); 98 } 99 } 100 } 101 102 public static void assertTokenEquals(TokenSequence<? extends TokenId> ts, TokenId id, String text, int offset, 103 int lookahead, Object state) { 104 assertTokenEquals(null, ts, id, text, offset, lookahead, state); 105 } 106 107 public static void assertTokenEquals(String message, TokenSequence<? extends TokenId> ts, TokenId id, String text, int offset, 108 int lookahead, Object state) { 109 assertTokenEquals(message, ts, id, text, offset); 110 111 Token t = ts.token(); 112 message = messagePrefix(message); 113 TestCase.assertEquals(message + "Invalid token.lookahead()", lookahead, lookahead(ts)); 114 TestCase.assertEquals(message + "Invalid token.state()", state, state(ts)); 115 } 116 117 public static void assertTokenOffsetsEqual(String message, int offset1, int offset2) { 118 if (offset1 != -1 && offset2 != -1) { TestCase.assertEquals(messagePrefix(message) 120 + "Offsets equal", offset1, offset2); 121 } 122 } 123 124 public static void assertTokenFlyweight(Token token) { 125 TestCase.assertEquals("Token flyweight", true, token.isFlyweight()); 126 } 127 128 public static void assertTokenNotFlyweight(Token token) { 129 TestCase.assertEquals("Token not flyweight", true, !token.isFlyweight()); 130 } 131 132 private static void assertTokenOffsetMinusOneForFlyweight(boolean tokenFlyweight, int offset) { 133 if (tokenFlyweight) { 134 TestCase.assertEquals("Flyweight token => token.offset()=-1", -1, offset); 135 } else { TestCase.assertTrue("Non-flyweight token => token.offset()!=-1 but " + offset, (offset != -1)); 137 } 138 } 139 140 143 public static void assertNextTokenEquals(TokenSequence<? extends TokenId> ts, TokenId id, String text) { 144 assertNextTokenEquals(null, ts, id, text); 145 } 146 147 public static void assertNextTokenEquals(String message, TokenSequence<? extends TokenId> ts, TokenId id, String text) { 148 String messagePrefix = messagePrefix(message); 149 TestCase.assertTrue(messagePrefix + "No next token available", ts.moveNext()); 150 assertTokenEquals(message, ts, id, text, -1); 151 } 152 153 156 public static void assertTokenSequencesEqual( 157 TokenSequence<? extends TokenId> expected, TokenHierarchy<?> expectedHi, 158 TokenSequence<? extends TokenId> actual, TokenHierarchy<?> actualHi, 159 boolean testLookaheadAndState) { 160 assertTokenSequencesEqual(null, expected, expectedHi, actual, actualHi, testLookaheadAndState); 161 } 162 163 179 public static void assertTokenSequencesEqual(String message, 180 TokenSequence<? extends TokenId> expected, TokenHierarchy<?> expectedHi, 181 TokenSequence<? extends TokenId> actual, TokenHierarchy<?> actualHi, 182 boolean testLookaheadAndState) { 183 boolean success = false; 184 try { 185 String prefix = messagePrefix(message); 186 TestCase.assertEquals(prefix + "Move previous: ", expected.movePrevious(), actual.movePrevious()); 187 while (expected.moveNext()) { 188 TestCase.assertTrue(prefix + "Move next: ", actual.moveNext()); 189 assertTokensEqual(message, expected, expectedHi, actual, actualHi, testLookaheadAndState); 190 } 191 TestCase.assertFalse(prefix + "Move next not disabled", actual.moveNext()); 192 success = true; 193 } finally { 194 if (!success) { 195 System.err.println("Expected token sequence dump:\n" + expected); 196 System.err.println("Test token sequence dump:\n" + actual); 197 } 198 } 199 } 200 201 private static void assertTokensEqual(String message, 202 TokenSequence<? extends TokenId> ts, TokenHierarchy tokenHierarchy, 203 TokenSequence<? extends TokenId> ts2, TokenHierarchy tokenHierarchy2, boolean testLookaheadAndState) { 204 Token<? extends TokenId> t = ts.token(); 205 Token<? extends TokenId> t2 = ts2.token(); 206 207 message = messagePrefix(message); 208 TestCase.assertEquals(message + "Invalid token id", t.id(), t2.id()); 209 assertTextEquals(message + "Invalid token text", t.text(), t2.text()); 210 211 assertTokenOffsetsEqual(message, t.offset(tokenHierarchy), t2.offset(tokenHierarchy2)); 212 TestCase.assertEquals(message + "Invalid tokenSequence offset", ts.offset(), ts2.offset()); 213 214 if (testing && testLookaheadAndState) { 216 TestCase.assertEquals(message + "Invalid token.lookahead()", lookahead(ts), lookahead(ts2)); 217 TestCase.assertEquals(message + "Invalid token.state()", state(ts), state(ts2)); 218 } 219 TestCase.assertEquals(message + "Invalid token length", t.length(), t2.length()); 220 TestCase.assertEquals(message + "Invalid token part", t.partType(), t2.partType()); 221 } 222 223 229 public static int flyweightTokenCount(TokenSequence<? extends TokenId> ts) { 230 int flyTokenCount = 0; 231 ts.moveIndex(0); 232 while (ts.moveNext()) { 233 if (ts.token().isFlyweight()) { 234 flyTokenCount++; 235 } 236 } 237 return flyTokenCount; 238 } 239 240 248 public static int flyweightTextLength(TokenSequence<? extends TokenId> ts) { 249 int flyTokenTextLength = 0; 250 ts.moveIndex(0); 251 while (ts.moveNext()) { 252 if (ts.token().isFlyweight()) { 253 flyTokenTextLength += ts.token().text().length(); 254 } 255 } 256 return flyTokenTextLength; 257 } 258 259 266 public static List <Integer > flyweightDistribution(TokenSequence<? extends TokenId> ts) { 267 List <Integer > distribution = new ArrayList <Integer >(); 268 ts.moveIndex(0); 269 while (ts.moveNext()) { 270 if (ts.token().isFlyweight()) { 271 int len = ts.token().text().length(); 272 while (distribution.size() <= len) { 273 distribution.add(0); 274 } 275 distribution.set(len, distribution.get(len) + 1); 276 } 277 } 278 return distribution; 279 } 280 281 public static boolean collectionsEqual(Collection <?> c1, Collection <?> c2) { 282 return c1.containsAll(c2) && c2.containsAll(c1); 283 } 284 285 public static void assertCollectionsEqual(Collection expected, Collection actual) { 286 assertCollectionsEqual(null, expected, actual); 287 } 288 289 public static void assertCollectionsEqual(String message, Collection expected, Collection actual) { 290 if (!collectionsEqual(expected, actual)) { 291 message = messagePrefix(message); 292 for (Iterator it = expected.iterator(); it.hasNext();) { 293 Object o = it.next(); 294 if (!actual.contains(o)) { 295 System.err.println(actual.toString()); 296 TestCase.fail(message + " Object " + o + " not contained in tested collection"); 297 } 298 } 299 for (Iterator it = actual.iterator(); it.hasNext();) { 300 Object o = it.next(); 301 if (!expected.contains(o)) { 302 System.err.println(actual.toString()); 303 TestCase.fail(message + " Extra object " + o + " contained in tested collection"); 304 } 305 } 306 TestCase.fail("Collections not equal for unknown reason!"); 307 } 308 } 309 310 public static void incCheck(Document doc, boolean nested) { 311 TokenHierarchy<?> thInc = TokenHierarchy.get(doc); 312 Language<? extends TokenId> language = (Language<? extends TokenId>) 313 doc.getProperty(Language.class); 314 String docText = null; 315 try { 316 docText = doc.getText(0, doc.getLength()); 317 } catch (BadLocationException e) { 318 e.printStackTrace(); 319 TestCase.fail("BadLocationException occurred"); 320 } 321 TokenHierarchy<?> thBatch = TokenHierarchy.create(docText, language); 322 boolean success = false; 323 TokenSequence<?> batchTS = thBatch.tokenSequence(); 324 try { 325 assertTokenSequencesEqual(batchTS, thBatch, 327 thInc.tokenSequence(), thInc, true); 328 success = true; 329 } finally { 330 if (!success) { 331 batchTS.moveNext(); 333 batchTS.moveNext(); 334 System.err.println("BATCH token sequence dump:\n" + thBatch.tokenSequence()); 335 TokenHierarchy<?> lastHi = (TokenHierarchy<?>)doc.getProperty(LAST_TOKEN_HIERARCHY); 336 if (lastHi != null) { 337 System.err.println("PREVIOUS batch token sequence dump:\n" + lastHi.tokenSequence()); 338 } 339 } 340 } 341 342 TokenHierarchy<?> lastHi = (TokenHierarchy<?>)doc.getProperty(LAST_TOKEN_HIERARCHY); 344 if (lastHi != null) { 345 } 347 doc.putProperty(LAST_TOKEN_HIERARCHY, thBatch); } 349 350 353 public static void incInit(Document doc) { 354 TestCase.assertNull(doc.getProperty(TokenHierarchyListener.class)); 355 doc.putProperty(TokenHierarchyListener.class, TestTokenChangeListener.INSTANCE); 356 } 357 358 363 public static int lookahead(TokenSequence<? extends TokenId> ts) { 364 return tokenList(ts).lookahead(ts.index()); 365 } 366 367 372 public static Object state(TokenSequence<? extends TokenId> ts) { 373 return tokenList(ts).state(ts.index()); 374 } 375 376 379 public static boolean textEquals(CharSequence text1, CharSequence text2) { 380 return TokenUtilities.equals(text1, text2); 381 } 382 383 public static void assertTextEquals(CharSequence expected, CharSequence actual) { 384 assertTextEquals(null, expected, actual); 385 } 386 387 public static void assertTextEquals(String message, CharSequence expected, CharSequence actual) { 388 if (!textEquals(expected, actual)) { 389 TestCase.fail(messagePrefix(message) + 390 " expected:\"" + expected + "\" but was:\"" + actual + "\""); 391 } 392 } 393 394 401 public static String debugText(CharSequence text) { 402 return TokenUtilities.debugText(text); 403 } 404 405 public static void initLastDocumentEventListening(Document doc) { 406 doc.addDocumentListener(new DocumentListener () { 407 public void insertUpdate(DocumentEvent evt) { 408 storeEvent(evt); 409 } 410 public void removeUpdate(DocumentEvent evt) { 411 storeEvent(evt); 412 } 413 public void changedUpdate(DocumentEvent evt) { 414 storeEvent(evt); 415 } 416 private void storeEvent(DocumentEvent evt) { 417 evt.getDocument().putProperty(DocumentEvent .class, evt); 418 } 419 }); 420 } 421 422 public static DocumentEvent getLastDocumentEvent(Document doc) { 423 return (DocumentEvent )doc.getProperty(DocumentEvent .class); 424 } 425 426 public static void initLastTokenHierarchyEventListening(Document doc) { 427 TokenHierarchy hi = TokenHierarchy.get(doc); 428 hi.addTokenHierarchyListener(new TokenHierarchyListener() { 429 public void tokenHierarchyChanged(TokenHierarchyEvent evt) { 430 ((Document )evt.tokenHierarchy().mutableInputSource()).putProperty( 431 TokenHierarchyEvent.class, evt); 432 } 433 }); 434 } 435 436 public static TokenHierarchyEvent getLastTokenHierarchyEvent(Document doc) { 437 return (TokenHierarchyEvent)doc.getProperty(TokenHierarchyEvent.class); 438 } 439 440 443 public static <T extends TokenId> TokenList<T> tokenList(TokenSequence<T> ts) { 444 try { 445 if (tokenListField == null) { 446 tokenListField = ts.getClass().getDeclaredField("tokenList"); 447 tokenListField.setAccessible(true); 448 } 449 @SuppressWarnings ("unchecked") 450 TokenList<T> tl = (TokenList<T>)tokenListField.get(ts); 451 return tl; 452 } catch (Exception e) { 453 TestCase.fail(e.getMessage()); 454 return null; } 456 } 457 458 private static String messagePrefix(String message) { 459 if (message != null) { 460 message = message + ": "; 461 } else { 462 message = ""; 463 } 464 return message; 465 } 466 467 471 public static void setTesting(boolean testing) { 472 System.setProperty("netbeans.debug.lexer.test", testing ? "true" : "false"); 473 } 474 475 505 public static void checkTokenDump(NbTestCase test, String relFilePath, 506 Language<? extends TokenId> language) throws Exception { 507 TokenDumpCheck.checkTokenDump(test, relFilePath, language); 508 } 509 510 private static final class TestTokenChangeListener implements TokenHierarchyListener { 511 512 static TestTokenChangeListener INSTANCE = new TestTokenChangeListener(); 513 514 public void tokenHierarchyChanged(TokenHierarchyEvent evt) { 515 TokenHierarchy hi = evt.tokenHierarchy(); 516 Document d = (Document )hi.mutableInputSource(); 517 d.putProperty(TokenHierarchyEvent.class, evt); 518 } 519 520 } 521 } 522 | Popular Tags |