diff --git a/src/java/apiview-java-processor/src/main/java/com/azure/tools/apiview/processor/analysers/JavaASTAnalyser.java b/src/java/apiview-java-processor/src/main/java/com/azure/tools/apiview/processor/analysers/JavaASTAnalyser.java index 7ac15f26b6c..1d446430fda 100644 --- a/src/java/apiview-java-processor/src/main/java/com/azure/tools/apiview/processor/analysers/JavaASTAnalyser.java +++ b/src/java/apiview-java-processor/src/main/java/com/azure/tools/apiview/processor/analysers/JavaASTAnalyser.java @@ -1031,7 +1031,7 @@ private void getAnnotations(final NodeWithAnnotations nodeWithAnnotations, addToken(makeWhitespace()); } - addToken(new Token(TYPE_NAME, "@" + annotation.getName().toString(), makeId(annotation))); + addToken(new Token(TYPE_NAME, "@" + annotation.getName().toString(), makeId(annotation, nodeWithAnnotations))); if (showAnnotationProperties) { if (annotation instanceof NormalAnnotationExpr) { addToken(new Token(PUNCTUATION, "(")); diff --git a/src/java/apiview-java-processor/src/main/java/com/azure/tools/apiview/processor/analysers/util/ASTUtils.java b/src/java/apiview-java-processor/src/main/java/com/azure/tools/apiview/processor/analysers/util/ASTUtils.java index 86f1921ba08..9d71fe29f56 100644 --- a/src/java/apiview-java-processor/src/main/java/com/azure/tools/apiview/processor/analysers/util/ASTUtils.java +++ b/src/java/apiview-java-processor/src/main/java/com/azure/tools/apiview/processor/analysers/util/ASTUtils.java @@ -10,6 +10,8 @@ import com.github.javaparser.ast.body.CallableDeclaration; import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; import com.github.javaparser.ast.body.ConstructorDeclaration; +import com.github.javaparser.ast.body.EnumConstantDeclaration; +import com.github.javaparser.ast.body.EnumDeclaration; import com.github.javaparser.ast.body.FieldDeclaration; import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.body.TypeDeclaration; @@ -17,6 +19,7 @@ import com.github.javaparser.ast.comments.Comment; import com.github.javaparser.ast.comments.JavadocComment; import com.github.javaparser.ast.expr.AnnotationExpr; +import com.github.javaparser.ast.nodeTypes.NodeWithAnnotations; import com.github.javaparser.ast.nodeTypes.NodeWithJavadoc; import java.util.Collections; @@ -197,9 +200,43 @@ public static String makeId(String fullPath) { return MAKE_ID.matcher(fullPath).replaceAll("-"); } - public static String makeId(AnnotationExpr annotation) { - int line = annotation.getBegin().orElseThrow(RuntimeException::new).line; - return makeId(getNodeFullyQualifiedName(annotation.getParentNode()) + "." + annotation.getNameAsString() + "-L" + line); + public static String makeId(AnnotationExpr annotation, NodeWithAnnotations nodeWithAnnotations) { + String annotationContext = getAnnotationContext(nodeWithAnnotations); + + String idSuffix; + + if (annotationContext == null || annotationContext.isEmpty()) { + idSuffix = "-L" + annotation.getBegin().orElseThrow(RuntimeException::new).line; + } else { + idSuffix = "-" + annotationContext; + } + return makeId(getNodeFullyQualifiedName(annotation.getParentNode()) + "." + annotation.getNameAsString() + idSuffix); + } + + private static String getAnnotationContext(NodeWithAnnotations nodeWithAnnotations) { + if (nodeWithAnnotations == null) { + return ""; + } + if (nodeWithAnnotations instanceof MethodDeclaration) { + MethodDeclaration methodDeclaration = (MethodDeclaration) nodeWithAnnotations; + // use the method declaration string instead of method name as there can be overloads + return methodDeclaration.getDeclarationAsString(true, true, true); + } else if (nodeWithAnnotations instanceof ClassOrInterfaceDeclaration) { + ClassOrInterfaceDeclaration classOrInterfaceDeclaration = (ClassOrInterfaceDeclaration) nodeWithAnnotations; + return classOrInterfaceDeclaration.getNameAsString(); + } else if (nodeWithAnnotations instanceof EnumDeclaration) { + EnumDeclaration enumDeclaration = (EnumDeclaration) nodeWithAnnotations; + return enumDeclaration.getNameAsString(); + } else if (nodeWithAnnotations instanceof EnumConstantDeclaration) { + EnumConstantDeclaration enumValueDeclaration = (EnumConstantDeclaration) nodeWithAnnotations; + return enumValueDeclaration.getNameAsString(); + } else if (nodeWithAnnotations instanceof ConstructorDeclaration) { + ConstructorDeclaration constructorDeclaration = (ConstructorDeclaration) nodeWithAnnotations; + // use the constructor declaration string instead of the name as there can be overloads + return constructorDeclaration.getDeclarationAsString(true, true, true); + } else { + return ""; + } } /** diff --git a/src/java/apiview-java-processor/src/main/java/com/azure/tools/apiview/processor/diagnostics/rules/BadAnnotationDiagnosticRule.java b/src/java/apiview-java-processor/src/main/java/com/azure/tools/apiview/processor/diagnostics/rules/BadAnnotationDiagnosticRule.java index b18c2919b4c..420644a26b5 100644 --- a/src/java/apiview-java-processor/src/main/java/com/azure/tools/apiview/processor/diagnostics/rules/BadAnnotationDiagnosticRule.java +++ b/src/java/apiview-java-processor/src/main/java/com/azure/tools/apiview/processor/diagnostics/rules/BadAnnotationDiagnosticRule.java @@ -5,9 +5,9 @@ import com.azure.tools.apiview.processor.model.Diagnostic; import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.expr.AnnotationExpr; +import com.github.javaparser.ast.nodeTypes.NodeWithAnnotations; import java.util.*; -import java.util.function.Consumer; import static com.azure.tools.apiview.processor.analysers.util.ASTUtils.*; import static com.azure.tools.apiview.processor.model.DiagnosticKind.WARNING; @@ -18,7 +18,7 @@ */ public class BadAnnotationDiagnosticRule implements DiagnosticRule { - private List badAnnotations; + private final List badAnnotations; public BadAnnotationDiagnosticRule(BadAnnotation... badAnnotations) { this.badAnnotations = Arrays.asList(badAnnotations); @@ -26,24 +26,36 @@ public BadAnnotationDiagnosticRule(BadAnnotation... badAnnotations) { @Override public void scanIndividual(final CompilationUnit cu, final APIListing listing) { - Consumer annotationConsumer = a -> { - badAnnotations.forEach(badAnnotation -> { - // check if the badAnnotation is the same as the found annotation - if (badAnnotation.annotation.equals(a.getNameAsString())) { - // we've got a match - file it as a diagnostic - listing.addDiagnostic(new Diagnostic(WARNING, makeId(a), badAnnotation.errorMessage)); - } - }); - }; getClasses(cu).forEach(typeDeclaration -> { // check annotations on the type itself - typeDeclaration.getAnnotations().stream().forEach(annotationConsumer); + typeDeclaration.getAnnotations() + .forEach(annotation -> checkForBadAnnotations(listing, typeDeclaration, annotation)); - // check annotations on fields, constructors, methods - getPublicOrProtectedFields(typeDeclaration).flatMap(method -> method.getAnnotations().stream()).forEach(annotationConsumer); - getPublicOrProtectedConstructors(typeDeclaration).flatMap(method -> method.getAnnotations().stream()).forEach(annotationConsumer); - getPublicOrProtectedMethods(typeDeclaration).flatMap(method -> method.getAnnotations().stream()).forEach(annotationConsumer); + // check annotations on fields + getPublicOrProtectedFields(typeDeclaration) + .forEach(field -> field.getAnnotations() + .forEach(annotation -> checkForBadAnnotations(listing, field, annotation))); + + // check annotations on constructors + getPublicOrProtectedConstructors(typeDeclaration) + .forEach(constructor -> constructor.getAnnotations() + .forEach(annotation -> checkForBadAnnotations(listing, constructor, annotation))); + // check annotations on methods + getPublicOrProtectedMethods(typeDeclaration) + .forEach(method -> method.getAnnotations() + .forEach(annotation -> checkForBadAnnotations(listing, method, annotation))); + }); + } + + private void checkForBadAnnotations(APIListing listing, NodeWithAnnotations nodeWithAnnotations, AnnotationExpr annotation) { + badAnnotations.forEach(badAnnotation -> { + // check if the badAnnotation is the same as the found annotation + if (badAnnotation.annotation.equals(annotation.getNameAsString())) { + // we've got a match - file it as a diagnostic + listing.addDiagnostic(new Diagnostic(WARNING, makeId(annotation, nodeWithAnnotations), + badAnnotation.errorMessage)); + } }); }