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