United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-6634138 Source generated in last round not compiled
JDK-6634138 : Source generated in last round not compiled

Details
Type:
Bug
Submit Date:
2007-11-27
Status:
Closed
Updated Date:
2011-03-08
Project Name:
JDK
Resolved Date:
2011-03-08
Component:
core-libs
OS:
generic
Sub-Component:
javax.annotation.processing
CPU:
generic
Priority:
P3
Resolution:
Fixed
Affected Versions:
6
Fixed Versions:

Related Reports
Backport:

Sub Tasks

Description
It seems that javac does not compile source that is generated in the last round (when RoundEnvironment.processingOver() is true).

Although source generated in this round will not be annotation processed, it should still take part in javac's compile phase that happens after the "annotation processing".

                                    

Comments
EVALUATION

Should be fixed.
                                     
2007-11-27
SUGGESTED FIX

# HG changeset patch
# User darcy
# Date 1266286857 28800
# Node ID af18e39569850733517428b83f3407934d673134
# Parent 7d9e3a15d2b32d5e7ac43d235fcb7df328b5affc
6634138: Source generated in last round not compiled
Reviewed-by: jjg

--- a/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Mon Feb 15 16:09:50 2010 -0800
+++ b/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Mon Feb 15 18:20:57 2010 -0800
@@ -874,20 +874,9 @@ public class JavacProcessingEnvironment 
 
                     JavaFileManager fileManager = currentContext.get(JavaFileManager.class);
 
-                    List<JavaFileObject> fileObjects = List.nil();
-                    for (JavaFileObject jfo : filer.getGeneratedSourceFileObjects() ) {
-                        fileObjects = fileObjects.prepend(jfo);
-                    }
-
-
                     compiler = JavaCompiler.instance(currentContext);
-                    List<JCCompilationUnit> parsedFiles = compiler.parseFiles(fileObjects);
-                    roots = cleanTrees(roots).reverse();
-
-
-                    for (JCCompilationUnit unit : parsedFiles)
-                        roots = roots.prepend(unit);
-                    roots = roots.reverse();
+                    List<JCCompilationUnit> parsedFiles = sourcesToParsedFiles(compiler);
+                    roots = cleanTrees(roots).appendList(parsedFiles);
 
                     // Check for errors after parsing
                     if (compiler.parseErrors()) {
@@ -921,11 +910,16 @@ public class JavacProcessingEnvironment 
                     break runAround; // No new files
             }
         }
-        runLastRound(xout, roundNumber, errorStatus, taskListener);
+        roots = runLastRound(xout, roundNumber, errorStatus, compiler, roots, taskListener);
+        // Set error status for any files compiled and generated in
+        // the last round
+        if (compiler.parseErrors())
+            errorStatus = true;
 
         compiler.close(false);
         currentContext = contextForNextRound(currentContext, true);
         compiler = JavaCompiler.instance(currentContext);
+
         filer.newRound(currentContext, true);
         filer.warnIfUnclosedFiles();
         warnIfUnmatchedOptions();
@@ -979,10 +973,22 @@ public class JavacProcessingEnvironment 
         return compiler;
     }
 
+    private List<JCCompilationUnit> sourcesToParsedFiles(JavaCompiler compiler)
+        throws IOException {
+        List<JavaFileObject> fileObjects = List.nil();
+        for (JavaFileObject jfo : filer.getGeneratedSourceFileObjects() ) {
+            fileObjects = fileObjects.prepend(jfo);
+        }
+
+       return compiler.parseFiles(fileObjects);
+    }
+
     // Call the last round of annotation processing
-    private void runLastRound(PrintWriter xout,
-                              int roundNumber,
-                              boolean errorStatus,
+    private List<JCCompilationUnit> runLastRound(PrintWriter xout,
+                                                 int roundNumber,
+                                                 boolean errorStatus,
+                                                 JavaCompiler compiler,
+                                                 List<JCCompilationUnit> roots,
                               TaskListener taskListener) throws IOException {
         roundNumber++;
         List<ClassSymbol> noTopLevelClasses = List.nil();
@@ -1003,6 +1009,15 @@ public class JavacProcessingEnvironment 
             if (taskListener != null)
                 taskListener.finished(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING_ROUND));
         }
