Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down Expand Up @@ -200,3 +202,51 @@ class JakartaRepo {
@jakarta.annotation.Resource
String email2 = null; // Compliant
}

@Service
@RequiredArgsConstructor
class LombokInjected {

private final String injected; // Compliant
private String notInjected; // Noncompliant {{Annotate this member with "@Autowired", "@Resource", "@Inject", or "@Value", or remove it.}}
// ^^^^^^^^^^^

public void foo() {
System.out.println(injected);
System.out.println(notInjected);
}

}

@Component
@RequiredArgsConstructor
class LombokInjected1 {

private final String injected; // Compliant
@lombok.NonNull
private String injectedNonNull; // Compliant
private String notInjected; // Noncompliant {{Annotate this member with "@Autowired", "@Resource", "@Inject", or "@Value", or remove it.}}
// ^^^^^^^^^^^

public void foo() {
System.out.println(injected);
System.out.println(injectedNonNull);
System.out.println(notInjected);
}

}

@Service
@AllArgsConstructor
class LombokInjected2 {

private final String injected; // Compliant
private String notInjected; // Compliant


public void foo() {
System.out.println(injected);
System.out.println(notInjected);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,22 @@ public List<Tree.Kind> nodesToVisit() {
@Override
public void visitNode(Tree tree) {
ClassTree clazzTree = (ClassTree) tree;
Set<Symbol> symbolsUsedInConstructors = symbolsUsedInConstructors(clazzTree);
SymbolMetadata classMetadata = clazzTree.symbol().metadata();

if (classMetadata.isAnnotatedWith("lombok.AllArgsConstructor")) {
return;
}
boolean requiredArgsConstructorAnnotationPresent = classMetadata.isAnnotatedWith("lombok.RequiredArgsConstructor");

if (isSpringSingletonComponent(clazzTree.symbol().metadata())) {
Set<Symbol> symbolsUsedInConstructors = symbolsUsedInConstructors(clazzTree);
if (isSpringSingletonComponent(classMetadata)) {
clazzTree.members().stream().filter(v -> v.is(Tree.Kind.VARIABLE))
.map(VariableTree.class::cast)
.filter(v -> !v.symbol().isStatic())
.filter(v -> !isSpringInjectionAnnotated(v.symbol().metadata()))
.filter(v -> !isCustomInjectionAnnotated(v.symbol().metadata()))
.filter(v -> !symbolsUsedInConstructors.contains(v.symbol()))
.filter(v -> !isInjectedByLombok(v, requiredArgsConstructorAnnotationPresent))
.forEach(v -> reportIssue(v.simpleName(), "Annotate this member with \"@Autowired\", \"@Resource\", \"@Inject\", or \"@Value\", or remove it."));
}
}
Expand All @@ -103,6 +110,12 @@ private static boolean isUsingConfigurationProperties(SymbolMetadata classMeta)
return classMeta.isAnnotatedWith("org.springframework.boot.context.properties.ConfigurationProperties");
}

private static boolean isInjectedByLombok(VariableTree field, boolean requiredArgsConstructorAnnotationPresent) {
return requiredArgsConstructorAnnotationPresent
&& field.initializer() == null
&& (field.symbol().isFinal() || field.symbol().metadata().isAnnotatedWith("lombok.NonNull"));
}

private Set<Symbol> symbolsUsedInConstructors(ClassTree clazzTree) {
List<Symbol.MethodSymbol> constructors = constructors(clazzTree);
return constructors.stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
import org.sonar.java.checks.UtilityClassWithPublicConstructorCheck;
import org.sonar.java.checks.helpers.ExpressionsHelper;
import org.sonar.java.checks.naming.BadFieldNameCheck;
import org.sonar.java.checks.spring.SpringComponentWithNonAutowiredMembersCheck;
import org.sonar.java.checks.tests.AssertionTypesCheck;
import org.sonar.java.checks.unused.UnusedPrivateFieldCheck;
import org.sonar.plugins.java.api.JavaCheck;
Expand Down Expand Up @@ -69,7 +68,6 @@ public class LombokFilter extends BaseTreeVisitorIssueFilter {
/* S1450 */ PrivateFieldUsedLocallyCheck.class,
/* S4248 */ RegexPatternsNeedlesslyCheck.class,
/* S2159 */ SillyEqualsCheck.class,
/* S3749 */ SpringComponentWithNonAutowiredMembersCheck.class,
/* S2325 */ StaticMethodCheck.class,
/* S1068 */ UnusedPrivateFieldCheck.class,
/* S1128 */ UselessImportCheck.class,
Expand Down Expand Up @@ -130,7 +128,7 @@ public void visitClass(ClassTree tree) {
boolean generatesEquals = usesAnnotation(tree, GENERATE_EQUALS);

excludeLinesIfTrue(generatesEquals || usesAnnotation(tree, GENERATE_UNUSED_FIELD_RELATED_METHODS), tree, UnusedPrivateFieldCheck.class, PrivateFieldUsedLocallyCheck.class);
excludeLinesIfTrue(usesAnnotation(tree, GENERATE_CONSTRUCTOR), tree, AtLeastOneConstructorCheck.class, SpringComponentWithNonAutowiredMembersCheck.class);
excludeLinesIfTrue(usesAnnotation(tree, GENERATE_CONSTRUCTOR), tree, AtLeastOneConstructorCheck.class);
excludeLinesIfTrue(generatesEquals, tree, EqualsNotOverriddenInSubclassCheck.class, EqualsNotOverriddenWithCompareToCheck.class);
excludeLinesIfTrue(generatesNonPublicConstructor(tree), tree, UtilityClassWithPublicConstructorCheck.class);
boolean isUtilityClass = usesAnnotation(tree, UTILITY_CLASS);
Expand Down
Loading