Skip to content

Commit

Permalink
SONARJAVA-4973 Fix FP on S1118 with Lombok @UtilityClass in automatic…
Browse files Browse the repository at this point in the history
… analysis (#4960)

Co-authored-by: Dorian Burihabwa <[email protected]>
  • Loading branch information
1 parent bf9a0b3 commit def406e
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 4 deletions.
25 changes: 23 additions & 2 deletions java-checks/src/main/java/org/sonar/java/filters/LombokFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.util.Optional;
import java.util.Set;
import javax.annotation.Nullable;
import org.sonar.java.annotations.VisibleForTesting;
import org.sonar.java.checks.AtLeastOneConstructorCheck;
import org.sonar.java.checks.CollectionInappropriateCallsCheck;
import org.sonar.java.checks.ConstantsShouldBeStaticFinalCheck;
Expand Down Expand Up @@ -181,12 +182,32 @@ public void visitAssignmentExpression(AssignmentExpressionTree tree) {
}

private static boolean usesAnnotation(ClassTree classTree, List<String> annotations) {
return usesAnnotation(classTree, annotations, false);
}

private static boolean usesAnnotation(ClassTree classTree, List<String> annotations, boolean shouldCheckAnnotationLocalName) {
SymbolMetadata classMetadata = classTree.symbol().metadata();
return annotations.stream().anyMatch(classMetadata::isAnnotatedWith);

for(String fullyQualified: annotations) {
if(classMetadata.isAnnotatedWith(fullyQualified)) {
return true;
}
// In automatic analysis use only the last part of the annotation.
if(shouldCheckAnnotationLocalName && classMetadata.isAnnotatedWith(annotationTypeIdentifier(fullyQualified))) {
return true;
}
}

return false;
}

@VisibleForTesting
static String annotationTypeIdentifier(String fullyQualified) {
return fullyQualified.substring(fullyQualified.lastIndexOf('.') + 1);
}

private static boolean generatesNonPublicConstructor(ClassTree classTree) {
if (usesAnnotation(classTree, UTILITY_CLASS)) {
if (usesAnnotation(classTree, UTILITY_CLASS, true)) {
return true;
}
SymbolMetadata metadata = classTree.symbol().metadata();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
import lombok.experimental.UtilityClass;

// FP happening without semantics.
class Utility { // WithIssue
public static int triple(int in) {
return in * 3;
}
}

@UtilityClass
public class Utility { // WithIssue
class UtilityAnnotated { // NoIssue
public static int triple(int in) {
return in * 3;
}
}

@lombok.experimental.UtilityClass
class UtilityFullyQualified { // NoIssue
public static int triple(int in) {
return in * 3;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@

import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.java.filters.LombokFilter.annotationTypeIdentifier;

class LombokFilterTest {

@Test
Expand All @@ -32,4 +35,11 @@ void testWithoutSemantic() {
.withoutSemantic()
.verify("src/test/files/filters/LombokFilterWithoutSemantic.java", new LombokFilter());
}

@Test
void testAnnotationTypeIdentifier() {
assertThat(annotationTypeIdentifier("noDot")).isEqualTo("noDot");
assertThat(annotationTypeIdentifier("one.dot")).isEqualTo("dot");
assertThat(annotationTypeIdentifier("many.many.dots")).isEqualTo("dots");
}
}

0 comments on commit def406e

Please sign in to comment.