46 import com.sun.tools.javac.code.Symbol.ClassSymbol;
47 import com.sun.tools.javac.code.Symbol.Completer;
48 import com.sun.tools.javac.code.Symbol.CompletionFailure;
49 import com.sun.tools.javac.code.Symbol.ModuleSymbol;
50 import com.sun.tools.javac.code.Symbol.PackageSymbol;
51 import com.sun.tools.javac.code.Symbol.TypeSymbol;
52 import com.sun.tools.javac.comp.Annotate;
53 import com.sun.tools.javac.file.JRTIndex;
54 import com.sun.tools.javac.file.JavacFileManager;
55 import com.sun.tools.javac.jvm.ClassReader;
56 import com.sun.tools.javac.jvm.Profile;
57 import com.sun.tools.javac.main.Option;
58 import com.sun.tools.javac.platform.PlatformDescription;
59 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
60 import com.sun.tools.javac.util.*;
61
62 import static javax.tools.StandardLocation.*;
63
64 import static com.sun.tools.javac.code.Flags.*;
65 import static com.sun.tools.javac.code.Kinds.Kind.*;
66 import com.sun.tools.javac.main.DelegatingJavaFileManager;
67
68 import com.sun.tools.javac.util.Dependencies.CompletionCause;
69
70 /**
71 * This class provides operations to locate class definitions
72 * from the source and class files on the paths provided to javac.
73 *
74 * <p><b>This is NOT part of any supported API.
75 * If you write code that depends on this, you do so at your own risk.
76 * This code and its internal interfaces are subject to change or
77 * deletion without notice.</b>
78 */
79 public class ClassFinder {
80 /** The context key for the class finder. */
81 protected static final Context.Key<ClassFinder> classFinderKey = new Context.Key<>();
82
83 ClassReader reader;
84
85 private final Annotate annotate;
114
115 /** The name table. */
116 final Names names;
117
118 /** Force a completion failure on this name
119 */
120 final Name completionFailureName;
121
122 /** Access to files
123 */
124 private final JavaFileManager fileManager;
125
126 /** Dependency tracker
127 */
128 private final Dependencies dependencies;
129
130 /** Factory for diagnostics
131 */
132 JCDiagnostic.Factory diagFactory;
133
134 /** Can be reassigned from outside:
135 * the completer to be used for ".java" files. If this remains unassigned
136 * ".java" files will not be loaded.
137 */
138 public Completer sourceCompleter = Completer.NULL_COMPLETER;
139
140 /** The path name of the class file currently being read.
141 */
142 protected JavaFileObject currentClassFile = null;
143
144 /** The class or method currently being read.
145 */
146 protected Symbol currentOwner = null;
147
148 /**
149 * The currently selected profile.
150 */
151 private final Profile profile;
152
153 /**
168
169 /** Get the ClassFinder instance for this invocation. */
170 public static ClassFinder instance(Context context) {
171 ClassFinder instance = context.get(classFinderKey);
172 if (instance == null)
173 instance = new ClassFinder(context);
174 return instance;
175 }
176
177 /** Construct a new class finder. */
178 protected ClassFinder(Context context) {
179 context.put(classFinderKey, this);
180 reader = ClassReader.instance(context);
181 names = Names.instance(context);
182 syms = Symtab.instance(context);
183 fileManager = context.get(JavaFileManager.class);
184 dependencies = Dependencies.instance(context);
185 if (fileManager == null)
186 throw new AssertionError("FileManager initialization error");
187 diagFactory = JCDiagnostic.Factory.instance(context);
188
189 log = Log.instance(context);
190 annotate = Annotate.instance(context);
191
192 Options options = Options.instance(context);
193 verbose = options.isSet(Option.VERBOSE);
194 cacheCompletionFailure = options.isUnset("dev");
195 preferSource = "source".equals(options.get("-Xprefer"));
196 userPathsFirst = options.isSet(Option.XXUSERPATHSFIRST);
197
198 completionFailureName =
199 options.isSet("failcomplete")
200 ? names.fromString(options.get("failcomplete"))
201 : null;
202
203 // Temporary, until more info is available from the module system.
204 boolean useCtProps;
205 JavaFileManager fm = context.get(JavaFileManager.class);
206 if (fm instanceof DelegatingJavaFileManager) {
207 fm = ((DelegatingJavaFileManager) fm).getBaseFileManager();
208 }
209 if (fm instanceof JavacFileManager) {
210 JavacFileManager jfm = (JavacFileManager) fm;
211 useCtProps = jfm.isDefaultBootClassPath() && jfm.isSymbolFileEnabled();
212 } else if (fm.getClass().getName().equals("com.sun.tools.sjavac.comp.SmartFileManager")) {
213 useCtProps = !options.isSet("ignore.symbol.file");
214 } else {
215 useCtProps = false;
216 }
217 jrtIndex = useCtProps && JRTIndex.isAvailable() ? JRTIndex.getSharedInstance() : null;
218
219 profile = Profile.instance(context);
220 }
221
222
223 /************************************************************************
224 * Temporary ct.sym replacement
225 *
226 * The following code is a temporary substitute for the ct.sym mechanism
227 * used in JDK 6 thru JDK 8.
228 * This mechanism will eventually be superseded by the Jigsaw module system.
229 ***********************************************************************/
230
231 /**
232 * Returns any extra flags for a class symbol.
233 * This information used to be provided using private annotations
234 * in the class file in ct.sym; in time, this information will be
235 * available from the module system.
236 */
237 long getSupplementaryFlags(ClassSymbol c) {
238 if (jrtIndex == null || !jrtIndex.isInJRT(c.classfile) || c.name == names.module_info) {
239 return 0;
276 if (sym.kind == TYP) {
277 try {
278 ClassSymbol c = (ClassSymbol) sym;
279 dependencies.push(c, CompletionCause.CLASS_READER);
280 annotate.blockAnnotations();
281 c.members_field = new Scope.ErrorScope(c); // make sure it's always defined
282 completeOwners(c.owner);
283 completeEnclosing(c);
284 fillIn(c);
285 } finally {
286 annotate.unblockAnnotationsNoFlush();
287 dependencies.pop();
288 }
289 } else if (sym.kind == PCK) {
290 PackageSymbol p = (PackageSymbol)sym;
291 try {
292 fillIn(p);
293 } catch (IOException ex) {
294 JCDiagnostic msg =
295 diagFactory.fragment(Fragments.ExceptionMessage(ex.getLocalizedMessage()));
296 throw new CompletionFailure(sym, msg).initCause(ex);
297 }
298 }
299 if (!reader.filling)
300 annotate.flush(); // finish attaching annotations
301 }
302
303 /** complete up through the enclosing package. */
304 private void completeOwners(Symbol o) {
305 if (o.kind != PCK) completeOwners(o.owner);
306 o.complete();
307 }
308
309 /**
310 * Tries to complete lexically enclosing classes if c looks like a
311 * nested class. This is similar to completeOwners but handles
312 * the situation when a nested class is accessed directly as it is
313 * possible with the Tree API or javax.lang.model.*.
314 */
315 private void completeEnclosing(ClassSymbol c) {
316 if (c.owner.kind == PCK) {
317 Symbol owner = c.owner;
318 for (Name name : Convert.enclosingCandidates(Convert.shortName(c.name))) {
319 Symbol encl = owner.members().findFirst(name);
320 if (encl == null)
321 encl = syms.getClass(c.packge().modle, TypeSymbol.formFlatName(name, owner));
322 if (encl != null)
323 encl.complete();
324 }
325 }
326 }
327
328 /** Fill in definition of class `c' from corresponding class or
329 * source file.
330 */
331 void fillIn(ClassSymbol c) {
332 if (completionFailureName == c.fullname) {
333 JCDiagnostic msg =
334 diagFactory.fragment(Fragments.UserSelectedCompletionFailure);
335 throw new CompletionFailure(c, msg);
336 }
337 currentOwner = c;
338 JavaFileObject classfile = c.classfile;
339 if (classfile != null) {
340 JavaFileObject previousClassFile = currentClassFile;
341 Symbol prevOwner = c.owner;
342 Name prevName = c.fullname;
343 try {
344 if (reader.filling) {
345 Assert.error("Filling " + classfile.toUri() + " during " + previousClassFile);
346 }
347 currentClassFile = classfile;
348 if (verbose) {
349 log.printVerbose("loading", currentClassFile.getName());
350 }
351 if (classfile.getKind() == JavaFileObject.Kind.CLASS) {
352 reader.readClassFile(c);
353 c.flags_field |= getSupplementaryFlags(c);
354 } else {
355 if (!sourceCompleter.isTerminal()) {
380 } else {
381 throw classFileNotFound(c);
382 }
383 }
384 // where
385 private CompletionFailure classFileNotFound(ClassSymbol c) {
386 JCDiagnostic diag =
387 diagFactory.fragment(Fragments.ClassFileNotFound(c.flatname));
388 return newCompletionFailure(c, diag);
389 }
390 /** Static factory for CompletionFailure objects.
391 * In practice, only one can be used at a time, so we share one
392 * to reduce the expense of allocating new exception objects.
393 */
394 private CompletionFailure newCompletionFailure(TypeSymbol c,
395 JCDiagnostic diag) {
396 if (!cacheCompletionFailure) {
397 // log.warning("proc.messager",
398 // Log.getLocalizedString("class.file.not.found", c.flatname));
399 // c.debug.printStackTrace();
400 return new CompletionFailure(c, diag);
401 } else {
402 CompletionFailure result = cachedCompletionFailure;
403 result.sym = c;
404 result.diag = diag;
405 return result;
406 }
407 }
408 private final CompletionFailure cachedCompletionFailure =
409 new CompletionFailure(null, (JCDiagnostic) null);
410 {
411 cachedCompletionFailure.setStackTrace(new StackTraceElement[0]);
412 }
413
414
415 /** Load a toplevel class with given fully qualified name
416 * The class is entered into `classes' only if load was successful.
417 */
418 public ClassSymbol loadClass(ModuleSymbol msym, Name flatname) throws CompletionFailure {
419 Assert.checkNonNull(msym);
420 Name packageName = Convert.packagePart(flatname);
421 PackageSymbol ps = syms.lookupPackage(msym, packageName);
422
423 Assert.checkNonNull(ps.modle, () -> "msym=" + msym + "; flatName=" + flatname);
424
425 boolean absent = syms.getClass(ps.modle, flatname) == null;
426 ClassSymbol c = syms.enterClass(ps.modle, flatname);
427
428 if (c.members_field == null) {
429 try {
430 c.complete();
431 } catch (CompletionFailure ex) {
432 if (absent) syms.removeClass(ps.modle, flatname);
758 @Override
759 public JavaFileObject next() {
760 if (!hasNext())
761 throw new NoSuchElementException();
762 JavaFileObject result = next;
763 next = null;
764 return result;
765 }
766
767 };
768 }
769
770 /**
771 * Used for bad class definition files, such as bad .class files or
772 * for .java files with unexpected package or class names.
773 */
774 public static class BadClassFile extends CompletionFailure {
775 private static final long serialVersionUID = 0;
776
777 public BadClassFile(TypeSymbol sym, JavaFileObject file, JCDiagnostic diag,
778 JCDiagnostic.Factory diagFactory) {
779 super(sym, createBadClassFileDiagnostic(file, diag, diagFactory));
780 }
781 // where
782 private static JCDiagnostic createBadClassFileDiagnostic(
783 JavaFileObject file, JCDiagnostic diag, JCDiagnostic.Factory diagFactory) {
784 String key = (file.getKind() == JavaFileObject.Kind.SOURCE
785 ? "bad.source.file.header" : "bad.class.file.header");
786 return diagFactory.fragment(key, file, diag);
787 }
788 }
789
790 public static class BadEnclosingMethodAttr extends BadClassFile {
791 private static final long serialVersionUID = 0;
792
793 public BadEnclosingMethodAttr(TypeSymbol sym, JavaFileObject file, JCDiagnostic diag,
794 JCDiagnostic.Factory diagFactory) {
795 super(sym, file, diag, diagFactory);
796 }
797 }
798 }
|
46 import com.sun.tools.javac.code.Symbol.ClassSymbol;
47 import com.sun.tools.javac.code.Symbol.Completer;
48 import com.sun.tools.javac.code.Symbol.CompletionFailure;
49 import com.sun.tools.javac.code.Symbol.ModuleSymbol;
50 import com.sun.tools.javac.code.Symbol.PackageSymbol;
51 import com.sun.tools.javac.code.Symbol.TypeSymbol;
52 import com.sun.tools.javac.comp.Annotate;
53 import com.sun.tools.javac.file.JRTIndex;
54 import com.sun.tools.javac.file.JavacFileManager;
55 import com.sun.tools.javac.jvm.ClassReader;
56 import com.sun.tools.javac.jvm.Profile;
57 import com.sun.tools.javac.main.Option;
58 import com.sun.tools.javac.platform.PlatformDescription;
59 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
60 import com.sun.tools.javac.util.*;
61
62 import static javax.tools.StandardLocation.*;
63
64 import static com.sun.tools.javac.code.Flags.*;
65 import static com.sun.tools.javac.code.Kinds.Kind.*;
66 import com.sun.tools.javac.code.Symbol;
67 import com.sun.tools.javac.code.Symbol.CompletionFailure;
68 import com.sun.tools.javac.main.DelegatingJavaFileManager;
69
70 import com.sun.tools.javac.util.Dependencies.CompletionCause;
71
72 /**
73 * This class provides operations to locate class definitions
74 * from the source and class files on the paths provided to javac.
75 *
76 * <p><b>This is NOT part of any supported API.
77 * If you write code that depends on this, you do so at your own risk.
78 * This code and its internal interfaces are subject to change or
79 * deletion without notice.</b>
80 */
81 public class ClassFinder {
82 /** The context key for the class finder. */
83 protected static final Context.Key<ClassFinder> classFinderKey = new Context.Key<>();
84
85 ClassReader reader;
86
87 private final Annotate annotate;
116
117 /** The name table. */
118 final Names names;
119
120 /** Force a completion failure on this name
121 */
122 final Name completionFailureName;
123
124 /** Access to files
125 */
126 private final JavaFileManager fileManager;
127
128 /** Dependency tracker
129 */
130 private final Dependencies dependencies;
131
132 /** Factory for diagnostics
133 */
134 JCDiagnostic.Factory diagFactory;
135
136 final DeferredCompletionFailureHandler dcfh;
137
138 /** Can be reassigned from outside:
139 * the completer to be used for ".java" files. If this remains unassigned
140 * ".java" files will not be loaded.
141 */
142 public Completer sourceCompleter = Completer.NULL_COMPLETER;
143
144 /** The path name of the class file currently being read.
145 */
146 protected JavaFileObject currentClassFile = null;
147
148 /** The class or method currently being read.
149 */
150 protected Symbol currentOwner = null;
151
152 /**
153 * The currently selected profile.
154 */
155 private final Profile profile;
156
157 /**
172
173 /** Get the ClassFinder instance for this invocation. */
174 public static ClassFinder instance(Context context) {
175 ClassFinder instance = context.get(classFinderKey);
176 if (instance == null)
177 instance = new ClassFinder(context);
178 return instance;
179 }
180
181 /** Construct a new class finder. */
182 protected ClassFinder(Context context) {
183 context.put(classFinderKey, this);
184 reader = ClassReader.instance(context);
185 names = Names.instance(context);
186 syms = Symtab.instance(context);
187 fileManager = context.get(JavaFileManager.class);
188 dependencies = Dependencies.instance(context);
189 if (fileManager == null)
190 throw new AssertionError("FileManager initialization error");
191 diagFactory = JCDiagnostic.Factory.instance(context);
192 dcfh = DeferredCompletionFailureHandler.instance(context);
193
194 log = Log.instance(context);
195 annotate = Annotate.instance(context);
196
197 Options options = Options.instance(context);
198 verbose = options.isSet(Option.VERBOSE);
199 cacheCompletionFailure = options.isUnset("dev");
200 preferSource = "source".equals(options.get("-Xprefer"));
201 userPathsFirst = options.isSet(Option.XXUSERPATHSFIRST);
202
203 completionFailureName =
204 options.isSet("failcomplete")
205 ? names.fromString(options.get("failcomplete"))
206 : null;
207
208 // Temporary, until more info is available from the module system.
209 boolean useCtProps;
210 JavaFileManager fm = context.get(JavaFileManager.class);
211 if (fm instanceof DelegatingJavaFileManager) {
212 fm = ((DelegatingJavaFileManager) fm).getBaseFileManager();
213 }
214 if (fm instanceof JavacFileManager) {
215 JavacFileManager jfm = (JavacFileManager) fm;
216 useCtProps = jfm.isDefaultBootClassPath() && jfm.isSymbolFileEnabled();
217 } else if (fm.getClass().getName().equals("com.sun.tools.sjavac.comp.SmartFileManager")) {
218 useCtProps = !options.isSet("ignore.symbol.file");
219 } else {
220 useCtProps = false;
221 }
222 jrtIndex = useCtProps && JRTIndex.isAvailable() ? JRTIndex.getSharedInstance() : null;
223
224 profile = Profile.instance(context);
225 cachedCompletionFailure = new CompletionFailure(null, (JCDiagnostic) null, dcfh);
226 cachedCompletionFailure.setStackTrace(new StackTraceElement[0]);
227 }
228
229
230 /************************************************************************
231 * Temporary ct.sym replacement
232 *
233 * The following code is a temporary substitute for the ct.sym mechanism
234 * used in JDK 6 thru JDK 8.
235 * This mechanism will eventually be superseded by the Jigsaw module system.
236 ***********************************************************************/
237
238 /**
239 * Returns any extra flags for a class symbol.
240 * This information used to be provided using private annotations
241 * in the class file in ct.sym; in time, this information will be
242 * available from the module system.
243 */
244 long getSupplementaryFlags(ClassSymbol c) {
245 if (jrtIndex == null || !jrtIndex.isInJRT(c.classfile) || c.name == names.module_info) {
246 return 0;
283 if (sym.kind == TYP) {
284 try {
285 ClassSymbol c = (ClassSymbol) sym;
286 dependencies.push(c, CompletionCause.CLASS_READER);
287 annotate.blockAnnotations();
288 c.members_field = new Scope.ErrorScope(c); // make sure it's always defined
289 completeOwners(c.owner);
290 completeEnclosing(c);
291 fillIn(c);
292 } finally {
293 annotate.unblockAnnotationsNoFlush();
294 dependencies.pop();
295 }
296 } else if (sym.kind == PCK) {
297 PackageSymbol p = (PackageSymbol)sym;
298 try {
299 fillIn(p);
300 } catch (IOException ex) {
301 JCDiagnostic msg =
302 diagFactory.fragment(Fragments.ExceptionMessage(ex.getLocalizedMessage()));
303 throw new CompletionFailure(sym, msg, dcfh).initCause(ex);
304 }
305 }
306 if (!reader.filling)
307 annotate.flush(); // finish attaching annotations
308 }
309
310 /** complete up through the enclosing package. */
311 private void completeOwners(Symbol o) {
312 if (o.kind != PCK) completeOwners(o.owner);
313 o.complete();
314 }
315
316 /**
317 * Tries to complete lexically enclosing classes if c looks like a
318 * nested class. This is similar to completeOwners but handles
319 * the situation when a nested class is accessed directly as it is
320 * possible with the Tree API or javax.lang.model.*.
321 */
322 private void completeEnclosing(ClassSymbol c) {
323 if (c.owner.kind == PCK) {
324 Symbol owner = c.owner;
325 for (Name name : Convert.enclosingCandidates(Convert.shortName(c.name))) {
326 Symbol encl = owner.members().findFirst(name);
327 if (encl == null)
328 encl = syms.getClass(c.packge().modle, TypeSymbol.formFlatName(name, owner));
329 if (encl != null)
330 encl.complete();
331 }
332 }
333 }
334
335 /** Fill in definition of class `c' from corresponding class or
336 * source file.
337 */
338 void fillIn(ClassSymbol c) {
339 if (completionFailureName == c.fullname) {
340 JCDiagnostic msg =
341 diagFactory.fragment(Fragments.UserSelectedCompletionFailure);
342 throw new CompletionFailure(c, msg, dcfh);
343 }
344 currentOwner = c;
345 JavaFileObject classfile = c.classfile;
346 if (classfile != null) {
347 JavaFileObject previousClassFile = currentClassFile;
348 Symbol prevOwner = c.owner;
349 Name prevName = c.fullname;
350 try {
351 if (reader.filling) {
352 Assert.error("Filling " + classfile.toUri() + " during " + previousClassFile);
353 }
354 currentClassFile = classfile;
355 if (verbose) {
356 log.printVerbose("loading", currentClassFile.getName());
357 }
358 if (classfile.getKind() == JavaFileObject.Kind.CLASS) {
359 reader.readClassFile(c);
360 c.flags_field |= getSupplementaryFlags(c);
361 } else {
362 if (!sourceCompleter.isTerminal()) {
387 } else {
388 throw classFileNotFound(c);
389 }
390 }
391 // where
392 private CompletionFailure classFileNotFound(ClassSymbol c) {
393 JCDiagnostic diag =
394 diagFactory.fragment(Fragments.ClassFileNotFound(c.flatname));
395 return newCompletionFailure(c, diag);
396 }
397 /** Static factory for CompletionFailure objects.
398 * In practice, only one can be used at a time, so we share one
399 * to reduce the expense of allocating new exception objects.
400 */
401 private CompletionFailure newCompletionFailure(TypeSymbol c,
402 JCDiagnostic diag) {
403 if (!cacheCompletionFailure) {
404 // log.warning("proc.messager",
405 // Log.getLocalizedString("class.file.not.found", c.flatname));
406 // c.debug.printStackTrace();
407 return new CompletionFailure(c, diag, dcfh);
408 } else {
409 CompletionFailure result = cachedCompletionFailure;
410 result.sym = c;
411 result.diag = diag;
412 return result;
413 }
414 }
415 private final CompletionFailure cachedCompletionFailure;
416
417
418 /** Load a toplevel class with given fully qualified name
419 * The class is entered into `classes' only if load was successful.
420 */
421 public ClassSymbol loadClass(ModuleSymbol msym, Name flatname) throws CompletionFailure {
422 Assert.checkNonNull(msym);
423 Name packageName = Convert.packagePart(flatname);
424 PackageSymbol ps = syms.lookupPackage(msym, packageName);
425
426 Assert.checkNonNull(ps.modle, () -> "msym=" + msym + "; flatName=" + flatname);
427
428 boolean absent = syms.getClass(ps.modle, flatname) == null;
429 ClassSymbol c = syms.enterClass(ps.modle, flatname);
430
431 if (c.members_field == null) {
432 try {
433 c.complete();
434 } catch (CompletionFailure ex) {
435 if (absent) syms.removeClass(ps.modle, flatname);
761 @Override
762 public JavaFileObject next() {
763 if (!hasNext())
764 throw new NoSuchElementException();
765 JavaFileObject result = next;
766 next = null;
767 return result;
768 }
769
770 };
771 }
772
773 /**
774 * Used for bad class definition files, such as bad .class files or
775 * for .java files with unexpected package or class names.
776 */
777 public static class BadClassFile extends CompletionFailure {
778 private static final long serialVersionUID = 0;
779
780 public BadClassFile(TypeSymbol sym, JavaFileObject file, JCDiagnostic diag,
781 JCDiagnostic.Factory diagFactory, DeferredCompletionFailureHandler dcfh) {
782 super(sym, createBadClassFileDiagnostic(file, diag, diagFactory), dcfh);
783 }
784 // where
785 private static JCDiagnostic createBadClassFileDiagnostic(
786 JavaFileObject file, JCDiagnostic diag, JCDiagnostic.Factory diagFactory) {
787 String key = (file.getKind() == JavaFileObject.Kind.SOURCE
788 ? "bad.source.file.header" : "bad.class.file.header");
789 return diagFactory.fragment(key, file, diag);
790 }
791 }
792
793 public static class BadEnclosingMethodAttr extends BadClassFile {
794 private static final long serialVersionUID = 0;
795
796 public BadEnclosingMethodAttr(TypeSymbol sym, JavaFileObject file, JCDiagnostic diag,
797 JCDiagnostic.Factory diagFactory, DeferredCompletionFailureHandler dcfh) {
798 super(sym, file, diag, diagFactory, dcfh);
799 }
800 }
801 }
|