KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > apt > core > internal > env > AbstractCompilationEnv


1 /*******************************************************************************
2  * Copyright (c) 2005, 2007 BEA Systems, Inc.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * tyeung@bea.com - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.apt.core.internal.env;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Collection JavaDoc;
15 import java.util.Collections JavaDoc;
16 import java.util.HashMap JavaDoc;
17 import java.util.HashSet JavaDoc;
18 import java.util.List JavaDoc;
19 import java.util.Map JavaDoc;
20 import java.util.Set JavaDoc;
21
22 import org.eclipse.core.resources.IFile;
23 import org.eclipse.core.runtime.CoreException;
24 import org.eclipse.core.runtime.IStatus;
25 import org.eclipse.jdt.apt.core.env.EclipseAnnotationProcessorEnvironment;
26 import org.eclipse.jdt.apt.core.env.Phase;
27 import org.eclipse.jdt.apt.core.internal.AptPlugin;
28 import org.eclipse.jdt.apt.core.internal.declaration.EclipseMirrorObject;
29 import org.eclipse.jdt.apt.core.internal.declaration.TypeDeclarationImpl;
30 import org.eclipse.jdt.apt.core.internal.env.MessagerImpl.Severity;
31 import org.eclipse.jdt.apt.core.internal.util.Factory;
32 import org.eclipse.jdt.apt.core.internal.util.Visitors.AnnotationVisitor;
33 import org.eclipse.jdt.apt.core.util.AptPreferenceConstants;
34 import org.eclipse.jdt.apt.core.util.EclipseMessager;
35 import org.eclipse.jdt.core.ICompilationUnit;
36 import org.eclipse.jdt.core.IJavaProject;
37 import org.eclipse.jdt.core.JavaConventions;
38 import org.eclipse.jdt.core.JavaCore;
39 import org.eclipse.jdt.core.compiler.BuildContext;
40 import org.eclipse.jdt.core.compiler.CategorizedProblem;
41 import org.eclipse.jdt.core.compiler.ReconcileContext;
42 import org.eclipse.jdt.core.dom.ASTRequestor;
43 import org.eclipse.jdt.core.dom.Annotation;
44 import org.eclipse.jdt.core.dom.CompilationUnit;
45 import org.eclipse.jdt.core.dom.ITypeBinding;
46
47 import com.sun.mirror.apt.AnnotationProcessorFactory;
48 import com.sun.mirror.apt.AnnotationProcessorListener;
49 import com.sun.mirror.apt.Filer;
50 import com.sun.mirror.declaration.AnnotationTypeDeclaration;
51
52 /** Base environment to be used during reconcile or build */
53 public abstract class AbstractCompilationEnv
54     extends BaseProcessorEnv
55     implements EclipseAnnotationProcessorEnvironment {
56     
57     // Bugzilla 188185: accept "-AenableTypeGenerationInEditor" as well as "enableTypeGenerationInEditor".
58
private final static String JavaDoc RTTG_ENABLED_DASH_A_OPTION = "-A" + AptPreferenceConstants.RTTG_ENABLED_OPTION; //$NON-NLS-1$
59

60     private Set JavaDoc<AnnotationProcessorListener> _listeners = null;
61     
62     protected List JavaDoc<APTProblem> _problems = new ArrayList JavaDoc<APTProblem>();
63     private boolean _isClosed = false;
64     
65     EnvCallback _callback;
66
67     private Set JavaDoc<IFile> _allGeneratedSourceFiles = new HashSet JavaDoc<IFile>();
68     private Set JavaDoc<IFile> _modifiedGeneratedSourceFiles = new HashSet JavaDoc<IFile>();
69
70     /**
71      * Currently open dom pipeline, used to request type bindings.
72      */

73     protected ASTRequestor _requestor;
74
75     /**
76      * The processor that is currently being executed, or null if processing is not underway.
77      */

78     private AnnotationProcessorFactory _currentProcessorFactory = null;
79     
80     public static interface EnvCallback {
81         public void run(AbstractCompilationEnv env);
82     }
83     
84     public static void newReconcileEnv(ReconcileContext reconcileContext, EnvCallback callback)
85     {
86         assert reconcileContext != null : "reconcile context is null"; //$NON-NLS-1$
87
ReconcileEnv env = ReconcileEnv.newEnv(reconcileContext);
88         env._callback = callback;
89         env.openPipeline();
90     }
91     
92     public static void newBuildEnv(
93             BuildContext[] filesWithAnnotations,
94             final BuildContext[] additionalFiles,
95             IJavaProject javaProj,
96             EnvCallback callback)
97     {
98         assert filesWithAnnotations != null : "missing files"; //$NON-NLS-1$
99

100         // note, we are not reading any files.
101
BuildEnv env = new BuildEnv(filesWithAnnotations, additionalFiles, javaProj);
102         env._callback = callback;
103         env.createASTs(filesWithAnnotations);
104     }
105     
106     AbstractCompilationEnv(
107             CompilationUnit compilationUnit,
108             IFile file,
109             IJavaProject javaProj,
110             Phase phase)
111     {
112         super(compilationUnit, file, javaProj, phase);
113     }
114     
115     @Override JavaDoc
116     protected ITypeBinding getTypeBindingFromKey(String JavaDoc key, ICompilationUnit unit) {
117         return (ITypeBinding)_requestor.createBindings(new String JavaDoc[] {key})[0];
118     }
119
120     public void addListener(AnnotationProcessorListener listener)
121     {
122         checkValid();
123         if(_listeners == null )
124             _listeners = new HashSet JavaDoc<AnnotationProcessorListener>();
125         _listeners.add(listener);
126     }
127
128     public void removeListener(AnnotationProcessorListener listener)
129     {
130         checkValid();
131         if( _listeners == null ) return;
132         _listeners.remove(listener);
133     }
134
135     public Set JavaDoc<AnnotationProcessorListener> getProcessorListeners()
136     {
137         if( _listeners == null )
138             return Collections.emptySet();
139         // Return a copy, to avoid ConcurrentModificationException if a listener
140
// removes itself in response to the callback.
141
return new HashSet JavaDoc<AnnotationProcessorListener>(_listeners);
142     }
143     
144     public Map JavaDoc<String JavaDoc, String JavaDoc> getOptions()
145     {
146         final HashMap JavaDoc<String JavaDoc, String JavaDoc> options = new HashMap JavaDoc<String JavaDoc, String JavaDoc>(_options);
147         options.put("phase", getPhase().toString()); //$NON-NLS-1$
148
return options;
149     }
150     
151     abstract public CompilationUnit getASTFrom(final IFile file);
152     
153     public CompilationUnit getAST(){
154         return _astRoot;
155     }
156     
157     public EclipseMessager getMessager()
158     {
159         checkValid();
160         return new MessagerImpl(this);
161     }
162     
163     abstract void addMessage(
164             IFile resource,
165             int start,
166             int end,
167             Severity severity,
168             String JavaDoc msg,
169             int line,
170             String JavaDoc[] arguments);
171     
172     public List JavaDoc<? extends CategorizedProblem> getProblems(){
173         checkValid();
174         if( !_problems.isEmpty() )
175             EnvUtil.updateProblemLength(_problems, getAstCompilationUnit());
176         return _problems;
177     }
178     
179     APTProblem createProblem(
180                 IFile resource,
181                 int start,
182                 int end,
183                 Severity severity,
184                 String JavaDoc msg,
185                 int line,
186                 String JavaDoc[] arguments)
187     {
188         // end-1 since IProblem ending offsets are inclusive but DOM layer
189
// ending offsets are exclusive.
190
final APTProblem newProblem =
191             new APTProblem(msg, severity, resource, start, end-1, line, arguments);
192         return newProblem;
193     }
194     
195     public abstract Filer getFiler();
196     
197     public void addGeneratedSourceFile( IFile f, boolean contentsChanged ) {
198         if (!f.toString().endsWith(".java")) { //$NON-NLS-1$
199
throw new IllegalArgumentException JavaDoc("Source files must be java source files, and end with .java"); //$NON-NLS-1$
200
}
201         
202         boolean addedToAll = _allGeneratedSourceFiles.add(f);
203         boolean addedToMod = false;
204         if (contentsChanged)
205             addedToMod = _modifiedGeneratedSourceFiles.add(f);
206         if (AptPlugin.DEBUG_COMPILATION_ENV) {
207             AptPlugin.trace("add generated file " + f + " to env " + this + //$NON-NLS-1$ //$NON-NLS-2$
208
"; addToAll = " + addedToAll + "; addToMod = " + addedToMod + //$NON-NLS-1$ //$NON-NLS-2$
209
"; contentsChanged = " + contentsChanged); //$NON-NLS-1$
210
}
211     }
212     
213     public void addGeneratedNonSourceFile(final IFile file) {
214         _allGeneratedSourceFiles.add(file);
215     }
216     
217     public Set JavaDoc<IFile> getAllGeneratedFiles() {
218         return _allGeneratedSourceFiles;
219     }
220     
221     public Set JavaDoc<IFile> getModifiedGeneratedFiles() {
222         return _modifiedGeneratedSourceFiles;
223     }
224
225     /**
226      * @return true iff source files has been generated.
227      * Always return false when this environment is closed.
228      */

229     public boolean hasGeneratedSourceFiles(){ return !_allGeneratedSourceFiles.isEmpty(); }
230
231
232     /**
233      * @return all annotation types in the current compilation unit.
234      */

235     public Map JavaDoc<String JavaDoc, AnnotationTypeDeclaration> getAnnotationTypes()
236     {
237         checkValid();
238         final List JavaDoc<Annotation> instances = new ArrayList JavaDoc<Annotation>();
239         final Map JavaDoc<String JavaDoc, AnnotationTypeDeclaration> decls =
240             new HashMap JavaDoc<String JavaDoc, AnnotationTypeDeclaration>();
241         final AnnotationVisitor visitor = new AnnotationVisitor(instances);
242         _astRoot.accept(visitor);
243             
244         for (int instanceIndex=0, size = instances.size(); instanceIndex < size; instanceIndex++) {
245             final Annotation instance = instances.get(instanceIndex);
246             final ITypeBinding annoType = instance.resolveTypeBinding();
247             if (annoType == null)
248                 continue;
249             final TypeDeclarationImpl decl =
250                 Factory.createReferenceType(annoType, this);
251             if (decl.kind() == EclipseMirrorObject.MirrorKind.TYPE_ANNOTATION){
252                 final AnnotationTypeDeclaration annoDecl = (AnnotationTypeDeclaration)decl;
253                 decls.put(annoDecl.getQualifiedName(), annoDecl);
254             }
255         }
256         
257         return decls;
258     }
259     
260     /* package */ void checkValid()
261     {
262         if( _isClosed )
263             throw new IllegalStateException JavaDoc("Environment has expired"); //$NON-NLS-1$
264
}
265     
266     // Call this after each file; cf. BuildEnv#beginFileProcessing()
267
protected void completedProcessing() {
268         _modifiedGeneratedSourceFiles.clear();
269     }
270     
271     public void close(){
272         if (isClosed())
273             return;
274         if(_listeners != null)
275             _listeners.clear();
276         _problems = null;
277         _typeCache.clear();
278         _packageRootsCache = null;
279         _isClosed = true;
280         _callback = null;
281         _requestor = null;
282         _allGeneratedSourceFiles = null;
283         _modifiedGeneratedSourceFiles = null;
284         if (AptPlugin.DEBUG_COMPILATION_ENV) AptPlugin.trace(
285                 "closed env " + this); //$NON-NLS-1$
286
}
287     
288     boolean isClosed(){ return _isClosed; }
289
290     /**
291      * Check typeName to ensure it doesn't contain any bogus characters.
292      * @param typeName
293      * @throws CoreException
294      */

295     @SuppressWarnings JavaDoc("unchecked")
296     public void validateTypeName(String JavaDoc typeName) throws CoreException
297     {
298         Map JavaDoc<String JavaDoc, String JavaDoc> options = getJavaProject().getOptions(true);
299         String JavaDoc sourceLevel = options.get(JavaCore.COMPILER_SOURCE);
300         String JavaDoc complianceLevel = options.get(JavaCore.COMPILER_COMPLIANCE);
301         IStatus status = JavaConventions.validateJavaTypeName(typeName, sourceLevel, complianceLevel);
302         if (status.matches(IStatus.ERROR)) {
303             throw new CoreException(status);
304         }
305     }
306
307     public AnnotationProcessorFactory getCurrentProcessorFactory() {
308         return _currentProcessorFactory;
309     }
310     
311     public void setCurrentProcessorFactory(AnnotationProcessorFactory processor)
312     {
313         _currentProcessorFactory = processor;
314     }
315
316     public boolean currentProcessorSupportsRTTG()
317     {
318         AnnotationProcessorFactory factory = getCurrentProcessorFactory();
319         if (null == factory) {
320             return false;
321         }
322         Collection JavaDoc<String JavaDoc> options = factory.supportedOptions();
323         if (null == options) {
324             return false;
325         }
326         return options.contains(AptPreferenceConstants.RTTG_ENABLED_OPTION) ||
327             options.contains(RTTG_ENABLED_DASH_A_OPTION);
328     }
329
330 }
331
Popular Tags