| /******************************************************************************* |
| * Copyright (c) 2008 IONA Technologies PLC, Shane Clarke |
| * 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: |
| * IONA Technologies PLC - initial API and implementation |
| * Shane Clarke - Rewrote API |
| *******************************************************************************/ |
| package org.eclipse.jst.ws.annotations.core.utils; |
| |
| import java.lang.annotation.ElementType; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| 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.IProgressMonitor; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.jdt.core.IAnnotatable; |
| import org.eclipse.jdt.core.IAnnotation; |
| import org.eclipse.jdt.core.ICompilationUnit; |
| import org.eclipse.jdt.core.IField; |
| import org.eclipse.jdt.core.IJavaElement; |
| import org.eclipse.jdt.core.ILocalVariable; |
| import org.eclipse.jdt.core.IMemberValuePair; |
| import org.eclipse.jdt.core.IMethod; |
| import org.eclipse.jdt.core.IPackageDeclaration; |
| import org.eclipse.jdt.core.IType; |
| import org.eclipse.jdt.core.JavaCore; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jdt.core.Signature; |
| import org.eclipse.jdt.core.dom.AST; |
| import org.eclipse.jdt.core.dom.ASTNode; |
| import org.eclipse.jdt.core.dom.ASTParser; |
| import org.eclipse.jdt.core.dom.ASTVisitor; |
| import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; |
| import org.eclipse.jdt.core.dom.Annotation; |
| import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration; |
| import org.eclipse.jdt.core.dom.BodyDeclaration; |
| import org.eclipse.jdt.core.dom.BooleanLiteral; |
| import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor; |
| import org.eclipse.jdt.core.dom.CompilationUnit; |
| import org.eclipse.jdt.core.dom.EnumDeclaration; |
| import org.eclipse.jdt.core.dom.Expression; |
| import org.eclipse.jdt.core.dom.FieldDeclaration; |
| import org.eclipse.jdt.core.dom.IExtendedModifier; |
| import org.eclipse.jdt.core.dom.MemberValuePair; |
| import org.eclipse.jdt.core.dom.MethodDeclaration; |
| import org.eclipse.jdt.core.dom.Name; |
| import org.eclipse.jdt.core.dom.NormalAnnotation; |
| import org.eclipse.jdt.core.dom.PackageDeclaration; |
| import org.eclipse.jdt.core.dom.QualifiedName; |
| import org.eclipse.jdt.core.dom.SingleMemberAnnotation; |
| import org.eclipse.jdt.core.dom.SingleVariableDeclaration; |
| import org.eclipse.jdt.core.dom.StringLiteral; |
| import org.eclipse.jdt.core.dom.TypeDeclaration; |
| import org.eclipse.jdt.core.dom.VariableDeclarationFragment; |
| import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; |
| import org.eclipse.jdt.core.dom.rewrite.ImportRewrite; |
| import org.eclipse.jdt.core.dom.rewrite.ListRewrite; |
| import org.eclipse.jdt.ui.CodeStyleConfiguration; |
| import org.eclipse.jst.ws.annotations.core.AnnotationDefinition; |
| import org.eclipse.jst.ws.annotations.core.AnnotationsCorePlugin; |
| import org.eclipse.jst.ws.annotations.core.AnnotationsManager; |
| import org.eclipse.ltk.core.refactoring.Change; |
| import org.eclipse.ltk.core.refactoring.IUndoManager; |
| import org.eclipse.ltk.core.refactoring.RefactoringCore; |
| import org.eclipse.ltk.core.refactoring.RefactoringStatus; |
| import org.eclipse.ltk.core.refactoring.TextFileChange; |
| import org.eclipse.text.edits.MultiTextEdit; |
| import org.eclipse.text.edits.TextEdit; |
| |
| import com.sun.mirror.declaration.AnnotationMirror; |
| import com.sun.mirror.declaration.AnnotationTypeElementDeclaration; |
| import com.sun.mirror.declaration.AnnotationValue; |
| import com.sun.mirror.declaration.Declaration; |
| import com.sun.mirror.declaration.ParameterDeclaration; |
| |
| /** |
| * Utility class for adding, removing and updating annotations and member value pairs. |
| * <p> |
| * <strong>Provisional API:</strong> This class/interface is part of an interim API that is still under |
| * development and expected to change significantly before reaching stability. It is being made available at |
| * this early stage to solicit feedback from pioneering adopters on the understanding that any code that uses |
| * this API will almost certainly be broken (repeatedly) as the API evolves. |
| * </p> |
| */ |
| public final class AnnotationUtils { |
| |
| private AnnotationUtils() { |
| } |
| |
| /** |
| * Adds an import to the compilation unit of the given {@link IJavaElement}. |
| * @param javaElement the java element which is used to get the compilation unit to add the import to. |
| * The following types of java elements are supported: |
| * <li>IJavaElement.COMPILATION_UNIT</li> |
| * <li>IJavaElement.PACKAGE_DECLARATION</li> |
| * <li>IJavaElement.TYPE</li> |
| * <li>IJavaElement.FIELD</li> |
| * <li>IJavaElement.METHOD</li> |
| * <li>IJavaElement.LOCAL_VARIABLE</li> |
| * @param qualifiedName the import to add. |
| * @throws CoreException the exception is thrown if the import rewrite fails. |
| */ |
| public static void addImport(IJavaElement javaElement, String qualifiedName) throws CoreException { |
| TextFileChange change = new TextFileChange("Add Import", (IFile) javaElement.getResource()); |
| MultiTextEdit multiTextEdit = new MultiTextEdit(); |
| change.setEdit(multiTextEdit); |
| |
| TextEdit annotationEdit = AnnotationUtils.createAddImportTextEdit(javaElement, qualifiedName); |
| change.addEdit(annotationEdit); |
| applyChange(null, change); |
| } |
| |
| /** |
| * Removes an import from the compilation unit of the given {@link IJavaElement}. The import will not be removed if the |
| * import type is referenced on more than one annotatable element in the source code. This method |
| * is intended to be used in conjunction with {@link AnnotationUtils#removeAnnotation(IJavaElement, Annotation)}}. |
| * @param javaElement the java element which is used to get the compilation unit to remove the import from. |
| * The following types of java elements are supported: |
| * <li>IJavaElement.COMPILATION_UNIT</li> |
| * <li>IJavaElement.PACKAGE_DECLARATION</li> |
| * <li>IJavaElement.TYPE</li> |
| * <li>IJavaElement.FIELD</li> |
| * <li>IJavaElement.METHOD</li> |
| * <li>IJavaElement.LOCAL_VARIABLE</li> |
| * @param qualifiedName the import to remove. |
| * @throws CoreException the exception is thrown if the import rewrite fails. |
| */ |
| public static void removeImport(IJavaElement javaElement, String qualifiedName) throws CoreException { |
| TextFileChange change = new TextFileChange("Remove Import", (IFile) javaElement.getResource()); |
| MultiTextEdit multiTextEdit = new MultiTextEdit(); |
| change.setEdit(multiTextEdit); |
| |
| TextEdit annotationEdit = AnnotationUtils.createRemoveImportTextEdit(javaElement, qualifiedName); |
| change.addEdit(annotationEdit); |
| applyChange(null, change); |
| } |
| |
| /** |
| * Adds the given {@link Annotation} to the {@link IJavaElement}. |
| * @param javaElement the following types of java elements are supported: |
| * <li>IJavaElement.PACKAGE_DECLARATION</li> |
| * <li>IJavaElement.TYPE</li> |
| * <li>IJavaElement.FIELD</li> |
| * <li>IJavaElement.METHOD</li> |
| * <li>IJavaElement.LOCAL_VARIABLE</li> |
| * @param annotation the annotation to add. |
| * @throws JavaModelException A {@link JavaModelException} is thrown when the underlying compilation units |
| * buffer could not be accessed. |
| */ |
| public static void addAnnotation(IJavaElement javaElement, Annotation annotation) throws JavaModelException { |
| TextFileChange change = new TextFileChange("Add annotation", (IFile) javaElement.getResource()); |
| MultiTextEdit multiTextEdit = new MultiTextEdit(); |
| change.setEdit(multiTextEdit); |
| |
| TextEdit annotationEdit = AnnotationUtils.createAddAnnotationTextEdit(javaElement, annotation); |
| change.addEdit(annotationEdit); |
| applyChange(null, change); |
| } |
| |
| /** |
| * Removes the given {@link Annotation} from the {@link IJavaElement}. |
| * @param javaElement the following types of java elements are supported: |
| * <li>IJavaElement.PACKAGE_DECLARATION</li> |
| * <li>IJavaElement.TYPE</li> |
| * <li>IJavaElement.FIELD</li> |
| * <li>IJavaElement.METHOD</li> |
| * <li>IJavaElement.LOCAL_VARIABLE</li> |
| * @param annotation the annotation to remove. |
| * @throws JavaModelException A {@link JavaModelException} is thrown when the underlying compilation units |
| * buffer could not be accessed. |
| */ |
| public static void removeAnnotation(IJavaElement javaElement, Annotation annotation) throws JavaModelException { |
| TextFileChange change = new TextFileChange("Remove annotation", (IFile) javaElement.getResource()); |
| MultiTextEdit multiTextEdit = new MultiTextEdit(); |
| change.setEdit(multiTextEdit); |
| |
| TextEdit textEdit = AnnotationUtils.createRemoveAnnotationTextEdit(javaElement, annotation); |
| change.addEdit(textEdit); |
| applyChange(null, change); |
| } |
| |
| /** |
| * Adds the {@link MemberValuePair} to the {@link NormalAnnotation}. |
| * @param annotation the normal annotation to add the member value pair to. |
| * @param memberValuePair the member value pair to add. |
| * @throws JavaModelException A {@link JavaModelException} is thrown when the underlying compilation units |
| * buffer could not be accessed. |
| */ |
| public static void addMemberValuePair(NormalAnnotation annotation, MemberValuePair memberValuePair) throws JavaModelException { |
| if (annotation.getRoot() instanceof CompilationUnit) { |
| CompilationUnit compilationUnit = (CompilationUnit) annotation.getRoot(); |
| TextFileChange change = new TextFileChange("Add Member Value Pair", (IFile) compilationUnit.getJavaElement().getResource()); |
| MultiTextEdit multiTextEdit = new MultiTextEdit(); |
| change.setEdit(multiTextEdit); |
| |
| TextEdit annotationEdit = AnnotationUtils.createAddMemberValuePairTextEdit(annotation, memberValuePair); |
| change.addEdit(annotationEdit); |
| applyChange(null, change); |
| } |
| } |
| |
| /** |
| * Removes the {@link MemberValuePair} from the {@link NormalAnnotation}. |
| * @param annotation the normal annotation from which to remove the member value pair. |
| * @param memberValuePair the member value pair to remove. |
| * @throws JavaModelException A {@link JavaModelException} is thrown when the underlying compilation units |
| * buffer could not be accessed. |
| */ |
| public static void removeMemberValuePair(NormalAnnotation annotation, MemberValuePair memberValuePair) throws JavaModelException { |
| if (annotation.getRoot() instanceof CompilationUnit) { |
| CompilationUnit compilationUnit = (CompilationUnit) annotation.getRoot(); |
| TextFileChange change = new TextFileChange("Remove Member Value Pair", (IFile) compilationUnit.getJavaElement().getResource()); |
| MultiTextEdit multiTextEdit = new MultiTextEdit(); |
| change.setEdit(multiTextEdit); |
| |
| TextEdit annotationEdit = AnnotationUtils.createRemoveMemberValuePairTextEdit(annotation, memberValuePair); |
| change.addEdit(annotationEdit); |
| applyChange(null, change); |
| } |
| } |
| |
| /** |
| * Updates the {@link MemberValuePair} value with the given {@link ASTNode}. |
| * @param memberValuePair the member value pair to update. |
| * @param value the value to set. |
| * @throws JavaModelException A {@link JavaModelException} is thrown when the underlying compilation units |
| * buffer could not be accessed. |
| */ |
| public static void updateMemberValuePair(MemberValuePair memberValuePair, ASTNode value) throws JavaModelException { |
| if (memberValuePair.getRoot() instanceof CompilationUnit) { |
| CompilationUnit compilationUnit = (CompilationUnit) memberValuePair.getRoot(); |
| TextFileChange change = new TextFileChange("Update Member Value Pair", (IFile) compilationUnit.getJavaElement().getResource()); |
| MultiTextEdit multiTextEdit = new MultiTextEdit(); |
| change.setEdit(multiTextEdit); |
| |
| TextEdit annotationEdit = AnnotationUtils.createUpdateMemberValuePairTextEdit(memberValuePair, value); |
| change.addEdit(annotationEdit); |
| applyChange(null, change); |
| } |
| } |
| |
| /** |
| * Updates the value of the {@link SingleMemberAnnotation} with the given {@link ASTNode}. |
| * @param annotation the single member annotation to update. |
| * @param value the value to set. |
| * @throws JavaModelException A {@link JavaModelException} is thrown when the underlying compilation units |
| * buffer could not be accessed. |
| */ |
| public static void updateSingleMemberAnnotation(SingleMemberAnnotation annotation, ASTNode value) throws JavaModelException { |
| if (annotation.getRoot() instanceof CompilationUnit) { |
| CompilationUnit compilationUnit = (CompilationUnit) annotation.getRoot(); |
| TextFileChange change = new TextFileChange("Update Single Member Annotation", (IFile) compilationUnit.getJavaElement().getResource()); |
| MultiTextEdit multiTextEdit = new MultiTextEdit(); |
| change.setEdit(multiTextEdit); |
| |
| TextEdit annotationEdit = AnnotationUtils.createUpdateSingleMemberAnnotationTextEdit(annotation, value); |
| change.addEdit(annotationEdit); |
| applyChange(null, change); |
| } |
| } |
| |
| /** |
| * Creates a {@link TextEdit} object representing the add import change to the source code of the java elements compilation unit. |
| * The compilation unit itself is not modified. |
| * @param javaElement one of the following types of java element: |
| * <li>IJavaElement.COMPILATION_UNIT</li> |
| * <li>IJavaElement.PACKAGE_DECLARATION</li> |
| * <li>IJavaElement.TYPE</li> |
| * <li>IJavaElement.FIELD</li> |
| * <li>IJavaElement.METHOD</li> |
| * <li>IJavaElement.LOCAL_VARIABLE</li> |
| * <p> |
| * The java element will be used to create a {@link CompilationUnit} which will in turn be used to create an {@link ImportRewrite}. |
| * </p> |
| * @param qualifiedName the import to add. |
| * @return text edit object describing the add import changes. |
| * @throws CoreException the exception is thrown if the import rewrite fails. |
| */ |
| public static TextEdit createAddImportTextEdit(IJavaElement javaElement, String qualifiedName) throws CoreException { |
| CompilationUnit compilationUnit = getAST(getCompilationUnitFromJavaElement(javaElement), false); |
| ImportRewrite importRewrite = CodeStyleConfiguration.createImportRewrite(compilationUnit, true); |
| importRewrite.addImport(qualifiedName); |
| return importRewrite.rewriteImports(null); |
| } |
| |
| /** |
| * Creates a {@link TextEdit} object representing the remove import change to the source code of the java elements compilation unit. |
| * The compilation unit itself is not modified. No change will be recorded if the import type is referenced on more than one an annotatable |
| * element in the source code. This method should be called in conjunction with {@link AnnotationUtils#createRemoveAnnotationTextEdit(IJavaElement, Annotation)}}. |
| * @param javaElement one of the following types of java element: |
| * <li>IJavaElement.COMPILATION_UNIT</li> |
| * <li>IJavaElement.PACKAGE_DECLARATION</li> |
| * <li>IJavaElement.TYPE</li> |
| * <li>IJavaElement.FIELD</li> |
| * <li>IJavaElement.METHOD</li> |
| * <li>IJavaElement.LOCAL_VARIABLE</li> |
| * <p> |
| * The java element will be used to create a {@link CompilationUnit} which will in turn be used to create an {@link ImportRewrite}. |
| * </p> |
| * @param qualifiedName the annotation import to remove. |
| * @return text edit object describing the remove import changes. |
| * @throws CoreException the exception is thrown if the import rewrite fails. |
| */ |
| @SuppressWarnings("unchecked") |
| public static TextEdit createRemoveImportTextEdit(IJavaElement javaElement, String qualifiedName) throws CoreException { |
| CompilationUnit compilationUnit = getAST(getCompilationUnitFromJavaElement(javaElement), false); |
| ImportRewrite importRewrite = CodeStyleConfiguration.createImportRewrite(compilationUnit, true); |
| final String annotationSimpleName = qualifiedName.substring(qualifiedName.lastIndexOf(".") + 1); |
| final List<String> occurences = new ArrayList<String>(); |
| AnnotationDefinition annotationDefinition = AnnotationsManager.getAnnotationDefinitionForClass(qualifiedName); |
| annotationDefinition.setJavaProject(javaElement.getJavaProject()); |
| List<ElementType> elementTypes = Collections.emptyList(); |
| if (annotationDefinition != null) { |
| elementTypes = annotationDefinition.getAnnotationTypeTargets(); |
| } |
| for (ElementType elementType : elementTypes) { |
| if (elementType == ElementType.PACKAGE) { |
| compilationUnit.accept(new ASTVisitor() { |
| @Override |
| public boolean visit(PackageDeclaration packageDeclaration) { |
| countAnnotationOccurrences(packageDeclaration.annotations(), |
| annotationSimpleName, occurences); |
| return false; |
| } |
| }); |
| } |
| if (elementType == ElementType.TYPE) { |
| compilationUnit.accept(new ASTVisitor() { |
| @Override |
| public boolean visit(TypeDeclaration typeDeclaration) { |
| countAnnotationOccurrences(typeDeclaration.modifiers(), |
| annotationSimpleName, occurences); |
| return false; |
| } |
| }); |
| } |
| if (elementType == ElementType.FIELD) { |
| compilationUnit.accept(new ASTVisitor() { |
| @Override |
| public boolean visit(FieldDeclaration fieldDeclaration) { |
| countAnnotationOccurrences( |
| fieldDeclaration.modifiers(), |
| annotationSimpleName, occurences); |
| return false; |
| } |
| }); |
| } |
| if (elementType == ElementType.METHOD) { |
| compilationUnit.accept(new ASTVisitor() { |
| @Override |
| public boolean visit(MethodDeclaration methodDeclaration) { |
| countAnnotationOccurrences(methodDeclaration |
| .modifiers(), annotationSimpleName, occurences); |
| return false; |
| } |
| }); |
| } |
| if (elementType == ElementType.PARAMETER) { |
| compilationUnit.accept(new ASTVisitor() { |
| @Override |
| public boolean visit( |
| SingleVariableDeclaration singleVariableDeclaration) { |
| countAnnotationOccurrences(singleVariableDeclaration |
| .modifiers(), annotationSimpleName, occurences); |
| return false; |
| } |
| }); |
| } |
| } |
| if (occurences.size() == 1) { |
| importRewrite.removeImport(qualifiedName); |
| } |
| // TODO Cleanup imports. Repeatedly adding and removing an import |
| // where none existed before will |
| // insert a new line on each insert. |
| return importRewrite.rewriteImports(null); |
| } |
| |
| private static void countAnnotationOccurrences(List<IExtendedModifier> modifiers, String annotationSimpleName, |
| List<String> occurences) { |
| for (IExtendedModifier extendedModifier : modifiers) { |
| if (extendedModifier instanceof Annotation) { |
| Annotation existingAnnotation = (Annotation) extendedModifier; |
| if (AnnotationUtils.getAnnotationName(existingAnnotation).equals(annotationSimpleName)) { |
| occurences.add(annotationSimpleName); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Creates a {@link TextEdit} object representing the add annotation change to the source code of the java elements compilation unit. |
| * The compilation unit itself is not modified. |
| * @param javaElement one of the following types of java element: |
| * <li>IJavaElement.PACKAGE_DECLARATION</li> |
| * <li>IJavaElement.TYPE</li> |
| * <li>IJavaElement.FIELD</li> |
| * <li>IJavaElement.METHOD</li> |
| * <li>IJavaElement.LOCAL_VARIABLE</li> |
| * @param annotation the annotation to add. |
| * @return text edit object describing the add annotation changes. Returns a {@link MultiTextEdit} if the given java element isn't supported. |
| * @throws JavaModelException A {@link JavaModelException} is thrown when the underlying compilation units |
| * buffer could not be accessed. |
| */ |
| public static TextEdit createAddAnnotationTextEdit(IJavaElement javaElement, Annotation annotation) throws JavaModelException { |
| switch(javaElement.getElementType()) { |
| case IJavaElement.PACKAGE_DECLARATION: |
| return createAddAnnotationTextEdit((IPackageDeclaration) javaElement, annotation); |
| case IJavaElement.TYPE: |
| return createAddAnnotationTextEdit((IType) javaElement, annotation); |
| case IJavaElement.FIELD: |
| return createAddAnnotationTextEdit((IField) javaElement, annotation); |
| case IJavaElement.METHOD: |
| return createAddAnnotationTextEdit((IMethod) javaElement, annotation); |
| case IJavaElement.LOCAL_VARIABLE: |
| return createAddAnnotationTextEdit((ILocalVariable) javaElement, annotation); |
| default: |
| return new MultiTextEdit(); |
| } |
| } |
| |
| /** |
| * Creates a {@link TextEdit} object representing the remove annotation change to the source code of the java elements compilation unit. |
| * The compilation unit itself is not modified. |
| * @param javaElement one of the following types of java element: |
| * <li>IJavaElement.PACKAGE_DECLARATION</li> |
| * <li>IJavaElement.TYPE</li> |
| * <li>IJavaElement.FIELD</li> |
| * <li>IJavaElement.METHOD</li> |
| * <li>IJavaElement.LOCAL_VARIABLE</li> |
| * @param annotation the annotation to add. |
| * @return text edit object describing the add annotation changes. Returns a {@link MultiTextEdit} if the given java element isn't supported. |
| * @throws JavaModelException A {@link JavaModelException} is thrown when the underlying compilation units |
| * buffer could not be accessed. |
| */ |
| public static TextEdit createRemoveAnnotationTextEdit(IJavaElement javaElement, Annotation annotation) throws JavaModelException { |
| switch(javaElement.getElementType()) { |
| case IJavaElement.PACKAGE_DECLARATION: |
| return createRemoveAnnotationTextEdit((IPackageDeclaration) javaElement, annotation); |
| case IJavaElement.TYPE: |
| return createRemoveAnnotationTextEdit((IType) javaElement, annotation); |
| case IJavaElement.FIELD: |
| return createRemoveAnnotationTextEdit((IField) javaElement, annotation); |
| case IJavaElement.METHOD: |
| return createRemoveAnnotationTextEdit((IMethod) javaElement, annotation); |
| case IJavaElement.LOCAL_VARIABLE: |
| return createRemoveAnnotationTextEdit((ILocalVariable) javaElement, annotation); |
| default: |
| return new MultiTextEdit(); |
| } |
| } |
| |
| private static void applyChange(IProgressMonitor monitor, Change change) { |
| if (change == null) { |
| return; |
| } |
| |
| if (monitor == null) { |
| monitor = new NullProgressMonitor(); |
| } |
| |
| IUndoManager manager = RefactoringCore.getUndoManager(); |
| boolean successful = false; |
| Change undoChange = null; |
| try { |
| change.initializeValidationData(monitor); |
| RefactoringStatus valid = change.isValid(monitor); |
| if (valid.isOK()) { |
| manager.aboutToPerformChange(change); |
| undoChange = change.perform(monitor); |
| successful = true; |
| } |
| } catch (CoreException ce) { |
| AnnotationsCorePlugin.log(ce.getStatus()); |
| } finally { |
| manager.changePerformed(change, successful); |
| } |
| if (undoChange != null) { |
| undoChange.initializeValidationData(monitor); |
| manager.addUndo(undoChange.getName(), undoChange); |
| } |
| } |
| |
| private static TextEdit createAddAnnotationTextEdit(IPackageDeclaration packageDeclaration, Annotation annotation) throws JavaModelException { |
| if (packageDeclaration != null && !isAnnotationPresent(packageDeclaration, AnnotationUtils.getAnnotationName(annotation))) { |
| ICompilationUnit source = getCompilationUnitFromJavaElement(packageDeclaration); |
| CompilationUnit compilationUnit = getAST(source, false); |
| ASTRewrite rewriter = ASTRewrite.create(compilationUnit.getAST()); |
| |
| ListRewrite listRewrite = rewriter.getListRewrite(compilationUnit.getPackage(), PackageDeclaration.ANNOTATIONS_PROPERTY); |
| |
| listRewrite.insertFirst(annotation, null); |
| |
| return rewriter.rewriteAST(); |
| } |
| return new MultiTextEdit(); |
| } |
| |
| private static TextEdit createRemoveAnnotationTextEdit(IPackageDeclaration packageDeclaration, Annotation annotation) throws JavaModelException { |
| if (packageDeclaration != null && isAnnotationPresent(packageDeclaration, getAnnotationName(annotation))) { |
| ICompilationUnit source = getCompilationUnitFromJavaElement(packageDeclaration); |
| CompilationUnit compilationUnit = getAST(source, false); |
| ASTRewrite rewriter = ASTRewrite.create(compilationUnit.getAST()); |
| |
| PackageDeclaration pkgDeclaration = compilationUnit.getPackage(); |
| |
| ListRewrite listRewrite = rewriter.getListRewrite(pkgDeclaration, PackageDeclaration.ANNOTATIONS_PROPERTY); |
| |
| @SuppressWarnings("rawtypes") |
| List originalList = listRewrite.getOriginalList(); |
| for (Object object : originalList) { |
| if (object instanceof Annotation && compareAnnotationNames((Annotation) object, annotation)) { |
| listRewrite.remove((Annotation) object, null); |
| } |
| } |
| return rewriter.rewriteAST(); |
| } |
| return new MultiTextEdit(); |
| } |
| |
| private static TextEdit createAddAnnotationTextEdit(IType type, Annotation annotation) throws JavaModelException { |
| AbstractTypeDeclaration typeDeclaration = getTypeDeclaration(type); |
| if(typeDeclaration != null && !isAnnotationPresent(type, annotation)) { |
| ASTRewrite rewriter = ASTRewrite.create(typeDeclaration.getAST()); |
| |
| ListRewrite listRewrite = rewriter.getListRewrite(typeDeclaration, getChildListPropertyDescriptorForType(typeDeclaration)); |
| |
| listRewrite.insertFirst(annotation, null); |
| |
| return rewriter.rewriteAST(); |
| } |
| return new MultiTextEdit(); |
| } |
| |
| private static TextEdit createRemoveAnnotationTextEdit(IType type, Annotation annotation) throws JavaModelException { |
| AbstractTypeDeclaration typeDeclaration = getTypeDeclaration(type); |
| if (typeDeclaration != null && isAnnotationPresent(type, annotation)) { |
| ASTRewrite rewriter = ASTRewrite.create(typeDeclaration.getAST()); |
| |
| ListRewrite listRewrite = rewriter.getListRewrite(typeDeclaration, getChildListPropertyDescriptorForType(typeDeclaration)); |
| |
| @SuppressWarnings("rawtypes") |
| List originalList = listRewrite.getOriginalList(); |
| for (Object object : originalList) { |
| if (object instanceof Annotation && compareAnnotationNames((Annotation)object, annotation)) { |
| listRewrite.remove((Annotation)object, null); |
| } |
| } |
| return rewriter.rewriteAST(); |
| } |
| return new MultiTextEdit(); |
| } |
| |
| private static TextEdit createAddAnnotationTextEdit(IMethod method, Annotation annotation) throws JavaModelException { |
| MethodDeclaration methodDeclaration = getMethodDeclaration(method); |
| if (methodDeclaration != null && !isAnnotationPresent(method, annotation)) { |
| ASTRewrite rewriter = ASTRewrite.create(methodDeclaration.getAST()); |
| |
| ListRewrite listRewrite = rewriter.getListRewrite(methodDeclaration, MethodDeclaration.MODIFIERS2_PROPERTY); |
| |
| listRewrite.insertAt(annotation, 0, null); |
| |
| return rewriter.rewriteAST(); |
| } |
| return new MultiTextEdit(); |
| } |
| |
| private static TextEdit createRemoveAnnotationTextEdit(IMethod method, Annotation annotation) throws JavaModelException { |
| MethodDeclaration methodDeclaration = getMethodDeclaration(method); |
| if (methodDeclaration != null && isAnnotationPresent(method, annotation)) { |
| ASTRewrite rewriter = ASTRewrite.create(methodDeclaration.getAST()); |
| |
| ListRewrite listRewrite = rewriter.getListRewrite(methodDeclaration, MethodDeclaration.MODIFIERS2_PROPERTY); |
| |
| @SuppressWarnings("rawtypes") |
| List originalList = listRewrite.getOriginalList(); |
| for (Object object : originalList) { |
| if (object instanceof Annotation && compareAnnotationNames((Annotation) object, annotation)) { |
| listRewrite.remove((Annotation) object, null); |
| } |
| } |
| return rewriter.rewriteAST(); |
| } |
| return new MultiTextEdit(); |
| } |
| |
| private static TextEdit createAddAnnotationTextEdit(IField field, Annotation annotation) throws JavaModelException { |
| FieldDeclaration fieldDeclaration = getFieldDeclaration(field); |
| if (fieldDeclaration != null && !isAnnotationPresent(field, annotation)) { |
| |
| ASTRewrite rewriter = ASTRewrite.create(fieldDeclaration.getAST()); |
| |
| ListRewrite listRewrite = rewriter.getListRewrite(fieldDeclaration, FieldDeclaration.MODIFIERS2_PROPERTY); |
| listRewrite.insertAt(annotation, 0, null); |
| |
| return rewriter.rewriteAST(); |
| } |
| |
| return new MultiTextEdit(); |
| } |
| |
| private static TextEdit createRemoveAnnotationTextEdit(IField field, Annotation annotation) throws JavaModelException { |
| FieldDeclaration fieldDeclaration = getFieldDeclaration(field); |
| if (fieldDeclaration != null && isAnnotationPresent(field, annotation)) { |
| ASTRewrite rewriter = ASTRewrite.create(fieldDeclaration.getAST()); |
| |
| ListRewrite listRewrite = rewriter.getListRewrite(fieldDeclaration, FieldDeclaration.MODIFIERS2_PROPERTY); |
| |
| @SuppressWarnings("rawtypes") |
| List originalList = listRewrite.getOriginalList(); |
| for (Object object : originalList) { |
| if (object instanceof Annotation && compareAnnotationNames((Annotation) object, annotation)) { |
| listRewrite.remove((Annotation) object, null); |
| } |
| } |
| return rewriter.rewriteAST(); |
| } |
| return new MultiTextEdit(); |
| } |
| |
| private static TextEdit createAddAnnotationTextEdit(ILocalVariable methodParameter, Annotation annotation) throws JavaModelException { |
| SingleVariableDeclaration parameter = getSingleVariableDeclaration(methodParameter); |
| if (parameter != null && !isAnnotationPresent(methodParameter, AnnotationUtils.getAnnotationName(annotation))) { |
| ASTRewrite rewriter = ASTRewrite.create(parameter.getAST()); |
| |
| ListRewrite listRewrite = rewriter.getListRewrite(parameter, SingleVariableDeclaration.MODIFIERS2_PROPERTY); |
| |
| listRewrite.insertAt(annotation, -1, null); |
| |
| return rewriter.rewriteAST(); |
| } |
| return new MultiTextEdit(); |
| } |
| |
| private static TextEdit createRemoveAnnotationTextEdit(ILocalVariable methodParameter, Annotation annotation) throws JavaModelException { |
| SingleVariableDeclaration parameter = getSingleVariableDeclaration(methodParameter); |
| if (isAnnotationPresent(methodParameter, AnnotationUtils.getAnnotationName(annotation))) { |
| ASTRewrite rewriter = ASTRewrite.create(parameter.getAST()); |
| |
| ListRewrite listRewrite = rewriter.getListRewrite(parameter, SingleVariableDeclaration.MODIFIERS2_PROPERTY); |
| |
| @SuppressWarnings("rawtypes") |
| List originalList = listRewrite.getOriginalList(); |
| for (Object object : originalList) { |
| if (object instanceof Annotation && compareAnnotationNames((Annotation)object, annotation)) { |
| listRewrite.remove((Annotation)object, null); |
| } |
| } |
| |
| return rewriter.rewriteAST(); |
| } |
| return new MultiTextEdit(); |
| } |
| |
| /** |
| * Creates a {@link TextEdit} object representing the change of adding the {@link MemberValuePair} to the {@link NormalAnnotation}. |
| * The underlying compilation unit itself is not modified. |
| * @param annotation the normal annotation to add the member value pair to. |
| * @param memberValuePair the member value pair to add. |
| * @return text edit object describing the add member value pair change. |
| * @throws JavaModelException A {@link JavaModelException} is thrown when |
| * the underlying compilation units buffer could not be accessed. |
| */ |
| public static TextEdit createAddMemberValuePairTextEdit(NormalAnnotation annotation, MemberValuePair memberValuePair) throws JavaModelException { |
| ASTRewrite rewriter = ASTRewrite.create(annotation.getAST()); |
| |
| ListRewrite listRewrite = rewriter.getListRewrite(annotation, NormalAnnotation.VALUES_PROPERTY); |
| |
| listRewrite.insertLast(memberValuePair, null); |
| |
| return rewriter.rewriteAST(); |
| } |
| |
| /** |
| * Creates a {@link TextEdit} object representing the change of removing the {@link MemberValuePair} from the {@link NormalAnnotation}. |
| * The underlying compilation unit itself is not modified. |
| * @param annotation the normal annotation to remove the member value pair from. |
| * @param memberValuePair the member value pair to remove. |
| * @return text edit object describing the remove member value pair change. |
| * @throws JavaModelException A {@link JavaModelException} is thrown when |
| * the underlying compilation units buffer could not be accessed. |
| */ |
| public static TextEdit createRemoveMemberValuePairTextEdit(NormalAnnotation annotation, MemberValuePair memberValuePair) throws JavaModelException { |
| ASTRewrite rewriter = ASTRewrite.create(annotation.getAST()); |
| |
| ListRewrite listRewrite = rewriter.getListRewrite(annotation, NormalAnnotation.VALUES_PROPERTY); |
| |
| @SuppressWarnings("rawtypes") |
| List originalList = listRewrite.getOriginalList(); |
| for (Object object : originalList) { |
| if (object instanceof MemberValuePair) { |
| MemberValuePair mvp = (MemberValuePair) object; |
| if (mvp.getName().getIdentifier().equals(memberValuePair.getName().getIdentifier())) { |
| listRewrite.remove(mvp, null); |
| } |
| } |
| } |
| return rewriter.rewriteAST(); |
| } |
| |
| /** |
| * Creates a {@link TextEdit} object representing the change of updating the {@link MemberValuePair} with the {@link ASTNode} value. |
| * The underlying compilation unit itself is not modified. |
| * @param memberValuePair the member value pair to update. |
| * @param value the value to set. |
| * @return text edit object describing the update member value pair change. |
| * @throws JavaModelException A {@link JavaModelException} is thrown when |
| * the underlying compilation units buffer could not be accessed. |
| */ |
| public static TextEdit createUpdateMemberValuePairTextEdit(MemberValuePair memberValuePair, ASTNode value) throws JavaModelException { |
| ASTRewrite rewriter = ASTRewrite.create(memberValuePair.getAST()); |
| |
| rewriter.set(memberValuePair, MemberValuePair.VALUE_PROPERTY, value, null); |
| |
| return rewriter.rewriteAST(); |
| } |
| |
| /** |
| * Creates a {@link TextEdit} object representing the change of updating the {@link SingleMemberAnnotation} with the {@link ASTNode} value. |
| * The underlying compilation unit itself is not modified. |
| * @param annotation the single memeber annotation to update. |
| * @param value the value to set. |
| * @return text edit object describing the update single member annotation change. |
| * @throws JavaModelException A {@link JavaModelException} is thrown when |
| * the underlying compilation units buffer could not be accessed. |
| */ |
| public static TextEdit createUpdateSingleMemberAnnotationTextEdit(SingleMemberAnnotation annotation, ASTNode value) throws JavaModelException { |
| ASTRewrite rewriter = ASTRewrite.create(annotation.getAST()); |
| |
| rewriter.set(annotation, SingleMemberAnnotation.VALUE_PROPERTY, value, null); |
| |
| return rewriter.rewriteAST(); |
| } |
| |
| /** |
| * Returns a {@link ICompilationUnit} for the given {@link IJavaElement}. |
| * @param javaElement one of the following types of java element: |
| * <li>IJavaElement.COMPILATION_UNIT</li> |
| * <li>IJavaElement.PACKAGE_DECLARATION</li> |
| * <li>IJavaElement.TYPE</li> |
| * <li>IJavaElement.FIELD</li> |
| * <li>IJavaElement.METHOD</li> |
| * <li>IJavaElement.LOCAL_VARIABLE</li> |
| * @return a compilation unit. |
| */ |
| public static ICompilationUnit getCompilationUnitFromJavaElement(IJavaElement javaElement) { |
| switch(javaElement.getElementType()) { |
| case IJavaElement.COMPILATION_UNIT: |
| return (ICompilationUnit) javaElement; |
| case IJavaElement.PACKAGE_DECLARATION: |
| IPackageDeclaration packageDeclaration = (IPackageDeclaration) javaElement; |
| return (ICompilationUnit) packageDeclaration.getParent(); |
| case IJavaElement.TYPE: |
| IType type = (IType) javaElement; |
| return type.getCompilationUnit(); |
| case IJavaElement.METHOD: |
| IMethod method = (IMethod) javaElement; |
| return method.getCompilationUnit(); |
| case IJavaElement.FIELD: |
| IField field = (IField) javaElement; |
| return field.getCompilationUnit(); |
| case IJavaElement.LOCAL_VARIABLE: |
| ILocalVariable localVariable = (ILocalVariable) javaElement; |
| if (localVariable.getParent() instanceof IMethod) { |
| return getCompilationUnitFromJavaElement(localVariable.getParent()); |
| } |
| default: |
| return JavaCore.createCompilationUnitFrom((IFile) javaElement.getResource()); |
| } |
| } |
| |
| /** |
| * Returns the {@link AbstractTypeDeclaration} that corresponds to the given {@link IType}. |
| * @param type the type. |
| * @return a type declaration or null if not found. |
| */ |
| @SuppressWarnings("unchecked") |
| public static AbstractTypeDeclaration getTypeDeclaration(IType type) { |
| CompilationUnit compilationUnit = getAST(type.getCompilationUnit(), false); |
| List<TypeDeclaration> types = compilationUnit.types(); |
| for (AbstractTypeDeclaration abstractTypeDeclaration : types) { |
| if (compareTypeNames(abstractTypeDeclaration, type)) { |
| return abstractTypeDeclaration; |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the {@link MethodDeclaration} that corresponds to the given {@link IMethod}. |
| * @param method the method |
| * @return a method declaration or null if not found. |
| */ |
| @SuppressWarnings("unchecked") |
| public static MethodDeclaration getMethodDeclaration(IMethod method) { |
| AbstractTypeDeclaration typeDeclaration = getTypeDeclaration(method.getDeclaringType()); |
| if (typeDeclaration != null) { |
| List<BodyDeclaration> bodyDeclarations = typeDeclaration.bodyDeclarations(); |
| for (BodyDeclaration bodyDeclaration : bodyDeclarations) { |
| if (bodyDeclaration instanceof MethodDeclaration) { |
| MethodDeclaration methodDeclaration = (MethodDeclaration) bodyDeclaration; |
| if (compareMethods(methodDeclaration, method)) { |
| return methodDeclaration; |
| } |
| } |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the {@link FieldDeclaration} that corresponds to the given {@link IField}. |
| * @param field the field |
| * @return a field declaration or null if not found. |
| */ |
| @SuppressWarnings("unchecked") |
| public static FieldDeclaration getFieldDeclaration(IField field) { |
| AbstractTypeDeclaration typeDeclaration = getTypeDeclaration(field.getDeclaringType()); |
| if (typeDeclaration != null) { |
| List<BodyDeclaration> bodyDeclarations = typeDeclaration.bodyDeclarations(); |
| for (BodyDeclaration bodyDeclaration : bodyDeclarations) { |
| if (bodyDeclaration instanceof FieldDeclaration) { |
| FieldDeclaration fieldDeclaration = (FieldDeclaration) bodyDeclaration; |
| if (compareFieldNames(fieldDeclaration, field)) { |
| return fieldDeclaration; |
| } |
| } |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the {@link SingleVariableDeclaration} that corresponds to the given {@link ILocalVariable}. |
| * @param javaElement the local variable |
| * @return a single variable declaration or null if not found. |
| */ |
| public static SingleVariableDeclaration getSingleVariableDeclaration(ILocalVariable javaElement) { |
| if (javaElement instanceof ILocalVariable && javaElement.getParent() instanceof IMethod) { |
| ILocalVariable localVariable = javaElement; |
| IMethod method = (IMethod) localVariable.getParent(); |
| MethodDeclaration methodDeclaration = getMethodDeclaration(method); |
| |
| @SuppressWarnings("unchecked") |
| List<SingleVariableDeclaration> parameters = methodDeclaration.parameters(); |
| for (SingleVariableDeclaration singleVariableDeclaration : parameters) { |
| if (singleVariableDeclaration.getName().getIdentifier().equals(localVariable.getElementName())) { |
| return singleVariableDeclaration; |
| } |
| } |
| } |
| return null; |
| } |
| |
| private static ChildListPropertyDescriptor getChildListPropertyDescriptorForType(AbstractTypeDeclaration |
| abstractTypeDeclaration) { |
| ChildListPropertyDescriptor childListPropertyDescriptor = null; |
| if (abstractTypeDeclaration instanceof TypeDeclaration) { |
| childListPropertyDescriptor = TypeDeclaration.MODIFIERS2_PROPERTY; |
| } |
| if (abstractTypeDeclaration instanceof EnumDeclaration) { |
| childListPropertyDescriptor = EnumDeclaration.MODIFIERS2_PROPERTY; |
| } |
| if (abstractTypeDeclaration instanceof AnnotationTypeDeclaration) { |
| childListPropertyDescriptor = AnnotationTypeDeclaration.MODIFIERS2_PROPERTY; |
| } |
| return childListPropertyDescriptor; |
| } |
| |
| /** |
| * Returns the annotations type name. If the annotation name is a simple name, the result is the |
| * name's identifier. If the name is a qualified name, the result is the name of the qualifier |
| * followed by "." followed by the name's identifier. |
| |
| * @param annotation the annotation. |
| * @return the annotation name. The simple name or the fully qualified name. |
| */ |
| public static String getAnnotationName(Annotation annotation) { |
| Name annotationTypeName = annotation.getTypeName(); |
| return annotationTypeName.getFullyQualifiedName(); |
| } |
| |
| /** |
| * Compares the {@link AbstractTypeDeclaration} and {@link IType}. |
| * @param abstractTypeDeclaration the type declaration. |
| * @param type the type. |
| * @return <code>true</code> if the names match. |
| */ |
| public static boolean compareTypeNames(AbstractTypeDeclaration abstractTypeDeclaration, IType type) { |
| return abstractTypeDeclaration.getName().getIdentifier().equals(type.getElementName()); |
| } |
| |
| /** |
| * Compares the {@link MethodDeclaration} and {@link IMethod}. |
| * @param methodDeclaration the method declaration. |
| * @param method the method. |
| * @return <code>true</code> if the method names and parameter types match. |
| */ |
| @SuppressWarnings("unchecked") |
| public static boolean compareMethods(MethodDeclaration methodDeclaration, IMethod method) { |
| if (methodDeclaration.getName().getIdentifier().equals(method.getElementName())) { |
| String[] parametetTypes = method.getParameterTypes(); |
| List<SingleVariableDeclaration> methodDeclarationParameters = methodDeclaration.parameters(); |
| if (parametetTypes.length == methodDeclarationParameters.size()) { |
| for (int i = 0; i < parametetTypes.length; i++) { |
| String simpleName1 = Signature.toString(parametetTypes[i]); |
| String simpleName2 = methodDeclarationParameters.get(i).getType().toString(); |
| if (!simpleName1.equals(simpleName2)) { |
| return false; |
| } |
| } |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Compares the two {@link MethodDeclaration}. |
| * @param methodOne the first method declaration. |
| * @param methodTwo the second method declaration. |
| * @return <code>true</code> if the method names and parameter types match. |
| */ |
| @SuppressWarnings("unchecked") |
| public static boolean compareMethods(MethodDeclaration methodOne, MethodDeclaration methodTwo) { |
| if (methodOne.getName().getIdentifier().equals(methodTwo.getName().getIdentifier())) { |
| List<SingleVariableDeclaration> methodParametersOne = methodOne.parameters(); |
| List<SingleVariableDeclaration> methodParametersTwo = methodTwo.parameters(); |
| if (methodParametersOne.size() == methodParametersTwo.size()) { |
| for (int i = 0; i < methodParametersOne.size(); i++) { |
| String simpleName1 = methodParametersOne.get(i).getType().toString(); |
| String simpleName2 = methodParametersTwo.get(i).getType().toString(); |
| if (!simpleName1.equals(simpleName2)) { |
| return false; |
| } |
| } |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Compares the two {@link com.sun.mirror.declaration.MethodDeclaration}. |
| * @param methodOne the first method declaration. |
| * @param methodTwo the second method declaration. |
| * @return <code>true</code> if the method names and parameter types match. |
| */ |
| public static boolean compareMethods(com.sun.mirror.declaration.MethodDeclaration methodOne, |
| com.sun.mirror.declaration.MethodDeclaration methodTwo) { |
| return compareMethodNames(methodOne, methodTwo) && compareMethodParameterTypes(methodOne, methodTwo); |
| } |
| |
| private static boolean compareMethodNames(com.sun.mirror.declaration.MethodDeclaration methodOne, |
| com.sun.mirror.declaration.MethodDeclaration methodTwo) { |
| return methodOne.getSimpleName().equals(methodTwo.getSimpleName()); |
| } |
| |
| private static boolean compareMethodParameterTypes(com.sun.mirror.declaration.MethodDeclaration methodOne, |
| com.sun.mirror.declaration.MethodDeclaration methodTwo) { |
| int numberOfParametersOne = methodOne.getParameters().size(); |
| int numberOfParametersTwo = methodTwo.getParameters().size(); |
| |
| if (numberOfParametersOne == numberOfParametersTwo) { |
| List<ParameterDeclaration> parametersOne = (List<ParameterDeclaration>) methodOne.getParameters(); |
| List<ParameterDeclaration> parametersTwo = (List<ParameterDeclaration>) methodTwo.getParameters(); |
| for (int i = 0; i < parametersOne.size(); i++) { |
| if (!parametersOne.get(i).getType().equals(parametersTwo.get(i).getType())) { |
| return false; |
| } |
| } |
| return true; |
| } |
| return false; |
| } |
| |
| /** |
| * Compares the {@link FieldDeclaration} and {@link IField}. |
| * @param fieldDeclaration the field declaration. |
| * @param field the field. |
| * @return <code>true</code> if the field names match. |
| */ |
| @SuppressWarnings("unchecked") |
| public static boolean compareFieldNames(FieldDeclaration fieldDeclaration, IField field) { |
| List<VariableDeclarationFragment> fragments = fieldDeclaration.fragments(); |
| for (VariableDeclarationFragment variableDeclarationFragment : fragments) { |
| if (variableDeclarationFragment.getName().getIdentifier().equals(field.getElementName())) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| private static boolean compareAnnotationNames(Annotation newAnnotation, Annotation existingAnnotation) { |
| return AnnotationUtils.getAnnotationName(existingAnnotation).equals( |
| AnnotationUtils.getAnnotationName(newAnnotation)); |
| } |
| |
| /** |
| * Checks if the given {@link Annotation} is present on the {@link IJavaElement}. |
| * @param javaElement one of the following types of java element: |
| * <li>IJavaElement.PACKAGE_DECLARATION</li> |
| * <li>IJavaElement.TYPE</li> |
| * <li>IJavaElement.FIELD</li> |
| * <li>IJavaElement.METHOD</li> |
| * <li>IJavaElement.LOCAL_VARIABLE</li> |
| * @param annotation the annotation. |
| * @return <code>true</code> if the annotation is present. |
| */ |
| public static boolean isAnnotationPresent(IJavaElement javaElement, Annotation annotation) { |
| return AnnotationUtils.isAnnotationPresent(javaElement, AnnotationUtils.getAnnotationName(annotation)); |
| } |
| |
| /** |
| * Checks if the annotation with the given name is present on the {@link IJavaElement}. |
| * @param javaElement one of the following types of java element: |
| * <li>IJavaElement.PACKAGE_DECLARATION</li> |
| * <li>IJavaElement.TYPE</li> |
| * <li>IJavaElement.FIELD</li> |
| * <li>IJavaElement.METHOD</li> |
| * <li>IJavaElement.LOCAL_VARIABLE</li> |
| * @param annotationName the annotation name. |
| * @return <code>true</code> if the annotation is present. |
| */ |
| public static boolean isAnnotationPresent(IJavaElement javaElement, String annotationName) { |
| if (javaElement.getElementType() == IJavaElement.COMPILATION_UNIT) { |
| return isAnnotationPresent(((ICompilationUnit)javaElement).findPrimaryType(), annotationName); |
| } |
| |
| int elementType = javaElement.getElementType(); |
| |
| if (elementType == IJavaElement.PACKAGE_DECLARATION |
| || elementType == IJavaElement.TYPE |
| || elementType == IJavaElement.METHOD |
| || elementType == IJavaElement.LOCAL_VARIABLE |
| || elementType == IJavaElement.FIELD) { |
| |
| List<Annotation> annotations = getAnnotations(javaElement); |
| for (Annotation annotation : annotations) { |
| if (AnnotationUtils.getAnnotationName(annotation).equals(annotationName)) { |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Returns a list of all the {@link Annotation} that are present on the given {@link IJavaElement} |
| * @param javaElement one of the following types of java element: |
| * <li>IJavaElement.PACKAGE_DECLARATION</li> |
| * <li>IJavaElement.TYPE</li> |
| * <li>IJavaElement.FIELD</li> |
| * <li>IJavaElement.METHOD</li> |
| * <li>IJavaElement.LOCAL_VARIABLE</li> |
| * @return a list of annotations. |
| */ |
| @SuppressWarnings("unchecked") |
| public static List<Annotation> getAnnotations(IJavaElement javaElement) { |
| if (javaElement.getElementType() == IJavaElement.PACKAGE_DECLARATION) { |
| ICompilationUnit source = AnnotationUtils.getCompilationUnitFromJavaElement(javaElement); |
| CompilationUnit compilationUnit = getAST(source, false); |
| PackageDeclaration packageDeclaration = compilationUnit.getPackage(); |
| return packageDeclaration.annotations(); |
| } |
| |
| |
| if (javaElement.getElementType() == IJavaElement.TYPE) { |
| IType type = (IType) javaElement; |
| AbstractTypeDeclaration typeDeclaration = AnnotationUtils.getTypeDeclaration(type); |
| if (typeDeclaration != null) { |
| return extractAnnotations(typeDeclaration.modifiers()); |
| } |
| } |
| |
| if (javaElement.getElementType() == IJavaElement.METHOD) { |
| IMethod method = (IMethod) javaElement; |
| MethodDeclaration methodDeclaration = AnnotationUtils.getMethodDeclaration(method); |
| if (methodDeclaration != null) { |
| return extractAnnotations(methodDeclaration.modifiers()); |
| } |
| } |
| |
| if (javaElement.getElementType() == IJavaElement.FIELD) { |
| IField field = (IField) javaElement; |
| FieldDeclaration fieldDeclaration = AnnotationUtils.getFieldDeclaration(field); |
| if (fieldDeclaration != null) { |
| return extractAnnotations(fieldDeclaration.modifiers()); |
| } |
| } |
| |
| if (javaElement.getElementType() == IJavaElement.LOCAL_VARIABLE) { |
| SingleVariableDeclaration singleVariableDeclaration = getSingleVariableDeclaration((ILocalVariable) javaElement); |
| if (singleVariableDeclaration != null) { |
| return extractAnnotations(singleVariableDeclaration.modifiers()); |
| } |
| } |
| |
| return Collections.emptyList(); |
| } |
| |
| private static List<Annotation> extractAnnotations(List<IExtendedModifier> extendedModifiers) { |
| List<Annotation> annotations = new ArrayList<Annotation>(); |
| for (IExtendedModifier extendedModifier : extendedModifiers) { |
| if (extendedModifier.isAnnotation()) { |
| annotations.add((Annotation) extendedModifier); |
| } |
| } |
| return annotations; |
| } |
| |
| /** |
| * Returns a list of all the {@link SingleVariableDeclaration} for the given {@link IMethod}. |
| * @param method the method. |
| * @return a list of single variable declarations. |
| */ |
| @SuppressWarnings("unchecked") |
| public static List<SingleVariableDeclaration> getSingleVariableDeclarations(final IMethod method) { |
| ICompilationUnit source = method.getCompilationUnit(); |
| CompilationUnit compilationUnit = getAST(source, true); |
| final List<SingleVariableDeclaration> parameters = new ArrayList<SingleVariableDeclaration>(); |
| compilationUnit.accept(new ASTVisitor() { |
| @Override |
| public boolean visit(MethodDeclaration methodDeclaration) { |
| if (compareMethods(methodDeclaration, method)) { |
| parameters.addAll(methodDeclaration.parameters()); |
| } |
| return false; |
| } |
| }); |
| return parameters; |
| } |
| |
| /** |
| * Returns the {@link ILocalVariable} at the given offset position in the source file. |
| * @param method the method in which the local variable is declared. |
| * @param offset the character index of the local variable in the source file. |
| * The offset must be >= to the start position of the node representing the local variable and |
| * <= the nodes start position plus length. |
| * @return the local variable or null if not found. |
| */ |
| public static ILocalVariable getLocalVariable(IMethod method, int offset) { |
| List<SingleVariableDeclaration> parameters = getSingleVariableDeclarations(method); |
| for (SingleVariableDeclaration parameter : parameters) { |
| int parameterStartPosition = parameter.getStartPosition(); |
| int parameterLength = parameter.getLength(); |
| if (offset >= parameterStartPosition |
| && offset <= parameterStartPosition + parameterLength) { |
| return (ILocalVariable) parameter.resolveBinding().getJavaElement(); |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the {@link ILocalVariable} with the given name within the declared {@link IMethod}. |
| * @param method the method in which the local variable is declared. |
| * @param paramName the local variable name. |
| * @return the local variable or null if not found. |
| */ |
| public static ILocalVariable getLocalVariable(IMethod method, String paramName) { |
| List<SingleVariableDeclaration> parameters = getSingleVariableDeclarations(method); |
| for (SingleVariableDeclaration parameter : parameters) { |
| if (parameter.getName().getIdentifier().equals(paramName)) { |
| return (ILocalVariable) parameter.resolveBinding().getJavaElement(); |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the AST {@link Annotation} that corresponds to the given {@link java.lang.annotation.Annotation} class |
| * on the {@link IJavaElement}. |
| * @param javaElement one of the following types of java element: |
| * <li>IJavaElement.PACKAGE_DECLARATION</li> |
| * <li>IJavaElement.TYPE</li> |
| * <li>IJavaElement.FIELD</li> |
| * <li>IJavaElement.METHOD</li> |
| * <li>IJavaElement.LOCAL_VARIABLE</li> |
| * @param annotation the {@link java.lang.annotation.Annotation} class. |
| * @return the AST annotation or null if not found. |
| */ |
| public static Annotation getAnnotation(IJavaElement javaElement, Class<? extends java.lang.annotation.Annotation> annotation) { |
| List<Annotation> annotations = getAnnotations(javaElement); |
| for (Annotation astAnnotation : annotations) { |
| String typeName = astAnnotation.getTypeName().getFullyQualifiedName(); |
| if (typeName.equals(annotation.getCanonicalName()) |
| || typeName.equals(annotation.getSimpleName())) { |
| return astAnnotation; |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the {@link AnnotationMirror} that corresponds to the given {@link java.lang.annotation.Annotation} class |
| * on the {@link Declaration}. |
| * @param declaration the declaration |
| * @param annotation the {@link java.lang.annotation.Annotation} class. |
| * @return the annotation mirror or null if not found. |
| */ |
| public static AnnotationMirror getAnnotation(Declaration declaration, |
| Class<? extends java.lang.annotation.Annotation> annotation) { |
| Collection<AnnotationMirror> aannotationMirrors = declaration.getAnnotationMirrors(); |
| |
| for (AnnotationMirror annotationMirror : aannotationMirrors) { |
| com.sun.mirror.declaration.AnnotationTypeDeclaration annotationTypeDeclaration = annotationMirror |
| .getAnnotationType().getDeclaration(); |
| if (annotationTypeDeclaration != null |
| && annotationTypeDeclaration.getQualifiedName().equals(annotation.getCanonicalName())) { |
| return annotationMirror; |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the JDT {@link IAnnotation} that corresponds to the given {@link java.lang.annotation.Annotation} class |
| * on the {@link IAnnotatable} element. |
| * @param annotation the {@link java.lang.annotation.Annotation} class. |
| * @param annotatable a package declaration, a type, a method, a field or a local variable in a compilation unit. |
| * @return the annotation or null if not found. |
| * @throws JavaModelException if the annotatable element does not exist or if an exception occurs while accessing its corresponding resource. |
| */ |
| public static IAnnotation getAnnotation(Class<? extends java.lang.annotation.Annotation> annotation, |
| IAnnotatable annotatable) throws JavaModelException { |
| IAnnotation[] annotations = annotatable.getAnnotations(); |
| for (IAnnotation jdtAnnotation : annotations) { |
| String annotationName = jdtAnnotation.getElementName(); |
| if (annotationName.equals(annotation.getCanonicalName()) |
| || annotationName.equals(annotation.getSimpleName())) { |
| return jdtAnnotation; |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the {@link AnnotationValue} with the given member name that is declared within the {@link AnnotationMirror}. |
| * @param mirror the annotation mirror. |
| * @param memberName the member name. |
| * @return the annotation value or null if not found. |
| */ |
| public static AnnotationValue getAnnotationValue(AnnotationMirror mirror, String memberName) { |
| Map<AnnotationTypeElementDeclaration, AnnotationValue> values = mirror.getElementValues(); |
| Set<Map.Entry<AnnotationTypeElementDeclaration, AnnotationValue>> entrySet = values.entrySet(); |
| for (Map.Entry<AnnotationTypeElementDeclaration, AnnotationValue> entry : entrySet) { |
| AnnotationTypeElementDeclaration element = entry.getKey(); |
| if (element.getSimpleName().equals(memberName)) { |
| return entry.getValue(); |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the {@link NormalAnnotation} member value pair value with the given member name. |
| * @param normalAnnotation the normal annotation. |
| * @param memberName the member value pair member name. |
| * @return the value expression or null if not found. |
| */ |
| @SuppressWarnings("unchecked") |
| public static Expression getAnnotationValue(NormalAnnotation normalAnnotation, String memberName) { |
| List<MemberValuePair> memberValuePairs = normalAnnotation.values(); |
| for (MemberValuePair memberValuePair : memberValuePairs) { |
| if (memberValuePair.getName().getIdentifier().equals(memberName)) { |
| return memberValuePair.getValue(); |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the JDT {@link IAnnotation} member value pair value with the given member name. |
| * @param annotation the annotation. |
| * @param memberName the member name. |
| * @return an object representing the member value pairs value. |
| * @throws JavaModelException if the annotation does not exist or if an exception occurs while accessing its corresponding resource. |
| */ |
| public static Object getAnnotationValue(IAnnotation annotation, String memberName) throws JavaModelException { |
| IMemberValuePair[] memberValuePairs = annotation.getMemberValuePairs(); |
| if (memberValuePairs.length > 0) { |
| for (IMemberValuePair memberValuePair : memberValuePairs) { |
| if (memberValuePair.getMemberName().equals(memberName)) { |
| return memberValuePair.getValue(); |
| } |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the {@link MemberValuePair} with the given member name from the {@link NormalAnnotation}. |
| * @param normalAnnotation the normal annotation. |
| * @param memberName the member name of the member value pair to return. |
| * @return a member value pair or null if no member value pair with the given member name can be found. |
| */ |
| @SuppressWarnings("unchecked") |
| public static MemberValuePair getMemberValuePair(NormalAnnotation normalAnnotation, String memberName) { |
| List<MemberValuePair> memberValuesPairs = normalAnnotation.values(); |
| for (MemberValuePair memberValuePair : memberValuesPairs) { |
| if (memberValuePair.getName().getIdentifier().equals(memberName)) { |
| return memberValuePair; |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the member value with the given member name from the {@link AnnotationMirror} as a {@link String} value. |
| * @param mirror the annotation mirror. |
| * @param memberName the member name. |
| * @return the member value as a String or null if no member with the member name can be found. |
| */ |
| public static String getStringValue(AnnotationMirror mirror, String memberName) { |
| AnnotationValue annotationValue = getAnnotationValue(mirror, memberName); |
| if (annotationValue != null) { |
| return annotationValue.getValue().toString(); |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the member value with the given member name from the {@link Annotation} as a {@link String} value. |
| * @param annotation the AST annotation. |
| * @param memberName the member name. |
| * @return the member value as a String or null if no member with the member name can be found. |
| */ |
| public static String getStringValue(Annotation annotation, String memberName) { |
| if (annotation instanceof NormalAnnotation) { |
| Expression expression = getAnnotationValue((NormalAnnotation) annotation, memberName); |
| if (expression != null && expression instanceof StringLiteral) { |
| return ((StringLiteral) expression).getLiteralValue(); |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the member value with the given member name from the {@link IAnnotation} as a {@link String} value. |
| * @param annotation the JDT annotation. |
| * @param memberName the member name. |
| * @return the member value as a String or null if no member with the member name can be found. |
| * @throws JavaModelException if the annotation does not exist or if an exception occurs while accessing |
| * its corresponding resource. |
| */ |
| public static String getStringValue(IAnnotation annotation, String memberName) throws JavaModelException { |
| Object value = AnnotationUtils.getAnnotationValue(annotation, memberName); |
| if (value != null) { |
| return value.toString(); |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the member value with the given member name from the {@link AnnotationMirror} as a {@link Boolean} value. |
| * @param mirror the annotation mirror. |
| * @param memberName the member name. |
| * @return the member value as a Boolean or null if no member with the member name can be found. |
| */ |
| public static Boolean getBooleanValue(AnnotationMirror mirror, String memberName) { |
| String value = getStringValue(mirror, memberName); |
| if (value != null) { |
| return Boolean.valueOf(value); |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the member value with the given member name from the {@link Annotation} as a {@link Boolean} value. |
| * @param annotation the AST annotation. |
| * @param memberName the member name. |
| * @return the member value as a Boolean or null if no member with the member name can be found. |
| */ |
| public static Boolean getBooleanValue(Annotation annotation, String memberName) { |
| if (annotation instanceof NormalAnnotation) { |
| Expression expression = getAnnotationValue((NormalAnnotation) annotation, memberName); |
| if (expression != null && expression instanceof BooleanLiteral) { |
| return Boolean.valueOf(((BooleanLiteral) expression).booleanValue()); |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the member value with the given member name from the {@link IAnnotation} as a {@link Boolean} value. |
| * @param annotation the JDT annotation. |
| * @param memberName the member name. |
| * @return the member value as a Boolean or null if no member with the member name can be found. |
| * @throws JavaModelException if the annotation does not exist or if an exception occurs while accessing |
| * its corresponding resource. |
| */ |
| public static Boolean getBooleanValue(IAnnotation annotation, String memberName) throws JavaModelException { |
| String value = AnnotationUtils.getStringValue(annotation, memberName); |
| if (value != null) { |
| return Boolean.valueOf(value); |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the member value with the given member name from the {@link Annotation} as a {@link String} value. |
| * The returned String value is the name of the enum constant. |
| * @param annotation the AST annotation. |
| * @param memberName the member name. |
| * @return the member value as a String or null if no member with the member name can be found. |
| */ |
| public static String getEnumValue(Annotation annotation, String memberName) { |
| if (annotation instanceof NormalAnnotation) { |
| Expression expression = getAnnotationValue((NormalAnnotation) annotation, memberName); |
| if (expression != null && expression instanceof QualifiedName) { |
| return ((QualifiedName) expression).getName().getIdentifier(); |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Returns the member value with the given member name from the {@link IAnnotation} as a {@link String} value. |
| * The returned String value is the name of the enum constant. |
| * @param annotation the JDT annotation. |
| * @param memberName the member name. |
| * @return the member value as a String or null if no member with the member name can be found. |
| * @throws JavaModelException if the annotation does not exist or if an exception occurs while accessing |
| * its corresponding resource. |
| */ |
| public static String getEnumValue(IAnnotation annotation, String memberName) throws JavaModelException { |
| String value = AnnotationUtils.getStringValue(annotation, memberName); |
| if (value != null && value.indexOf(".") != -1) { |
| return value.substring(value.lastIndexOf(".") + 1); |
| } |
| return null; |
| } |
| |
| private static CompilationUnit getAST(ICompilationUnit source, boolean resolveBindings) { |
| final ASTParser parser = ASTParser.newParser(AST.JLS3); |
| parser.setResolveBindings(resolveBindings); |
| parser.setSource(source); |
| return (CompilationUnit) parser.createAST(null); |
| } |
| |
| } |