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