PageRenderTime 43ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/eclipse_SDK-3.7.1/plugins/org.eclipse.jdt.apt.core.source_3.3.500.v20110420-1015/org/eclipse/jdt/apt/core/internal/env/AbstractCompilationEnv.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 360 lines | 257 code | 49 blank | 54 comment | 31 complexity | 9a22f393cb68065b43adfd76fa14a3d7 MD5 | raw file
  1. /*******************************************************************************
  2. * Copyright (c) 2005, 2008 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. import java.util.ArrayList;
  13. import java.util.Collection;
  14. import java.util.Collections;
  15. import java.util.HashMap;
  16. import java.util.HashSet;
  17. import java.util.List;
  18. import java.util.Map;
  19. import java.util.Set;
  20. import org.eclipse.core.resources.IFile;
  21. import org.eclipse.core.runtime.CoreException;
  22. import org.eclipse.core.runtime.IStatus;
  23. import org.eclipse.jdt.apt.core.env.EclipseAnnotationProcessorEnvironment;
  24. import org.eclipse.jdt.apt.core.env.Phase;
  25. import org.eclipse.jdt.apt.core.internal.AptPlugin;
  26. import org.eclipse.jdt.apt.core.internal.declaration.EclipseMirrorObject;
  27. import org.eclipse.jdt.apt.core.internal.declaration.TypeDeclarationImpl;
  28. import org.eclipse.jdt.apt.core.internal.env.MessagerImpl.Severity;
  29. import org.eclipse.jdt.apt.core.internal.util.Factory;
  30. import org.eclipse.jdt.apt.core.internal.util.Visitors.AnnotationVisitor;
  31. import org.eclipse.jdt.apt.core.util.AptPreferenceConstants;
  32. import org.eclipse.jdt.apt.core.util.EclipseMessager;
  33. import org.eclipse.jdt.core.ICompilationUnit;
  34. import org.eclipse.jdt.core.IJavaProject;
  35. import org.eclipse.jdt.core.JavaConventions;
  36. import org.eclipse.jdt.core.JavaCore;
  37. import org.eclipse.jdt.core.compiler.BuildContext;
  38. import org.eclipse.jdt.core.compiler.CategorizedProblem;
  39. import org.eclipse.jdt.core.compiler.ReconcileContext;
  40. import org.eclipse.jdt.core.dom.ASTRequestor;
  41. import org.eclipse.jdt.core.dom.Annotation;
  42. import org.eclipse.jdt.core.dom.CompilationUnit;
  43. import org.eclipse.jdt.core.dom.IBinding;
  44. import org.eclipse.jdt.core.dom.ITypeBinding;
  45. import com.sun.mirror.apt.AnnotationProcessorFactory;
  46. import com.sun.mirror.apt.AnnotationProcessorListener;
  47. import com.sun.mirror.apt.Filer;
  48. import com.sun.mirror.declaration.AnnotationTypeDeclaration;
  49. /** Base environment to be used during reconcile or build */
  50. public abstract class AbstractCompilationEnv
  51. extends BaseProcessorEnv
  52. implements EclipseAnnotationProcessorEnvironment {
  53. // Bugzilla 188185: accept "-AenableTypeGenerationInEditor" as well as "enableTypeGenerationInEditor".
  54. private final static String RTTG_ENABLED_DASH_A_OPTION = "-A" + AptPreferenceConstants.RTTG_ENABLED_OPTION; //$NON-NLS-1$
  55. private final static String PROCESSING_IN_EDITOR_DISABLED_DASH_A_OPTION = "-A" + AptPreferenceConstants.PROCESSING_IN_EDITOR_DISABLED_OPTION; //$NON-NLS-1$
  56. private Set<AnnotationProcessorListener> _listeners = null;
  57. protected List<APTProblem> _problems = new ArrayList<APTProblem>();
  58. private boolean _isClosed = false;
  59. EnvCallback _callback;
  60. private Set<IFile> _allGeneratedSourceFiles = new HashSet<IFile>();
  61. private Set<IFile> _modifiedGeneratedSourceFiles = new HashSet<IFile>();
  62. /**
  63. * Currently open dom pipeline, used to request type bindings.
  64. */
  65. protected ASTRequestor _requestor;
  66. /**
  67. * The processor that is currently being executed, or null if processing is not underway.
  68. */
  69. private AnnotationProcessorFactory _currentProcessorFactory = null;
  70. /**
  71. * True if the currently active processor will be called during reconcile as well as build.
  72. * Takes into account project settings, factory path, and processor options.
  73. */
  74. private boolean _currentProcessorFactoryWillReconcile;
  75. public static interface EnvCallback {
  76. public void run(AbstractCompilationEnv env);
  77. }
  78. public static void newReconcileEnv(ReconcileContext reconcileContext, EnvCallback callback)
  79. {
  80. assert reconcileContext != null : "reconcile context is null"; //$NON-NLS-1$
  81. ReconcileEnv env = ReconcileEnv.newEnv(reconcileContext);
  82. env._callback = callback;
  83. env.openPipeline();
  84. }
  85. public static void newBuildEnv(
  86. BuildContext[] filesWithAnnotations,
  87. final BuildContext[] additionalFiles,
  88. IJavaProject javaProj,
  89. EnvCallback callback)
  90. {
  91. assert filesWithAnnotations != null : "missing files"; //$NON-NLS-1$
  92. // note, we are not reading any files.
  93. BuildEnv env = new BuildEnv(filesWithAnnotations, additionalFiles, javaProj);
  94. env._callback = callback;
  95. env.createASTs(filesWithAnnotations);
  96. }
  97. /**
  98. * Determine whether a processor wants to be called during reconcile. By default
  99. * processors are called during both build and reconcile, but a processor can choose
  100. * not to be called during reconcile by reporting
  101. * {@link AptPreferenceConstants#PROCESSING_IN_EDITOR_DISABLED_OPTION}
  102. * in its supportedOptions() method.
  103. * @return false if the processor reports PROCESSING_IN_EDITOR_DISABLED_OPTION.
  104. * This does not consider project or factory path settings.
  105. */
  106. public static boolean doesFactorySupportReconcile(AnnotationProcessorFactory factory) {
  107. Collection<String> options = factory.supportedOptions();
  108. return options == null ||
  109. (!options.contains(AptPreferenceConstants.PROCESSING_IN_EDITOR_DISABLED_OPTION) &&
  110. !options.contains(PROCESSING_IN_EDITOR_DISABLED_DASH_A_OPTION));
  111. }
  112. AbstractCompilationEnv(
  113. CompilationUnit compilationUnit,
  114. IFile file,
  115. IJavaProject javaProj,
  116. Phase phase)
  117. {
  118. super(compilationUnit, file, javaProj, phase);
  119. }
  120. @Override
  121. protected IBinding getBindingFromKey(String key, ICompilationUnit unit) {
  122. return _requestor.createBindings(new String[] {key})[0];
  123. }
  124. public void addListener(AnnotationProcessorListener listener)
  125. {
  126. checkValid();
  127. if(_listeners == null )
  128. _listeners = new HashSet<AnnotationProcessorListener>();
  129. _listeners.add(listener);
  130. }
  131. public void removeListener(AnnotationProcessorListener listener)
  132. {
  133. checkValid();
  134. if( _listeners == null ) return;
  135. _listeners.remove(listener);
  136. }
  137. public Set<AnnotationProcessorListener> getProcessorListeners()
  138. {
  139. if( _listeners == null )
  140. return Collections.emptySet();
  141. // Return a copy, to avoid ConcurrentModificationException if a listener
  142. // removes itself in response to the callback.
  143. return new HashSet<AnnotationProcessorListener>(_listeners);
  144. }
  145. public Map<String, String> getOptions()
  146. {
  147. final HashMap<String, String> options = new HashMap<String, String>(_options);
  148. options.put("phase", getPhase().toString()); //$NON-NLS-1$
  149. return options;
  150. }
  151. abstract public CompilationUnit getASTFrom(final IFile file);
  152. public CompilationUnit getAST(){
  153. return _astRoot;
  154. }
  155. public EclipseMessager getMessager()
  156. {
  157. checkValid();
  158. return new MessagerImpl(this);
  159. }
  160. abstract void addMessage(
  161. IFile resource,
  162. int start,
  163. int end,
  164. Severity severity,
  165. String msg,
  166. int line,
  167. String[] arguments);
  168. public List<? extends CategorizedProblem> getProblems(){
  169. checkValid();
  170. if( !_problems.isEmpty() )
  171. EnvUtil.updateProblemLength(_problems, getAstCompilationUnit());
  172. return _problems;
  173. }
  174. APTProblem createProblem(
  175. IFile resource,
  176. int start,
  177. int end,
  178. Severity severity,
  179. String msg,
  180. int line,
  181. String[] arguments)
  182. {
  183. // end-1 since IProblem ending offsets are inclusive but DOM layer
  184. // ending offsets are exclusive.
  185. final APTProblem newProblem =
  186. new APTProblem(msg, severity, resource, start, end-1, line, arguments, !_currentProcessorFactoryWillReconcile);
  187. return newProblem;
  188. }
  189. public abstract Filer getFiler();
  190. public void addGeneratedSourceFile( IFile f, boolean contentsChanged ) {
  191. if (!f.toString().endsWith(".java")) { //$NON-NLS-1$
  192. throw new IllegalArgumentException("Source files must be java source files, and end with .java"); //$NON-NLS-1$
  193. }
  194. boolean addedToAll = _allGeneratedSourceFiles.add(f);
  195. boolean addedToMod = false;
  196. if (contentsChanged)
  197. addedToMod = _modifiedGeneratedSourceFiles.add(f);
  198. if (AptPlugin.DEBUG_COMPILATION_ENV) {
  199. AptPlugin.trace("add generated file " + f + " to env " + this + //$NON-NLS-1$ //$NON-NLS-2$
  200. "; addToAll = " + addedToAll + "; addToMod = " + addedToMod + //$NON-NLS-1$ //$NON-NLS-2$
  201. "; contentsChanged = " + contentsChanged); //$NON-NLS-1$
  202. }
  203. }
  204. public void addGeneratedNonSourceFile(final IFile file) {
  205. _allGeneratedSourceFiles.add(file);
  206. }
  207. public Set<IFile> getAllGeneratedFiles() {
  208. return _allGeneratedSourceFiles;
  209. }
  210. public Set<IFile> getModifiedGeneratedFiles() {
  211. return _modifiedGeneratedSourceFiles;
  212. }
  213. /**
  214. * @return true iff source files has been generated.
  215. * Always return false when this environment is closed.
  216. */
  217. public boolean hasGeneratedSourceFiles(){ return !_allGeneratedSourceFiles.isEmpty(); }
  218. /**
  219. * @return all annotation types in the current compilation unit.
  220. */
  221. public Map<String, AnnotationTypeDeclaration> getAnnotationTypes()
  222. {
  223. checkValid();
  224. final List<Annotation> instances = new ArrayList<Annotation>();
  225. final Map<String, AnnotationTypeDeclaration> decls =
  226. new HashMap<String, AnnotationTypeDeclaration>();
  227. final AnnotationVisitor visitor = new AnnotationVisitor(instances);
  228. _astRoot.accept(visitor);
  229. for (int instanceIndex=0, size = instances.size(); instanceIndex < size; instanceIndex++) {
  230. final Annotation instance = instances.get(instanceIndex);
  231. final ITypeBinding annoType = instance.resolveTypeBinding();
  232. if (annoType == null)
  233. continue;
  234. final TypeDeclarationImpl decl =
  235. Factory.createReferenceType(annoType, this);
  236. if (decl != null && decl.kind() == EclipseMirrorObject.MirrorKind.TYPE_ANNOTATION){
  237. final AnnotationTypeDeclaration annoDecl = (AnnotationTypeDeclaration)decl;
  238. decls.put(annoDecl.getQualifiedName(), annoDecl);
  239. }
  240. }
  241. return decls;
  242. }
  243. /* package */ void checkValid()
  244. {
  245. if( _isClosed )
  246. throw new IllegalStateException("Environment has expired"); //$NON-NLS-1$
  247. }
  248. // Call this after each file; cf. BuildEnv#beginFileProcessing()
  249. protected void completedProcessing() {
  250. _modifiedGeneratedSourceFiles.clear();
  251. }
  252. public void close(){
  253. if (isClosed())
  254. return;
  255. if(_listeners != null)
  256. _listeners.clear();
  257. _problems = null;
  258. _typeCache.clear();
  259. _packageRootsCache = null;
  260. _isClosed = true;
  261. _callback = null;
  262. _requestor = null;
  263. _allGeneratedSourceFiles = null;
  264. _modifiedGeneratedSourceFiles = null;
  265. if (AptPlugin.DEBUG_COMPILATION_ENV) AptPlugin.trace(
  266. "closed env " + this); //$NON-NLS-1$
  267. }
  268. boolean isClosed(){ return _isClosed; }
  269. /**
  270. * Check typeName to ensure it doesn't contain any bogus characters.
  271. * @param typeName
  272. * @throws CoreException
  273. */
  274. @SuppressWarnings("unchecked")
  275. public void validateTypeName(String typeName) throws CoreException
  276. {
  277. Map<String, String> options = getJavaProject().getOptions(true);
  278. String sourceLevel = options.get(JavaCore.COMPILER_SOURCE);
  279. String complianceLevel = options.get(JavaCore.COMPILER_COMPLIANCE);
  280. IStatus status = JavaConventions.validateJavaTypeName(typeName, sourceLevel, complianceLevel);
  281. if (status.matches(IStatus.ERROR)) {
  282. throw new CoreException(status);
  283. }
  284. }
  285. public AnnotationProcessorFactory getCurrentProcessorFactory() {
  286. return _currentProcessorFactory;
  287. }
  288. /**
  289. * @param factory a processor factory, or null to indicate processing is over.
  290. * @param willReconcile true if the processor will be called during reconcile as well as during build,
  291. * taking into account project settings, factory path, and processor options.
  292. */
  293. public void setCurrentProcessorFactory(AnnotationProcessorFactory factory, boolean willReconcile)
  294. {
  295. _currentProcessorFactory = factory;
  296. _currentProcessorFactoryWillReconcile = willReconcile;
  297. }
  298. public boolean currentProcessorSupportsRTTG()
  299. {
  300. AnnotationProcessorFactory factory = getCurrentProcessorFactory();
  301. if (null == factory) {
  302. return false;
  303. }
  304. Collection<String> options = factory.supportedOptions();
  305. if (null == options) {
  306. return false;
  307. }
  308. return options.contains(AptPreferenceConstants.RTTG_ENABLED_OPTION) ||
  309. options.contains(RTTG_ENABLED_DASH_A_OPTION);
  310. }
  311. }