Skip to content

Commit 8a4de4d

Browse files
SONARJAVA-4837 S6878 Fix FP on record methods (#4727)
1 parent 2f70d6b commit 8a4de4d

2 files changed

Lines changed: 9 additions & 5 deletions

File tree

java-checks-test-sources/default/src/main/java/checks/RecordPatternInsteadOfFieldAccessCheckSample.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ int notAComponentAccessTwice(Object obj){
2828
}
2929

3030
int allComponentsPlusAMethod(Object obj){
31-
if (obj instanceof Point p) { // Noncompliant
31+
if (obj instanceof Point p) { // Compliant, using record pattern would not allow access to p.notAComponent
3232
return p.x() + p.y() + p.notAComponent();
3333
}
3434
return 0;

java-checks/src/main/java/org/sonar/java/checks/RecordPatternInsteadOfFieldAccessCheck.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.util.List;
2424
import java.util.Optional;
2525
import java.util.Set;
26+
import java.util.stream.Collectors;
2627
import org.sonar.check.Rule;
2728
import org.sonar.plugins.java.api.IssuableSubscriptionVisitor;
2829
import org.sonar.plugins.java.api.JavaFileScannerContext;
@@ -36,7 +37,6 @@
3637
import org.sonar.plugins.java.api.tree.TypePatternTree;
3738
import org.sonar.plugins.java.api.tree.VariableTree;
3839

39-
4040
@Rule(key = "S6878")
4141
public class RecordPatternInsteadOfFieldAccessCheck extends IssuableSubscriptionVisitor implements JavaVersionAwareVisitor {
4242

@@ -97,7 +97,11 @@ private void checkTypePatternVariableUsage(VariableTree patternVariable) {
9797

9898
private static boolean isEveryRecordComponentUsed(Set<MemberSelectExpressionTree> secondaryLocationsTrees, Symbol.TypeSymbol recordSymbol) {
9999
var recordComponentNames = recordComponentNames(recordSymbol);
100-
return !recordComponentNames.isEmpty() && secondaryLocationsTrees.stream().map(mse -> mse.identifier().name()).toList().containsAll(recordComponentNames);
100+
return !recordComponentNames.isEmpty() &&
101+
secondaryLocationsTrees.stream()
102+
.map(mse -> mse.identifier().name())
103+
.collect(Collectors.toSet())
104+
.equals(recordComponentNames);
101105
}
102106

103107
private static boolean isNotRecordGetter(MemberSelectExpressionTree mse) {
@@ -115,14 +119,14 @@ private static boolean isRecordPattern(TypePatternTree typePattern) {
115119
return typePattern.patternVariable().type().symbolType().isSubtypeOf("java.lang.Record");
116120
}
117121

118-
private static List<String> recordComponentNames(Symbol.TypeSymbol recordSymbol) {
122+
private static Set<String> recordComponentNames(Symbol.TypeSymbol recordSymbol) {
119123
return recordSymbol
120124
.memberSymbols()
121125
.stream()
122126
.filter(Symbol::isVariableSymbol)
123127
.map(Symbol.VariableSymbol.class::cast)
124128
.map(Symbol.VariableSymbol::name)
125-
.toList();
129+
.collect(Collectors.toSet());
126130
}
127131

128132
}

0 commit comments

Comments
 (0)