Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/langtools/make/tools/genstubs/GenStubs.java
32285 views
1
/*
2
* Copyright (c) 2009, 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. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package genstubs;
27
28
import java.io.*;
29
import java.util.*;
30
import javax.tools.JavaFileObject;
31
import javax.tools.StandardJavaFileManager;
32
import javax.tools.StandardLocation;
33
34
import com.sun.source.tree.CompilationUnitTree;
35
import com.sun.source.util.JavacTask;
36
import com.sun.tools.javac.api.JavacTool;
37
import com.sun.tools.javac.code.Flags;
38
import com.sun.tools.javac.code.TypeTag;
39
import com.sun.tools.javac.tree.JCTree;
40
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
41
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
42
import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
43
import com.sun.tools.javac.tree.JCTree.JCIdent;
44
import com.sun.tools.javac.tree.JCTree.JCImport;
45
import com.sun.tools.javac.tree.JCTree.JCLiteral;
46
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
47
import com.sun.tools.javac.tree.JCTree.JCModifiers;
48
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
49
import com.sun.tools.javac.tree.Pretty;
50
import com.sun.tools.javac.tree.TreeMaker;
51
import com.sun.tools.javac.tree.TreeScanner;
52
import com.sun.tools.javac.tree.TreeTranslator;
53
import com.sun.tools.javac.util.Context;
54
import com.sun.tools.javac.util.ListBuffer;
55
import com.sun.tools.javac.util.Name;
56
import javax.tools.JavaFileManager;
57
58
/**
59
* Generate stub source files by removing implementation details from input files.
60
*
61
* This is a special purpose stub generator, specific to the needs of generating
62
* stub files for JDK 7 API that are needed to compile langtools files that depend
63
* on that API. The stub generator works by removing as much of the API source code
64
* as possible without affecting the public signature, in order to reduce the
65
* transitive closure of the API being referenced. The resulting stubs can be
66
* put on the langtools sourcepath with -implicit:none to compile the langtools
67
* files that depend on the JDK 7 API.
68
*
69
* Usage:
70
* genstubs -s <outdir> -sourcepath <path> <classnames>
71
*
72
* The specified class names are looked up on the sourcepath, and corresponding
73
* stubs are written to the source output directory.
74
*
75
* Classes are parsed into javac ASTs, then processed with a javac TreeTranslator
76
* to remove implementation details, and written out in the source output directory.
77
* Documentation comments and annotations are removed. Method bodies are removed
78
* and methods are marked native. Private and package-private field definitions
79
* have their initializers replace with 0, 0.0, false, null as appropriate.
80
*/
81
82
public class GenStubs {
83
static class Fault extends Exception {
84
private static final long serialVersionUID = 0;
85
Fault(String message) {
86
super(message);
87
}
88
Fault(String message, Throwable cause) {
89
super(message);
90
initCause(cause);
91
}
92
}
93
94
public static void main(String[] args) {
95
boolean ok = new GenStubs().run(args);
96
if (!ok)
97
System.exit(1);
98
}
99
100
public boolean run(String... args) {
101
File outdir = null;
102
String sourcepath = null;
103
List<String> classes = new ArrayList<String>();
104
for (ListIterator<String> iter = Arrays.asList(args).listIterator(); iter.hasNext(); ) {
105
String arg = iter.next();
106
if (arg.equals("-s") && iter.hasNext())
107
outdir = new File(iter.next());
108
else if (arg.equals("-sourcepath") && iter.hasNext())
109
sourcepath = iter.next();
110
else if (arg.startsWith("-"))
111
throw new IllegalArgumentException(arg);
112
else {
113
classes.add(arg);
114
while (iter.hasNext())
115
classes.add(iter.next());
116
}
117
}
118
119
return run(sourcepath, outdir, classes);
120
}
121
122
public boolean run(String sourcepath, File outdir, List<String> classes) {
123
//System.err.println("run: sourcepath:" + sourcepath + " outdir:" + outdir + " classes:" + classes);
124
if (sourcepath == null)
125
throw new IllegalArgumentException("sourcepath not set");
126
if (outdir == null)
127
throw new IllegalArgumentException("source output dir not set");
128
129
JavacTool tool = JavacTool.create();
130
StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);
131
132
try {
133
fm.setLocation(StandardLocation.SOURCE_OUTPUT, Collections.singleton(outdir));
134
fm.setLocation(StandardLocation.SOURCE_PATH, splitPath(sourcepath));
135
List<JavaFileObject> files = new ArrayList<JavaFileObject>();
136
for (String c: classes) {
137
JavaFileObject fo = fm.getJavaFileForInput(
138
StandardLocation.SOURCE_PATH, c, JavaFileObject.Kind.SOURCE);
139
if (fo == null)
140
error("class not found: " + c);
141
else
142
files.add(fo);
143
}
144
145
JavacTask t = tool.getTask(null, fm, null, null, null, files);
146
Iterable<? extends CompilationUnitTree> trees = t.parse();
147
for (CompilationUnitTree tree: trees) {
148
makeStub(fm, tree);
149
}
150
} catch (IOException e) {
151
error("IO error " + e, e);
152
}
153
154
return (errors == 0);
155
}
156
157
void makeStub(StandardJavaFileManager fm, CompilationUnitTree tree) throws IOException {
158
CompilationUnitTree tree2 = new StubMaker().translate(tree);
159
CompilationUnitTree tree3 = new ImportCleaner(fm).removeRedundantImports(tree2);
160
161
String className = fm.inferBinaryName(StandardLocation.SOURCE_PATH, tree.getSourceFile());
162
JavaFileObject fo = fm.getJavaFileForOutput(StandardLocation.SOURCE_OUTPUT,
163
className, JavaFileObject.Kind.SOURCE, null);
164
// System.err.println("Writing " + className + " to " + fo.getName());
165
Writer out = fo.openWriter();
166
try {
167
new Pretty(out, true).printExpr((JCTree) tree3);
168
} finally {
169
out.close();
170
}
171
}
172
173
List<File> splitPath(String path) {
174
List<File> list = new ArrayList<File>();
175
for (String p: path.split(File.pathSeparator)) {
176
if (p.length() > 0)
177
list.add(new File(p));
178
}
179
return list;
180
}
181
182
void error(String message) {
183
System.err.println(message);
184
errors++;
185
}
186
187
void error(String message, Throwable cause) {
188
error(message);
189
}
190
191
int errors;
192
193
class StubMaker extends TreeTranslator {
194
CompilationUnitTree translate(CompilationUnitTree tree) {
195
return super.translate((JCCompilationUnit) tree);
196
}
197
198
/**
199
* compilation units: remove javadoc comments
200
* -- required, in order to remove @deprecated tags, since we
201
* (separately) remove all annotations, including @Deprecated
202
*/
203
public void visitTopLevel(JCCompilationUnit tree) {
204
super.visitTopLevel(tree);
205
tree.docComments = null;
206
}
207
208
/**
209
* methods: remove method bodies, make methods native
210
*/
211
@Override
212
public void visitClassDef(JCClassDecl tree) {
213
long prevClassMods = currClassMods;
214
currClassMods = tree.mods.flags;
215
try {
216
super.visitClassDef(tree);;
217
} finally {
218
currClassMods = prevClassMods;
219
}
220
}
221
private long currClassMods = 0;
222
223
/**
224
* methods: remove method bodies, make methods native
225
*/
226
@Override
227
public void visitMethodDef(JCMethodDecl tree) {
228
tree.mods = translate(tree.mods);
229
tree.restype = translate(tree.restype);
230
tree.typarams = translateTypeParams(tree.typarams);
231
tree.params = translateVarDefs(tree.params);
232
tree.thrown = translate(tree.thrown);
233
if (tree.body != null) {
234
if ((currClassMods & Flags.INTERFACE) != 0) {
235
tree.mods.flags &= ~(Flags.DEFAULT | Flags.STATIC);
236
} else {
237
tree.mods.flags |= Flags.NATIVE;
238
}
239
tree.body = null;
240
}
241
result = tree;
242
}
243
244
/**
245
* modifiers: remove annotations
246
*/
247
@Override
248
public void visitModifiers(JCModifiers tree) {
249
tree.annotations = com.sun.tools.javac.util.List.nil();
250
result = tree;
251
}
252
253
/**
254
* field definitions: replace initializers with 0, 0.0, false etc
255
* when possible -- i.e. leave public, protected initializers alone
256
*/
257
@Override
258
public void visitVarDef(JCVariableDecl tree) {
259
tree.mods = translate(tree.mods);
260
tree.vartype = translate(tree.vartype);
261
if (tree.init != null) {
262
if ((tree.mods.flags & (Flags.PUBLIC | Flags.PROTECTED)) != 0)
263
tree.init = translate(tree.init);
264
else {
265
String t = tree.vartype.toString();
266
if (t.equals("boolean"))
267
tree.init = new JCLiteral(TypeTag.BOOLEAN, 0) { };
268
else if (t.equals("byte"))
269
tree.init = new JCLiteral(TypeTag.BYTE, 0) { };
270
else if (t.equals("char"))
271
tree.init = new JCLiteral(TypeTag.CHAR, 0) { };
272
else if (t.equals("double"))
273
tree.init = new JCLiteral(TypeTag.DOUBLE, 0.d) { };
274
else if (t.equals("float"))
275
tree.init = new JCLiteral(TypeTag.FLOAT, 0.f) { };
276
else if (t.equals("int"))
277
tree.init = new JCLiteral(TypeTag.INT, 0) { };
278
else if (t.equals("long"))
279
tree.init = new JCLiteral(TypeTag.LONG, 0) { };
280
else if (t.equals("short"))
281
tree.init = new JCLiteral(TypeTag.SHORT, 0) { };
282
else
283
tree.init = new JCLiteral(TypeTag.BOT, null) { };
284
}
285
}
286
result = tree;
287
}
288
}
289
290
class ImportCleaner extends TreeScanner {
291
private Set<Name> names = new HashSet<Name>();
292
private TreeMaker m;
293
294
ImportCleaner(JavaFileManager fm) {
295
// ImportCleaner itself doesn't require a filemanager, but instantiating
296
// a TreeMaker does, indirectly (via ClassReader, sigh)
297
Context c = new Context();
298
c.put(JavaFileManager.class, fm);
299
m = TreeMaker.instance(c);
300
}
301
302
CompilationUnitTree removeRedundantImports(CompilationUnitTree t) {
303
JCCompilationUnit tree = (JCCompilationUnit) t;
304
tree.accept(this);
305
ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
306
for (JCTree def: tree.defs) {
307
if (def.getTag() == JCTree.Tag.IMPORT) {
308
JCImport imp = (JCImport) def;
309
if (imp.qualid.getTag() == JCTree.Tag.SELECT) {
310
JCFieldAccess qualid = (JCFieldAccess) imp.qualid;
311
if (!qualid.name.toString().equals("*")
312
&& !names.contains(qualid.name)) {
313
continue;
314
}
315
}
316
}
317
defs.add(def);
318
}
319
return m.TopLevel(tree.packageAnnotations, tree.pid, defs.toList());
320
}
321
322
@Override
323
public void visitImport(JCImport tree) { } // ignore names found in imports
324
325
@Override
326
public void visitIdent(JCIdent tree) {
327
names.add(tree.name);
328
}
329
330
@Override
331
public void visitSelect(JCFieldAccess tree) {
332
super.visitSelect(tree);
333
names.add(tree.name);
334
}
335
}
336
}
337
338