org.aspectj.org.eclipse.jdt.internal.compiler.apt.dispatch.RoundDispatcher Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aspectjtools Show documentation
Show all versions of aspectjtools Show documentation
Tools from the AspectJ project
/*******************************************************************************
* Copyright (c) 2006, 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:
* [email protected] - initial API and implementation
*
*******************************************************************************/
package org.aspectj.org.eclipse.jdt.internal.compiler.apt.dispatch;
import java.io.PrintWriter;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
/**
* Manages context during a single round of annotation processing.
*/
public class RoundDispatcher {
private final Set _unclaimedAnnotations;
private final RoundEnvironment _roundEnv;
private final IProcessorProvider _provider;
private boolean _searchForStar = false;
private final PrintWriter _traceProcessorInfo;
private final PrintWriter _traceRounds;
/**
* Processors discovered so far. This list may grow during the
* course of a round, as additional processors are discovered.
*/
private final List _processors;
/**
* @param rootAnnotations a possibly empty but non-null set of annotations on the
* root compilation units of this round. A local copy of the set will be made, to
* avoid modifying the set passed in.
* @param traceProcessorInfo a PrintWriter that processor trace output will be sent
* to, or null if tracing is not desired.
* @param traceRounds
*/
public RoundDispatcher(
IProcessorProvider provider,
RoundEnvironment env,
Set rootAnnotations,
PrintWriter traceProcessorInfo,
PrintWriter traceRounds)
{
_provider = provider;
_processors = provider.getDiscoveredProcessors();
_roundEnv = env;
_unclaimedAnnotations = new HashSet(rootAnnotations);
_traceProcessorInfo = traceProcessorInfo;
_traceRounds = traceRounds;
}
/**
* Handle a complete round, dispatching to all appropriate processors.
*/
public void round()
{
if (null != _traceRounds) {
StringBuilder sbElements = new StringBuilder();
sbElements.append("\tinput files: {"); //$NON-NLS-1$
Iterator iElements = _roundEnv.getRootElements().iterator();
boolean hasNext = iElements.hasNext();
while (hasNext) {
sbElements.append(iElements.next());
hasNext = iElements.hasNext();
if (hasNext) {
sbElements.append(',');
}
}
sbElements.append('}');
_traceRounds.println(sbElements.toString());
StringBuilder sbAnnots = new StringBuilder();
sbAnnots.append("\tannotations: ["); //$NON-NLS-1$
Iterator iAnnots = _unclaimedAnnotations.iterator();
hasNext = iAnnots.hasNext();
while (hasNext) {
sbAnnots.append(iAnnots.next());
hasNext = iAnnots.hasNext();
if (hasNext) {
sbAnnots.append(',');
}
}
sbAnnots.append(']');
_traceRounds.println(sbAnnots.toString());
_traceRounds.println("\tlast round: " + _roundEnv.processingOver()); //$NON-NLS-1$
}
// If there are no root annotations, try to find a processor that claims "*"
_searchForStar = _unclaimedAnnotations.isEmpty();
// Iterate over all the already-found processors, giving each one a chance at the unclaimed
// annotations. If a processor is called at all, it is called on every subsequent round
// including the final round, but it may be called with an empty set of annotations.
for (ProcessorInfo pi : _processors) {
handleProcessor(pi);
}
// If there are any unclaimed annotations, or if there were no root annotations and
// we have not yet run into a processor that claimed "*", continue discovery.
while (_searchForStar || !_unclaimedAnnotations.isEmpty()) {
ProcessorInfo pi = _provider.discoverNextProcessor();
if (null == pi) {
// There are no more processors to be discovered.
break;
}
handleProcessor(pi);
}
// TODO: If !unclaimedAnnos.isEmpty(), issue a warning.
}
/**
* Evaluate a single processor. Depending on the unclaimed annotations,
* the annotations this processor supports, and whether it has already been
* called in a previous round, possibly call its process() method.
*/
private void handleProcessor(ProcessorInfo pi)
{
try {
Set annotationsToProcess = new HashSet();
boolean shouldCall = pi.computeSupportedAnnotations(
_unclaimedAnnotations, annotationsToProcess);
if (shouldCall) {
boolean claimed = pi._processor.process(annotationsToProcess, _roundEnv);
if (null != _traceProcessorInfo && !_roundEnv.processingOver()) {
StringBuilder sb = new StringBuilder();
sb.append("Processor "); //$NON-NLS-1$
sb.append(pi._processor.getClass().getName());
sb.append(" matches ["); //$NON-NLS-1$
Iterator i = annotationsToProcess.iterator();
boolean hasNext = i.hasNext();
while (hasNext) {
sb.append(i.next());
hasNext = i.hasNext();
if (hasNext) {
sb.append(' ');
}
}
sb.append("] and returns "); //$NON-NLS-1$
sb.append(claimed);
_traceProcessorInfo.println(sb.toString());
}
if (claimed) {
// The processor claimed its annotations.
_unclaimedAnnotations.removeAll(annotationsToProcess);
if (pi.supportsStar()) {
_searchForStar = false;
}
}
}
} catch (Exception e) {
// If a processor throws an exception (as opposed to reporting an error),
// report it and abort compilation by throwing AbortCompilation.
_provider.reportProcessorException(pi._processor, e);
}
}
}