+
+        // Add any sources generated during the last round to the set
+        // of files to be compiled.
+        if (moreToDo()) {
+            List<JCCompilationUnit> parsedFiles = sourcesToParsedFiles(compiler);
+            roots = cleanTrees(roots).appendList(parsedFiles);
+        }
+
+        return roots;
     }
 
     private void updateProcessingState(Context currentContext, boolean lastRound) {
--- a/test/tools/javac/T6403466.java	Mon Feb 15 16:09:50 2010 -0800
+++ b/test/tools/javac/T6403466.java	Mon Feb 15 18:20:57 2010 -0800
@@ -41,7 +41,6 @@ import com.sun.tools.javac.api.JavacTool
 
 @Wrap
 @SupportedAnnotationTypes("Wrap")
-@SupportedSourceVersion(SourceVersion.RELEASE_6)
 public class T6403466 extends AbstractProcessor {
 
     static final String testSrcDir = System.getProperty("test.src");
@@ -73,23 +72,30 @@ public class T6403466 extends AbstractPr
     }
 
     public boolean process(Set<? extends TypeElement> annos, RoundEnvironment rEnv) {
-        Filer filer = processingEnv.getFiler();
-        for (TypeElement anno: annos) {
-            Set<? extends Element> elts = rEnv.getElementsAnnotatedWith(anno);
-            System.err.println("anno: " + anno);
-            System.err.println("elts: " + elts);
-            for (TypeElement te: ElementFilter.typesIn(elts)) {
-                try {
-                    Writer out = filer.createSourceFile(te.getSimpleName() + "Wrapper").openWriter();
-                    out.write("class " + te.getSimpleName() + "Wrapper { }");
-                    out.close();
-                } catch (IOException ex) {
-                    ex.printStackTrace();
+        if (!rEnv.processingOver()) {
+            Filer filer = processingEnv.getFiler();
+            for (TypeElement anno: annos) {
+                Set<? extends Element> elts = rEnv.getElementsAnnotatedWith(anno);
+                System.err.println("anno: " + anno);
+                System.err.println("elts: " + elts);
+                for (TypeElement te: ElementFilter.typesIn(elts)) {
+                    try {
+                        Writer out = filer.createSourceFile(te.getSimpleName() + "Wrapper").openWriter();
+                        out.write("class " + te.getSimpleName() + "Wrapper { }");
+                        out.close();
+                    } catch (IOException ex) {
+                        ex.printStackTrace();
+                    }
                 }
+
             }
-
         }
         return true;
+    }
+
+    @Override
+    public SourceVersion getSupportedSourceVersion() {
+        return SourceVersion.latest();
     }
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/processing/6634138/Dummy.java	Mon Feb 15 18:20:57 2010 -0800
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * A dummy class to be compiled.
+ */
+public class Dummy {}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/processing/6634138/ExerciseDependency.java	Mon Feb 15 18:20:57 2010 -0800
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * Class to exercise dependencies on the two source files generated by
+ * T6634138.java, foo.WrittenAfterProcessing.java and
+ * foo.package-info.java.
+ */
+public class ExerciseDependency {
+    public static void main(String... args) {
+        foo.WrittenAfterProcessing wap = new foo.WrittenAfterProcessing();
+        java.lang.Package pkg = wap.getClass().getPackage();
+        Deprecated d = pkg.getAnnotation(Deprecated.class);
+        if (d == null)
+            throw new RuntimeException();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/processing/6634138/T6634138.java	Mon Feb 15 18:20:57 2010 -0800
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6634138
+ * @author  Joseph D. Darcy
+ * @summary Verify source files output after processing is over are compiled
+ * @compile T6634138.java
+ * @compile -processor T6634138 Dummy.java
+ * @run main ExerciseDependency
+ */
+
+import java.lang.annotation.Annotation;
+import java.io.*;
+import java.util.Collections;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import javax.annotation.processing.*;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.*;
+import javax.lang.model.util.*;
+
+@SupportedAnnotationTypes("*")
+public class T6634138 extends AbstractProcessor {
+    private Filer filer;
+
+    public boolean process(Set<? extends TypeElement> annotations,
+                           RoundEnvironment roundEnvironment) {
+        // Write out files *after* processing is over.
+        if (roundEnvironment.processingOver()) {
+            System.out.println("Writing out source files.");
+            try {
+                PrintWriter pw = new PrintWriter(filer.createSourceFile("foo.WrittenAfterProcessing").openWriter());
+                try {
+                     pw.println("package foo;");
+                     pw.println("public class WrittenAfterProcessing {");
+                     pw.println("  public WrittenAfterProcessing() {super();}");
+                     pw.println("}");
+                 } finally {
+                     pw.close();
+                 }
+
+                pw = new PrintWriter(filer.createSourceFile("foo.package-info").openWriter());
+                try {
+                     pw.println("@Deprecated");
+                     pw.println("package foo;");
+                 } finally {
+                     pw.close();
+                 }
+            } catch(IOException io) {
+                throw new RuntimeException(io);
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public SourceVersion getSupportedSourceVersion() {
+        return SourceVersion.latest();
+    }
+
+    public void init(ProcessingEnvironment processingEnv) {
+        super.init(processingEnv);
+        filer    = processingEnv.getFiler();
+    }
+}
+
+
+
                                     
2010-02-16
PUBLIC COMMENTS

See
http://hg.openjdk.java.net/jdk7/tl/langtools/rev/af18e3956985
                                     
2010-02-16



Hardware and Software, Engineered to Work Together