Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 7fe708c072a6afdc2ec73b093efb9ecd110cfc84 (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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/*******************************************************************************
 * Copyright (c) 2007, 2018 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.compiler.apt.dispatch;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.jdt.internal.compiler.AbstractAnnotationProcessorManager;
import org.eclipse.jdt.internal.compiler.Compiler;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;

/**
 * This class is the central dispatch point for Java 6 annotation processing.
 * This is created and configured by the JDT core; specifics depend on how
 * compilation is being performed, ie from the command line, via the Tool
 * interface, or within the IDE.  This class manages the discovery of annotation
 * processors and other information spanning multiple rounds of processing;
 * context that is valid only within a single round is managed by
 * {@link RoundDispatcher}.  There may be multiple instances of this class;
 * there is in general one of these for every Compiler that has annotation
 * processing enabled.  Within the IDE there will typically be one for every
 * Java project, because each project potentially has a separate processor path.
 *  
 * TODO: do something useful with _supportedOptions and _supportedAnnotationTypes.
 */
public abstract class BaseAnnotationProcessorManager extends AbstractAnnotationProcessorManager 
		implements IProcessorProvider 
{

	protected PrintWriter _out;
	protected PrintWriter _err;
	protected BaseProcessingEnvImpl _processingEnv;
	protected boolean _isFirstRound = true;
	
	/**
	 * The list of processors that have been loaded so far.  A processor on this
	 * list has been initialized, but may not yet have been called to process().
	 */
	protected List<ProcessorInfo> _processors = new ArrayList<>();
	
	// Tracing
	protected boolean _printProcessorInfo = false;
	protected boolean _printRounds = false;
	protected int _round;
	
	/* (non-Javadoc)
	 * @see org.eclipse.jdt.internal.compiler.AbstractAnnotationProcessorManager#configure(org.eclipse.jdt.internal.compiler.batch.Main, java.lang.String[])
	 */
	@Override
	public void configure(Object batchCompiler, String[] options) {
		// Implemented by BatchAnnotationProcessorManager.
		throw new UnsupportedOperationException();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jdt.internal.compiler.AbstractAnnotationProcessorManager#configureFromPlatform(org.eclipse.jdt.internal.compiler.Compiler, java.lang.Object)
	 */
	@Override
	public void configureFromPlatform(Compiler compiler, Object compilationUnitLocator, Object javaProject, boolean isTestCode) {
		// Implemented by IdeAnnotationProcessorManager.
		throw new UnsupportedOperationException();
	}

	@Override
	public List<ProcessorInfo> getDiscoveredProcessors() {
		return _processors;
	}

	@Override
	public ICompilationUnit[] getDeletedUnits() {
		return _processingEnv.getDeletedUnits();
	}

	@Override
	public ICompilationUnit[] getNewUnits() {
		return _processingEnv.getNewUnits();
	}

	@Override
	public ReferenceBinding[] getNewClassFiles() {
		return _processingEnv.getNewClassFiles();
	}

	@Override
	public void reset() {
		_processingEnv.reset();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jdt.internal.compiler.AbstractAnnotationProcessorManager#setErr(java.io.PrintWriter)
	 */
	@Override
	public void setErr(PrintWriter err) {
		_err = err;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jdt.internal.compiler.AbstractAnnotationProcessorManager#setOut(java.io.PrintWriter)
	 */
	@Override
	public void setOut(PrintWriter out) {
		_out = out;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jdt.internal.compiler.AbstractAnnotationProcessorManager#setProcessors(java.lang.Object[])
	 */
	@Override
	public void setProcessors(Object[] processors) {
		// Only meaningful in batch mode.
		throw new UnsupportedOperationException();
	}

	/**
	 * A single "round" of processing, in the sense implied in
	 * {@link javax.annotation.processing.Processor}.
	 * <p>
	 * The Java 6 Processor spec contains ambiguities about how processors that support "*" are
	 * handled. Eclipse tries to match Sun's implementation in javac. What that actually does is
	 * analogous to inspecting the set of annotions found in the root units and adding an
	 * "imaginary" annotation if the set is empty. Processors are then called in order of discovery;
	 * for each processor, the intersection between the set of root annotations and the set of
	 * annotations the processor supports is calculated, and if it is non-empty, the processor is
	 * called. If the processor returns <code>true</code> then the intersection (including the
	 * imaginary annotation if one exists) is removed from the set of root annotations and the loop
	 * continues, until the set is empty. Of course, the imaginary annotation is not actually
	 * included in the set of annotations passed in to the processor. A processor's process() method
	 * is not called until its intersection set is non-empty, but thereafter it is called on every
	 * round. Note that even if a processor is not called in the first round, if it is called in
	 * subsequent rounds, it will be called in the order in which the processors were discovered,
	 * rather than being added to the end of the list.
	 */
	@Override
	public void processAnnotations(CompilationUnitDeclaration[] units, ReferenceBinding[] referenceBindings, boolean isLastRound) {
		RoundEnvImpl roundEnv = new RoundEnvImpl(units, referenceBindings, isLastRound, _processingEnv);
		if (_isFirstRound) {
			_isFirstRound = false;
		}
		PrintWriter traceProcessorInfo = _printProcessorInfo ? _out : null;
		PrintWriter traceRounds = _printRounds ? _out : null;
		if (traceRounds != null) {
			traceRounds.println("Round " + ++_round + ':'); //$NON-NLS-1$
		}
		RoundDispatcher dispatcher = new RoundDispatcher(
				this, roundEnv, roundEnv.getRootAnnotations(), traceProcessorInfo, traceRounds);
		dispatcher.round();
	}

}

Back to the top