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