| /******************************************************************************* |
| * Copyright (c) 2006, 2007 IBM Corporation and others. |
| * 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: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.compiler.apt.dispatch; |
| |
| import javax.lang.model.element.Element; |
| import javax.lang.model.element.TypeElement; |
| |
| import org.eclipse.jdt.internal.compiler.ASTVisitor; |
| import org.eclipse.jdt.internal.compiler.apt.model.Factory; |
| import org.eclipse.jdt.internal.compiler.apt.util.ManyToMany; |
| import org.eclipse.jdt.internal.compiler.ast.ASTNode; |
| import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; |
| import org.eclipse.jdt.internal.compiler.ast.Annotation; |
| import org.eclipse.jdt.internal.compiler.ast.Argument; |
| import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration; |
| import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; |
| import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; |
| import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; |
| import org.eclipse.jdt.internal.compiler.lookup.AnnotationBinding; |
| import org.eclipse.jdt.internal.compiler.lookup.Binding; |
| import org.eclipse.jdt.internal.compiler.lookup.BlockScope; |
| import org.eclipse.jdt.internal.compiler.lookup.ClassScope; |
| import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope; |
| import org.eclipse.jdt.internal.compiler.lookup.MethodScope; |
| |
| /** |
| * This class is used to visit the JDT compiler internal AST to discover annotations, |
| * in the course of dispatching to annotation processors. |
| */ |
| public class AnnotationDiscoveryVisitor extends ASTVisitor { |
| final BaseProcessingEnvImpl _env; |
| final Factory _factory; |
| /** |
| * Collects a many-to-many map of annotation types to |
| * the elements they appear on. |
| */ |
| ManyToMany<TypeElement, Element> _annoToElement; |
| |
| public AnnotationDiscoveryVisitor(BaseProcessingEnvImpl env) { |
| _env = env; |
| _factory = env.getFactory(); |
| this._annoToElement = new ManyToMany<TypeElement, Element>(); |
| } |
| |
| @Override |
| public boolean visit(Argument argument, BlockScope scope) { |
| Annotation[] annotations = argument.annotations; |
| if (annotations != null) { |
| TypeDeclaration typeDeclaration = scope.referenceType(); |
| typeDeclaration.binding.resolveTypesFor(((AbstractMethodDeclaration) scope.referenceContext()).binding); |
| this.resolveAnnotations( |
| scope, |
| annotations, |
| argument.binding); |
| } |
| return false; |
| } |
| |
| @Override |
| public boolean visit(ConstructorDeclaration constructorDeclaration, ClassScope scope) { |
| Annotation[] annotations = constructorDeclaration.annotations; |
| if (annotations != null) { |
| this.resolveAnnotations( |
| constructorDeclaration.scope, |
| annotations, |
| constructorDeclaration.binding); |
| } |
| Argument[] arguments = constructorDeclaration.arguments; |
| if (arguments != null) { |
| int argumentLength = arguments.length; |
| for (int i = 0; i < argumentLength; i++) { |
| arguments[i].traverse(this, constructorDeclaration.scope); |
| } |
| } |
| return false; |
| } |
| |
| @Override |
| public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) { |
| Annotation[] annotations = fieldDeclaration.annotations; |
| if (annotations != null) { |
| this.resolveAnnotations(scope, annotations, fieldDeclaration.binding); |
| } |
| return false; |
| } |
| |
| @Override |
| public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) { |
| Annotation[] annotations = methodDeclaration.annotations; |
| if (annotations != null) { |
| this.resolveAnnotations( |
| methodDeclaration.scope, |
| annotations, |
| methodDeclaration.binding); |
| } |
| |
| Argument[] arguments = methodDeclaration.arguments; |
| if (arguments != null) { |
| int argumentLength = arguments.length; |
| for (int i = 0; i < argumentLength; i++) { |
| arguments[i].traverse(this, methodDeclaration.scope); |
| } |
| } |
| return false; |
| } |
| |
| @Override |
| public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope scope) { |
| Annotation[] annotations = memberTypeDeclaration.annotations; |
| if (annotations != null) { |
| this.resolveAnnotations( |
| memberTypeDeclaration.staticInitializerScope, |
| annotations, |
| memberTypeDeclaration.binding); |
| } |
| return true; |
| } |
| |
| @Override |
| public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope scope) { |
| Annotation[] annotations = typeDeclaration.annotations; |
| if (annotations != null) { |
| this.resolveAnnotations( |
| typeDeclaration.staticInitializerScope, |
| annotations, |
| typeDeclaration.binding); |
| } |
| return true; |
| } |
| |
| private void resolveAnnotations( |
| BlockScope scope, |
| Annotation[] annotations, |
| Binding currentBinding) { |
| ASTNode.resolveAnnotations(scope, annotations, currentBinding); |
| |
| for (Annotation annotation : annotations) { |
| AnnotationBinding binding = annotation.getCompilerAnnotation(); |
| if (binding != null) { // binding should be resolved, but in case it's not, ignore it |
| TypeElement anno = (TypeElement)_factory.newElement(binding.getAnnotationType()); |
| Element element = _factory.newElement(currentBinding); |
| _annoToElement.put(anno, element); |
| } |
| } |
| } |
| } |