1 /*
2  * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 /*
25  * @test
26  * @bug 8017216 8019422 8019421
27  * @summary verify start and end positions
28  * @run main TreeEndPosTest
29  */
30 
31 import java.io.ByteArrayOutputStream;
32 import java.io.File;
33 import java.io.IOException;
34 import java.io.PrintWriter;
35 import java.net.URI;
36 import java.util.ArrayList;
37 import java.util.List;
38 import javax.tools.Diagnostic;
39 import javax.tools.DiagnosticCollector;
40 import javax.tools.JavaCompiler;
41 import javax.tools.JavaFileManager;
42 import javax.tools.JavaFileObject;
43 import javax.tools.SimpleJavaFileObject;
44 import javax.tools.ToolProvider;
45 
46 public class TreeEndPosTest {
getJavaFileManager(JavaCompiler compiler, DiagnosticCollector dc)47     private static JavaFileManager getJavaFileManager(JavaCompiler compiler,
48             DiagnosticCollector dc) {
49         return compiler.getStandardFileManager(dc, null, null);
50     }
51 
52     static class JavaSource extends SimpleJavaFileObject {
53 
54         final String source;
55         int startPos;
56         int endPos;
57 
JavaSource(String filename, String source)58         private JavaSource(String filename, String source) {
59             super(URI.create("myfo:/" + filename), JavaFileObject.Kind.SOURCE);
60             this.source = source;
61         }
62 
63         @Override
getCharContent(boolean ignoreEncodingErrors)64         public CharSequence getCharContent(boolean ignoreEncodingErrors) {
65             return source;
66         }
67 
createJavaSource(String preamble, String body, String postamble, String expected)68         static JavaSource createJavaSource(String preamble, String body,
69                 String postamble, String expected) {
70             JavaSource js = createJavaSource(preamble, body, postamble, -1, -1);
71             js.startPos = js.source.indexOf(expected);
72             js.endPos   = js.startPos + expected.length();
73             return js;
74         }
75 
createJavaSource(String body, String expected)76         static JavaSource createJavaSource(String body, String expected) {
77             return createJavaSource(null, body, null, expected);
78         }
79 
createJavaSource(String preamble, String body, String postamble, int start, int end)80         private static JavaSource createJavaSource(String preamble, String body,
81                 String postamble, int start, int end) {
82             final String name = "Bug";
83             StringBuilder code = new StringBuilder();
84             if (preamble != null) {
85                 code.append(preamble);
86             }
87             code.append("public class " + name + "{");
88             if (body != null) {
89                 code.append(body);
90             }
91             code.append("}");
92             if (postamble != null) {
93                 code.append(postamble);
94             }
95             JavaSource js = new JavaSource(name + ".java", code.toString());
96             js.startPos = start;
97             js.endPos = end;
98             return js;
99         }
100     }
101 
main(String... args)102     public static void main(String... args) throws IOException {
103         testUninitializedVariable();
104         testMissingAnnotationValue();
105         testFinalVariableWithDefaultConstructor();
106         testFinalVariableWithConstructor();
107     }
108 
testUninitializedVariable()109     static void testUninitializedVariable() throws IOException {
110         compile(JavaSource.createJavaSource("Object o = new A().new B(); class A { }",
111                 "B()"));
112     }
testMissingAnnotationValue()113     static void testMissingAnnotationValue() throws IOException {
114         compile(JavaSource.createJavaSource("@Foo(\"vvvv\")",
115                 null, "@interface Foo { }", "\"vvvv\""));
116     }
117 
testFinalVariableWithDefaultConstructor()118     static void testFinalVariableWithDefaultConstructor() throws IOException {
119         compile(JavaSource.createJavaSource("private static final String Foo; public void bar() { }",
120                 "private static final String Foo;"));
121     }
122 
testFinalVariableWithConstructor()123     static void testFinalVariableWithConstructor() throws IOException {
124         compile(JavaSource.createJavaSource("public Bug (){} private static final String Foo; public void bar() { }",
125                 "{}"));
126     }
127 
compile(JavaSource src)128     static void compile(JavaSource src) throws IOException {
129         ByteArrayOutputStream ba = new ByteArrayOutputStream();
130         PrintWriter writer = new PrintWriter(ba);
131         File tempDir = new File(".");
132         JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
133         DiagnosticCollector dc = new DiagnosticCollector();
134         JavaFileManager javaFileManager = getJavaFileManager(compiler, dc);
135         List<String> options = new ArrayList<>();
136         options.add("-cp");
137         options.add(tempDir.getPath());
138         options.add("-d");
139         options.add(tempDir.getPath());
140         options.add("-XDshouldStopPolicy=GENERATE");
141 
142         List<JavaFileObject> sources = new ArrayList<>();
143         sources.add(src);
144         JavaCompiler.CompilationTask task =
145                 compiler.getTask(writer, javaFileManager,
146                 dc, options, null,
147                 sources);
148         task.call();
149         for (Diagnostic diagnostic : (List<Diagnostic>) dc.getDiagnostics()) {
150             long actualStart = diagnostic.getStartPosition();
151             long actualEnd = diagnostic.getEndPosition();
152             System.out.println("Source: " + src.source);
153             System.out.println("Diagnostic: " + diagnostic);
154             System.out.print("Start position: Expected: " + src.startPos);
155             System.out.println(", Actual: " + actualStart);
156             System.out.print("End position: Expected: " + src.endPos);
157             System.out.println(", Actual: " + actualEnd);
158             if (src.startPos != actualStart || src.endPos != actualEnd) {
159                 throw new RuntimeException("error: trees don't match");
160             }
161         }
162     }
163 }
164