/* * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * @test * @bug 7073631 7159445 7156633 8028235 8065753 * @summary tests error and diagnostics positions * @author Jan Lahoda * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.main * jdk.compiler/com.sun.tools.javac.tree */ import com.sun.source.tree.BinaryTree; import com.sun.source.tree.BlockTree; import com.sun.source.tree.ClassTree; import com.sun.source.tree.CompilationUnitTree; import com.sun.source.tree.ErroneousTree; import com.sun.source.tree.ExpressionStatementTree; import com.sun.source.tree.ExpressionTree; import com.sun.source.tree.LambdaExpressionTree; import com.sun.source.tree.MethodInvocationTree; import com.sun.source.tree.MethodTree; import com.sun.source.tree.ModifiersTree; import com.sun.source.tree.PrimitiveTypeTree; import com.sun.source.tree.StatementTree; import com.sun.source.tree.Tree; import com.sun.source.tree.Tree.Kind; import com.sun.source.tree.VariableTree; import com.sun.source.tree.WhileLoopTree; import com.sun.source.util.SourcePositions; import com.sun.source.util.TreeScanner; import com.sun.source.util.Trees; import com.sun.tools.javac.api.JavacTaskImpl; import com.sun.tools.javac.main.Main; import com.sun.tools.javac.main.Main.Result; import com.sun.tools.javac.tree.JCTree; import java.io.IOException; import java.io.StringWriter; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Method; import java.net.URI; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.regex.Pattern; import javax.lang.model.type.TypeKind; import javax.tools.Diagnostic; import javax.tools.DiagnosticCollector; import javax.tools.DiagnosticListener; import javax.tools.JavaCompiler; import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; import javax.tools.SimpleJavaFileObject; import javax.tools.ToolProvider; public class JavacParserTest extends TestCase { static final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); static final JavaFileManager fm = tool.getStandardFileManager(null, null, null); private JavacParserTest(){} public static void main(String... args) throws Exception { try { new JavacParserTest().run(args); } finally { fm.close(); } } class MyFileObject extends SimpleJavaFileObject { private String text; public MyFileObject(String text) { super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); this.text = text; } @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) { return text; } } /* * converts Windows to Unix style LFs for comparing strings */ String normalize(String in) { return in.replace(System.getProperty("line.separator"), "\n"); } CompilationUnitTree getCompilationUnitTree(String code) throws IOException { JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, null, null, Arrays.asList(new MyFileObject(code))); CompilationUnitTree cut = ct.parse().iterator().next(); return cut; } List<String> getErroneousTreeValues(ErroneousTree node) { List<String> values = new ArrayList<>(); if (node.getErrorTrees() != null) { for (Tree t : node.getErrorTrees()) { values.add(t.toString()); } } else { throw new RuntimeException("ERROR: No Erroneous tree " + "has been created."); } return values; } @Test void testPositionForSuperConstructorCalls() throws IOException { assert tool != null; String code = "package test; public class Test {public Test() {super();}}"; JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, null, null, Arrays.asList(new MyFileObject(code))); CompilationUnitTree cut = ct.parse().iterator().next(); SourcePositions pos = Trees.instance(ct).getSourcePositions(); MethodTree method = (MethodTree) ((ClassTree) cut.getTypeDecls().get(0)).getMembers().get(0); ExpressionStatementTree es = (ExpressionStatementTree) method.getBody().getStatements().get(0); final int esStartPos = code.indexOf(es.toString()); final int esEndPos = esStartPos + es.toString().length(); assertEquals("testPositionForSuperConstructorCalls", esStartPos, pos.getStartPosition(cut, es)); assertEquals("testPositionForSuperConstructorCalls", esEndPos, pos.getEndPosition(cut, es)); MethodInvocationTree mit = (MethodInvocationTree) es.getExpression(); final int mitStartPos = code.indexOf(mit.toString()); final int mitEndPos = mitStartPos + mit.toString().length(); assertEquals("testPositionForSuperConstructorCalls", mitStartPos, pos.getStartPosition(cut, mit)); assertEquals("testPositionForSuperConstructorCalls", mitEndPos, pos.getEndPosition(cut, mit)); final int methodStartPos = mitStartPos; final int methodEndPos = methodStartPos + mit.getMethodSelect().toString().length(); assertEquals("testPositionForSuperConstructorCalls", methodStartPos, pos.getStartPosition(cut, mit.getMethodSelect())); assertEquals("testPositionForSuperConstructorCalls", methodEndPos, pos.getEndPosition(cut, mit.getMethodSelect())); } @Test void testPositionForEnumModifiers() throws IOException { final String theString = "public"; String code = "package test; " + theString + " enum Test {A;}"; JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, null, null, Arrays.asList(new MyFileObject(code))); CompilationUnitTree cut = ct.parse().iterator().next(); SourcePositions pos = Trees.instance(ct).getSourcePositions(); ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); ModifiersTree mt = clazz.getModifiers(); int spos = code.indexOf(theString); int epos = spos + theString.length(); assertEquals("testPositionForEnumModifiers", spos, pos.getStartPosition(cut, mt)); assertEquals("testPositionForEnumModifiers", epos, pos.getEndPosition(cut, mt)); } @Test void testNewClassWithEnclosing() throws IOException { final String theString = "Test.this.new d()"; String code = "package test; class Test { " + "class d {} private void method() { " + "Object o = " + theString + "; } }"; JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, null, null, Arrays.asList(new MyFileObject(code))); CompilationUnitTree cut = ct.parse().iterator().next(); SourcePositions pos = Trees.instance(ct).getSourcePositions(); ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); ExpressionTree est = ((VariableTree) ((MethodTree) clazz.getMembers().get(1)).getBody().getStatements().get(0)).getInitializer(); final int spos = code.indexOf(theString); final int epos = spos + theString.length(); assertEquals("testNewClassWithEnclosing", spos, pos.getStartPosition(cut, est)); assertEquals("testNewClassWithEnclosing", epos, pos.getEndPosition(cut, est)); } @Test void testPreferredPositionForBinaryOp() throws IOException { String code = "package test; public class Test {" + "private void test() {" + "Object o = null; boolean b = o != null && o instanceof String;" + "} private Test() {}}"; CompilationUnitTree cut = getCompilationUnitTree(code); ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); MethodTree method = (MethodTree) clazz.getMembers().get(0); VariableTree condSt = (VariableTree) method.getBody().getStatements().get(1); BinaryTree cond = (BinaryTree) condSt.getInitializer(); JCTree condJC = (JCTree) cond; int condStartPos = code.indexOf("&&"); assertEquals("testPreferredPositionForBinaryOp", condStartPos, condJC.pos); } @Test void testErrorRecoveryForEnhancedForLoop142381() throws IOException { String code = "package test; class Test { " + "private void method() { " + "java.util.Set<String> s = null; for (a : s) {} } }"; final List<Diagnostic<? extends JavaFileObject>> errors = new LinkedList<Diagnostic<? extends JavaFileObject>>(); JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, new DiagnosticListener<JavaFileObject>() { public void report(Diagnostic<? extends JavaFileObject> diagnostic) { errors.add(diagnostic); } }, null, null, Arrays.asList(new MyFileObject(code))); CompilationUnitTree cut = ct.parse().iterator().next(); ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); StatementTree forStatement = ((MethodTree) clazz.getMembers().get(0)).getBody().getStatements().get(1); assertEquals("testErrorRecoveryForEnhancedForLoop142381", Kind.ENHANCED_FOR_LOOP, forStatement.getKind()); assertFalse("testErrorRecoveryForEnhancedForLoop142381", errors.isEmpty()); } @Test void testPositionAnnotationNoPackage187551() throws IOException { String code = "\n@interface Test {}"; JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, null, null, Arrays.asList(new MyFileObject(code))); CompilationUnitTree cut = ct.parse().iterator().next(); ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); Trees t = Trees.instance(ct); assertEquals("testPositionAnnotationNoPackage187551", 1, t.getSourcePositions().getStartPosition(cut, clazz)); } @Test void testPositionsSane1() throws IOException { performPositionsSanityTest("package test; class Test { " + "private void method() { " + "java.util.List<? extends java.util.List<? extends String>> l; " + "} }"); } @Test void testPositionsSane2() throws IOException { performPositionsSanityTest("package test; class Test { " + "private void method() { " + "java.util.List<? super java.util.List<? super String>> l; " + "} }"); } @Test void testPositionsSane3() throws IOException { performPositionsSanityTest("package test; class Test { " + "private void method() { " + "java.util.List<? super java.util.List<?>> l; } }"); } private void performPositionsSanityTest(String code) throws IOException { final List<Diagnostic<? extends JavaFileObject>> errors = new LinkedList<Diagnostic<? extends JavaFileObject>>(); JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, new DiagnosticListener<JavaFileObject>() { public void report(Diagnostic<? extends JavaFileObject> diagnostic) { errors.add(diagnostic); } }, null, null, Arrays.asList(new MyFileObject(code))); final CompilationUnitTree cut = ct.parse().iterator().next(); final Trees trees = Trees.instance(ct); new TreeScanner<Void, Void>() { private long parentStart = 0; private long parentEnd = Integer.MAX_VALUE; @Override public Void scan(Tree node, Void p) { if (node == null) { return null; } long start = trees.getSourcePositions().getStartPosition(cut, node); if (start == (-1)) { return null; // synthetic tree } assertTrue(node.toString() + ":" + start + "/" + parentStart, parentStart <= start); long prevParentStart = parentStart; parentStart = start; long end = trees.getSourcePositions().getEndPosition(cut, node); assertTrue(node.toString() + ":" + end + "/" + parentEnd, end <= parentEnd); long prevParentEnd = parentEnd; parentEnd = end; super.scan(node, p); parentStart = prevParentStart; parentEnd = prevParentEnd; return null; } private void assertTrue(String message, boolean b) { if (!b) fail(message); } }.scan(cut, null); } @Test void testCorrectWildcardPositions1() throws IOException { performWildcardPositionsTest("package test; import java.util.List; " + "class Test { private void method() { List<? extends List<? extends String>> l; } }", Arrays.asList("List<? extends List<? extends String>> l;", "List<? extends List<? extends String>>", "List", "? extends List<? extends String>", "List<? extends String>", "List", "? extends String", "String")); } @Test void testCorrectWildcardPositions2() throws IOException { performWildcardPositionsTest("package test; import java.util.List; " + "class Test { private void method() { List<? super List<? super String>> l; } }", Arrays.asList("List<? super List<? super String>> l;", "List<? super List<? super String>>", "List", "? super List<? super String>", "List<? super String>", "List", "? super String", "String")); } @Test void testCorrectWildcardPositions3() throws IOException { performWildcardPositionsTest("package test; import java.util.List; " + "class Test { private void method() { List<? super List<?>> l; } }", Arrays.asList("List<? super List<?>> l;", "List<? super List<?>>", "List", "? super List<?>", "List<?>", "List", "?")); } @Test void testCorrectWildcardPositions4() throws IOException { performWildcardPositionsTest("package test; import java.util.List; " + "class Test { private void method() { " + "List<? extends List<? extends List<? extends String>>> l; } }", Arrays.asList("List<? extends List<? extends List<? extends String>>> l;", "List<? extends List<? extends List<? extends String>>>", "List", "? extends List<? extends List<? extends String>>", "List<? extends List<? extends String>>", "List", "? extends List<? extends String>", "List<? extends String>", "List", "? extends String", "String")); } @Test void testCorrectWildcardPositions5() throws IOException { performWildcardPositionsTest("package test; import java.util.List; " + "class Test { private void method() { " + "List<? extends List<? extends List<? extends String >>> l; } }", Arrays.asList("List<? extends List<? extends List<? extends String >>> l;", "List<? extends List<? extends List<? extends String >>>", "List", "? extends List<? extends List<? extends String >>", "List<? extends List<? extends String >>", "List", "? extends List<? extends String >", "List<? extends String >", "List", "? extends String", "String")); } void performWildcardPositionsTest(final String code, List<String> golden) throws IOException { final List<Diagnostic<? extends JavaFileObject>> errors = new LinkedList<Diagnostic<? extends JavaFileObject>>(); JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, new DiagnosticListener<JavaFileObject>() { public void report(Diagnostic<? extends JavaFileObject> diagnostic) { errors.add(diagnostic); } }, null, null, Arrays.asList(new MyFileObject(code))); final CompilationUnitTree cut = ct.parse().iterator().next(); final List<String> content = new LinkedList<String>(); final Trees trees = Trees.instance(ct); new TreeScanner<Void, Void>() { @Override public Void scan(Tree node, Void p) { if (node == null) { return null; } long start = trees.getSourcePositions().getStartPosition(cut, node); if (start == (-1)) { return null; // synthetic tree } long end = trees.getSourcePositions().getEndPosition(cut, node); String s = code.substring((int) start, (int) end); content.add(s); return super.scan(node, p); } }.scan(((MethodTree) ((ClassTree) cut.getTypeDecls().get(0)).getMembers().get(0)).getBody().getStatements().get(0), null); assertEquals("performWildcardPositionsTest",golden.toString(), content.toString()); } @Test void testStartPositionForMethodWithoutModifiers() throws IOException { String code = "package t; class Test { <T> void t() {} }"; JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, null, null, Arrays.asList(new MyFileObject(code))); CompilationUnitTree cut = ct.parse().iterator().next(); ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); MethodTree mt = (MethodTree) clazz.getMembers().get(0); Trees t = Trees.instance(ct); int start = (int) t.getSourcePositions().getStartPosition(cut, mt); int end = (int) t.getSourcePositions().getEndPosition(cut, mt); assertEquals("testStartPositionForMethodWithoutModifiers", "<T> void t() {}", code.substring(start, end)); } @Test void testVariableInIfThen1() throws IOException { String code = "package t; class Test { " + "private static void t(String name) { " + "if (name != null) String nn = name.trim(); } }"; DiagnosticCollector<JavaFileObject> coll = new DiagnosticCollector<JavaFileObject>(); JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, coll, null, null, Arrays.asList(new MyFileObject(code))); ct.parse(); List<String> codes = new LinkedList<String>(); for (Diagnostic<? extends JavaFileObject> d : coll.getDiagnostics()) { codes.add(d.getCode()); } assertEquals("testVariableInIfThen1", Arrays.<String>asList("compiler.err.variable.not.allowed"), codes); } @Test void testVariableInIfThen2() throws IOException { String code = "package t; class Test { " + "private static void t(String name) { " + "if (name != null) class X {} } }"; DiagnosticCollector<JavaFileObject> coll = new DiagnosticCollector<JavaFileObject>(); JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, coll, null, null, Arrays.asList(new MyFileObject(code))); ct.parse(); List<String> codes = new LinkedList<String>(); for (Diagnostic<? extends JavaFileObject> d : coll.getDiagnostics()) { codes.add(d.getCode()); } assertEquals("testVariableInIfThen2", Arrays.<String>asList("compiler.err.class.not.allowed"), codes); } @Test void testVariableInIfThen3() throws IOException { String code = "package t; class Test { "+ "private static void t() { " + "if (true) abstract class F {} }}"; DiagnosticCollector<JavaFileObject> coll = new DiagnosticCollector<JavaFileObject>(); JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, coll, null, null, Arrays.asList(new MyFileObject(code))); ct.parse(); List<String> codes = new LinkedList<String>(); for (Diagnostic<? extends JavaFileObject> d : coll.getDiagnostics()) { codes.add(d.getCode()); } assertEquals("testVariableInIfThen3", Arrays.<String>asList("compiler.err.class.not.allowed"), codes); } @Test void testVariableInIfThen4() throws IOException { String code = "package t; class Test { "+ "private static void t(String name) { " + "if (name != null) interface X {} } }"; DiagnosticCollector<JavaFileObject> coll = new DiagnosticCollector<JavaFileObject>(); JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, coll, null, null, Arrays.asList(new MyFileObject(code))); ct.parse(); List<String> codes = new LinkedList<String>(); for (Diagnostic<? extends JavaFileObject> d : coll.getDiagnostics()) { codes.add(d.getCode()); } assertEquals("testVariableInIfThen4", Arrays.<String>asList("compiler.err.class.not.allowed"), codes); } @Test void testVariableInIfThen5() throws IOException { String code = "package t; class Test { "+ "private static void t() { " + "if (true) } }"; DiagnosticCollector<JavaFileObject> coll = new DiagnosticCollector<JavaFileObject>(); JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, coll, null, null, Arrays.asList(new MyFileObject(code))); ct.parse(); List<String> codes = new LinkedList<String>(); for (Diagnostic<? extends JavaFileObject> d : coll.getDiagnostics()) { codes.add(d.getCode()); } assertEquals("testVariableInIfThen5", Arrays.<String>asList("compiler.err.illegal.start.of.stmt"), codes); } // see javac bug #6882235, NB bug #98234: @Test void testMissingExponent() throws IOException { String code = "\nclass Test { { System.err.println(0e); } }"; JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, null, null, Arrays.asList(new MyFileObject(code))); assertNotNull(ct.parse().iterator().next()); } @Test void testTryResourcePos() throws IOException { final String code = "package t; class Test { " + "{ try (java.io.InputStream in = null) { } } }"; CompilationUnitTree cut = getCompilationUnitTree(code); new TreeScanner<Void, Void>() { @Override public Void visitVariable(VariableTree node, Void p) { if ("in".contentEquals(node.getName())) { JCTree.JCVariableDecl var = (JCTree.JCVariableDecl) node; assertEquals("testTryResourcePos", "in = null) { } } }", code.substring(var.pos)); } return super.visitVariable(node, p); } }.scan(cut, null); } @Test void testVarPos() throws IOException { final String code = "package t; class Test { " + "{ java.io.InputStream in = null; } }"; CompilationUnitTree cut = getCompilationUnitTree(code); new TreeScanner<Void, Void>() { @Override public Void visitVariable(VariableTree node, Void p) { if ("in".contentEquals(node.getName())) { JCTree.JCVariableDecl var = (JCTree.JCVariableDecl) node; assertEquals("testVarPos","in = null; } }", code.substring(var.pos)); } return super.visitVariable(node, p); } }.scan(cut, null); } // expected erroneous tree: int x = y;(ERROR); @Test void testOperatorMissingError() throws IOException { String code = "package test; public class ErrorTest { " + "void method() { int x = y z } }"; CompilationUnitTree cut = getCompilationUnitTree(code); final List<String> values = new ArrayList<>(); final List<String> expectedValues = new ArrayList<>(Arrays.asList("[z]")); new TreeScanner<Void, Void>() { @Override public Void visitErroneous(ErroneousTree node, Void p) { values.add(getErroneousTreeValues(node).toString()); return null; } }.scan(cut, null); assertEquals("testOperatorMissingError: The Erroneous tree " + "error values: " + values + " do not match expected error values: " + expectedValues, values, expectedValues); } // expected erroneous tree: String s = (ERROR); @Test void testMissingParenthesisError() throws IOException { String code = "package test; public class ErrorTest { " + "void f() {String s = new String; } }"; CompilationUnitTree cut = getCompilationUnitTree(code); final List<String> values = new ArrayList<>(); final List<String> expectedValues = new ArrayList<>(Arrays.asList("[new String()]")); new TreeScanner<Void, Void>() { @Override public Void visitErroneous(ErroneousTree node, Void p) { values.add(getErroneousTreeValues(node).toString()); return null; } }.scan(cut, null); assertEquals("testMissingParenthesisError: The Erroneous tree " + "error values: " + values + " do not match expected error values: " + expectedValues, values, expectedValues); } // expected erroneous tree: package test; (ERROR)(ERROR) @Test void testMissingClassError() throws IOException { String code = "package Test; clas ErrorTest { " + "void f() {String s = new String(); } }"; CompilationUnitTree cut = getCompilationUnitTree(code); final List<String> values = new ArrayList<>(); final List<String> expectedValues = new ArrayList<>(Arrays.asList("[, clas]", "[]")); new TreeScanner<Void, Void>() { @Override public Void visitErroneous(ErroneousTree node, Void p) { values.add(getErroneousTreeValues(node).toString()); return null; } }.scan(cut, null); assertEquals("testMissingClassError: The Erroneous tree " + "error values: " + values + " do not match expected error values: " + expectedValues, values, expectedValues); } // expected erroneous tree: void m1(int i) {(ERROR);{(ERROR);} @Test void testSwitchError() throws IOException { String code = "package test; public class ErrorTest { " + "int numDays; void m1(int i) { switchh {i} { case 1: " + "numDays = 31; break; } } }"; CompilationUnitTree cut = getCompilationUnitTree(code); final List<String> values = new ArrayList<>(); final List<String> expectedValues = new ArrayList<>(Arrays.asList("[switchh]", "[i]")); new TreeScanner<Void, Void>() { @Override public Void visitErroneous(ErroneousTree node, Void p) { values.add(getErroneousTreeValues(node).toString()); return null; } }.scan(cut, null); assertEquals("testSwitchError: The Erroneous tree " + "error values: " + values + " do not match expected error values: " + expectedValues, values, expectedValues); } // expected erroneous tree: class ErrorTest {(ERROR) @Test void testMethodError() throws IOException { String code = "package Test; class ErrorTest { " + "static final void f) {String s = new String(); } }"; CompilationUnitTree cut = cut = getCompilationUnitTree(code); final List<String> values = new ArrayList<>(); final List<String> expectedValues = new ArrayList<>(Arrays.asList("[\nstatic final void f();]")); new TreeScanner<Void, Void>() { @Override public Void visitErroneous(ErroneousTree node, Void p) { values.add(normalize(getErroneousTreeValues(node).toString())); return null; } }.scan(cut, null); assertEquals("testMethodError: The Erroneous tree " + "error value: " + values + " does not match expected error values: " + expectedValues, values, expectedValues); } /* * The following tests do not work just yet with nb-javac nor javac, * they need further investigation, see CR: 7167356 */ void testPositionBrokenSource126732a() throws IOException { String[] commands = new String[]{ "return Runnable()", "do { } while (true)", "throw UnsupportedOperationException()", "assert true", "1 + 1",}; for (String command : commands) { String code = "package test;\n" + "public class Test {\n" + " public static void test() {\n" + " " + command + " {\n" + " new Runnable() {\n" + " };\n" + " }\n" + "}"; JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, null, null, Arrays.asList(new MyFileObject(code))); CompilationUnitTree cut = ct.parse().iterator().next(); ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); MethodTree method = (MethodTree) clazz.getMembers().get(0); List<? extends StatementTree> statements = method.getBody().getStatements(); StatementTree ret = statements.get(0); StatementTree block = statements.get(1); Trees t = Trees.instance(ct); int len = code.indexOf(command + " {") + (command + " ").length(); assertEquals(command, len, t.getSourcePositions().getEndPosition(cut, ret)); assertEquals(command, len, t.getSourcePositions().getStartPosition(cut, block)); } } void testPositionBrokenSource126732b() throws IOException { String[] commands = new String[]{ "break", "break A", "continue ", "continue A",}; for (String command : commands) { String code = "package test;\n" + "public class Test {\n" + " public static void test() {\n" + " while (true) {\n" + " " + command + " {\n" + " new Runnable() {\n" + " };\n" + " }\n" + " }\n" + "}"; JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, null, null, Arrays.asList(new MyFileObject(code))); CompilationUnitTree cut = ct.parse().iterator().next(); ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); MethodTree method = (MethodTree) clazz.getMembers().get(0); List<? extends StatementTree> statements = ((BlockTree) ((WhileLoopTree) method.getBody().getStatements().get(0)).getStatement()).getStatements(); StatementTree ret = statements.get(0); StatementTree block = statements.get(1); Trees t = Trees.instance(ct); int len = code.indexOf(command + " {") + (command + " ").length(); assertEquals(command, len, t.getSourcePositions().getEndPosition(cut, ret)); assertEquals(command, len, t.getSourcePositions().getStartPosition(cut, block)); } } void testStartPositionEnumConstantInit() throws IOException { String code = "package t; enum Test { AAA; }"; JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, null, null, Arrays.asList(new MyFileObject(code))); CompilationUnitTree cut = ct.parse().iterator().next(); ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); VariableTree enumAAA = (VariableTree) clazz.getMembers().get(0); Trees t = Trees.instance(ct); int start = (int) t.getSourcePositions().getStartPosition(cut, enumAAA.getInitializer()); assertEquals("testStartPositionEnumConstantInit", -1, start); } @Test void testVoidLambdaParameter() throws IOException { String code = "package t; class Test { " + "Runnable r = (void v) -> { };" + "}"; DiagnosticCollector<JavaFileObject> coll = new DiagnosticCollector<>(); JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, coll, null, null, Arrays.asList(new MyFileObject(code))); CompilationUnitTree cut = ct.parse().iterator().next(); ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); VariableTree field = (VariableTree) clazz.getMembers().get(0); assertEquals("actual kind: " + field.getInitializer().getKind(), field.getInitializer().getKind(), Kind.LAMBDA_EXPRESSION); LambdaExpressionTree lambda = (LambdaExpressionTree) field.getInitializer(); assertEquals("actual parameters: " + lambda.getParameters().size(), lambda.getParameters().size(), 1); Tree paramType = lambda.getParameters().get(0).getType(); assertEquals("actual parameter type: " + paramType.getKind(), paramType.getKind(), Kind.PRIMITIVE_TYPE); TypeKind primitiveTypeKind = ((PrimitiveTypeTree) paramType).getPrimitiveTypeKind(); assertEquals("actual parameter type: " + primitiveTypeKind, primitiveTypeKind, TypeKind.VOID); } @Test //JDK-8065753 void testWrongFirstToken() throws IOException { String code = "<"; String expectedErrors = "Test.java:1:1: compiler.err.expected3: class, interface, enum\n" + "1 error\n"; StringWriter out = new StringWriter(); JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(out, fm, null, Arrays.asList("-XDrawDiagnostics"), null, Arrays.asList(new MyFileObject(code))); Result errorCode = ct.doCall(); assertEquals("the error code is not correct; actual:" + errorCode, Main.Result.ERROR, errorCode); String actualErrors = normalize(out.toString()); assertEquals("the error message is not correct, actual: " + actualErrors, expectedErrors, actualErrors); } void run(String[] args) throws Exception { int passed = 0, failed = 0; final Pattern p = (args != null && args.length > 0) ? Pattern.compile(args[0]) : null; for (Method m : this.getClass().getDeclaredMethods()) { boolean selected = (p == null) ? m.isAnnotationPresent(Test.class) : p.matcher(m.getName()).matches(); if (selected) { try { m.invoke(this, (Object[]) null); System.out.println(m.getName() + ": OK"); passed++; } catch (Throwable ex) { System.out.printf("Test %s failed: %s %n", m, ex.getCause()); failed++; } } } System.out.printf("Passed: %d, Failed %d%n", passed, failed); if (failed > 0) { throw new RuntimeException("Tests failed: " + failed); } if (passed == 0 && failed == 0) { throw new AssertionError("No test(s) selected: passed = " + passed + ", failed = " + failed + " ??????????"); } } } abstract class TestCase { void assertEquals(String message, int i, int pos) { if (i != pos) { fail(message); } } void assertFalse(String message, boolean bvalue) { if (bvalue == true) { fail(message); } } void assertEquals(String message, int i, long l) { if (i != l) { fail(message + ":" + i + ":" + l); } } void assertEquals(String message, Object o1, Object o2) { if (o1 != null && o2 != null && !o1.equals(o2)) { fail(message); } if (o1 == null && o2 != null) { fail(message); } } void assertNotNull(Object o) { if (o == null) { fail(); } } void fail() { fail("test failed"); } void fail(String message) { throw new RuntimeException(message); } /** * Indicates that the annotated method is a test method. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Test {} }