Using TaskListener to get attributed trees instead of attributing them outselves (analogous to AbstractTypeProcessor)
authorJan Lahoda <jlahoda@netbeans.org>
Sun, 16 Jan 2011 19:22:56 +0100
changeset 520cb67f7df8dd1
parent 519 7c187dccaf45
child 521 28cbfe7484a0
Using TaskListener to get attributed trees instead of attributing them outselves (analogous to AbstractTypeProcessor)
cmdline/compiler/src/org/netbeans/modules/jackpot30/compiler/HintsAnnotationProcessing.java
cmdline/compiler/src/org/netbeans/modules/jackpot30/compiler/HintsAnnotationProcessingImpl.java
cmdline/compiler/test/unit/src/org/netbeans/modules/jackpot30/compiler/HintsAnnotationProcessingTestBase.java
     1.1 --- a/cmdline/compiler/src/org/netbeans/modules/jackpot30/compiler/HintsAnnotationProcessing.java	Sun Jan 16 19:22:56 2011 +0100
     1.2 +++ b/cmdline/compiler/src/org/netbeans/modules/jackpot30/compiler/HintsAnnotationProcessing.java	Sun Jan 16 19:22:56 2011 +0100
     1.3 @@ -71,6 +71,7 @@
     1.4  import org.netbeans.modules.jackpot30.spi.HintDescription;
     1.5  import org.netbeans.modules.jackpot30.spi.HintMetadata;
     1.6  import org.netbeans.modules.jackpot30.spi.HintsRunner;
     1.7 +import org.netbeans.modules.parsing.impl.indexing.CacheFolder;
     1.8  import org.netbeans.spi.editor.hints.ErrorDescription;
     1.9  import org.netbeans.spi.editor.hints.Fix;
    1.10  import org.openide.filesystems.FileUtil;
    1.11 @@ -101,6 +102,27 @@
    1.12  
    1.13      @Override
    1.14      protected boolean initialize(ProcessingEnvironment processingEnv) {
    1.15 +        try {
    1.16 +            File tmp = File.createTempFile("jackpot30", null);
    1.17 +
    1.18 +            tmp.delete();
    1.19 +            tmp.mkdirs();
    1.20 +            tmp.deleteOnExit();
    1.21 +
    1.22 +            tmp = FileUtil.normalizeFile(tmp);
    1.23 +            FileUtil.refreshFor(tmp.getParentFile());
    1.24 +
    1.25 +            org.openide.filesystems.FileObject tmpFO = FileUtil.toFileObject(tmp);
    1.26 +
    1.27 +            if (tmpFO == null) {
    1.28 +                return false;
    1.29 +            }
    1.30 +
    1.31 +            CacheFolder.setCacheFolder(tmpFO);
    1.32 +        } catch (IOException ex) {
    1.33 +            ex.printStackTrace();
    1.34 +        }
    1.35 +
    1.36          return true;
    1.37      }
    1.38  
     2.1 --- a/cmdline/compiler/src/org/netbeans/modules/jackpot30/compiler/HintsAnnotationProcessingImpl.java	Sun Jan 16 19:22:56 2011 +0100
     2.2 +++ b/cmdline/compiler/src/org/netbeans/modules/jackpot30/compiler/HintsAnnotationProcessingImpl.java	Sun Jan 16 19:22:56 2011 +0100
     2.3 @@ -46,6 +46,8 @@
     2.4  import com.sun.source.tree.ParameterizedTypeTree;
     2.5  import com.sun.source.tree.Tree;
     2.6  import com.sun.source.util.SourcePositions;
     2.7 +import com.sun.source.util.TaskEvent;
     2.8 +import com.sun.source.util.TaskListener;
     2.9  import com.sun.source.util.TreePath;
    2.10  import com.sun.source.util.TreeScanner;
    2.11  import com.sun.source.util.Trees;
    2.12 @@ -83,6 +85,7 @@
    2.13  import java.util.prefs.Preferences;
    2.14  import java.util.prefs.PreferencesFactory;
    2.15  import javax.annotation.processing.AbstractProcessor;
    2.16 +import javax.annotation.processing.ProcessingEnvironment;
    2.17  import javax.annotation.processing.Processor;
    2.18  import javax.annotation.processing.RoundEnvironment;
    2.19  import javax.annotation.processing.SupportedAnnotationTypes;
    2.20 @@ -90,6 +93,7 @@
    2.21  import javax.lang.model.element.Element;
    2.22  import javax.lang.model.element.ElementKind;
    2.23  import javax.lang.model.element.TypeElement;
    2.24 +import javax.lang.model.util.ElementFilter;
    2.25  import javax.swing.event.ChangeListener;
    2.26  import javax.tools.Diagnostic.Kind;
    2.27  import javax.tools.JavaFileManager;
    2.28 @@ -123,55 +127,12 @@
    2.29  @ServiceProvider(service=Processor.class)
    2.30  public final class HintsAnnotationProcessingImpl extends AbstractProcessor {
    2.31  
    2.32 -    private final Collection<Element> types = new LinkedList<Element>();
    2.33 +    private final Collection<String> seenTypes = new LinkedList<String>();
    2.34 +    private final Collection<AbstractHintsAnnotationProcessing> processors = new LinkedList<AbstractHintsAnnotationProcessing>();
    2.35  
    2.36      @Override
    2.37 -    public final boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    2.38 -        try {
    2.39 -            return doProcess(annotations, roundEnv);
    2.40 -        } catch (Throwable ex) {
    2.41 -            ex.printStackTrace();
    2.42 -            return false;
    2.43 -        }
    2.44 -    }
    2.45 -
    2.46 -    private boolean doProcess(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    2.47 -        types.addAll(roundEnv.getRootElements());
    2.48 -        
    2.49 -        if (!roundEnv.processingOver())
    2.50 -            return false;
    2.51 -
    2.52 -        try {
    2.53 -            File tmp = File.createTempFile("jackpot30", null);
    2.54 -
    2.55 -            tmp.delete();
    2.56 -            tmp.mkdirs();
    2.57 -            tmp.deleteOnExit();
    2.58 -
    2.59 -            tmp = FileUtil.normalizeFile(tmp);
    2.60 -            FileUtil.refreshFor(tmp.getParentFile());
    2.61 -
    2.62 -            org.openide.filesystems.FileObject tmpFO = FileUtil.toFileObject(tmp);
    2.63 -
    2.64 -            if (tmpFO == null) {
    2.65 -                return false;
    2.66 -            }
    2.67 -
    2.68 -            CacheFolder.setCacheFolder(tmpFO);
    2.69 -        } catch (IOException ex) {
    2.70 -            ex.printStackTrace();
    2.71 -        }
    2.72 -
    2.73 -        Context c = ((JavacProcessingEnvironment) processingEnv).getContext();
    2.74 -        StandardJavaFileManager s = (StandardJavaFileManager) c.get(JavaFileManager.class);
    2.75 -        ClassPath boot = computeClassPath(s, StandardLocation.PLATFORM_CLASS_PATH);
    2.76 -        ClassPath compile = computeClassPath(s, StandardLocation.CLASS_PATH);
    2.77 -        ClassPath source = computeClassPath(s, StandardLocation.SOURCE_PATH);
    2.78 -        Trees trees = JavacTrees.instance(c);
    2.79 -        Collection<CompilationUnitTree> toClean = new LinkedList<CompilationUnitTree>();
    2.80 -        final Log log = Log.instance(c);
    2.81 -
    2.82 -        List<AbstractHintsAnnotationProcessing> processors = new ArrayList<AbstractHintsAnnotationProcessing>();
    2.83 +    public synchronized void init(ProcessingEnvironment processingEnv) {
    2.84 +        super.init(processingEnv);
    2.85  
    2.86          for (AbstractHintsAnnotationProcessing p : Lookup.getDefault().lookupAll(AbstractHintsAnnotationProcessing.class)) {
    2.87              if (p.initialize(processingEnv)) {
    2.88 @@ -179,63 +140,85 @@
    2.89              }
    2.90          }
    2.91  
    2.92 +        if (processors.isEmpty()) {
    2.93 +            return;
    2.94 +        }
    2.95 +
    2.96 +        if (!(processingEnv instanceof JavacProcessingEnvironment)) {
    2.97 +            throw new UnsupportedOperationException("Not a JavacProcessingEnvironment");
    2.98 +        }
    2.99 +
   2.100 +        Context c = ((JavacProcessingEnvironment) processingEnv).getContext();
   2.101 +        TaskListener prev = c.get(TaskListener.class);
   2.102 +
   2.103 +        c.put(TaskListener.class, (TaskListener) null);
   2.104 +        c.put(TaskListener.class, new TaskListenerImpl(prev));
   2.105 +    }
   2.106 +
   2.107 +    @Override
   2.108 +    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
   2.109 +        for (TypeElement type : ElementFilter.typesIn(roundEnv.getRootElements())) {
   2.110 +            seenTypes.add(type.getQualifiedName().toString());
   2.111 +        }
   2.112 +
   2.113 +        if (roundEnv.processingOver()) {
   2.114 +            try {
   2.115 +                //XXX: workarounding a bug in CRTable (see HintsAnnotationProcessingTest.testCRTable):
   2.116 +                Context c = ((JavacProcessingEnvironment) processingEnv).getContext();
   2.117 +                Options.instance(c).remove("-Xjcov");
   2.118 +                Field f = Gen.class.getDeclaredField("genCrt");
   2.119 +                f.setAccessible(true);
   2.120 +                f.set(Gen.instance(c), false);
   2.121 +            } catch (Exception e) {
   2.122 +                e.printStackTrace();
   2.123 +            }
   2.124 +        }
   2.125 +        return false;
   2.126 +    }
   2.127 +
   2.128 +    private void doProcessing(TypeElement type) {
   2.129 +        if (!seenTypes.remove(type.getQualifiedName().toString())) return;
   2.130 +        
   2.131 +        Context c = ((JavacProcessingEnvironment) processingEnv).getContext();
   2.132 +        StandardJavaFileManager s = (StandardJavaFileManager) c.get(JavaFileManager.class);
   2.133 +        ClassPath boot = computeClassPath(s, StandardLocation.PLATFORM_CLASS_PATH);
   2.134 +        ClassPath compile = computeClassPath(s, StandardLocation.CLASS_PATH);
   2.135 +        ClassPath source = computeClassPath(s, StandardLocation.SOURCE_PATH);
   2.136 +        Trees trees = JavacTrees.instance(c);
   2.137 +        final Log log = Log.instance(c);
   2.138 +
   2.139          try {
   2.140 -            for (Element el : types) {
   2.141 -                if (!el.getKind().isClass() && !el.getKind().isInterface()) {
   2.142 -    //                processingEnv.getMessager().printMessage(Kind.NOTE, "Not a class", el);
   2.143 -                    continue;
   2.144 +            TreePath elTree = trees.getPath(type);
   2.145 +            JCCompilationUnit cut = (JCCompilationUnit) elTree.getCompilationUnit();
   2.146 +
   2.147 +            if (!cut.sourcefile.toUri().isAbsolute()) {
   2.148 +                processingEnv.getMessager().printMessage(Kind.NOTE, "Not an absolute URI: " + cut.sourcefile.toUri().toASCIIString(), type);
   2.149 +                return ; //XXX
   2.150 +            }
   2.151 +
   2.152 +            CompilationInfoHack info = new CompilationInfoHack(c, ClasspathInfo.create(boot, compile, source), cut);
   2.153 +            JavaFileObject origSourceFile = log.currentSourceFile();
   2.154 +
   2.155 +            try {
   2.156 +                log.useSource(cut.sourcefile);
   2.157 +
   2.158 +                for (AbstractHintsAnnotationProcessing p : processors) {
   2.159 +                    p.doProcess(info, processingEnv, new Reporter() {
   2.160 +                        @Override public void warning(int offset, String message) {
   2.161 +                            log.warning(offset, "proc.messager", message);
   2.162 +                        }
   2.163 +                    });
   2.164                  }
   2.165 -
   2.166 -                TreePath elTree = trees.getPath(el);
   2.167 -                JCCompilationUnit cut = (JCCompilationUnit) elTree.getCompilationUnit();
   2.168 -
   2.169 -                if (!cut.sourcefile.toUri().isAbsolute()) {
   2.170 -                    processingEnv.getMessager().printMessage(Kind.NOTE, "Not an absolute URI: " + cut.sourcefile.toUri().toASCIIString(), el);
   2.171 -                    continue; //XXX
   2.172 -                }
   2.173 -
   2.174 -                toClean.add(cut);
   2.175 -
   2.176 -                doAttribute(c, cut);
   2.177 -
   2.178 -                CompilationInfoHack info = new CompilationInfoHack(c, ClasspathInfo.create(boot, compile, source), cut);
   2.179 -                JavaFileObject origSourceFile = log.currentSourceFile();
   2.180 -
   2.181 -                try {
   2.182 -                    log.useSource(cut.sourcefile);
   2.183 -
   2.184 -                    for (AbstractHintsAnnotationProcessing p : processors) {
   2.185 -                        p.doProcess(info, processingEnv, new Reporter() {
   2.186 -                            @Override public void warning(int offset, String message) {
   2.187 -                                log.warning(offset, "proc.messager", message);
   2.188 -                            }
   2.189 -                        });
   2.190 -                    }
   2.191 -                } finally {
   2.192 -                    log.useSource(origSourceFile);
   2.193 +            } finally {
   2.194 +                log.useSource(origSourceFile);
   2.195 +            }
   2.196 +        } finally {
   2.197 +            if (seenTypes.isEmpty()) {
   2.198 +                for (AbstractHintsAnnotationProcessing p : processors) {
   2.199 +                    p.finish();
   2.200                  }
   2.201              }
   2.202 -        } finally {
   2.203 -            for (AbstractHintsAnnotationProcessing p : processors) {
   2.204 -                p.finish();
   2.205 -            }
   2.206          }
   2.207 -
   2.208 -        for (CompilationUnitTree cut : toClean) {
   2.209 -            new ThoroughTreeCleaner(cut, trees.getSourcePositions()).scan(cut, null);
   2.210 -        }
   2.211 -
   2.212 -        try {
   2.213 -            //XXX: workarounding a bug in CRTable (see HintsAnnotationProcessingTest.testCRTable):
   2.214 -            Options.instance(c).remove("-Xjcov");
   2.215 -            Field f = Gen.class.getDeclaredField("genCrt");
   2.216 -            f.setAccessible(true);
   2.217 -            f.set(Gen.instance(c), false);
   2.218 -        } catch (Exception e) {
   2.219 -            e.printStackTrace();
   2.220 -        }
   2.221 -        
   2.222 -        return false;
   2.223      }
   2.224  
   2.225      @Override
   2.226 @@ -267,30 +250,35 @@
   2.227          return ClassPathSupport.createClassPath(urls.toArray(new URL[0]));
   2.228      }
   2.229  
   2.230 -    private static void doAttribute(Context c, JCCompilationUnit cut) {
   2.231 -        JavaCompiler jc = JavaCompiler.instance(c);
   2.232 -        final Enter enter = Enter.instance(c);
   2.233 -        final Queue<Env<AttrContext>> queued = new LinkedList<Env<AttrContext>>();
   2.234 +    private final class TaskListenerImpl implements TaskListener {
   2.235  
   2.236 -        queued.add(enter.getTopLevelEnv(cut));
   2.237 +        private final TaskListener delegate;
   2.238  
   2.239 -        new TreeScanner<Void, Void>() {
   2.240 -            @Override
   2.241 -            public Void visitClass(ClassTree node, Void p) {
   2.242 -                Env<AttrContext> env = enter.getEnv(((JCClassDecl) node).sym);
   2.243 +        public TaskListenerImpl(TaskListener delegate) {
   2.244 +            this.delegate = delegate;
   2.245 +        }
   2.246  
   2.247 -                if (env != null)
   2.248 -                    queued.add(env);
   2.249 +        @Override
   2.250 +        public void started(TaskEvent te) {
   2.251 +            if (delegate != null) {
   2.252 +                delegate.started(te);
   2.253 +            }
   2.254 +        }
   2.255  
   2.256 -                return super.visitClass(node, p);
   2.257 +        @Override
   2.258 +        public void finished(TaskEvent te) {
   2.259 +            if (delegate != null) {
   2.260 +                delegate.finished(te);
   2.261              }
   2.262 -        }.scan(cut, null);
   2.263  
   2.264 -        Attr attr = Attr.instance(c);
   2.265 +            if (te.getKind() == TaskEvent.Kind.ANALYZE) {
   2.266 +                TypeElement toProcess = te.getTypeElement();
   2.267  
   2.268 -        for (Env<AttrContext> env : queued) {
   2.269 -            attr.attribClass(env.tree.pos(), env.enclClass.sym);
   2.270 +                assert toProcess != null;
   2.271 +                doProcessing(toProcess);
   2.272 +            }
   2.273          }
   2.274 +
   2.275      }
   2.276  
   2.277  
   2.278 @@ -309,66 +297,6 @@
   2.279          }
   2.280      }
   2.281  
   2.282 -    private static final class ThoroughTreeCleaner extends TreeScanner<Void, Void> {
   2.283 -
   2.284 -        private final CompilationUnitTree cut;
   2.285 -        private final SourcePositions positions;
   2.286 -
   2.287 -        public ThoroughTreeCleaner(CompilationUnitTree cut, SourcePositions positions) {
   2.288 -            this.cut = cut;
   2.289 -            this.positions = positions;
   2.290 -        }
   2.291 -
   2.292 -        @Override
   2.293 -        public Void scan(Tree node, Void p) {
   2.294 -            if (node != null) ((JCTree) node).type = null;
   2.295 -            return super.scan(node, p);
   2.296 -        }
   2.297 -
   2.298 -        @Override
   2.299 -        public Void visitParameterizedType(ParameterizedTypeTree node, Void p) {
   2.300 -            return super.visitParameterizedType(node, p);
   2.301 -        }
   2.302 -
   2.303 -        @Override
   2.304 -        public Void visitMemberSelect(MemberSelectTree node, Void p) {
   2.305 -            ((JCFieldAccess) node).sym = null;
   2.306 -            return super.visitMemberSelect(node, p);
   2.307 -        }
   2.308 -
   2.309 -        @Override
   2.310 -        public Void visitIdentifier(IdentifierTree node, Void p) {
   2.311 -            ((JCIdent) node).sym = null;
   2.312 -            return super.visitIdentifier(node, p);
   2.313 -        }
   2.314 -
   2.315 -        @Override
   2.316 -        public Void visitMethod(MethodTree node, Void p) {
   2.317 -            JCMethodDecl method = (JCMethodDecl) node;
   2.318 -
   2.319 -            if (method.sym != null && method.sym.getKind() == ElementKind.CONSTRUCTOR && method.sym.owner.getKind() == ElementKind.ENUM) {
   2.320 -                if (positions.getEndPosition(cut, method.body.stats.head) == (-1)) {
   2.321 -                    method.body.stats = method.body.stats.tail;
   2.322 -                }
   2.323 -            }
   2.324 -
   2.325 -            return super.visitMethod(node, p);
   2.326 -        }
   2.327 -
   2.328 -        @Override
   2.329 -        public Void visitClass(ClassTree node, Void p) {
   2.330 -            JCClassDecl decl = (JCClassDecl) node;
   2.331 -
   2.332 -            if (decl.sym.getKind() == ElementKind.ENUM) {
   2.333 -                if (positions.getEndPosition(cut, decl.defs.head) == (-1)) {
   2.334 -                    decl.defs = decl.defs.tail;
   2.335 -                }
   2.336 -            }
   2.337 -            return super.visitClass(node, p);
   2.338 -        }
   2.339 -
   2.340 -    }
   2.341 -
   2.342      @ServiceProvider(service=MimeDataProvider.class)
   2.343      public static final class MimeDataProviderImpl implements MimeDataProvider {
   2.344  
     3.1 --- a/cmdline/compiler/test/unit/src/org/netbeans/modules/jackpot30/compiler/HintsAnnotationProcessingTestBase.java	Sun Jan 16 19:22:56 2011 +0100
     3.2 +++ b/cmdline/compiler/test/unit/src/org/netbeans/modules/jackpot30/compiler/HintsAnnotationProcessingTestBase.java	Sun Jan 16 19:22:56 2011 +0100
     3.3 @@ -146,6 +146,8 @@
     3.4              List<String> ll = new LinkedList<String>();
     3.5  
     3.6              ll.add("java");
     3.7 +//            ll.add("-Xdebug");
     3.8 +//            ll.add("-Xrunjdwp:transport=dt_socket,suspend=y,server=y,address=8889");
     3.9              ll.add("-Xbootclasspath/p:" + compiler.getAbsolutePath());
    3.10              ll.add("com.sun.tools.javac.Main");
    3.11              ll.addAll(Arrays.asList(params));