49 |
49 |
50 import static javax.tools.StandardLocation.SOURCE_OUTPUT; |
50 import static javax.tools.StandardLocation.SOURCE_OUTPUT; |
51 import static javax.tools.StandardLocation.CLASS_OUTPUT; |
51 import static javax.tools.StandardLocation.CLASS_OUTPUT; |
52 |
52 |
53 import com.sun.tools.javac.code.Lint; |
53 import com.sun.tools.javac.code.Lint; |
|
54 import com.sun.tools.javac.code.Symbol.ClassSymbol; |
54 import com.sun.tools.javac.code.Symbol.ModuleSymbol; |
55 import com.sun.tools.javac.code.Symbol.ModuleSymbol; |
55 import com.sun.tools.javac.code.Symtab; |
56 import com.sun.tools.javac.code.Symtab; |
56 import com.sun.tools.javac.comp.Modules; |
57 import com.sun.tools.javac.comp.Modules; |
|
58 import com.sun.tools.javac.model.JavacElements; |
57 import com.sun.tools.javac.util.*; |
59 import com.sun.tools.javac.util.*; |
58 import com.sun.tools.javac.util.DefinedBy.Api; |
60 import com.sun.tools.javac.util.DefinedBy.Api; |
59 |
61 |
60 import static com.sun.tools.javac.code.Lint.LintCategory.PROCESSING; |
62 import static com.sun.tools.javac.code.Lint.LintCategory.PROCESSING; |
61 |
63 |
319 } |
321 } |
320 } |
322 } |
321 } |
323 } |
322 |
324 |
323 JavaFileManager fileManager; |
325 JavaFileManager fileManager; |
|
326 JavacElements elementUtils; |
324 Log log; |
327 Log log; |
325 Modules modules; |
328 Modules modules; |
326 Names names; |
329 Names names; |
327 Symtab syms; |
330 Symtab syms; |
328 Context context; |
331 Context context; |
329 boolean lastRound; |
332 boolean lastRound; |
330 |
333 |
331 private final boolean lint; |
334 private final boolean lint; |
332 |
335 |
333 /** |
336 /** |
|
337 * Initial inputs passed to the tool. This set must be |
|
338 * synchronized. |
|
339 */ |
|
340 private final Set<FileObject> initialInputs; |
|
341 |
|
342 /** |
334 * Logical names of all created files. This set must be |
343 * Logical names of all created files. This set must be |
335 * synchronized. |
344 * synchronized. |
336 */ |
345 */ |
337 private final Set<FileObject> fileObjectHistory; |
346 private final Set<FileObject> fileObjectHistory; |
338 |
347 |
371 * Names of all created class files. Its iterators should |
380 * Names of all created class files. Its iterators should |
372 * preserve insertion order. |
381 * preserve insertion order. |
373 */ |
382 */ |
374 private final Set<Pair<ModuleSymbol, String>> aggregateGeneratedClassNames; |
383 private final Set<Pair<ModuleSymbol, String>> aggregateGeneratedClassNames; |
375 |
384 |
|
385 private final Set<String> initialClassNames; |
376 |
386 |
377 JavacFiler(Context context) { |
387 JavacFiler(Context context) { |
378 this.context = context; |
388 this.context = context; |
379 fileManager = context.get(JavaFileManager.class); |
389 fileManager = context.get(JavaFileManager.class); |
|
390 elementUtils = JavacElements.instance(context); |
380 |
391 |
381 log = Log.instance(context); |
392 log = Log.instance(context); |
382 modules = Modules.instance(context); |
393 modules = Modules.instance(context); |
383 names = Names.instance(context); |
394 names = Names.instance(context); |
384 syms = Symtab.instance(context); |
395 syms = Symtab.instance(context); |
385 |
396 |
386 fileObjectHistory = synchronizedSet(new LinkedHashSet<FileObject>()); |
397 initialInputs = synchronizedSet(new LinkedHashSet<>()); |
387 generatedSourceNames = synchronizedSet(new LinkedHashSet<String>()); |
398 fileObjectHistory = synchronizedSet(new LinkedHashSet<>()); |
388 generatedSourceFileObjects = synchronizedSet(new LinkedHashSet<JavaFileObject>()); |
399 generatedSourceNames = synchronizedSet(new LinkedHashSet<>()); |
|
400 generatedSourceFileObjects = synchronizedSet(new LinkedHashSet<>()); |
389 |
401 |
390 generatedClasses = synchronizedMap(new LinkedHashMap<>()); |
402 generatedClasses = synchronizedMap(new LinkedHashMap<>()); |
391 |
403 |
392 openTypeNames = synchronizedSet(new LinkedHashSet<String>()); |
404 openTypeNames = synchronizedSet(new LinkedHashSet<>()); |
393 |
405 |
394 aggregateGeneratedSourceNames = new LinkedHashSet<>(); |
406 aggregateGeneratedSourceNames = new LinkedHashSet<>(); |
395 aggregateGeneratedClassNames = new LinkedHashSet<>(); |
407 aggregateGeneratedClassNames = new LinkedHashSet<>(); |
|
408 initialClassNames = new LinkedHashSet<>(); |
396 |
409 |
397 lint = (Lint.instance(context)).isEnabled(PROCESSING); |
410 lint = (Lint.instance(context)).isEnabled(PROCESSING); |
398 } |
411 } |
399 |
412 |
400 @Override @DefinedBy(Api.ANNOTATION_PROCESSING) |
413 @Override @DefinedBy(Api.ANNOTATION_PROCESSING) |
594 |
607 |
595 private void checkNameAndExistence(ModuleSymbol mod, String typename, boolean allowUnnamedPackageInfo) throws FilerException { |
608 private void checkNameAndExistence(ModuleSymbol mod, String typename, boolean allowUnnamedPackageInfo) throws FilerException { |
596 // TODO: Check if type already exists on source or class path? |
609 // TODO: Check if type already exists on source or class path? |
597 // If so, use warning message key proc.type.already.exists |
610 // If so, use warning message key proc.type.already.exists |
598 checkName(typename, allowUnnamedPackageInfo); |
611 checkName(typename, allowUnnamedPackageInfo); |
599 if (aggregateGeneratedSourceNames.contains(Pair.of(mod, typename)) || |
612 ClassSymbol existing; |
600 aggregateGeneratedClassNames.contains(Pair.of(mod, typename))) { |
613 boolean alreadySeen = aggregateGeneratedSourceNames.contains(Pair.of(mod, typename)) || |
|
614 aggregateGeneratedClassNames.contains(Pair.of(mod, typename)) || |
|
615 initialClassNames.contains(typename) || |
|
616 ((existing = elementUtils.getTypeElement(typename)) != null && |
|
617 initialInputs.contains(existing.sourcefile)); |
|
618 if (alreadySeen) { |
601 if (lint) |
619 if (lint) |
602 log.warning("proc.type.recreate", typename); |
620 log.warning("proc.type.recreate", typename); |
603 throw new FilerException("Attempt to recreate a file for type " + typename); |
621 throw new FilerException("Attempt to recreate a file for type " + typename); |
604 } |
622 } |
605 if (!mod.isUnnamed() && !typename.contains(".")) { |
623 if (!mod.isUnnamed() && !typename.contains(".")) { |
609 |
627 |
610 /** |
628 /** |
611 * Check to see if the file has already been opened; if so, throw |
629 * Check to see if the file has already been opened; if so, throw |
612 * an exception, otherwise add it to the set of files. |
630 * an exception, otherwise add it to the set of files. |
613 */ |
631 */ |
614 private void checkFileReopening(FileObject fileObject, boolean addToHistory) throws FilerException { |
632 private void checkFileReopening(FileObject fileObject, boolean forWriting) throws FilerException { |
|
633 if (isInFileObjectHistory(fileObject, forWriting)) { |
|
634 if (lint) |
|
635 log.warning("proc.file.reopening", fileObject.getName()); |
|
636 throw new FilerException("Attempt to reopen a file for path " + fileObject.getName()); |
|
637 } |
|
638 if (forWriting) |
|
639 fileObjectHistory.add(fileObject); |
|
640 } |
|
641 |
|
642 private boolean isInFileObjectHistory(FileObject fileObject, boolean forWriting) { |
|
643 if (forWriting) { |
|
644 for(FileObject veteran : initialInputs) { |
|
645 try { |
|
646 if (fileManager.isSameFile(veteran, fileObject)) { |
|
647 return true; |
|
648 } |
|
649 } catch (IllegalArgumentException e) { |
|
650 //ignore... |
|
651 } |
|
652 } |
|
653 for (String className : initialClassNames) { |
|
654 try { |
|
655 ClassSymbol existing = elementUtils.getTypeElement(className); |
|
656 if ( existing != null |
|
657 && ( (existing.sourcefile != null && fileManager.isSameFile(existing.sourcefile, fileObject)) |
|
658 || (existing.classfile != null && fileManager.isSameFile(existing.classfile, fileObject)))) { |
|
659 return true; |
|
660 } |
|
661 } catch (IllegalArgumentException e) { |
|
662 //ignore... |
|
663 } |
|
664 } |
|
665 } |
|
666 |
615 for(FileObject veteran : fileObjectHistory) { |
667 for(FileObject veteran : fileObjectHistory) { |
616 if (fileManager.isSameFile(veteran, fileObject)) { |
668 if (fileManager.isSameFile(veteran, fileObject)) { |
617 if (lint) |
669 return true; |
618 log.warning("proc.file.reopening", fileObject.getName()); |
670 } |
619 throw new FilerException("Attempt to reopen a file for path " + fileObject.getName()); |
671 } |
620 } |
672 |
621 } |
673 return false; |
622 if (addToHistory) |
|
623 fileObjectHistory.add(fileObject); |
|
624 } |
674 } |
625 |
675 |
626 public boolean newFiles() { |
676 public boolean newFiles() { |
627 return (!generatedSourceNames.isEmpty()) |
677 return (!generatedSourceNames.isEmpty()) |
628 || (!generatedClasses.isEmpty()); |
678 || (!generatedClasses.isEmpty()); |
654 |
704 |
655 void setLastRound(boolean lastRound) { |
705 void setLastRound(boolean lastRound) { |
656 this.lastRound = lastRound; |
706 this.lastRound = lastRound; |
657 } |
707 } |
658 |
708 |
|
709 public void setInitialState(Collection<? extends JavaFileObject> initialInputs, |
|
710 Collection<String> initialClassNames) { |
|
711 this.initialInputs.addAll(initialInputs); |
|
712 this.initialClassNames.addAll(initialClassNames); |
|
713 } |
|
714 |
659 public void close() { |
715 public void close() { |
660 clearRoundState(); |
716 clearRoundState(); |
661 // Cross-round state |
717 // Cross-round state |
|
718 initialClassNames.clear(); |
|
719 initialInputs.clear(); |
662 fileObjectHistory.clear(); |
720 fileObjectHistory.clear(); |
663 openTypeNames.clear(); |
721 openTypeNames.clear(); |
664 aggregateGeneratedSourceNames.clear(); |
722 aggregateGeneratedSourceNames.clear(); |
665 aggregateGeneratedClassNames.clear(); |
723 aggregateGeneratedClassNames.clear(); |
666 } |
724 } |