/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
Java | 360 lines | 257 code | 49 blank | 54 comment | 31 complexity | 9a22f393cb68065b43adfd76fa14a3d7 MD5 | raw file
- /*******************************************************************************
- * Copyright (c) 2005, 2008 BEA Systems, Inc.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * tyeung@bea.com - initial API and implementation
- *******************************************************************************/
- package org.eclipse.jdt.apt.core.internal.env;
- import java.util.ArrayList;
- import java.util.Collection;
- import java.util.Collections;
- import java.util.HashMap;
- import java.util.HashSet;
- import java.util.List;
- import java.util.Map;
- import java.util.Set;
- import org.eclipse.core.resources.IFile;
- import org.eclipse.core.runtime.CoreException;
- import org.eclipse.core.runtime.IStatus;
- import org.eclipse.jdt.apt.core.env.EclipseAnnotationProcessorEnvironment;
- import org.eclipse.jdt.apt.core.env.Phase;
- import org.eclipse.jdt.apt.core.internal.AptPlugin;
- import org.eclipse.jdt.apt.core.internal.declaration.EclipseMirrorObject;
- import org.eclipse.jdt.apt.core.internal.declaration.TypeDeclarationImpl;
- import org.eclipse.jdt.apt.core.internal.env.MessagerImpl.Severity;
- import org.eclipse.jdt.apt.core.internal.util.Factory;
- import org.eclipse.jdt.apt.core.internal.util.Visitors.AnnotationVisitor;
- import org.eclipse.jdt.apt.core.util.AptPreferenceConstants;
- import org.eclipse.jdt.apt.core.util.EclipseMessager;
- import org.eclipse.jdt.core.ICompilationUnit;
- import org.eclipse.jdt.core.IJavaProject;
- import org.eclipse.jdt.core.JavaConventions;
- import org.eclipse.jdt.core.JavaCore;
- import org.eclipse.jdt.core.compiler.BuildContext;
- import org.eclipse.jdt.core.compiler.CategorizedProblem;
- import org.eclipse.jdt.core.compiler.ReconcileContext;
- import org.eclipse.jdt.core.dom.ASTRequestor;
- import org.eclipse.jdt.core.dom.Annotation;
- import org.eclipse.jdt.core.dom.CompilationUnit;
- import org.eclipse.jdt.core.dom.IBinding;
- import org.eclipse.jdt.core.dom.ITypeBinding;
- import com.sun.mirror.apt.AnnotationProcessorFactory;
- import com.sun.mirror.apt.AnnotationProcessorListener;
- import com.sun.mirror.apt.Filer;
- import com.sun.mirror.declaration.AnnotationTypeDeclaration;
- /** Base environment to be used during reconcile or build */
- public abstract class AbstractCompilationEnv
- extends BaseProcessorEnv
- implements EclipseAnnotationProcessorEnvironment {
-
- // Bugzilla 188185: accept "-AenableTypeGenerationInEditor" as well as "enableTypeGenerationInEditor".
- private final static String RTTG_ENABLED_DASH_A_OPTION = "-A" + AptPreferenceConstants.RTTG_ENABLED_OPTION; //$NON-NLS-1$
- private final static String PROCESSING_IN_EDITOR_DISABLED_DASH_A_OPTION = "-A" + AptPreferenceConstants.PROCESSING_IN_EDITOR_DISABLED_OPTION; //$NON-NLS-1$
-
- private Set<AnnotationProcessorListener> _listeners = null;
-
- protected List<APTProblem> _problems = new ArrayList<APTProblem>();
- private boolean _isClosed = false;
-
- EnvCallback _callback;
- private Set<IFile> _allGeneratedSourceFiles = new HashSet<IFile>();
- private Set<IFile> _modifiedGeneratedSourceFiles = new HashSet<IFile>();
- /**
- * Currently open dom pipeline, used to request type bindings.
- */
- protected ASTRequestor _requestor;
- /**
- * The processor that is currently being executed, or null if processing is not underway.
- */
- private AnnotationProcessorFactory _currentProcessorFactory = null;
- /**
- * True if the currently active processor will be called during reconcile as well as build.
- * Takes into account project settings, factory path, and processor options.
- */
- private boolean _currentProcessorFactoryWillReconcile;
-
- public static interface EnvCallback {
- public void run(AbstractCompilationEnv env);
- }
-
- public static void newReconcileEnv(ReconcileContext reconcileContext, EnvCallback callback)
- {
- assert reconcileContext != null : "reconcile context is null"; //$NON-NLS-1$
- ReconcileEnv env = ReconcileEnv.newEnv(reconcileContext);
- env._callback = callback;
- env.openPipeline();
- }
-
- public static void newBuildEnv(
- BuildContext[] filesWithAnnotations,
- final BuildContext[] additionalFiles,
- IJavaProject javaProj,
- EnvCallback callback)
- {
- assert filesWithAnnotations != null : "missing files"; //$NON-NLS-1$
-
- // note, we are not reading any files.
- BuildEnv env = new BuildEnv(filesWithAnnotations, additionalFiles, javaProj);
- env._callback = callback;
- env.createASTs(filesWithAnnotations);
- }
-
- /**
- * Determine whether a processor wants to be called during reconcile. By default
- * processors are called during both build and reconcile, but a processor can choose
- * not to be called during reconcile by reporting
- * {@link AptPreferenceConstants#PROCESSING_IN_EDITOR_DISABLED_OPTION}
- * in its supportedOptions() method.
- * @return false if the processor reports PROCESSING_IN_EDITOR_DISABLED_OPTION.
- * This does not consider project or factory path settings.
- */
- public static boolean doesFactorySupportReconcile(AnnotationProcessorFactory factory) {
- Collection<String> options = factory.supportedOptions();
- return options == null ||
- (!options.contains(AptPreferenceConstants.PROCESSING_IN_EDITOR_DISABLED_OPTION) &&
- !options.contains(PROCESSING_IN_EDITOR_DISABLED_DASH_A_OPTION));
- }
-
- AbstractCompilationEnv(
- CompilationUnit compilationUnit,
- IFile file,
- IJavaProject javaProj,
- Phase phase)
- {
- super(compilationUnit, file, javaProj, phase);
- }
-
- @Override
- protected IBinding getBindingFromKey(String key, ICompilationUnit unit) {
- return _requestor.createBindings(new String[] {key})[0];
- }
- public void addListener(AnnotationProcessorListener listener)
- {
- checkValid();
- if(_listeners == null )
- _listeners = new HashSet<AnnotationProcessorListener>();
- _listeners.add(listener);
- }
- public void removeListener(AnnotationProcessorListener listener)
- {
- checkValid();
- if( _listeners == null ) return;
- _listeners.remove(listener);
- }
- public Set<AnnotationProcessorListener> getProcessorListeners()
- {
- if( _listeners == null )
- return Collections.emptySet();
- // Return a copy, to avoid ConcurrentModificationException if a listener
- // removes itself in response to the callback.
- return new HashSet<AnnotationProcessorListener>(_listeners);
- }
-
- public Map<String, String> getOptions()
- {
- final HashMap<String, String> options = new HashMap<String, String>(_options);
- options.put("phase", getPhase().toString()); //$NON-NLS-1$
- return options;
- }
-
- abstract public CompilationUnit getASTFrom(final IFile file);
-
- public CompilationUnit getAST(){
- return _astRoot;
- }
-
- public EclipseMessager getMessager()
- {
- checkValid();
- return new MessagerImpl(this);
- }
-
- abstract void addMessage(
- IFile resource,
- int start,
- int end,
- Severity severity,
- String msg,
- int line,
- String[] arguments);
-
- public List<? extends CategorizedProblem> getProblems(){
- checkValid();
- if( !_problems.isEmpty() )
- EnvUtil.updateProblemLength(_problems, getAstCompilationUnit());
- return _problems;
- }
-
- APTProblem createProblem(
- IFile resource,
- int start,
- int end,
- Severity severity,
- String msg,
- int line,
- String[] arguments)
- {
- // end-1 since IProblem ending offsets are inclusive but DOM layer
- // ending offsets are exclusive.
- final APTProblem newProblem =
- new APTProblem(msg, severity, resource, start, end-1, line, arguments, !_currentProcessorFactoryWillReconcile);
- return newProblem;
- }
-
- public abstract Filer getFiler();
-
- public void addGeneratedSourceFile( IFile f, boolean contentsChanged ) {
- if (!f.toString().endsWith(".java")) { //$NON-NLS-1$
- throw new IllegalArgumentException("Source files must be java source files, and end with .java"); //$NON-NLS-1$
- }
-
- boolean addedToAll = _allGeneratedSourceFiles.add(f);
- boolean addedToMod = false;
- if (contentsChanged)
- addedToMod = _modifiedGeneratedSourceFiles.add(f);
- if (AptPlugin.DEBUG_COMPILATION_ENV) {
- AptPlugin.trace("add generated file " + f + " to env " + this + //$NON-NLS-1$ //$NON-NLS-2$
- "; addToAll = " + addedToAll + "; addToMod = " + addedToMod + //$NON-NLS-1$ //$NON-NLS-2$
- "; contentsChanged = " + contentsChanged); //$NON-NLS-1$
- }
- }
-
- public void addGeneratedNonSourceFile(final IFile file) {
- _allGeneratedSourceFiles.add(file);
- }
-
- public Set<IFile> getAllGeneratedFiles() {
- return _allGeneratedSourceFiles;
- }
-
- public Set<IFile> getModifiedGeneratedFiles() {
- return _modifiedGeneratedSourceFiles;
- }
- /**
- * @return true iff source files has been generated.
- * Always return false when this environment is closed.
- */
- public boolean hasGeneratedSourceFiles(){ return !_allGeneratedSourceFiles.isEmpty(); }
- /**
- * @return all annotation types in the current compilation unit.
- */
- public Map<String, AnnotationTypeDeclaration> getAnnotationTypes()
- {
- checkValid();
- final List<Annotation> instances = new ArrayList<Annotation>();
- final Map<String, AnnotationTypeDeclaration> decls =
- new HashMap<String, AnnotationTypeDeclaration>();
- final AnnotationVisitor visitor = new AnnotationVisitor(instances);
- _astRoot.accept(visitor);
-
- for (int instanceIndex=0, size = instances.size(); instanceIndex < size; instanceIndex++) {
- final Annotation instance = instances.get(instanceIndex);
- final ITypeBinding annoType = instance.resolveTypeBinding();
- if (annoType == null)
- continue;
- final TypeDeclarationImpl decl =
- Factory.createReferenceType(annoType, this);
- if (decl != null && decl.kind() == EclipseMirrorObject.MirrorKind.TYPE_ANNOTATION){
- final AnnotationTypeDeclaration annoDecl = (AnnotationTypeDeclaration)decl;
- decls.put(annoDecl.getQualifiedName(), annoDecl);
- }
- }
-
- return decls;
- }
-
- /* package */ void checkValid()
- {
- if( _isClosed )
- throw new IllegalStateException("Environment has expired"); //$NON-NLS-1$
- }
-
- // Call this after each file; cf. BuildEnv#beginFileProcessing()
- protected void completedProcessing() {
- _modifiedGeneratedSourceFiles.clear();
- }
-
- public void close(){
- if (isClosed())
- return;
- if(_listeners != null)
- _listeners.clear();
- _problems = null;
- _typeCache.clear();
- _packageRootsCache = null;
- _isClosed = true;
- _callback = null;
- _requestor = null;
- _allGeneratedSourceFiles = null;
- _modifiedGeneratedSourceFiles = null;
- if (AptPlugin.DEBUG_COMPILATION_ENV) AptPlugin.trace(
- "closed env " + this); //$NON-NLS-1$
- }
-
- boolean isClosed(){ return _isClosed; }
- /**
- * Check typeName to ensure it doesn't contain any bogus characters.
- * @param typeName
- * @throws CoreException
- */
- @SuppressWarnings("unchecked")
- public void validateTypeName(String typeName) throws CoreException
- {
- Map<String, String> options = getJavaProject().getOptions(true);
- String sourceLevel = options.get(JavaCore.COMPILER_SOURCE);
- String complianceLevel = options.get(JavaCore.COMPILER_COMPLIANCE);
- IStatus status = JavaConventions.validateJavaTypeName(typeName, sourceLevel, complianceLevel);
- if (status.matches(IStatus.ERROR)) {
- throw new CoreException(status);
- }
- }
- public AnnotationProcessorFactory getCurrentProcessorFactory() {
- return _currentProcessorFactory;
- }
-
- /**
- * @param factory a processor factory, or null to indicate processing is over.
- * @param willReconcile true if the processor will be called during reconcile as well as during build,
- * taking into account project settings, factory path, and processor options.
- */
- public void setCurrentProcessorFactory(AnnotationProcessorFactory factory, boolean willReconcile)
- {
- _currentProcessorFactory = factory;
- _currentProcessorFactoryWillReconcile = willReconcile;
- }
- public boolean currentProcessorSupportsRTTG()
- {
- AnnotationProcessorFactory factory = getCurrentProcessorFactory();
- if (null == factory) {
- return false;
- }
- Collection<String> options = factory.supportedOptions();
- if (null == options) {
- return false;
- }
- return options.contains(AptPreferenceConstants.RTTG_ENABLED_OPTION) ||
- options.contains(RTTG_ENABLED_DASH_A_OPTION);
- }
- }