JavacParserTest.java revision 2745:64f03461bb0e
1200062Sed/* 2200062Sed * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. 3200062Sed * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4200062Sed * 5200062Sed * This code is free software; you can redistribute it and/or modify it 6200062Sed * under the terms of the GNU General Public License version 2 only, as 7200062Sed * published by the Free Software Foundation. 8200062Sed * 9200062Sed * This code is distributed in the hope that it will be useful, but WITHOUT 10200062Sed * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11200062Sed * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12200062Sed * version 2 for more details (a copy is included in the LICENSE file that 13200062Sed * accompanied this code). 14200062Sed * 15200062Sed * You should have received a copy of the GNU General Public License version 16200062Sed * 2 along with this work; if not, write to the Free Software Foundation, 17200062Sed * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18200062Sed * 19200062Sed * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20200062Sed * or visit www.oracle.com if you need additional information or have any 21200062Sed * questions. 22200062Sed */ 23200062Sed 24200062Sed/* 25200062Sed * @test 26200062Sed * @bug 7073631 7159445 7156633 8028235 8065753 27200062Sed * @summary tests error and diagnostics positions 28200062Sed * @author Jan Lahoda 29200062Sed */ 30200062Sed 31200062Sedimport com.sun.source.tree.BinaryTree; 32200062Sedimport com.sun.source.tree.BlockTree; 33200062Sedimport com.sun.source.tree.ClassTree; 34200062Sedimport com.sun.source.tree.CompilationUnitTree; 35200062Sedimport com.sun.source.tree.ErroneousTree; 36200062Sedimport com.sun.source.tree.ExpressionStatementTree; 37200062Sedimport com.sun.source.tree.ExpressionTree; 38200062Sedimport com.sun.source.tree.LambdaExpressionTree; 39200062Sedimport com.sun.source.tree.MethodInvocationTree; 40200062Sedimport com.sun.source.tree.MethodTree; 41200062Sedimport com.sun.source.tree.ModifiersTree; 42200062Sedimport com.sun.source.tree.PrimitiveTypeTree; 43200062Sedimport com.sun.source.tree.StatementTree; 44200062Sedimport com.sun.source.tree.Tree; 45200062Sedimport com.sun.source.tree.Tree.Kind; 46200062Sedimport com.sun.source.tree.VariableTree; 47200062Sedimport com.sun.source.tree.WhileLoopTree; 48200062Sedimport com.sun.source.util.SourcePositions; 49200062Sedimport com.sun.source.util.TreeScanner; 50200062Sedimport com.sun.source.util.Trees; 51200062Sedimport com.sun.tools.javac.api.JavacTaskImpl; 52200062Sedimport com.sun.tools.javac.main.Main; 53200062Sedimport com.sun.tools.javac.tree.JCTree; 54200062Sedimport java.io.IOException; 55200062Sedimport java.io.StringWriter; 56200062Sedimport java.lang.annotation.ElementType; 57200062Sedimport java.lang.annotation.Retention; 58200062Sedimport java.lang.annotation.RetentionPolicy; 59200062Sedimport java.lang.annotation.Target; 60200062Sedimport java.lang.reflect.Method; 61200062Sedimport java.net.URI; 62200062Sedimport java.util.ArrayList; 63200062Sedimport java.util.Arrays; 64200062Sedimport java.util.LinkedList; 65200062Sedimport java.util.List; 66200062Sedimport java.util.regex.Pattern; 67200062Sedimport javax.lang.model.type.TypeKind; 68200062Sedimport javax.tools.Diagnostic; 69200062Sedimport javax.tools.DiagnosticCollector; 70200062Sedimport javax.tools.DiagnosticListener; 71200062Sedimport javax.tools.JavaCompiler; 72200062Sedimport javax.tools.JavaFileManager; 73200062Sedimport javax.tools.JavaFileObject; 74200062Sedimport javax.tools.SimpleJavaFileObject; 75200062Sedimport javax.tools.ToolProvider; 76200062Sed 77200062Sedpublic class JavacParserTest extends TestCase { 78200062Sed static final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); 79200062Sed static final JavaFileManager fm = tool.getStandardFileManager(null, null, null); 80200062Sed 81200062Sed private JavacParserTest(){} 82200062Sed 83200062Sed public static void main(String... args) throws Exception { 84200062Sed try { 85200062Sed new JavacParserTest().run(args); 86200062Sed } finally { 87200062Sed fm.close(); 88200062Sed } 89200062Sed } 90200062Sed 91200062Sed class MyFileObject extends SimpleJavaFileObject { 92200062Sed 93200062Sed private String text; 94200062Sed 95200062Sed public MyFileObject(String text) { 96200062Sed super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); 97200062Sed this.text = text; 98200062Sed } 99200062Sed 100200062Sed @Override 101200062Sed public CharSequence getCharContent(boolean ignoreEncodingErrors) { 102200062Sed return text; 103200062Sed } 104200062Sed } 105200062Sed /* 106200062Sed * converts Windows to Unix style LFs for comparing strings 107200062Sed */ 108200062Sed String normalize(String in) { 109200062Sed return in.replace(System.getProperty("line.separator"), "\n"); 110200062Sed } 111200062Sed 112200062Sed CompilationUnitTree getCompilationUnitTree(String code) throws IOException { 113200062Sed 114200062Sed JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, null, 115200062Sed null, Arrays.asList(new MyFileObject(code))); 116200062Sed CompilationUnitTree cut = ct.parse().iterator().next(); 117200062Sed return cut; 118200062Sed } 119200062Sed 120200062Sed List<String> getErroneousTreeValues(ErroneousTree node) { 121200062Sed 122200062Sed List<String> values = new ArrayList<>(); 123200062Sed if (node.getErrorTrees() != null) { 124200062Sed for (Tree t : node.getErrorTrees()) { 125200062Sed values.add(t.toString()); 126200062Sed } 127200062Sed } else { 128200062Sed throw new RuntimeException("ERROR: No Erroneous tree " 129200062Sed + "has been created."); 130200062Sed } 131200062Sed return values; 132200062Sed } 133200062Sed 134200062Sed @Test 135200062Sed void testPositionForSuperConstructorCalls() throws IOException { 136 assert tool != null; 137 138 String code = "package test; public class Test {public Test() {super();}}"; 139 140 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, null, 141 null, Arrays.asList(new MyFileObject(code))); 142 CompilationUnitTree cut = ct.parse().iterator().next(); 143 SourcePositions pos = Trees.instance(ct).getSourcePositions(); 144 145 MethodTree method = 146 (MethodTree) ((ClassTree) cut.getTypeDecls().get(0)).getMembers().get(0); 147 ExpressionStatementTree es = 148 (ExpressionStatementTree) method.getBody().getStatements().get(0); 149 150 final int esStartPos = code.indexOf(es.toString()); 151 final int esEndPos = esStartPos + es.toString().length(); 152 assertEquals("testPositionForSuperConstructorCalls", 153 esStartPos, pos.getStartPosition(cut, es)); 154 assertEquals("testPositionForSuperConstructorCalls", 155 esEndPos, pos.getEndPosition(cut, es)); 156 157 MethodInvocationTree mit = (MethodInvocationTree) es.getExpression(); 158 159 final int mitStartPos = code.indexOf(mit.toString()); 160 final int mitEndPos = mitStartPos + mit.toString().length(); 161 assertEquals("testPositionForSuperConstructorCalls", 162 mitStartPos, pos.getStartPosition(cut, mit)); 163 assertEquals("testPositionForSuperConstructorCalls", 164 mitEndPos, pos.getEndPosition(cut, mit)); 165 166 final int methodStartPos = mitStartPos; 167 final int methodEndPos = methodStartPos + mit.getMethodSelect().toString().length(); 168 assertEquals("testPositionForSuperConstructorCalls", 169 methodStartPos, pos.getStartPosition(cut, mit.getMethodSelect())); 170 assertEquals("testPositionForSuperConstructorCalls", 171 methodEndPos, pos.getEndPosition(cut, mit.getMethodSelect())); 172 } 173 174 @Test 175 void testPositionForEnumModifiers() throws IOException { 176 final String theString = "public"; 177 String code = "package test; " + theString + " enum Test {A;}"; 178 179 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, null, 180 null, Arrays.asList(new MyFileObject(code))); 181 CompilationUnitTree cut = ct.parse().iterator().next(); 182 SourcePositions pos = Trees.instance(ct).getSourcePositions(); 183 184 ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); 185 ModifiersTree mt = clazz.getModifiers(); 186 int spos = code.indexOf(theString); 187 int epos = spos + theString.length(); 188 assertEquals("testPositionForEnumModifiers", 189 spos, pos.getStartPosition(cut, mt)); 190 assertEquals("testPositionForEnumModifiers", 191 epos, pos.getEndPosition(cut, mt)); 192 } 193 194 @Test 195 void testNewClassWithEnclosing() throws IOException { 196 197 final String theString = "Test.this.new d()"; 198 String code = "package test; class Test { " + 199 "class d {} private void method() { " + 200 "Object o = " + theString + "; } }"; 201 202 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, null, 203 null, Arrays.asList(new MyFileObject(code))); 204 CompilationUnitTree cut = ct.parse().iterator().next(); 205 SourcePositions pos = Trees.instance(ct).getSourcePositions(); 206 207 ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); 208 ExpressionTree est = 209 ((VariableTree) ((MethodTree) clazz.getMembers().get(1)).getBody().getStatements().get(0)).getInitializer(); 210 211 final int spos = code.indexOf(theString); 212 final int epos = spos + theString.length(); 213 assertEquals("testNewClassWithEnclosing", 214 spos, pos.getStartPosition(cut, est)); 215 assertEquals("testNewClassWithEnclosing", 216 epos, pos.getEndPosition(cut, est)); 217 } 218 219 @Test 220 void testPreferredPositionForBinaryOp() throws IOException { 221 222 String code = "package test; public class Test {" 223 + "private void test() {" 224 + "Object o = null; boolean b = o != null && o instanceof String;" 225 + "} private Test() {}}"; 226 227 CompilationUnitTree cut = getCompilationUnitTree(code); 228 ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); 229 MethodTree method = (MethodTree) clazz.getMembers().get(0); 230 VariableTree condSt = (VariableTree) method.getBody().getStatements().get(1); 231 BinaryTree cond = (BinaryTree) condSt.getInitializer(); 232 233 JCTree condJC = (JCTree) cond; 234 int condStartPos = code.indexOf("&&"); 235 assertEquals("testPreferredPositionForBinaryOp", 236 condStartPos, condJC.pos); 237 } 238 239 @Test 240 void testErrorRecoveryForEnhancedForLoop142381() throws IOException { 241 242 String code = "package test; class Test { " + 243 "private void method() { " + 244 "java.util.Set<String> s = null; for (a : s) {} } }"; 245 246 final List<Diagnostic<? extends JavaFileObject>> errors = 247 new LinkedList<Diagnostic<? extends JavaFileObject>>(); 248 249 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, 250 new DiagnosticListener<JavaFileObject>() { 251 public void report(Diagnostic<? extends JavaFileObject> diagnostic) { 252 errors.add(diagnostic); 253 } 254 }, null, null, Arrays.asList(new MyFileObject(code))); 255 256 CompilationUnitTree cut = ct.parse().iterator().next(); 257 258 ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); 259 StatementTree forStatement = 260 ((MethodTree) clazz.getMembers().get(0)).getBody().getStatements().get(1); 261 262 assertEquals("testErrorRecoveryForEnhancedForLoop142381", 263 Kind.ENHANCED_FOR_LOOP, forStatement.getKind()); 264 assertFalse("testErrorRecoveryForEnhancedForLoop142381", errors.isEmpty()); 265 } 266 267 @Test 268 void testPositionAnnotationNoPackage187551() throws IOException { 269 270 String code = "\n@interface Test {}"; 271 272 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, null, 273 null, Arrays.asList(new MyFileObject(code))); 274 275 CompilationUnitTree cut = ct.parse().iterator().next(); 276 ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); 277 Trees t = Trees.instance(ct); 278 279 assertEquals("testPositionAnnotationNoPackage187551", 280 1, t.getSourcePositions().getStartPosition(cut, clazz)); 281 } 282 283 @Test 284 void testPositionsSane1() throws IOException { 285 performPositionsSanityTest("package test; class Test { " + 286 "private void method() { " + 287 "java.util.List<? extends java.util.List<? extends String>> l; " + 288 "} }"); 289 } 290 291 @Test 292 void testPositionsSane2() throws IOException { 293 performPositionsSanityTest("package test; class Test { " + 294 "private void method() { " + 295 "java.util.List<? super java.util.List<? super String>> l; " + 296 "} }"); 297 } 298 299 @Test 300 void testPositionsSane3() throws IOException { 301 performPositionsSanityTest("package test; class Test { " + 302 "private void method() { " + 303 "java.util.List<? super java.util.List<?>> l; } }"); 304 } 305 306 private void performPositionsSanityTest(String code) throws IOException { 307 308 final List<Diagnostic<? extends JavaFileObject>> errors = 309 new LinkedList<Diagnostic<? extends JavaFileObject>>(); 310 311 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, 312 new DiagnosticListener<JavaFileObject>() { 313 314 public void report(Diagnostic<? extends JavaFileObject> diagnostic) { 315 errors.add(diagnostic); 316 } 317 }, null, null, Arrays.asList(new MyFileObject(code))); 318 319 final CompilationUnitTree cut = ct.parse().iterator().next(); 320 final Trees trees = Trees.instance(ct); 321 322 new TreeScanner<Void, Void>() { 323 324 private long parentStart = 0; 325 private long parentEnd = Integer.MAX_VALUE; 326 327 @Override 328 public Void scan(Tree node, Void p) { 329 if (node == null) { 330 return null; 331 } 332 333 long start = trees.getSourcePositions().getStartPosition(cut, node); 334 335 if (start == (-1)) { 336 return null; // synthetic tree 337 } 338 assertTrue(node.toString() + ":" + start + "/" + parentStart, 339 parentStart <= start); 340 341 long prevParentStart = parentStart; 342 343 parentStart = start; 344 345 long end = trees.getSourcePositions().getEndPosition(cut, node); 346 347 assertTrue(node.toString() + ":" + end + "/" + parentEnd, 348 end <= parentEnd); 349 350 long prevParentEnd = parentEnd; 351 352 parentEnd = end; 353 354 super.scan(node, p); 355 356 parentStart = prevParentStart; 357 parentEnd = prevParentEnd; 358 359 return null; 360 } 361 362 private void assertTrue(String message, boolean b) { 363 if (!b) fail(message); 364 } 365 }.scan(cut, null); 366 } 367 368 @Test 369 void testCorrectWilcardPositions1() throws IOException { 370 performWildcardPositionsTest("package test; import java.util.List; " + 371 "class Test { private void method() { List<? extends List<? extends String>> l; } }", 372 373 Arrays.asList("List<? extends List<? extends String>> l;", 374 "List<? extends List<? extends String>>", 375 "List", 376 "? extends List<? extends String>", 377 "List<? extends String>", 378 "List", 379 "? extends String", 380 "String")); 381 } 382 383 @Test 384 void testCorrectWilcardPositions2() throws IOException { 385 performWildcardPositionsTest("package test; import java.util.List; " 386 + "class Test { private void method() { List<? super List<? super String>> l; } }", 387 Arrays.asList("List<? super List<? super String>> l;", 388 "List<? super List<? super String>>", 389 "List", 390 "? super List<? super String>", 391 "List<? super String>", 392 "List", 393 "? super String", 394 "String")); 395 } 396 397 @Test 398 void testCorrectWilcardPositions3() throws IOException { 399 performWildcardPositionsTest("package test; import java.util.List; " + 400 "class Test { private void method() { List<? super List<?>> l; } }", 401 402 Arrays.asList("List<? super List<?>> l;", 403 "List<? super List<?>>", 404 "List", 405 "? super List<?>", 406 "List<?>", 407 "List", 408 "?")); 409 } 410 411 @Test 412 void testCorrectWilcardPositions4() throws IOException { 413 performWildcardPositionsTest("package test; import java.util.List; " + 414 "class Test { private void method() { " + 415 "List<? extends List<? extends List<? extends String>>> l; } }", 416 417 Arrays.asList("List<? extends List<? extends List<? extends String>>> l;", 418 "List<? extends List<? extends List<? extends String>>>", 419 "List", 420 "? extends List<? extends List<? extends String>>", 421 "List<? extends List<? extends String>>", 422 "List", 423 "? extends List<? extends String>", 424 "List<? extends String>", 425 "List", 426 "? extends String", 427 "String")); 428 } 429 430 @Test 431 void testCorrectWilcardPositions5() throws IOException { 432 performWildcardPositionsTest("package test; import java.util.List; " + 433 "class Test { private void method() { " + 434 "List<? extends List<? extends List<? extends String >>> l; } }", 435 Arrays.asList("List<? extends List<? extends List<? extends String >>> l;", 436 "List<? extends List<? extends List<? extends String >>>", 437 "List", 438 "? extends List<? extends List<? extends String >>", 439 "List<? extends List<? extends String >>", 440 "List", 441 "? extends List<? extends String >", 442 "List<? extends String >", 443 "List", 444 "? extends String", 445 "String")); 446 } 447 448 void performWildcardPositionsTest(final String code, 449 List<String> golden) throws IOException { 450 451 final List<Diagnostic<? extends JavaFileObject>> errors = 452 new LinkedList<Diagnostic<? extends JavaFileObject>>(); 453 454 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, 455 new DiagnosticListener<JavaFileObject>() { 456 public void report(Diagnostic<? extends JavaFileObject> diagnostic) { 457 errors.add(diagnostic); 458 } 459 }, null, null, Arrays.asList(new MyFileObject(code))); 460 461 final CompilationUnitTree cut = ct.parse().iterator().next(); 462 final List<String> content = new LinkedList<String>(); 463 final Trees trees = Trees.instance(ct); 464 465 new TreeScanner<Void, Void>() { 466 @Override 467 public Void scan(Tree node, Void p) { 468 if (node == null) { 469 return null; 470 } 471 long start = trees.getSourcePositions().getStartPosition(cut, node); 472 473 if (start == (-1)) { 474 return null; // synthetic tree 475 } 476 long end = trees.getSourcePositions().getEndPosition(cut, node); 477 String s = code.substring((int) start, (int) end); 478 content.add(s); 479 480 return super.scan(node, p); 481 } 482 }.scan(((MethodTree) ((ClassTree) cut.getTypeDecls().get(0)).getMembers().get(0)).getBody().getStatements().get(0), null); 483 484 assertEquals("performWildcardPositionsTest",golden.toString(), 485 content.toString()); 486 } 487 488 @Test 489 void testStartPositionForMethodWithoutModifiers() throws IOException { 490 491 String code = "package t; class Test { <T> void t() {} }"; 492 493 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, null, 494 null, Arrays.asList(new MyFileObject(code))); 495 CompilationUnitTree cut = ct.parse().iterator().next(); 496 ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); 497 MethodTree mt = (MethodTree) clazz.getMembers().get(0); 498 Trees t = Trees.instance(ct); 499 int start = (int) t.getSourcePositions().getStartPosition(cut, mt); 500 int end = (int) t.getSourcePositions().getEndPosition(cut, mt); 501 502 assertEquals("testStartPositionForMethodWithoutModifiers", 503 "<T> void t() {}", code.substring(start, end)); 504 } 505 506 @Test 507 void testVariableInIfThen1() throws IOException { 508 509 String code = "package t; class Test { " + 510 "private static void t(String name) { " + 511 "if (name != null) String nn = name.trim(); } }"; 512 513 DiagnosticCollector<JavaFileObject> coll = 514 new DiagnosticCollector<JavaFileObject>(); 515 516 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, coll, null, 517 null, Arrays.asList(new MyFileObject(code))); 518 519 ct.parse(); 520 521 List<String> codes = new LinkedList<String>(); 522 523 for (Diagnostic<? extends JavaFileObject> d : coll.getDiagnostics()) { 524 codes.add(d.getCode()); 525 } 526 527 assertEquals("testVariableInIfThen1", 528 Arrays.<String>asList("compiler.err.variable.not.allowed"), 529 codes); 530 } 531 532 @Test 533 void testVariableInIfThen2() throws IOException { 534 535 String code = "package t; class Test { " + 536 "private static void t(String name) { " + 537 "if (name != null) class X {} } }"; 538 DiagnosticCollector<JavaFileObject> coll = 539 new DiagnosticCollector<JavaFileObject>(); 540 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, coll, null, 541 null, Arrays.asList(new MyFileObject(code))); 542 543 ct.parse(); 544 545 List<String> codes = new LinkedList<String>(); 546 547 for (Diagnostic<? extends JavaFileObject> d : coll.getDiagnostics()) { 548 codes.add(d.getCode()); 549 } 550 551 assertEquals("testVariableInIfThen2", 552 Arrays.<String>asList("compiler.err.class.not.allowed"), codes); 553 } 554 555 @Test 556 void testVariableInIfThen3() throws IOException { 557 558 String code = "package t; class Test { "+ 559 "private static void t() { " + 560 "if (true) abstract class F {} }}"; 561 DiagnosticCollector<JavaFileObject> coll = 562 new DiagnosticCollector<JavaFileObject>(); 563 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, coll, null, 564 null, Arrays.asList(new MyFileObject(code))); 565 566 ct.parse(); 567 568 List<String> codes = new LinkedList<String>(); 569 570 for (Diagnostic<? extends JavaFileObject> d : coll.getDiagnostics()) { 571 codes.add(d.getCode()); 572 } 573 574 assertEquals("testVariableInIfThen3", 575 Arrays.<String>asList("compiler.err.class.not.allowed"), codes); 576 } 577 578 @Test 579 void testVariableInIfThen4() throws IOException { 580 581 String code = "package t; class Test { "+ 582 "private static void t(String name) { " + 583 "if (name != null) interface X {} } }"; 584 DiagnosticCollector<JavaFileObject> coll = 585 new DiagnosticCollector<JavaFileObject>(); 586 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, coll, null, 587 null, Arrays.asList(new MyFileObject(code))); 588 589 ct.parse(); 590 591 List<String> codes = new LinkedList<String>(); 592 593 for (Diagnostic<? extends JavaFileObject> d : coll.getDiagnostics()) { 594 codes.add(d.getCode()); 595 } 596 597 assertEquals("testVariableInIfThen4", 598 Arrays.<String>asList("compiler.err.class.not.allowed"), codes); 599 } 600 601 @Test 602 void testVariableInIfThen5() throws IOException { 603 604 String code = "package t; class Test { "+ 605 "private static void t() { " + 606 "if (true) } }"; 607 DiagnosticCollector<JavaFileObject> coll = 608 new DiagnosticCollector<JavaFileObject>(); 609 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, coll, null, 610 null, Arrays.asList(new MyFileObject(code))); 611 612 ct.parse(); 613 614 List<String> codes = new LinkedList<String>(); 615 616 for (Diagnostic<? extends JavaFileObject> d : coll.getDiagnostics()) { 617 codes.add(d.getCode()); 618 } 619 620 assertEquals("testVariableInIfThen5", 621 Arrays.<String>asList("compiler.err.illegal.start.of.stmt"), 622 codes); 623 } 624 625 // see javac bug #6882235, NB bug #98234: 626 @Test 627 void testMissingExponent() throws IOException { 628 629 String code = "\nclass Test { { System.err.println(0e); } }"; 630 631 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, null, 632 null, Arrays.asList(new MyFileObject(code))); 633 634 assertNotNull(ct.parse().iterator().next()); 635 } 636 637 @Test 638 void testTryResourcePos() throws IOException { 639 640 final String code = "package t; class Test { " + 641 "{ try (java.io.InputStream in = null) { } } }"; 642 643 CompilationUnitTree cut = getCompilationUnitTree(code); 644 645 new TreeScanner<Void, Void>() { 646 @Override 647 public Void visitVariable(VariableTree node, Void p) { 648 if ("in".contentEquals(node.getName())) { 649 JCTree.JCVariableDecl var = (JCTree.JCVariableDecl) node; 650 assertEquals("testTryResourcePos", "in = null) { } } }", 651 code.substring(var.pos)); 652 } 653 return super.visitVariable(node, p); 654 } 655 }.scan(cut, null); 656 } 657 658 @Test 659 void testVarPos() throws IOException { 660 661 final String code = "package t; class Test { " + 662 "{ java.io.InputStream in = null; } }"; 663 664 CompilationUnitTree cut = getCompilationUnitTree(code); 665 666 new TreeScanner<Void, Void>() { 667 668 @Override 669 public Void visitVariable(VariableTree node, Void p) { 670 if ("in".contentEquals(node.getName())) { 671 JCTree.JCVariableDecl var = (JCTree.JCVariableDecl) node; 672 assertEquals("testVarPos","in = null; } }", 673 code.substring(var.pos)); 674 } 675 return super.visitVariable(node, p); 676 } 677 }.scan(cut, null); 678 } 679 680 // expected erroneous tree: int x = y;(ERROR); 681 @Test 682 void testOperatorMissingError() throws IOException { 683 684 String code = "package test; public class ErrorTest { " 685 + "void method() { int x = y z } }"; 686 CompilationUnitTree cut = getCompilationUnitTree(code); 687 final List<String> values = new ArrayList<>(); 688 final List<String> expectedValues = 689 new ArrayList<>(Arrays.asList("[z]")); 690 691 new TreeScanner<Void, Void>() { 692 @Override 693 public Void visitErroneous(ErroneousTree node, Void p) { 694 values.add(getErroneousTreeValues(node).toString()); 695 return null; 696 697 } 698 }.scan(cut, null); 699 700 assertEquals("testSwitchError: The Erroneous tree " 701 + "error values: " + values 702 + " do not match expected error values: " 703 + expectedValues, values, expectedValues); 704 } 705 706 // expected erroneous tree: String s = (ERROR); 707 @Test 708 void testMissingParenthesisError() throws IOException { 709 710 String code = "package test; public class ErrorTest { " 711 + "void f() {String s = new String; } }"; 712 CompilationUnitTree cut = getCompilationUnitTree(code); 713 final List<String> values = new ArrayList<>(); 714 final List<String> expectedValues = 715 new ArrayList<>(Arrays.asList("[new String()]")); 716 717 new TreeScanner<Void, Void>() { 718 @Override 719 public Void visitErroneous(ErroneousTree node, Void p) { 720 values.add(getErroneousTreeValues(node).toString()); 721 return null; 722 } 723 }.scan(cut, null); 724 725 assertEquals("testSwitchError: The Erroneous tree " 726 + "error values: " + values 727 + " do not match expected error values: " 728 + expectedValues, values, expectedValues); 729 } 730 731 // expected erroneous tree: package test; (ERROR)(ERROR) 732 @Test 733 void testMissingClassError() throws IOException { 734 735 String code = "package Test; clas ErrorTest { " 736 + "void f() {String s = new String(); } }"; 737 CompilationUnitTree cut = getCompilationUnitTree(code); 738 final List<String> values = new ArrayList<>(); 739 final List<String> expectedValues = 740 new ArrayList<>(Arrays.asList("[, clas]", "[]")); 741 742 new TreeScanner<Void, Void>() { 743 @Override 744 public Void visitErroneous(ErroneousTree node, Void p) { 745 values.add(getErroneousTreeValues(node).toString()); 746 return null; 747 } 748 }.scan(cut, null); 749 750 assertEquals("testSwitchError: The Erroneous tree " 751 + "error values: " + values 752 + " do not match expected error values: " 753 + expectedValues, values, expectedValues); 754 } 755 756 // expected erroneous tree: void m1(int i) {(ERROR);{(ERROR);} 757 @Test 758 void testSwitchError() throws IOException { 759 760 String code = "package test; public class ErrorTest { " 761 + "int numDays; void m1(int i) { switchh {i} { case 1: " 762 + "numDays = 31; break; } } }"; 763 CompilationUnitTree cut = getCompilationUnitTree(code); 764 final List<String> values = new ArrayList<>(); 765 final List<String> expectedValues = 766 new ArrayList<>(Arrays.asList("[switchh]", "[i]")); 767 768 new TreeScanner<Void, Void>() { 769 @Override 770 public Void visitErroneous(ErroneousTree node, Void p) { 771 values.add(getErroneousTreeValues(node).toString()); 772 return null; 773 } 774 }.scan(cut, null); 775 776 assertEquals("testSwitchError: The Erroneous tree " 777 + "error values: " + values 778 + " do not match expected error values: " 779 + expectedValues, values, expectedValues); 780 } 781 782 // expected erroneous tree: class ErrorTest {(ERROR) 783 @Test 784 void testMethodError() throws IOException { 785 786 String code = "package Test; class ErrorTest { " 787 + "static final void f) {String s = new String(); } }"; 788 CompilationUnitTree cut = cut = getCompilationUnitTree(code); 789 790 final List<String> values = new ArrayList<>(); 791 final List<String> expectedValues = 792 new ArrayList<>(Arrays.asList("[\nstatic final void f();]")); 793 794 new TreeScanner<Void, Void>() { 795 @Override 796 public Void visitErroneous(ErroneousTree node, Void p) { 797 values.add(normalize(getErroneousTreeValues(node).toString())); 798 return null; 799 } 800 }.scan(cut, null); 801 802 assertEquals("testMethodError: The Erroneous tree " 803 + "error value: " + values 804 + " does not match expected error values: " 805 + expectedValues, values, expectedValues); 806 } 807 808 /* 809 * The following tests do not work just yet with nb-javac nor javac, 810 * they need further investigation, see CR: 7167356 811 */ 812 813 void testPositionBrokenSource126732a() throws IOException { 814 String[] commands = new String[]{ 815 "return Runnable()", 816 "do { } while (true)", 817 "throw UnsupportedOperationException()", 818 "assert true", 819 "1 + 1",}; 820 821 for (String command : commands) { 822 823 String code = "package test;\n" 824 + "public class Test {\n" 825 + " public static void test() {\n" 826 + " " + command + " {\n" 827 + " new Runnable() {\n" 828 + " };\n" 829 + " }\n" 830 + "}"; 831 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, 832 null, null, Arrays.asList(new MyFileObject(code))); 833 CompilationUnitTree cut = ct.parse().iterator().next(); 834 835 ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); 836 MethodTree method = (MethodTree) clazz.getMembers().get(0); 837 List<? extends StatementTree> statements = 838 method.getBody().getStatements(); 839 840 StatementTree ret = statements.get(0); 841 StatementTree block = statements.get(1); 842 843 Trees t = Trees.instance(ct); 844 int len = code.indexOf(command + " {") + (command + " ").length(); 845 assertEquals(command, len, 846 t.getSourcePositions().getEndPosition(cut, ret)); 847 assertEquals(command, len, 848 t.getSourcePositions().getStartPosition(cut, block)); 849 } 850 } 851 852 void testPositionBrokenSource126732b() throws IOException { 853 String[] commands = new String[]{ 854 "break", 855 "break A", 856 "continue ", 857 "continue A",}; 858 859 for (String command : commands) { 860 861 String code = "package test;\n" 862 + "public class Test {\n" 863 + " public static void test() {\n" 864 + " while (true) {\n" 865 + " " + command + " {\n" 866 + " new Runnable() {\n" 867 + " };\n" 868 + " }\n" 869 + " }\n" 870 + "}"; 871 872 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, 873 null, null, Arrays.asList(new MyFileObject(code))); 874 CompilationUnitTree cut = ct.parse().iterator().next(); 875 876 ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); 877 MethodTree method = (MethodTree) clazz.getMembers().get(0); 878 List<? extends StatementTree> statements = 879 ((BlockTree) ((WhileLoopTree) method.getBody().getStatements().get(0)).getStatement()).getStatements(); 880 881 StatementTree ret = statements.get(0); 882 StatementTree block = statements.get(1); 883 884 Trees t = Trees.instance(ct); 885 int len = code.indexOf(command + " {") + (command + " ").length(); 886 assertEquals(command, len, 887 t.getSourcePositions().getEndPosition(cut, ret)); 888 assertEquals(command, len, 889 t.getSourcePositions().getStartPosition(cut, block)); 890 } 891 } 892 893 void testStartPositionEnumConstantInit() throws IOException { 894 895 String code = "package t; enum Test { AAA; }"; 896 897 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, null, 898 null, Arrays.asList(new MyFileObject(code))); 899 CompilationUnitTree cut = ct.parse().iterator().next(); 900 ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); 901 VariableTree enumAAA = (VariableTree) clazz.getMembers().get(0); 902 Trees t = Trees.instance(ct); 903 int start = (int) t.getSourcePositions().getStartPosition(cut, 904 enumAAA.getInitializer()); 905 906 assertEquals("testStartPositionEnumConstantInit", -1, start); 907 } 908 909 @Test 910 void testVoidLambdaParameter() throws IOException { 911 String code = "package t; class Test { " + 912 "Runnable r = (void v) -> { };" + 913 "}"; 914 DiagnosticCollector<JavaFileObject> coll = 915 new DiagnosticCollector<>(); 916 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, coll, null, 917 null, Arrays.asList(new MyFileObject(code))); 918 919 CompilationUnitTree cut = ct.parse().iterator().next(); 920 ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); 921 VariableTree field = (VariableTree) clazz.getMembers().get(0); 922 923 assertEquals("actual kind: " + field.getInitializer().getKind(), 924 field.getInitializer().getKind(), 925 Kind.LAMBDA_EXPRESSION); 926 927 LambdaExpressionTree lambda = (LambdaExpressionTree) field.getInitializer(); 928 929 assertEquals("actual parameters: " + lambda.getParameters().size(), 930 lambda.getParameters().size(), 931 1); 932 933 Tree paramType = lambda.getParameters().get(0).getType(); 934 935 assertEquals("actual parameter type: " + paramType.getKind(), 936 paramType.getKind(), 937 Kind.PRIMITIVE_TYPE); 938 939 TypeKind primitiveTypeKind = ((PrimitiveTypeTree) paramType).getPrimitiveTypeKind(); 940 941 assertEquals("actual parameter type: " + primitiveTypeKind, 942 primitiveTypeKind, 943 TypeKind.VOID); 944 } 945 946 @Test //JDK-8065753 947 void testWrongFirstToken() throws IOException { 948 String code = "<"; 949 String expectedErrors = "Test.java:1:1: compiler.err.expected3: class, interface, enum\n" + 950 "1 error\n"; 951 StringWriter out = new StringWriter(); 952 JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(out, fm, null, 953 Arrays.asList("-XDrawDiagnostics"), null, Arrays.asList(new MyFileObject(code))); 954 955 assertEquals("the error code is not correct", Main.Result.ERROR, ct.doCall()); 956 assertEquals("the error message is not correct", expectedErrors, out.toString()); 957 } 958 959 void run(String[] args) throws Exception { 960 int passed = 0, failed = 0; 961 final Pattern p = (args != null && args.length > 0) 962 ? Pattern.compile(args[0]) 963 : null; 964 for (Method m : this.getClass().getDeclaredMethods()) { 965 boolean selected = (p == null) 966 ? m.isAnnotationPresent(Test.class) 967 : p.matcher(m.getName()).matches(); 968 if (selected) { 969 try { 970 m.invoke(this, (Object[]) null); 971 System.out.println(m.getName() + ": OK"); 972 passed++; 973 } catch (Throwable ex) { 974 System.out.printf("Test %s failed: %s %n", m, ex.getCause()); 975 failed++; 976 } 977 } 978 } 979 System.out.printf("Passed: %d, Failed %d%n", passed, failed); 980 if (failed > 0) { 981 throw new RuntimeException("Tests failed: " + failed); 982 } 983 if (passed == 0 && failed == 0) { 984 throw new AssertionError("No test(s) selected: passed = " + 985 passed + ", failed = " + failed + " ??????????"); 986 } 987 } 988} 989 990abstract class TestCase { 991 992 void assertEquals(String message, int i, int pos) { 993 if (i != pos) { 994 fail(message); 995 } 996 } 997 998 void assertFalse(String message, boolean bvalue) { 999 if (bvalue == true) { 1000 fail(message); 1001 } 1002 } 1003 1004 void assertEquals(String message, int i, long l) { 1005 if (i != l) { 1006 fail(message + ":" + i + ":" + l); 1007 } 1008 } 1009 1010 void assertEquals(String message, Object o1, Object o2) { 1011 if (o1 != null && o2 != null && !o1.equals(o2)) { 1012 fail(message); 1013 } 1014 if (o1 == null && o2 != null) { 1015 fail(message); 1016 } 1017 } 1018 1019 void assertNotNull(Object o) { 1020 if (o == null) { 1021 fail(); 1022 } 1023 } 1024 1025 void fail() { 1026 fail("test failed"); 1027 } 1028 1029 void fail(String message) { 1030 throw new RuntimeException(message); 1031 } 1032 1033 /** 1034 * Indicates that the annotated method is a test method. 1035 */ 1036 @Retention(RetentionPolicy.RUNTIME) 1037 @Target(ElementType.METHOD) 1038 public @interface Test {} 1039} 1040