Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocTool.java
41161 views
1
/*
2
* Copyright (c) 2001, 2021, 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 jdk.javadoc.internal.tool;
27
28
import java.nio.file.Files;
29
import java.nio.file.InvalidPathException;
30
import java.nio.file.Paths;
31
import java.util.ArrayList;
32
import java.util.HashSet;
33
import java.util.LinkedHashSet;
34
import java.util.List;
35
import java.util.Set;
36
37
import javax.lang.model.element.Element;
38
import javax.lang.model.element.ElementKind;
39
import javax.tools.JavaFileObject;
40
import javax.tools.StandardJavaFileManager;
41
42
import com.sun.tools.javac.code.ClassFinder;
43
import com.sun.tools.javac.code.DeferredCompletionFailureHandler;
44
import com.sun.tools.javac.code.Symbol.Completer;
45
import com.sun.tools.javac.code.Symbol.CompletionFailure;
46
import com.sun.tools.javac.code.Symbol.PackageSymbol;
47
import com.sun.tools.javac.comp.Enter;
48
import com.sun.tools.javac.tree.JCTree;
49
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
50
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
51
import com.sun.tools.javac.util.Abort;
52
import com.sun.tools.javac.util.Context;
53
import com.sun.tools.javac.util.ListBuffer;
54
import com.sun.tools.javac.util.Position;
55
import jdk.javadoc.doclet.DocletEnvironment;
56
57
import static jdk.javadoc.internal.tool.Main.Result.*;
58
59
/**
60
* This class could be the main entry point for Javadoc when Javadoc is used as a
61
* component in a larger software system. It provides operations to
62
* construct a new javadoc processor, and to run it on a set of source
63
* files.
64
*
65
* <p><b>This is NOT part of any supported API.
66
* If you write code that depends on this, you do so at your own risk.
67
* This code and its internal interfaces are subject to change or
68
* deletion without notice.</b>
69
*/
70
public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler {
71
ToolEnvironment toolEnv;
72
73
final Messager messager;
74
final ClassFinder javadocFinder;
75
final DeferredCompletionFailureHandler dcfh;
76
final Enter javadocEnter;
77
final Set<JavaFileObject> uniquefiles;
78
79
/**
80
* Construct a new JavaCompiler processor, using appropriately
81
* extended phases of the underlying compiler.
82
*/
83
protected JavadocTool(Context context) {
84
super(context);
85
messager = Messager.instance0(context);
86
javadocFinder = JavadocClassFinder.instance(context);
87
dcfh = DeferredCompletionFailureHandler.instance(context);
88
javadocEnter = JavadocEnter.instance(context);
89
uniquefiles = new HashSet<>();
90
}
91
92
/**
93
* For javadoc, the parser needs to keep comments. Overrides method from JavaCompiler.
94
*/
95
@Override
96
protected boolean keepComments() {
97
return true;
98
}
99
100
/**
101
* Construct a new javadoc tool.
102
*/
103
public static JavadocTool make0(Context context) {
104
Messager messager = null;
105
try {
106
// force the use of Javadoc's class finder
107
JavadocClassFinder.preRegister(context);
108
109
// force the use of Javadoc's own enter phase
110
JavadocEnter.preRegister(context);
111
112
// force the use of Javadoc's own member enter phase
113
JavadocMemberEnter.preRegister(context);
114
115
// force the use of Javadoc's own todo phase
116
JavadocTodo.preRegister(context);
117
118
// force the use of Messager as a Log
119
messager = Messager.instance0(context);
120
121
return new JavadocTool(context);
122
} catch (CompletionFailure ex) {
123
assert messager != null;
124
messager.error(Position.NOPOS, ex.getMessage());
125
return null;
126
}
127
}
128
129
public DocletEnvironment getEnvironment(ToolOptions toolOptions,
130
List<String> javaNames,
131
Iterable<? extends JavaFileObject> fileObjects)
132
throws ToolException
133
{
134
toolEnv = ToolEnvironment.instance(context);
135
toolEnv.initialize(toolOptions);
136
ElementsTable etable = new ElementsTable(context, toolOptions);
137
javadocFinder.sourceCompleter = etable.xclasses
138
? Completer.NULL_COMPLETER
139
: sourceCompleter;
140
141
if (etable.xclasses) {
142
// If -Xclasses is set, the args should be a list of class names
143
for (String arg: javaNames) {
144
if (!isValidPackageName(arg)) { // checks
145
String text = messager.getText("main.illegal_class_name", arg);
146
throw new ToolException(CMDERR, text);
147
}
148
}
149
if (messager.hasErrors()) {
150
return null;
151
}
152
etable.setClassArgList(javaNames);
153
// prepare, force the data structures to be analyzed
154
etable.analyze();
155
return new DocEnvImpl(toolEnv, etable);
156
}
157
158
ListBuffer<JCCompilationUnit> classTrees = new ListBuffer<>();
159
160
try {
161
StandardJavaFileManager fm = toolEnv.fileManager instanceof StandardJavaFileManager sfm
162
? sfm
163
: null;
164
Set<String> packageNames = new LinkedHashSet<>();
165
// Normally, the args should be a series of package names or file names.
166
// Parse the files and collect the package names.
167
for (String arg: javaNames) {
168
if (fm != null && arg.endsWith(".java") && isRegularFile(arg)) {
169
parse(fm.getJavaFileObjects(arg), classTrees, true);
170
} else if (isValidPackageName(arg)) {
171
packageNames.add(arg);
172
} else if (arg.endsWith(".java")) {
173
if (fm == null) {
174
String text = messager.getText("main.assertion.error", "fm == null");
175
throw new ToolException(ABNORMAL, text);
176
} else {
177
String text = messager.getText("main.file_not_found", arg);
178
throw new ToolException(ERROR, text);
179
}
180
} else {
181
String text = messager.getText("main.illegal_package_name", arg);
182
throw new ToolException(CMDERR, text);
183
}
184
}
185
186
// Parse file objects provide via the DocumentationTool API
187
parse(fileObjects, classTrees, true);
188
189
etable.packages(packageNames)
190
.classTrees(classTrees.toList())
191
.scanSpecifiedItems();
192
193
// abort, if errors were encountered during modules initialization
194
if (messager.hasErrors()) {
195
return null;
196
}
197
198
// Parse the files in the packages and subpackages to be documented
199
ListBuffer<JCCompilationUnit> allTrees = new ListBuffer<>();
200
allTrees.addAll(classTrees);
201
parse(etable.getFilesToParse(), allTrees, false);
202
modules.newRound();
203
modules.initModules(allTrees.toList());
204
205
if (messager.hasErrors()) {
206
return null;
207
}
208
209
// Enter symbols for all files
210
toolEnv.notice("main.Building_tree");
211
javadocEnter.main(allTrees.toList());
212
213
if (messager.hasErrors()) {
214
return null;
215
}
216
217
etable.setClassDeclList(listClasses(classTrees.toList()));
218
219
dcfh.setHandler(dcfh.userCodeHandler);
220
etable.analyze();
221
222
// Ensure that package-info is read for all included packages
223
for (Element e : etable.getIncludedElements()) {
224
if (e.getKind() == ElementKind.PACKAGE) {
225
PackageSymbol p = (PackageSymbol) e;
226
if (p.package_info != null) {
227
p.package_info.complete();
228
}
229
}
230
}
231
232
} catch (CompletionFailure cf) {
233
throw new ToolException(ABNORMAL, cf.getMessage(), cf);
234
} catch (Abort abort) {
235
if (messager.hasErrors()) {
236
// presumably a message has been emitted, keep silent
237
throw new ToolException(ABNORMAL, "", abort);
238
} else {
239
String text = messager.getText("main.internal.error");
240
Throwable t = abort.getCause() == null ? abort : abort.getCause();
241
throw new ToolException(ABNORMAL, text, t);
242
}
243
}
244
245
if (messager.hasErrors())
246
return null;
247
248
toolEnv.docEnv = new DocEnvImpl(toolEnv, etable);
249
return toolEnv.docEnv;
250
}
251
252
private boolean isRegularFile(String s) {
253
try {
254
return Files.isRegularFile(Paths.get(s));
255
} catch (InvalidPathException e) {
256
return false;
257
}
258
}
259
260
/** Is the given string a valid package name? */
261
boolean isValidPackageName(String s) {
262
if (s.contains("/")) {
263
String[] a = s.split("/");
264
if (a.length == 2) {
265
return isValidPackageName0(a[0]) && isValidPackageName0(a[1]);
266
}
267
return false;
268
}
269
return isValidPackageName0(s);
270
}
271
272
private boolean isValidPackageName0(String s) {
273
for (int index = s.indexOf('.') ; index != -1; index = s.indexOf('.')) {
274
if (!isValidClassName(s.substring(0, index))) {
275
return false;
276
}
277
s = s.substring(index + 1);
278
}
279
return isValidClassName(s);
280
}
281
282
private void parse(Iterable<? extends JavaFileObject> files, ListBuffer<JCCompilationUnit> trees,
283
boolean trace) {
284
for (JavaFileObject fo: files) {
285
if (uniquefiles.add(fo)) { // ignore duplicates
286
if (trace)
287
toolEnv.notice("main.Loading_source_file", fo.getName());
288
trees.append(parse(fo));
289
}
290
}
291
}
292
293
/** Are surrogates supported? */
294
static final boolean surrogatesSupported = surrogatesSupported();
295
private static boolean surrogatesSupported() {
296
try {
297
boolean b = Character.isHighSurrogate('a');
298
return true;
299
} catch (NoSuchMethodError ex) {
300
return false;
301
}
302
}
303
304
/**
305
* Return true if given file name is a valid class name
306
* (including "package-info").
307
* @param s the name of the class to check.
308
* @return true if given class name is a valid class name
309
* and false otherwise.
310
*/
311
public static boolean isValidClassName(String s) {
312
if (s.length() < 1) return false;
313
if (s.equals("package-info")) return true;
314
if (surrogatesSupported) {
315
int cp = s.codePointAt(0);
316
if (!Character.isJavaIdentifierStart(cp))
317
return false;
318
for (int j = Character.charCount(cp); j < s.length(); j += Character.charCount(cp)) {
319
cp = s.codePointAt(j);
320
if (!Character.isJavaIdentifierPart(cp))
321
return false;
322
}
323
} else {
324
if (!Character.isJavaIdentifierStart(s.charAt(0)))
325
return false;
326
for (int j = 1; j < s.length(); j++)
327
if (!Character.isJavaIdentifierPart(s.charAt(j)))
328
return false;
329
}
330
return true;
331
}
332
333
/**
334
* From a list of top level trees, return the list of contained class definitions
335
*/
336
List<JCClassDecl> listClasses(List<JCCompilationUnit> trees) {
337
List<JCClassDecl> result = new ArrayList<>();
338
for (JCCompilationUnit t : trees) {
339
for (JCTree def : t.defs) {
340
if (def.hasTag(JCTree.Tag.CLASSDEF))
341
result.add((JCClassDecl)def);
342
}
343
}
344
return result;
345
}
346
}
347
348