Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: f21dbbde5f838ddca3e9b69315d84d675690dbcf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*******************************************************************************
 * Copyright (c) 2007 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:
 *    wharley@bea.com - initial API and implementation
 *    
 *******************************************************************************/

package org.eclipse.jdt.internal.apt.pluggable.core.dispatch;

import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import javax.annotation.processing.Processor;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.apt.core.internal.AnnotationProcessorFactoryLoader;
import org.eclipse.jdt.apt.core.internal.IServiceFactory;
import org.eclipse.jdt.apt.core.internal.util.FactoryPath;
import org.eclipse.jdt.apt.core.internal.util.FactoryPath.Attributes;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.internal.apt.pluggable.core.Apt6Plugin;
import org.eclipse.jdt.internal.compiler.Compiler;
import org.eclipse.jdt.internal.compiler.apt.dispatch.BaseAnnotationProcessorManager;
import org.eclipse.jdt.internal.compiler.apt.dispatch.ProcessorInfo;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.core.CompilationUnitProblemFinder;
import org.eclipse.jdt.internal.core.builder.ICompilationUnitLocator;

/**
 * Java 6 annotation processor manager used when compiling within the IDE. 
 * @see org.eclipse.jdt.internal.compiler.apt.dispatch.BatchAnnotationProcessorManager
 */
public class IdeAnnotationProcessorManager extends BaseAnnotationProcessorManager {
	
	private IJavaProject _javaProject;
	private ICompilationUnitLocator _cuLocator;
	private Map<IServiceFactory, FactoryPath.Attributes> _processors;
	private Iterator<Entry<IServiceFactory, Attributes>> _processorIter;

	/**
	 * Initialize the processor manager for a particular project.  It is an error
	 * to initialize a manager more than once.
	 * 
	 * @param abstractImageBuilder must be an instanceof AbstractImageBuilder.
	 * (But it can't be prototyped that way because the abstract base class must
	 * compile without Eclipse platform code.)
	 * 
	 * @param javaProject must be an instanceof IJavaProject.  (But it can't be
	 * prototyped that way because the abstract base class must compile without
	 * Eclipse platform code.)
	 */
	@Override
	public void configureFromPlatform(Compiler compiler, Object compilationUnitLocator, Object javaProject) {
		_javaProject = (IJavaProject) javaProject;
		_cuLocator = (ICompilationUnitLocator) compilationUnitLocator;
		if (null != _processingEnv) {
			throw new IllegalStateException(
					"Calling configure() more than once on an AnnotationProcessorManager is not supported"); //$NON-NLS-1$
		}
		// If it's a CompilationUnitProblemFinder, we're in reconcile phase.  Else it's build.
		if (compiler instanceof CompilationUnitProblemFinder) {
			_processingEnv = new IdeReconcileProcessingEnvImpl(this, _javaProject, compiler);
		} else {
			_processingEnv = new IdeBuildProcessingEnvImpl(this, _javaProject, compiler);
		}
		if (Apt6Plugin.DEBUG) {
			Apt6Plugin.trace("Java 6 annotation processor manager initialized for compiler " + 
					compiler.toString() + " on project " + _javaProject.getElementName());
		}
	}

	/**
	 * If this project has a ProcessorPath defined, use it.  Else, construct
	 * one from the classpath.
	 */
	@Override
	public ProcessorInfo discoverNextProcessor() {
		// _processorIter gets initialized the first time through processAnnotations()
		if (_processorIter.hasNext()) {
			Entry<IServiceFactory, Attributes> entry = _processorIter.next();
			Processor p;
			try {
				p = (Processor)entry.getKey().newInstance();
				p.init(_processingEnv);
				ProcessorInfo pi = new ProcessorInfo(p);
				if (Apt6Plugin.DEBUG) {
					Apt6Plugin.trace("Discovered processor " + p.toString());
				}
				return pi;
			} catch (CoreException e) {
				Apt6Plugin.log(e, "Unable to create instance of annotation processor " + entry.getKey()); //$NON-NLS-1$
			}
		}
		return null;
	}

	@Override
	public void reportProcessorException(Processor p, Exception e) {
		Apt6Plugin.log(e, "Exception thrown by Java annotation processor " + p); //$NON-NLS-1$
	}

	/**
	 * @return an ICompilationUnit corresponding to the specified file.  In IDE mode this
	 * will be backed by an org.eclipse.jdt.internal.core.builder.SourceFile.
	 */
	public ICompilationUnit findCompilationUnit(IFile file) {
		return _cuLocator.fromIFile(file);
	}

	/**
	 * In IDE mode, we are able to determine whether there are no processors.  If that's the case,
	 * then we can avoid doing the work of walking the ASTs to search for annotations.  We still
	 * need to clean up no-longer-generated files when the factory path is changed, but the best
	 * way to do that is to force a clean build.
	 * @see BaseAnnotationProcessorManager#processAnnotations(CompilationUnitDeclaration[], boolean)
	 */
	@Override
	public void processAnnotations(CompilationUnitDeclaration[] units, ReferenceBinding[] referenceBindings, boolean isLastRound) {
		if (null == _processors ) {
			_processors = AnnotationProcessorFactoryLoader.getLoader().getJava6FactoriesAndAttributesForProject(_javaProject);
			_processorIter = _processors.entrySet().iterator();
		}
		if (!_processors.isEmpty()) {
			super.processAnnotations(units, referenceBindings, isLastRound);
		}
	}

}

Back to the top