langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacFiler.java
changeset 43368 cabe410a7a5c
parent 42815 050370edaade
child 44291 e1b620ac6c98
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacFiler.java	Wed Jan 25 10:43:41 2017 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacFiler.java	Thu Jan 26 14:11:38 2017 +0100
@@ -51,9 +51,11 @@
 import static javax.tools.StandardLocation.CLASS_OUTPUT;
 
 import com.sun.tools.javac.code.Lint;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
 import com.sun.tools.javac.code.Symbol.ModuleSymbol;
 import com.sun.tools.javac.code.Symtab;
 import com.sun.tools.javac.comp.Modules;
+import com.sun.tools.javac.model.JavacElements;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.DefinedBy.Api;
 
@@ -321,6 +323,7 @@
     }
 
     JavaFileManager fileManager;
+    JavacElements elementUtils;
     Log log;
     Modules modules;
     Names names;
@@ -331,6 +334,12 @@
     private final boolean lint;
 
     /**
+     * Initial inputs passed to the tool.  This set must be
+     * synchronized.
+     */
+    private final Set<FileObject> initialInputs;
+
+    /**
      * Logical names of all created files.  This set must be
      * synchronized.
      */
@@ -373,26 +382,30 @@
      */
     private final Set<Pair<ModuleSymbol, String>> aggregateGeneratedClassNames;
 
+    private final Set<String> initialClassNames;
 
     JavacFiler(Context context) {
         this.context = context;
         fileManager = context.get(JavaFileManager.class);
+        elementUtils = JavacElements.instance(context);
 
         log = Log.instance(context);
         modules = Modules.instance(context);
         names = Names.instance(context);
         syms = Symtab.instance(context);
 
-        fileObjectHistory = synchronizedSet(new LinkedHashSet<FileObject>());
-        generatedSourceNames = synchronizedSet(new LinkedHashSet<String>());
-        generatedSourceFileObjects = synchronizedSet(new LinkedHashSet<JavaFileObject>());
+        initialInputs = synchronizedSet(new LinkedHashSet<>());
+        fileObjectHistory = synchronizedSet(new LinkedHashSet<>());
+        generatedSourceNames = synchronizedSet(new LinkedHashSet<>());
+        generatedSourceFileObjects = synchronizedSet(new LinkedHashSet<>());
 
         generatedClasses = synchronizedMap(new LinkedHashMap<>());
 
-        openTypeNames  = synchronizedSet(new LinkedHashSet<String>());
+        openTypeNames  = synchronizedSet(new LinkedHashSet<>());
 
         aggregateGeneratedSourceNames = new LinkedHashSet<>();
         aggregateGeneratedClassNames  = new LinkedHashSet<>();
+        initialClassNames  = new LinkedHashSet<>();
 
         lint = (Lint.instance(context)).isEnabled(PROCESSING);
     }
@@ -596,8 +609,13 @@
         // TODO: Check if type already exists on source or class path?
         // If so, use warning message key proc.type.already.exists
         checkName(typename, allowUnnamedPackageInfo);
-        if (aggregateGeneratedSourceNames.contains(Pair.of(mod, typename)) ||
-            aggregateGeneratedClassNames.contains(Pair.of(mod, typename))) {
+        ClassSymbol existing;
+        boolean alreadySeen = aggregateGeneratedSourceNames.contains(Pair.of(mod, typename)) ||
+                              aggregateGeneratedClassNames.contains(Pair.of(mod, typename)) ||
+                              initialClassNames.contains(typename) ||
+                              ((existing = elementUtils.getTypeElement(typename)) != null &&
+                               initialInputs.contains(existing.sourcefile));
+        if (alreadySeen) {
             if (lint)
                 log.warning("proc.type.recreate", typename);
             throw new FilerException("Attempt to recreate a file for type " + typename);
@@ -611,16 +629,48 @@
      * Check to see if the file has already been opened; if so, throw
      * an exception, otherwise add it to the set of files.
      */
-    private void checkFileReopening(FileObject fileObject, boolean addToHistory) throws FilerException {
+    private void checkFileReopening(FileObject fileObject, boolean forWriting) throws FilerException {
+        if (isInFileObjectHistory(fileObject, forWriting)) {
+            if (lint)
+                log.warning("proc.file.reopening", fileObject.getName());
+            throw new FilerException("Attempt to reopen a file for path " + fileObject.getName());
+        }
+        if (forWriting)
+            fileObjectHistory.add(fileObject);
+    }
+
+    private boolean isInFileObjectHistory(FileObject fileObject, boolean forWriting) {
+        if (forWriting) {
+            for(FileObject veteran : initialInputs) {
+                try {
+                    if (fileManager.isSameFile(veteran, fileObject)) {
+                        return true;
+                    }
+                } catch (IllegalArgumentException e) {
+                    //ignore...
+                }
+            }
+            for (String className : initialClassNames) {
+                try {
+                    ClassSymbol existing = elementUtils.getTypeElement(className);
+                    if (   existing != null
+                        && (   (existing.sourcefile != null && fileManager.isSameFile(existing.sourcefile, fileObject))
+                            || (existing.classfile != null && fileManager.isSameFile(existing.classfile, fileObject)))) {
+                        return true;
+                    }
+                } catch (IllegalArgumentException e) {
+                    //ignore...
+                }
+            }
+        }
+
         for(FileObject veteran : fileObjectHistory) {
             if (fileManager.isSameFile(veteran, fileObject)) {
-                if (lint)
-                    log.warning("proc.file.reopening", fileObject.getName());
-                throw new FilerException("Attempt to reopen a file for path " + fileObject.getName());
+                return true;
             }
         }
-        if (addToHistory)
-            fileObjectHistory.add(fileObject);
+
+        return false;
     }
 
     public boolean newFiles() {
@@ -656,9 +706,17 @@
         this.lastRound = lastRound;
     }
 
+    public void setInitialState(Collection<? extends JavaFileObject> initialInputs,
+                                Collection<String> initialClassNames) {
+        this.initialInputs.addAll(initialInputs);
+        this.initialClassNames.addAll(initialClassNames);
+    }
+
     public void close() {
         clearRoundState();
         // Cross-round state
+        initialClassNames.clear();
+        initialInputs.clear();
         fileObjectHistory.clear();
         openTypeNames.clear();
         aggregateGeneratedSourceNames.clear();