Skip to content

Commit d6fb9d7

Browse files
8255464: Cannot access ModuleTree in a CompilationUnitTree
Reviewed-by: vromero
1 parent 12ccd21 commit d6fb9d7

File tree

5 files changed

+179
-8
lines changed

5 files changed

+179
-8
lines changed

src/jdk.compiler/share/classes/com/sun/source/tree/CompilationUnitTree.java

+22-6
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,29 @@
2929
import javax.tools.JavaFileObject;
3030

3131
/**
32-
* Represents the abstract syntax tree for compilation units (source
33-
* files) and package declarations (package-info.java).
32+
* Represents the abstract syntax tree for ordinary compilation units
33+
* and modular compilation units.
3434
*
3535
* @jls 7.3 Compilation Units
3636
* @jls 7.4 Package Declarations
37+
* @jls 7.7 Module Declarations
3738
*
3839
* @author Peter von der Ahé
3940
* @since 1.6
4041
*/
4142
public interface CompilationUnitTree extends Tree {
43+
44+
/**
45+
* Returns the module tree associated with this compilation unit,
46+
* or {@code null} if there is no module declaration.
47+
* @return the module tree
48+
* @implSpec This implementation throws {@code UnsupportedOperationException}
49+
* @since 17
50+
*/
51+
default ModuleTree getModule() {
52+
throw new UnsupportedOperationException();
53+
}
54+
4255
/**
4356
* Returns the annotations listed on any package declaration
4457
* at the head of this compilation unit, or {@code null} if there
@@ -64,15 +77,18 @@ public interface CompilationUnitTree extends Tree {
6477
PackageTree getPackage();
6578

6679
/**
67-
* Returns the import declarations appearing in this compilation unit.
80+
* Returns the import declarations appearing in this compilation unit,
81+
* or an empty list if there are no import declarations.
6882
* @return the import declarations
6983
*/
7084
List<? extends ImportTree> getImports();
7185

7286
/**
73-
* Returns the type declarations appearing in this compilation unit.
87+
* Returns the type declarations appearing in this compilation unit,
88+
* or an empty list if there are no type declarations.
7489
* The list may also include empty statements resulting from
7590
* extraneous semicolons.
91+
* A modular compilation unit does not contain any type declarations.
7692
* @return the type declarations
7793
*/
7894
List<? extends Tree> getTypeDecls();
@@ -84,8 +100,8 @@ public interface CompilationUnitTree extends Tree {
84100
JavaFileObject getSourceFile();
85101

86102
/**
87-
* Returns the line map for this compilation unit, if available.
88-
* Returns {@code null} if the line map is not available.
103+
* Returns the line map for this compilation unit, if available,
104+
* or {@code null} if the line map is not available.
89105
* @return the line map for this compilation unit
90106
*/
91107
LineMap getLineMap();

src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java

+1
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ public R visitCompilationUnit(CompilationUnitTree node, P p) {
146146
R r = scan(node.getPackage(), p);
147147
r = scanAndReduce(node.getImports(), p, r);
148148
r = scanAndReduce(node.getTypeDecls(), p, r);
149+
r = scanAndReduce(node.getModule(), p, r);
149150
return r;
150151
}
151152

src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java

+10-2
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,11 @@ public JCModuleDecl getModuleDecl() {
553553
return null;
554554
}
555555

556+
@DefinedBy(Api.COMPILER_TREE)
557+
public JCModuleDecl getModule() {
558+
return getModuleDecl();
559+
}
560+
556561
@DefinedBy(Api.COMPILER_TREE)
557562
public JCPackageDecl getPackage() {
558563
// PackageDecl must be the first entry if it exists
@@ -593,9 +598,12 @@ public Position.LineMap getLineMap() {
593598
@DefinedBy(Api.COMPILER_TREE)
594599
public List<JCTree> getTypeDecls() {
595600
List<JCTree> typeDefs;
596-
for (typeDefs = defs; !typeDefs.isEmpty(); typeDefs = typeDefs.tail)
597-
if (!typeDefs.head.hasTag(PACKAGEDEF) && !typeDefs.head.hasTag(IMPORT))
601+
for (typeDefs = defs; !typeDefs.isEmpty(); typeDefs = typeDefs.tail) {
602+
if (!typeDefs.head.hasTag(MODULEDEF)
603+
&& !typeDefs.head.hasTag(PACKAGEDEF) && !typeDefs.head.hasTag(IMPORT)) {
598604
break;
605+
}
606+
}
599607
return typeDefs;
600608
}
601609
@Override @DefinedBy(Api.COMPILER_TREE)

src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java

+1
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,7 @@ public void visitModuleDef(JCModuleDecl tree) {
460460
if (tree.directives == null) {
461461
print(";");
462462
} else {
463+
print(" ");
463464
printBlock(tree.directives);
464465
}
465466
println();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/*
2+
* Copyright (c) 2020, 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 8255464
27+
* @summary Cannot access ModuleTree in a CompilationUnitTree
28+
* @modules jdk.compiler/com.sun.tools.javac.api
29+
*/
30+
31+
import java.io.IOException;
32+
import java.io.PrintStream;
33+
import java.net.URI;
34+
import java.util.List;
35+
import java.util.Objects;
36+
import javax.tools.JavaFileObject;
37+
import javax.tools.SimpleJavaFileObject;
38+
39+
import com.sun.source.tree.CompilationUnitTree;
40+
import com.sun.source.tree.Tree;
41+
import com.sun.source.util.JavacTask;
42+
import com.sun.tools.javac.api.JavacTool;
43+
44+
public class CompilationUnitTreeTest {
45+
public static void main(String... args) throws Exception {
46+
new CompilationUnitTreeTest().run();
47+
}
48+
49+
PrintStream out = System.err;
50+
int errors;
51+
52+
void run() throws Exception {
53+
testModuleCompilationUnit();
54+
testOrdinaryCompilationUnit();
55+
if (errors > 0) {
56+
out.println(errors + " errors");
57+
throw new Exception(errors + " errors");
58+
}
59+
}
60+
61+
void testModuleCompilationUnit() throws IOException {
62+
out.println("Test ModuleCompilationUnit");
63+
CompilationUnitTree cut = parse("import java.util.*; module m { }");
64+
checkTree("package", cut.getPackage(), null);
65+
checkList("imports", cut.getImports(), List.of("IMPORT import java.util.*;"));
66+
checkList("type decls", cut.getTypeDecls(), List.of());
67+
checkTree("module", cut.getModule(), "MODULE module m { }");
68+
}
69+
70+
void testOrdinaryCompilationUnit() throws IOException {
71+
out.println("Test OrdinaryCompilationUnit");
72+
CompilationUnitTree cut = parse("package p; import java.util.*; public class C { };");
73+
checkTree("package", cut.getPackage(), "PACKAGE package p;");
74+
checkList("imports", cut.getImports(), List.of("IMPORT import java.util.*;"));
75+
checkList("type decls", cut.getTypeDecls(), List.of("CLASS public class C { }", "EMPTY_STATEMENT ;"));
76+
checkTree("module", cut.getModule(), null);
77+
}
78+
79+
void checkTree(String label, Tree tree, String expect) {
80+
String f = tree == null ? null
81+
: tree.getKind() + " " + tree.toString().trim().replaceAll("\\s+", " ");
82+
if (Objects.equals(f, expect)) {
83+
out.println(" " + label + " OK: " + expect);
84+
} else {
85+
out.println(" " + label + " error");
86+
out.println(" expect: " + expect);
87+
out.println(" found: " + f);
88+
errors++;
89+
}
90+
}
91+
92+
void checkList(String label, List<? extends Tree> trees, List<String> expect) {
93+
Objects.requireNonNull(expect);
94+
if (trees == null) {
95+
out.println(" " + label + " error: list is null");
96+
errors++;
97+
return;
98+
}
99+
if (trees.size() != expect.size()) {
100+
out.println(" " + label + " error: list size mismatch");
101+
out.println(" expect: " + expect.size());
102+
out.println(" found: " + trees.size());
103+
errors++;
104+
}
105+
// compare entries in both lists
106+
for (int i = 0; i < Math.min(trees.size(), expect.size()); i++) {
107+
Tree ti = trees.get(i);
108+
String ei = expect.get(i);
109+
checkTree(label + "[" + i + "]", ti, ei);
110+
}
111+
// show any excess entries in expect list
112+
for (int i = trees.size(); i < expect.size(); i++) {
113+
String ei = expect.get(i);
114+
out.println(" " + label + "[" + i + "]: expect: " + ei);
115+
}
116+
// show any excess entries in trees list
117+
for (int i = expect.size(); i < trees.size(); i++) {
118+
Tree ti = trees.get(i);
119+
String fi = ti == null ? null : ti.getKind() + " " + ti.toString();
120+
out.println(" " + label + "[" + i + "]: found: " + fi);
121+
}
122+
}
123+
124+
CompilationUnitTree parse(String text) throws IOException {
125+
JavacTool tool = JavacTool.create();
126+
JavacTask ct = tool.getTask(null, null, null,
127+
null, null, List.of(new MyFileObject(text)));
128+
return ct.parse().iterator().next();
129+
}
130+
131+
static class MyFileObject extends SimpleJavaFileObject {
132+
133+
private final String text;
134+
135+
public MyFileObject(String text) {
136+
super(URI.create("fo:/Test.java"), JavaFileObject.Kind.SOURCE);
137+
this.text = text;
138+
}
139+
140+
@Override
141+
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
142+
return text;
143+
}
144+
}
145+
}

0 commit comments

Comments
 (0)