cmdline/compiler/src/org/netbeans/modules/jackpot30/compiler/HintsAnnotationProcessingImpl.java
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4 * Copyright 2009-2011 Sun Microsystems, Inc. All rights reserved.
6 * The contents of this file are subject to the terms of either the GNU
7 * General Public License Version 2 only ("GPL") or the Common
8 * Development and Distribution License("CDDL") (collectively, the
9 * "License"). You may not use this file except in compliance with the
10 * License. You can obtain a copy of the License at
11 * http://www.netbeans.org/cddl-gplv2.html
12 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13 * specific language governing permissions and limitations under the
14 * License. When distributing the software, include this License Header
15 * Notice in each file and include the License file at
16 * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17 * particular file as subject to the "Classpath" exception as provided
18 * by Sun in the GPL Version 2 section of the License file that
19 * accompanied this code. If applicable, add the following below the
20 * License Header, with the fields enclosed by brackets [] replaced by
21 * your own identifying information:
22 * "Portions Copyrighted [year] [name of copyright owner]"
24 * If you wish your version of this file to be governed by only the CDDL
25 * or only the GPL Version 2, indicate your decision by adding
26 * "[Contributor] elects to include this software in this distribution
27 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28 * single choice of license, a recipient has the option to distribute
29 * your version of this file under either the CDDL, the GPL Version 2 or
30 * to extend the choice of license to its licensees as provided above.
31 * However, if you add GPL Version 2 code and therefore, elected the GPL
32 * Version 2 license, then the option applies only if the new code is
33 * made subject to such option by the copyright holder.
37 * Portions Copyrighted 2009-2011 Sun Microsystems, Inc.
39 package org.netbeans.modules.jackpot30.compiler;
41 import com.sun.source.util.JavacTask;
42 import com.sun.source.util.TaskEvent;
43 import com.sun.source.util.TaskListener;
44 import com.sun.source.util.TreePath;
45 import com.sun.source.util.Trees;
46 import com.sun.tools.javac.api.JavacTrees;
47 import com.sun.tools.javac.api.MultiTaskListener;
48 import com.sun.tools.javac.jvm.Gen;
49 import com.sun.tools.javac.parser.ParserFactory;
50 import com.sun.tools.javac.processing.JavacProcessingEnvironment;
51 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
52 import com.sun.tools.javac.util.Context;
53 import com.sun.tools.javac.util.Context.Key;
54 import com.sun.tools.javac.util.Log;
55 import com.sun.tools.javac.util.Options;
57 import java.lang.reflect.Field;
59 import java.util.Collection;
60 import java.util.HashSet;
61 import java.util.LinkedList;
62 import java.util.List;
64 import javax.annotation.processing.AbstractProcessor;
65 import javax.annotation.processing.ProcessingEnvironment;
66 import javax.annotation.processing.Processor;
67 import javax.annotation.processing.RoundEnvironment;
68 import javax.annotation.processing.SupportedAnnotationTypes;
69 import javax.lang.model.SourceVersion;
70 import javax.lang.model.element.TypeElement;
71 import javax.lang.model.util.ElementFilter;
72 import javax.tools.Diagnostic.Kind;
73 import javax.tools.JavaFileManager;
74 import javax.tools.JavaFileObject;
75 import javax.tools.StandardJavaFileManager;
76 import javax.tools.StandardLocation;
77 import org.netbeans.api.java.classpath.ClassPath;
78 import org.netbeans.api.java.source.ClasspathInfo;
79 import org.netbeans.api.java.source.CompilationInfoHack;
80 import org.netbeans.lib.nbjavac.services.NBParserFactory;
81 import org.netbeans.modules.jackpot30.compiler.AbstractHintsAnnotationProcessing.Reporter;
82 import org.netbeans.spi.java.classpath.support.ClassPathSupport;
83 import org.openide.filesystems.FileUtil;
84 import org.openide.util.Lookup;
85 import org.openide.util.lookup.ServiceProvider;
91 @SupportedAnnotationTypes("*")
92 @ServiceProvider(service=Processor.class)
93 public final class HintsAnnotationProcessingImpl extends AbstractProcessor {
95 private final Collection<String> seenTypes = new LinkedList<String>();
96 private final Collection<AbstractHintsAnnotationProcessing> processors = new LinkedList<AbstractHintsAnnotationProcessing>();
99 public synchronized void init(ProcessingEnvironment processingEnv) {
100 super.init(processingEnv);
102 for (AbstractHintsAnnotationProcessing p : Lookup.getDefault().lookupAll(AbstractHintsAnnotationProcessing.class)) {
103 if (p.initialize(processingEnv)) {
108 if (processors.isEmpty()) {
112 if (!(processingEnv instanceof JavacProcessingEnvironment)) {
113 throw new UnsupportedOperationException("Not a JavacProcessingEnvironment");
116 Context c = ((JavacProcessingEnvironment) processingEnv).getContext();
118 MultiTaskListener.instance(c).add(new TaskListenerImpl());
122 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
123 for (TypeElement type : ElementFilter.typesIn(roundEnv.getRootElements())) {
124 seenTypes.add(type.getQualifiedName().toString());
127 if (roundEnv.processingOver()) {
129 //XXX: workarounding a bug in CRTable (see HintsAnnotationProcessingTest.testCRTable):
130 Context c = ((JavacProcessingEnvironment) processingEnv).getContext();
131 Options.instance(c).remove("-Xjcov");
132 Field f = Gen.class.getDeclaredField("genCrt");
133 f.setAccessible(true);
134 f.set(Gen.instance(c), false);
135 } catch (Exception e) {
142 private void doProcessing(TypeElement type) {
143 if (!seenTypes.remove(type.getQualifiedName().toString())) return;
145 Context c = ((JavacProcessingEnvironment) processingEnv).getContext();
146 StandardJavaFileManager s = (StandardJavaFileManager) c.get(JavaFileManager.class);
147 ClassPath boot = computeClassPath(s, StandardLocation.PLATFORM_CLASS_PATH);
148 ClassPath compile = computeClassPath(s, StandardLocation.CLASS_PATH);
149 ClassPath source = computeClassPath(s, StandardLocation.SOURCE_PATH);
150 Trees trees = JavacTrees.instance(c);
151 final Log log = Log.instance(c);
152 final Key<ParserFactory> key = ParserFactoryKeyAccessor.getContextKey();
153 ParserFactory origParserFactory = c.get(key);
154 c.put(key, (ParserFactory) null);
155 NBParserFactory.preRegister(c);
158 TreePath elTree = trees.getPath(type);
159 JCCompilationUnit cut = (JCCompilationUnit) elTree.getCompilationUnit();
161 if (!cut.sourcefile.toUri().isAbsolute()) {
162 processingEnv.getMessager().printMessage(Kind.NOTE, "Not an absolute URI: " + cut.sourcefile.toUri().toASCIIString(), type);
166 CompilationInfoHack info = new CompilationInfoHack(c, ClasspathInfo.create(boot, compile, source), cut);
167 JavaFileObject origSourceFile = log.currentSourceFile();
170 log.useSource(cut.sourcefile);
172 for (AbstractHintsAnnotationProcessing p : processors) {
173 p.doProcess(info, processingEnv, new Reporter() {
174 @Override public void warning(int offset, String message) {
175 log.warning(offset, "proc.messager", message);
180 log.useSource(origSourceFile);
183 if (seenTypes.isEmpty()) {
184 for (AbstractHintsAnnotationProcessing p : processors) {
189 c.put(key, (ParserFactory) null);
190 c.put(key, origParserFactory);
195 public SourceVersion getSupportedSourceVersion() {
196 return SourceVersion.latest();
200 public Set<String> getSupportedOptions() {
201 Set<String> options = new HashSet<String>();
203 for (AbstractHintsAnnotationProcessing p : Lookup.getDefault().lookupAll(AbstractHintsAnnotationProcessing.class)) {
204 options.addAll(p.getSupportedOptions());
210 private static ClassPath computeClassPath(StandardJavaFileManager m, StandardLocation kind) {
211 List<URL> urls = new LinkedList<URL>();
212 Iterable<? extends File> files = m.getLocation(kind);
215 for (File f : files) {
216 urls.add(FileUtil.urlForArchiveOrDir(FileUtil.normalizeFile(f)));
220 return ClassPathSupport.createClassPath(urls.toArray(new URL[0]));
223 private final class TaskListenerImpl implements TaskListener {
225 public TaskListenerImpl() { }
228 public void started(TaskEvent te) {
232 public void finished(TaskEvent te) {
233 if (te.getKind() == TaskEvent.Kind.ANALYZE) {
234 TypeElement toProcess = te.getTypeElement();
236 assert toProcess != null;
237 doProcessing(toProcess);
243 private static final class ParserFactoryKeyAccessor extends ParserFactory {
244 ParserFactoryKeyAccessor() {
247 public static Key<ParserFactory> getContextKey() {
248 return parserFactoryKey;
255 ClassLoader l = HintsAnnotationProcessingImpl.class.getClassLoader();
258 l = ClassLoader.getSystemClassLoader();
261 l.setClassAssertionStatus("org.netbeans.api.java.source.CompilationInfo", false);
262 } catch (Throwable t) {