1 /* 2 * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @bug 7073631 7159445 7156633 27 * @summary tests error and diagnostics positions 28 * @author Jan Lahoda 29 */ 30 31 import com.sun.source.tree.BinaryTree; 32 import com.sun.source.tree.BlockTree; 33 import com.sun.source.tree.ClassTree; 34 import com.sun.source.tree.CompilationUnitTree; 35 import com.sun.source.tree.ErroneousTree; 36 import com.sun.source.tree.ExpressionStatementTree; 37 import com.sun.source.tree.ExpressionTree; 38 import com.sun.source.tree.MethodInvocationTree; 39 import com.sun.source.tree.MethodTree; 40 import com.sun.source.tree.ModifiersTree; 41 import com.sun.source.tree.StatementTree; 42 import com.sun.source.tree.Tree; 43 import com.sun.source.tree.Tree.Kind; 44 import com.sun.source.tree.VariableTree; 45 import com.sun.source.tree.WhileLoopTree; 46 import com.sun.source.util.SourcePositions; 47 import com.sun.source.util.TreeScanner; 48 import com.sun.source.util.Trees; 49 import com.sun.tools.javac.api.JavacTaskImpl; 50 import com.sun.tools.javac.tree.JCTree; 51 import java.io.IOException; 52 import java.lang.annotation.ElementType; 53 import java.lang.annotation.Retention; 54 import java.lang.annotation.RetentionPolicy; 55 import java.lang.annotation.Target; 56 import java.lang.reflect.Method; 57 import java.net.URI; 58 import java.util.ArrayList; 59 import java.util.Arrays; 60 import java.util.LinkedList; 61 import java.util.List; 62 import java.util.regex.Pattern; 63 import javax.tools.Diagnostic; 64 import javax.tools.DiagnosticCollector; 65 import javax.tools.DiagnosticListener; 66 import javax.tools.JavaCompiler; 67 import javax.tools.JavaFileObject; 68 import javax.tools.SimpleJavaFileObject; 69 import javax.tools.ToolProvider; 70 71 public class JavacParserTest extends TestCase { 72 static final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); 73 JavacParserTest()74 private JavacParserTest(){} 75 main(String... args)76 public static void main(String... args) throws Exception { 77 new JavacParserTest().run(args); 78 } 79 80 class MyFileObject extends SimpleJavaFileObject { 81 82 private String text; 83 MyFileObject(String text)84 public MyFileObject(String text) { 85 super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); 86 this.text = text; 87 } 88 89 @Override getCharContent(boolean ignoreEncodingErrors)90 public CharSequence getCharContent(boolean ignoreEncodingErrors) { 91 return text; 92 } 93 } 94 /* 95 * converts Windows to Unix style LFs for comparing strings 96 */ normalize(String in)97 String normalize(String in) { 98 return in.replace(System.getProperty("line.separator"), "\n"); 99 } 100 getCompilationUnitTree(String code)101 CompilationUnitTree getCompilationUnitTree(String code) throws IOException { 102 103 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, 104 null, Arrays.asList(new MyFileObject(code))); 105 CompilationUnitTree cut = ct.parse().iterator().next(); 106 return cut; 107 } 108 getErroneousTreeValues(ErroneousTree node)109 List<String> getErroneousTreeValues(ErroneousTree node) { 110 111 List<String> values = new ArrayList<>(); 112 if (node.getErrorTrees() != null) { 113 for (Tree t : node.getErrorTrees()) { 114 values.add(t.toString()); 115 } 116 } else { 117 throw new RuntimeException("ERROR: No Erroneous tree " 118 + "has been created."); 119 } 120 return values; 121 } 122 123 @Test testPositionForSuperConstructorCalls()124 void testPositionForSuperConstructorCalls() throws IOException { 125 assert tool != null; 126 127 String code = "package test; public class Test {public Test() {super();}}"; 128 129 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, 130 null, Arrays.asList(new MyFileObject(code))); 131 CompilationUnitTree cut = ct.parse().iterator().next(); 132 SourcePositions pos = Trees.instance(ct).getSourcePositions(); 133 134 MethodTree method = 135 (MethodTree) ((ClassTree) cut.getTypeDecls().get(0)).getMembers().get(0); 136 ExpressionStatementTree es = 137 (ExpressionStatementTree) method.getBody().getStatements().get(0); 138 139 final int esStartPos = code.indexOf(es.toString()); 140 final int esEndPos = esStartPos + es.toString().length(); 141 assertEquals("testPositionForSuperConstructorCalls", 142 esStartPos, pos.getStartPosition(cut, es)); 143 assertEquals("testPositionForSuperConstructorCalls", 144 esEndPos, pos.getEndPosition(cut, es)); 145 146 MethodInvocationTree mit = (MethodInvocationTree) es.getExpression(); 147 148 final int mitStartPos = code.indexOf(mit.toString()); 149 final int mitEndPos = mitStartPos + mit.toString().length(); 150 assertEquals("testPositionForSuperConstructorCalls", 151 mitStartPos, pos.getStartPosition(cut, mit)); 152 assertEquals("testPositionForSuperConstructorCalls", 153 mitEndPos, pos.getEndPosition(cut, mit)); 154 155 final int methodStartPos = mitStartPos; 156 final int methodEndPos = methodStartPos + mit.getMethodSelect().toString().length(); 157 assertEquals("testPositionForSuperConstructorCalls", 158 methodStartPos, pos.getStartPosition(cut, mit.getMethodSelect())); 159 assertEquals("testPositionForSuperConstructorCalls", 160 methodEndPos, pos.getEndPosition(cut, mit.getMethodSelect())); 161 } 162 163 @Test testPositionForEnumModifiers()164 void testPositionForEnumModifiers() throws IOException { 165 final String theString = "public"; 166 String code = "package test; " + theString + " enum Test {A;}"; 167 168 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, 169 null, Arrays.asList(new MyFileObject(code))); 170 CompilationUnitTree cut = ct.parse().iterator().next(); 171 SourcePositions pos = Trees.instance(ct).getSourcePositions(); 172 173 ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); 174 ModifiersTree mt = clazz.getModifiers(); 175 int spos = code.indexOf(theString); 176 int epos = spos + theString.length(); 177 assertEquals("testPositionForEnumModifiers", 178 spos, pos.getStartPosition(cut, mt)); 179 assertEquals("testPositionForEnumModifiers", 180 epos, pos.getEndPosition(cut, mt)); 181 } 182 183 @Test testNewClassWithEnclosing()184 void testNewClassWithEnclosing() throws IOException { 185 186 final String theString = "Test.this.new d()"; 187 String code = "package test; class Test { " + 188 "class d {} private void method() { " + 189 "Object o = " + theString + "; } }"; 190 191 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, 192 null, Arrays.asList(new MyFileObject(code))); 193 CompilationUnitTree cut = ct.parse().iterator().next(); 194 SourcePositions pos = Trees.instance(ct).getSourcePositions(); 195 196 ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); 197 ExpressionTree est = 198 ((VariableTree) ((MethodTree) clazz.getMembers().get(1)).getBody().getStatements().get(0)).getInitializer(); 199 200 final int spos = code.indexOf(theString); 201 final int epos = spos + theString.length(); 202 assertEquals("testNewClassWithEnclosing", 203 spos, pos.getStartPosition(cut, est)); 204 assertEquals("testNewClassWithEnclosing", 205 epos, pos.getEndPosition(cut, est)); 206 } 207 208 @Test testPreferredPositionForBinaryOp()209 void testPreferredPositionForBinaryOp() throws IOException { 210 211 String code = "package test; public class Test {" 212 + "private void test() {" 213 + "Object o = null; boolean b = o != null && o instanceof String;" 214 + "} private Test() {}}"; 215 216 CompilationUnitTree cut = getCompilationUnitTree(code); 217 ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); 218 MethodTree method = (MethodTree) clazz.getMembers().get(0); 219 VariableTree condSt = (VariableTree) method.getBody().getStatements().get(1); 220 BinaryTree cond = (BinaryTree) condSt.getInitializer(); 221 222 JCTree condJC = (JCTree) cond; 223 int condStartPos = code.indexOf("&&"); 224 assertEquals("testPreferredPositionForBinaryOp", 225 condStartPos, condJC.pos); 226 } 227 228 @Test testErrorRecoveryForEnhancedForLoop142381()229 void testErrorRecoveryForEnhancedForLoop142381() throws IOException { 230 231 String code = "package test; class Test { " + 232 "private void method() { " + 233 "java.util.Set<String> s = null; for (a : s) {} } }"; 234 235 final List<Diagnostic<? extends JavaFileObject>> errors = 236 new LinkedList<Diagnostic<? extends JavaFileObject>>(); 237 238 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, 239 new DiagnosticListener<JavaFileObject>() { 240 public void report(Diagnostic<? extends JavaFileObject> diagnostic) { 241 errors.add(diagnostic); 242 } 243 }, null, null, Arrays.asList(new MyFileObject(code))); 244 245 CompilationUnitTree cut = ct.parse().iterator().next(); 246 247 ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); 248 StatementTree forStatement = 249 ((MethodTree) clazz.getMembers().get(0)).getBody().getStatements().get(1); 250 251 assertEquals("testErrorRecoveryForEnhancedForLoop142381", 252 Kind.ENHANCED_FOR_LOOP, forStatement.getKind()); 253 assertFalse("testErrorRecoveryForEnhancedForLoop142381", errors.isEmpty()); 254 } 255 256 @Test testPositionAnnotationNoPackage187551()257 void testPositionAnnotationNoPackage187551() throws IOException { 258 259 String code = "\n@interface Test {}"; 260 261 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, 262 null, Arrays.asList(new MyFileObject(code))); 263 264 CompilationUnitTree cut = ct.parse().iterator().next(); 265 ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); 266 Trees t = Trees.instance(ct); 267 268 assertEquals("testPositionAnnotationNoPackage187551", 269 1, t.getSourcePositions().getStartPosition(cut, clazz)); 270 } 271 272 @Test testPositionsSane1()273 void testPositionsSane1() throws IOException { 274 performPositionsSanityTest("package test; class Test { " + 275 "private void method() { " + 276 "java.util.List<? extends java.util.List<? extends String>> l; " + 277 "} }"); 278 } 279 280 @Test testPositionsSane2()281 void testPositionsSane2() throws IOException { 282 performPositionsSanityTest("package test; class Test { " + 283 "private void method() { " + 284 "java.util.List<? super java.util.List<? super String>> l; " + 285 "} }"); 286 } 287 288 @Test testPositionsSane3()289 void testPositionsSane3() throws IOException { 290 performPositionsSanityTest("package test; class Test { " + 291 "private void method() { " + 292 "java.util.List<? super java.util.List<?>> l; } }"); 293 } 294 performPositionsSanityTest(String code)295 private void performPositionsSanityTest(String code) throws IOException { 296 297 final List<Diagnostic<? extends JavaFileObject>> errors = 298 new LinkedList<Diagnostic<? extends JavaFileObject>>(); 299 300 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, 301 new DiagnosticListener<JavaFileObject>() { 302 303 public void report(Diagnostic<? extends JavaFileObject> diagnostic) { 304 errors.add(diagnostic); 305 } 306 }, null, null, Arrays.asList(new MyFileObject(code))); 307 308 final CompilationUnitTree cut = ct.parse().iterator().next(); 309 final Trees trees = Trees.instance(ct); 310 311 new TreeScanner<Void, Void>() { 312 313 private long parentStart = 0; 314 private long parentEnd = Integer.MAX_VALUE; 315 316 @Override 317 public Void scan(Tree node, Void p) { 318 if (node == null) { 319 return null; 320 } 321 322 long start = trees.getSourcePositions().getStartPosition(cut, node); 323 324 if (start == (-1)) { 325 return null; // synthetic tree 326 } 327 assertTrue(node.toString() + ":" + start + "/" + parentStart, 328 parentStart <= start); 329 330 long prevParentStart = parentStart; 331 332 parentStart = start; 333 334 long end = trees.getSourcePositions().getEndPosition(cut, node); 335 336 assertTrue(node.toString() + ":" + end + "/" + parentEnd, 337 end <= parentEnd); 338 339 long prevParentEnd = parentEnd; 340 341 parentEnd = end; 342 343 super.scan(node, p); 344 345 parentStart = prevParentStart; 346 parentEnd = prevParentEnd; 347 348 return null; 349 } 350 351 private void assertTrue(String message, boolean b) { 352 if (!b) fail(message); 353 } 354 }.scan(cut, null); 355 } 356 357 @Test testCorrectWilcardPositions1()358 void testCorrectWilcardPositions1() throws IOException { 359 performWildcardPositionsTest("package test; import java.util.List; " + 360 "class Test { private void method() { List<? extends List<? extends String>> l; } }", 361 362 Arrays.asList("List<? extends List<? extends String>> l;", 363 "List<? extends List<? extends String>>", 364 "List", 365 "? extends List<? extends String>", 366 "List<? extends String>", 367 "List", 368 "? extends String", 369 "String")); 370 } 371 372 @Test testCorrectWilcardPositions2()373 void testCorrectWilcardPositions2() throws IOException { 374 performWildcardPositionsTest("package test; import java.util.List; " 375 + "class Test { private void method() { List<? super List<? super String>> l; } }", 376 Arrays.asList("List<? super List<? super String>> l;", 377 "List<? super List<? super String>>", 378 "List", 379 "? super List<? super String>", 380 "List<? super String>", 381 "List", 382 "? super String", 383 "String")); 384 } 385 386 @Test testCorrectWilcardPositions3()387 void testCorrectWilcardPositions3() throws IOException { 388 performWildcardPositionsTest("package test; import java.util.List; " + 389 "class Test { private void method() { List<? super List<?>> l; } }", 390 391 Arrays.asList("List<? super List<?>> l;", 392 "List<? super List<?>>", 393 "List", 394 "? super List<?>", 395 "List<?>", 396 "List", 397 "?")); 398 } 399 400 @Test testCorrectWilcardPositions4()401 void testCorrectWilcardPositions4() throws IOException { 402 performWildcardPositionsTest("package test; import java.util.List; " + 403 "class Test { private void method() { " + 404 "List<? extends List<? extends List<? extends String>>> l; } }", 405 406 Arrays.asList("List<? extends List<? extends List<? extends String>>> l;", 407 "List<? extends List<? extends List<? extends String>>>", 408 "List", 409 "? extends List<? extends List<? extends String>>", 410 "List<? extends List<? extends String>>", 411 "List", 412 "? extends List<? extends String>", 413 "List<? extends String>", 414 "List", 415 "? extends String", 416 "String")); 417 } 418 419 @Test testCorrectWilcardPositions5()420 void testCorrectWilcardPositions5() throws IOException { 421 performWildcardPositionsTest("package test; import java.util.List; " + 422 "class Test { private void method() { " + 423 "List<? extends List<? extends List<? extends String >>> l; } }", 424 Arrays.asList("List<? extends List<? extends List<? extends String >>> l;", 425 "List<? extends List<? extends List<? extends String >>>", 426 "List", 427 "? extends List<? extends List<? extends String >>", 428 "List<? extends List<? extends String >>", 429 "List", 430 "? extends List<? extends String >", 431 "List<? extends String >", 432 "List", 433 "? extends String", 434 "String")); 435 } 436 performWildcardPositionsTest(final String code, List<String> golden)437 void performWildcardPositionsTest(final String code, 438 List<String> golden) throws IOException { 439 440 final List<Diagnostic<? extends JavaFileObject>> errors = 441 new LinkedList<Diagnostic<? extends JavaFileObject>>(); 442 443 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, 444 new DiagnosticListener<JavaFileObject>() { 445 public void report(Diagnostic<? extends JavaFileObject> diagnostic) { 446 errors.add(diagnostic); 447 } 448 }, null, null, Arrays.asList(new MyFileObject(code))); 449 450 final CompilationUnitTree cut = ct.parse().iterator().next(); 451 final List<String> content = new LinkedList<String>(); 452 final Trees trees = Trees.instance(ct); 453 454 new TreeScanner<Void, Void>() { 455 @Override 456 public Void scan(Tree node, Void p) { 457 if (node == null) { 458 return null; 459 } 460 long start = trees.getSourcePositions().getStartPosition(cut, node); 461 462 if (start == (-1)) { 463 return null; // synthetic tree 464 } 465 long end = trees.getSourcePositions().getEndPosition(cut, node); 466 String s = code.substring((int) start, (int) end); 467 content.add(s); 468 469 return super.scan(node, p); 470 } 471 }.scan(((MethodTree) ((ClassTree) cut.getTypeDecls().get(0)).getMembers().get(0)).getBody().getStatements().get(0), null); 472 473 assertEquals("performWildcardPositionsTest",golden.toString(), 474 content.toString()); 475 } 476 477 @Test testStartPositionForMethodWithoutModifiers()478 void testStartPositionForMethodWithoutModifiers() throws IOException { 479 480 String code = "package t; class Test { <T> void t() {} }"; 481 482 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, 483 null, Arrays.asList(new MyFileObject(code))); 484 CompilationUnitTree cut = ct.parse().iterator().next(); 485 ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); 486 MethodTree mt = (MethodTree) clazz.getMembers().get(0); 487 Trees t = Trees.instance(ct); 488 int start = (int) t.getSourcePositions().getStartPosition(cut, mt); 489 int end = (int) t.getSourcePositions().getEndPosition(cut, mt); 490 491 assertEquals("testStartPositionForMethodWithoutModifiers", 492 "<T> void t() {}", code.substring(start, end)); 493 } 494 495 @Test testVariableInIfThen1()496 void testVariableInIfThen1() throws IOException { 497 498 String code = "package t; class Test { " + 499 "private static void t(String name) { " + 500 "if (name != null) String nn = name.trim(); } }"; 501 502 DiagnosticCollector<JavaFileObject> coll = 503 new DiagnosticCollector<JavaFileObject>(); 504 505 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, coll, null, 506 null, Arrays.asList(new MyFileObject(code))); 507 508 ct.parse(); 509 510 List<String> codes = new LinkedList<String>(); 511 512 for (Diagnostic<? extends JavaFileObject> d : coll.getDiagnostics()) { 513 codes.add(d.getCode()); 514 } 515 516 assertEquals("testVariableInIfThen1", 517 Arrays.<String>asList("compiler.err.variable.not.allowed"), 518 codes); 519 } 520 521 @Test testVariableInIfThen2()522 void testVariableInIfThen2() throws IOException { 523 524 String code = "package t; class Test { " + 525 "private static void t(String name) { " + 526 "if (name != null) class X {} } }"; 527 DiagnosticCollector<JavaFileObject> coll = 528 new DiagnosticCollector<JavaFileObject>(); 529 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, coll, null, 530 null, Arrays.asList(new MyFileObject(code))); 531 532 ct.parse(); 533 534 List<String> codes = new LinkedList<String>(); 535 536 for (Diagnostic<? extends JavaFileObject> d : coll.getDiagnostics()) { 537 codes.add(d.getCode()); 538 } 539 540 assertEquals("testVariableInIfThen2", 541 Arrays.<String>asList("compiler.err.class.not.allowed"), codes); 542 } 543 544 @Test testVariableInIfThen3()545 void testVariableInIfThen3() throws IOException { 546 547 String code = "package t; class Test { "+ 548 "private static void t() { " + 549 "if (true) abstract class F {} }}"; 550 DiagnosticCollector<JavaFileObject> coll = 551 new DiagnosticCollector<JavaFileObject>(); 552 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, coll, null, 553 null, Arrays.asList(new MyFileObject(code))); 554 555 ct.parse(); 556 557 List<String> codes = new LinkedList<String>(); 558 559 for (Diagnostic<? extends JavaFileObject> d : coll.getDiagnostics()) { 560 codes.add(d.getCode()); 561 } 562 563 assertEquals("testVariableInIfThen3", 564 Arrays.<String>asList("compiler.err.class.not.allowed"), codes); 565 } 566 567 @Test testVariableInIfThen4()568 void testVariableInIfThen4() throws IOException { 569 570 String code = "package t; class Test { "+ 571 "private static void t(String name) { " + 572 "if (name != null) interface X {} } }"; 573 DiagnosticCollector<JavaFileObject> coll = 574 new DiagnosticCollector<JavaFileObject>(); 575 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, coll, null, 576 null, Arrays.asList(new MyFileObject(code))); 577 578 ct.parse(); 579 580 List<String> codes = new LinkedList<String>(); 581 582 for (Diagnostic<? extends JavaFileObject> d : coll.getDiagnostics()) { 583 codes.add(d.getCode()); 584 } 585 586 assertEquals("testVariableInIfThen4", 587 Arrays.<String>asList("compiler.err.class.not.allowed"), codes); 588 } 589 590 @Test testVariableInIfThen5()591 void testVariableInIfThen5() throws IOException { 592 593 String code = "package t; class Test { "+ 594 "private static void t() { " + 595 "if (true) } }"; 596 DiagnosticCollector<JavaFileObject> coll = 597 new DiagnosticCollector<JavaFileObject>(); 598 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, coll, null, 599 null, Arrays.asList(new MyFileObject(code))); 600 601 ct.parse(); 602 603 List<String> codes = new LinkedList<String>(); 604 605 for (Diagnostic<? extends JavaFileObject> d : coll.getDiagnostics()) { 606 codes.add(d.getCode()); 607 } 608 609 assertEquals("testVariableInIfThen5", 610 Arrays.<String>asList("compiler.err.illegal.start.of.stmt"), 611 codes); 612 } 613 614 // see javac bug #6882235, NB bug #98234: 615 @Test testMissingExponent()616 void testMissingExponent() throws IOException { 617 618 String code = "\nclass Test { { System.err.println(0e); } }"; 619 620 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, 621 null, Arrays.asList(new MyFileObject(code))); 622 623 assertNotNull(ct.parse().iterator().next()); 624 } 625 626 @Test testTryResourcePos()627 void testTryResourcePos() throws IOException { 628 629 final String code = "package t; class Test { " + 630 "{ try (java.io.InputStream in = null) { } } }"; 631 632 CompilationUnitTree cut = getCompilationUnitTree(code); 633 634 new TreeScanner<Void, Void>() { 635 @Override 636 public Void visitVariable(VariableTree node, Void p) { 637 if ("in".contentEquals(node.getName())) { 638 JCTree.JCVariableDecl var = (JCTree.JCVariableDecl) node; 639 assertEquals("testTryResourcePos", "in = null) { } } }", 640 code.substring(var.pos)); 641 } 642 return super.visitVariable(node, p); 643 } 644 }.scan(cut, null); 645 } 646 647 @Test testVarPos()648 void testVarPos() throws IOException { 649 650 final String code = "package t; class Test { " + 651 "{ java.io.InputStream in = null; } }"; 652 653 CompilationUnitTree cut = getCompilationUnitTree(code); 654 655 new TreeScanner<Void, Void>() { 656 657 @Override 658 public Void visitVariable(VariableTree node, Void p) { 659 if ("in".contentEquals(node.getName())) { 660 JCTree.JCVariableDecl var = (JCTree.JCVariableDecl) node; 661 assertEquals("testVarPos","in = null; } }", 662 code.substring(var.pos)); 663 } 664 return super.visitVariable(node, p); 665 } 666 }.scan(cut, null); 667 } 668 669 // expected erroneous tree: int x = y;(ERROR); 670 @Test testOperatorMissingError()671 void testOperatorMissingError() throws IOException { 672 673 String code = "package test; public class ErrorTest { " 674 + "void method() { int x = y z } }"; 675 CompilationUnitTree cut = getCompilationUnitTree(code); 676 final List<String> values = new ArrayList<>(); 677 final List<String> expectedValues = 678 new ArrayList<>(Arrays.asList("[z]")); 679 680 new TreeScanner<Void, Void>() { 681 @Override 682 public Void visitErroneous(ErroneousTree node, Void p) { 683 values.add(getErroneousTreeValues(node).toString()); 684 return null; 685 686 } 687 }.scan(cut, null); 688 689 assertEquals("testSwitchError: The Erroneous tree " 690 + "error values: " + values 691 + " do not match expected error values: " 692 + expectedValues, values, expectedValues); 693 } 694 695 // expected erroneous tree: String s = (ERROR); 696 @Test testMissingParenthesisError()697 void testMissingParenthesisError() throws IOException { 698 699 String code = "package test; public class ErrorTest { " 700 + "void f() {String s = new String; } }"; 701 CompilationUnitTree cut = getCompilationUnitTree(code); 702 final List<String> values = new ArrayList<>(); 703 final List<String> expectedValues = 704 new ArrayList<>(Arrays.asList("[new String()]")); 705 706 new TreeScanner<Void, Void>() { 707 @Override 708 public Void visitErroneous(ErroneousTree node, Void p) { 709 values.add(getErroneousTreeValues(node).toString()); 710 return null; 711 } 712 }.scan(cut, null); 713 714 assertEquals("testSwitchError: The Erroneous tree " 715 + "error values: " + values 716 + " do not match expected error values: " 717 + expectedValues, values, expectedValues); 718 } 719 720 // expected erroneous tree: package test; (ERROR)(ERROR) 721 @Test testMissingClassError()722 void testMissingClassError() throws IOException { 723 724 String code = "package Test; clas ErrorTest { " 725 + "void f() {String s = new String(); } }"; 726 CompilationUnitTree cut = getCompilationUnitTree(code); 727 final List<String> values = new ArrayList<>(); 728 final List<String> expectedValues = 729 new ArrayList<>(Arrays.asList("[, clas]", "[]")); 730 731 new TreeScanner<Void, Void>() { 732 @Override 733 public Void visitErroneous(ErroneousTree node, Void p) { 734 values.add(getErroneousTreeValues(node).toString()); 735 return null; 736 } 737 }.scan(cut, null); 738 739 assertEquals("testSwitchError: The Erroneous tree " 740 + "error values: " + values 741 + " do not match expected error values: " 742 + expectedValues, values, expectedValues); 743 } 744 745 // expected erroneous tree: void m1(int i) {(ERROR);{(ERROR);} 746 @Test testSwitchError()747 void testSwitchError() throws IOException { 748 749 String code = "package test; public class ErrorTest { " 750 + "int numDays; void m1(int i) { switchh {i} { case 1: " 751 + "numDays = 31; break; } } }"; 752 CompilationUnitTree cut = getCompilationUnitTree(code); 753 final List<String> values = new ArrayList<>(); 754 final List<String> expectedValues = 755 new ArrayList<>(Arrays.asList("[switchh]", "[i]")); 756 757 new TreeScanner<Void, Void>() { 758 @Override 759 public Void visitErroneous(ErroneousTree node, Void p) { 760 values.add(getErroneousTreeValues(node).toString()); 761 return null; 762 } 763 }.scan(cut, null); 764 765 assertEquals("testSwitchError: The Erroneous tree " 766 + "error values: " + values 767 + " do not match expected error values: " 768 + expectedValues, values, expectedValues); 769 } 770 771 // expected erroneous tree: class ErrorTest {(ERROR) 772 @Test testMethodError()773 void testMethodError() throws IOException { 774 775 String code = "package Test; class ErrorTest { " 776 + "static final void f) {String s = new String(); } }"; 777 CompilationUnitTree cut = cut = getCompilationUnitTree(code); 778 779 final List<String> values = new ArrayList<>(); 780 final List<String> expectedValues = 781 new ArrayList<>(Arrays.asList("[\nstatic final void f();]")); 782 783 new TreeScanner<Void, Void>() { 784 @Override 785 public Void visitErroneous(ErroneousTree node, Void p) { 786 values.add(normalize(getErroneousTreeValues(node).toString())); 787 return null; 788 } 789 }.scan(cut, null); 790 791 assertEquals("testMethodError: The Erroneous tree " 792 + "error value: " + values 793 + " does not match expected error values: " 794 + expectedValues, values, expectedValues); 795 } 796 797 /* 798 * The following tests do not work just yet with nb-javac nor javac, 799 * they need further investigation, see CR: 7167356 800 */ 801 testPositionBrokenSource126732a()802 void testPositionBrokenSource126732a() throws IOException { 803 String[] commands = new String[]{ 804 "return Runnable()", 805 "do { } while (true)", 806 "throw UnsupportedOperationException()", 807 "assert true", 808 "1 + 1",}; 809 810 for (String command : commands) { 811 812 String code = "package test;\n" 813 + "public class Test {\n" 814 + " public static void test() {\n" 815 + " " + command + " {\n" 816 + " new Runnable() {\n" 817 + " };\n" 818 + " }\n" 819 + "}"; 820 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, 821 null, null, Arrays.asList(new MyFileObject(code))); 822 CompilationUnitTree cut = ct.parse().iterator().next(); 823 824 ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); 825 MethodTree method = (MethodTree) clazz.getMembers().get(0); 826 List<? extends StatementTree> statements = 827 method.getBody().getStatements(); 828 829 StatementTree ret = statements.get(0); 830 StatementTree block = statements.get(1); 831 832 Trees t = Trees.instance(ct); 833 int len = code.indexOf(command + " {") + (command + " ").length(); 834 assertEquals(command, len, 835 t.getSourcePositions().getEndPosition(cut, ret)); 836 assertEquals(command, len, 837 t.getSourcePositions().getStartPosition(cut, block)); 838 } 839 } 840 testPositionBrokenSource126732b()841 void testPositionBrokenSource126732b() throws IOException { 842 String[] commands = new String[]{ 843 "break", 844 "break A", 845 "continue ", 846 "continue A",}; 847 848 for (String command : commands) { 849 850 String code = "package test;\n" 851 + "public class Test {\n" 852 + " public static void test() {\n" 853 + " while (true) {\n" 854 + " " + command + " {\n" 855 + " new Runnable() {\n" 856 + " };\n" 857 + " }\n" 858 + " }\n" 859 + "}"; 860 861 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, 862 null, null, Arrays.asList(new MyFileObject(code))); 863 CompilationUnitTree cut = ct.parse().iterator().next(); 864 865 ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); 866 MethodTree method = (MethodTree) clazz.getMembers().get(0); 867 List<? extends StatementTree> statements = 868 ((BlockTree) ((WhileLoopTree) method.getBody().getStatements().get(0)).getStatement()).getStatements(); 869 870 StatementTree ret = statements.get(0); 871 StatementTree block = statements.get(1); 872 873 Trees t = Trees.instance(ct); 874 int len = code.indexOf(command + " {") + (command + " ").length(); 875 assertEquals(command, len, 876 t.getSourcePositions().getEndPosition(cut, ret)); 877 assertEquals(command, len, 878 t.getSourcePositions().getStartPosition(cut, block)); 879 } 880 } 881 testStartPositionEnumConstantInit()882 void testStartPositionEnumConstantInit() throws IOException { 883 884 String code = "package t; enum Test { AAA; }"; 885 886 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, 887 null, Arrays.asList(new MyFileObject(code))); 888 CompilationUnitTree cut = ct.parse().iterator().next(); 889 ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); 890 VariableTree enumAAA = (VariableTree) clazz.getMembers().get(0); 891 Trees t = Trees.instance(ct); 892 int start = (int) t.getSourcePositions().getStartPosition(cut, 893 enumAAA.getInitializer()); 894 895 assertEquals("testStartPositionEnumConstantInit", -1, start); 896 } 897 run(String[] args)898 void run(String[] args) throws Exception { 899 int passed = 0, failed = 0; 900 final Pattern p = (args != null && args.length > 0) 901 ? Pattern.compile(args[0]) 902 : null; 903 for (Method m : this.getClass().getDeclaredMethods()) { 904 boolean selected = (p == null) 905 ? m.isAnnotationPresent(Test.class) 906 : p.matcher(m.getName()).matches(); 907 if (selected) { 908 try { 909 m.invoke(this, (Object[]) null); 910 System.out.println(m.getName() + ": OK"); 911 passed++; 912 } catch (Throwable ex) { 913 System.out.printf("Test %s failed: %s %n", m, ex.getCause()); 914 failed++; 915 } 916 } 917 } 918 System.out.printf("Passed: %d, Failed %d%n", passed, failed); 919 if (failed > 0) { 920 throw new RuntimeException("Tests failed: " + failed); 921 } 922 if (passed == 0 && failed == 0) { 923 throw new AssertionError("No test(s) selected: passed = " + 924 passed + ", failed = " + failed + " ??????????"); 925 } 926 } 927 } 928 929 abstract class TestCase { 930 assertEquals(String message, int i, int pos)931 void assertEquals(String message, int i, int pos) { 932 if (i != pos) { 933 fail(message); 934 } 935 } 936 assertFalse(String message, boolean bvalue)937 void assertFalse(String message, boolean bvalue) { 938 if (bvalue == true) { 939 fail(message); 940 } 941 } 942 assertEquals(String message, int i, long l)943 void assertEquals(String message, int i, long l) { 944 if (i != l) { 945 fail(message + ":" + i + ":" + l); 946 } 947 } 948 assertEquals(String message, Object o1, Object o2)949 void assertEquals(String message, Object o1, Object o2) { 950 if (o1 != null && o2 != null && !o1.equals(o2)) { 951 fail(message); 952 } 953 if (o1 == null && o2 != null) { 954 fail(message); 955 } 956 } 957 assertNotNull(Object o)958 void assertNotNull(Object o) { 959 if (o == null) { 960 fail(); 961 } 962 } 963 fail()964 void fail() { 965 fail("test failed"); 966 } 967 fail(String message)968 void fail(String message) { 969 throw new RuntimeException(message); 970 } 971 972 /** 973 * Indicates that the annotated method is a test method. 974 */ 975 @Retention(RetentionPolicy.RUNTIME) 976 @Target(ElementType.METHOD) 977 public @interface Test {} 978 } 979