6988836: A new JavacElements is created for each round of annotation processing
authorjjg
Tue, 05 Oct 2010 11:34:43 -0700
changeset 6924 ef7a9281ad2f
parent 6722 7a6305ae0721
child 6925 2196feb18c96
6988836: A new JavacElements is created for each round of annotation processing Reviewed-by: darcy
langtools/src/share/classes/com/sun/tools/javac/model/JavacElements.java
langtools/src/share/classes/com/sun/tools/javac/model/JavacTypes.java
langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java
langtools/test/tools/javac/processing/environment/round/TestContext.java
--- a/langtools/src/share/classes/com/sun/tools/javac/model/JavacElements.java	Sun Oct 03 19:40:15 2010 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/model/JavacElements.java	Tue Oct 05 11:34:43 2010 -0700
@@ -66,32 +66,26 @@
     private Types types;
     private Enter enter;
 
-    private static final Context.Key<JavacElements> KEY =
-            new Context.Key<JavacElements>();
-
     public static JavacElements instance(Context context) {
-        JavacElements instance = context.get(KEY);
-        if (instance == null) {
+        JavacElements instance = context.get(JavacElements.class);
+        if (instance == null)
             instance = new JavacElements(context);
-            context.put(KEY, instance);
-        }
         return instance;
     }
 
     /**
      * Public for use only by JavacProcessingEnvironment
      */
-    // TODO JavacElements constructor should be protected
-    public JavacElements(Context context) {
+    protected JavacElements(Context context) {
         setContext(context);
     }
 
     /**
      * Use a new context.  May be called from outside to update
      * internal state for a new annotation-processing round.
-     * This instance is *not* then registered with the new context.
      */
     public void setContext(Context context) {
+        context.put(JavacElements.class, this);
         javaCompiler = JavaCompiler.instance(context);
         syms = Symtab.instance(context);
         names = Names.instance(context);
--- a/langtools/src/share/classes/com/sun/tools/javac/model/JavacTypes.java	Sun Oct 03 19:40:15 2010 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/model/JavacTypes.java	Tue Oct 05 11:34:43 2010 -0700
@@ -47,32 +47,26 @@
     private Symtab syms;
     private Types types;
 
-    private static final Context.Key<JavacTypes> KEY =
-            new Context.Key<JavacTypes>();
-
     public static JavacTypes instance(Context context) {
-        JavacTypes instance = context.get(KEY);
-        if (instance == null) {
+        JavacTypes instance = context.get(JavacTypes.class);
+        if (instance == null)
             instance = new JavacTypes(context);
-            context.put(KEY, instance);
-        }
         return instance;
     }
 
     /**
      * Public for use only by JavacProcessingEnvironment
      */
-    // TODO JavacTypes constructor should be protected
-    public JavacTypes(Context context) {
+    protected JavacTypes(Context context) {
         setContext(context);
     }
 
     /**
      * Use a new context.  May be called from outside to update
      * internal state for a new annotation-processing round.
-     * This instance is *not* then registered with the new context.
      */
     public void setContext(Context context) {
+        context.put(JavacTypes.class, this);
         syms = Symtab.instance(context);
         types = Types.instance(context);
     }
--- a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Sun Oct 03 19:40:15 2010 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Tue Oct 05 11:34:43 2010 -0700
@@ -173,12 +173,12 @@
         platformAnnotations = initPlatformAnnotations();
         foundTypeProcessors = false;
 
-        // Initialize services before any processors are initialzied
+        // Initialize services before any processors are initialized
         // in case processors use them.
         filer = new JavacFiler(context);
         messager = new JavacMessager(context, this);
-        elementUtils = new JavacElements(context);
-        typeUtils = new JavacTypes(context);
+        elementUtils = JavacElements.instance(context);
+        typeUtils = JavacTypes.instance(context);
         processorOptions = initProcessorOptions(context);
         unmatchedProcessorOptions = initUnmatchedProcessorOptions();
         messages = JavacMessages.instance(context);
@@ -865,8 +865,6 @@
             this(prev.nextContext(), prev.number+1, prev.compiler.log.nwarnings);
             this.genClassFiles = prev.genClassFiles;
 
-            updateProcessingState();
-
             List<JCCompilationUnit> parsedFiles = compiler.parseFiles(newSourceFiles);
             roots = cleanTrees(prev.roots).appendList(parsedFiles);
 
@@ -1029,15 +1027,6 @@
             log.reportDeferredDiagnostics(kinds);
         }
 
-        /** Update the processing state for the current context. */
-        private void updateProcessingState() {
-            filer.newRound(context);
-            messager.newRound(context);
-
-            elementUtils.setContext(context);
-            typeUtils.setContext(context);
-        }
-
         /** Print info about this round. */
         private void printRoundInfo(boolean lastRound) {
             if (printRounds || verbose) {
@@ -1100,6 +1089,11 @@
             JavaCompiler nextCompiler = JavaCompiler.instance(next);
             nextCompiler.initRound(oldCompiler);
 
+            filer.newRound(next);
+            messager.newRound(next);
+            elementUtils.setContext(next);
+            typeUtils.setContext(next);
+
             JavacTaskImpl task = context.get(JavacTaskImpl.class);
             if (task != null) {
                 next.put(JavacTaskImpl.class, task);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/processing/environment/round/TestContext.java	Tue Oct 05 11:34:43 2010 -0700
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6988836
+ * @summary A new JavacElements is created for each round of annotation processing
+ * @library ../../../lib
+ * @build JavacTestingAbstractProcessor TestContext
+ * @compile/process -processor TestContext -XprintRounds TestContext
+ */
+
+import java.io.*;
+import java.util.*;
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+import javax.tools.*;
+import static javax.tools.Diagnostic.Kind.*;
+
+import com.sun.source.util.Trees;
+import com.sun.tools.javac.api.JavacTrees;
+import com.sun.tools.javac.model.JavacElements;
+import com.sun.tools.javac.model.JavacTypes;
+import com.sun.tools.javac.processing.JavacProcessingEnvironment;
+import com.sun.tools.javac.util.Context;
+
+public class TestContext extends JavacTestingAbstractProcessor {
+
+    Trees treeUtils;
+    int round = 0;
+
+    @Override
+    public void init(ProcessingEnvironment pEnv) {
+        super.init(pEnv);
+        treeUtils = Trees.instance(processingEnv);
+    }
+
+    @Override
+    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+        round++;
+
+        JavacProcessingEnvironment jpe = (JavacProcessingEnvironment) processingEnv;
+        Context c = jpe.getContext();
+        check(c.get(JavacElements.class), eltUtils);
+        check(c.get(JavacTypes.class), typeUtils);
+        check(c.get(JavacTrees.class), treeUtils);
+
+        final int MAXROUNDS = 3;
+        if (round < MAXROUNDS)
+            generateSource("Gen" + round);
+
+        return true;
+    }
+
+    <T> void check(T actual, T expected) {
+//        messager.printMessage(NOTE, "expect: " + expected);
+//        messager.printMessage(NOTE, "actual: " + actual);
+
+        if (actual != expected) {
+            messager.printMessage(ERROR,
+                "round " + round + " unexpected value for " + expected.getClass().getName() + ": " + actual);
+        }
+    }
+
+    void generateSource(String name) {
+        String text = "class " + name + " { }\n";
+
+        try (Writer out = filer.createSourceFile(name).openWriter()) {
+                out.write(text);
+        } catch (IOException e) {
+            throw new Error(e);
+        }
+    }
+
+}
+