|
16 | 16 |
|
17 | 17 | package com.google.errorprone.bugpatterns;
|
18 | 18 |
|
| 19 | +import static com.google.common.collect.ImmutableList.toImmutableList; |
19 | 20 | import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
|
20 | 21 | import static com.google.errorprone.matchers.Description.NO_MATCH;
|
21 | 22 | import static com.google.errorprone.matchers.Matchers.allOf;
|
22 | 23 | import static com.google.errorprone.matchers.Matchers.anyOf;
|
23 | 24 | import static com.google.errorprone.matchers.Matchers.not;
|
| 25 | +import static java.util.stream.Collectors.joining; |
24 | 26 |
|
25 |
| -import com.google.common.base.Joiner; |
26 | 27 | import com.google.errorprone.BugPattern;
|
27 | 28 | import com.google.errorprone.VisitorState;
|
28 | 29 | import com.google.errorprone.bugpatterns.BugChecker.ClassTreeMatcher;
|
|
34 | 35 | import com.google.errorprone.util.ASTHelpers;
|
35 | 36 | import com.sun.source.tree.ClassTree;
|
36 | 37 | import com.sun.source.tree.MethodTree;
|
37 |
| -import com.sun.source.tree.Tree; |
38 |
| -import java.util.ArrayList; |
39 |
| -import java.util.List; |
40 |
| -import java.util.Optional; |
41 | 38 | import javax.lang.model.element.Modifier;
|
42 | 39 |
|
43 | 40 | /**
|
@@ -71,34 +68,31 @@ public Description matchClass(ClassTree tree, VisitorState state) {
|
71 | 68 | if (!ASTHelpers.hasAnnotation(tree, "com.google.auto.value.AutoValue", state)) {
|
72 | 69 | return NO_MATCH;
|
73 | 70 | }
|
74 |
| - SuggestedFix.Builder fix = SuggestedFix.builder(); |
75 |
| - List<String> matchedMethods = new ArrayList<>(); |
76 |
| - MethodTree firstMatchedMethod = null; |
77 |
| - for (Tree memberTree : tree.getMembers()) { |
78 |
| - if (!(memberTree instanceof MethodTree)) { |
79 |
| - continue; |
80 |
| - } |
81 |
| - MethodTree method = (MethodTree) memberTree; |
82 |
| - if (METHOD_MATCHER.matches(method, state)) { |
83 |
| - Optional<SuggestedFix> optionalSuggestedFix = |
84 |
| - SuggestedFixes.addModifiers(method, state, Modifier.FINAL); |
85 |
| - if (optionalSuggestedFix.isPresent()) { |
86 |
| - matchedMethods.add(method.getName().toString()); |
87 |
| - fix.merge(optionalSuggestedFix.get()); |
88 |
| - if (firstMatchedMethod == null) { |
89 |
| - firstMatchedMethod = method; |
90 |
| - } |
91 |
| - } |
92 |
| - } |
93 |
| - } |
94 |
| - if (!fix.isEmpty()) { |
95 |
| - String message = |
96 |
| - String.format( |
97 |
| - "Make %s final in AutoValue classes, " |
98 |
| - + "so it is clear to readers that AutoValue is not overriding them", |
99 |
| - Joiner.on(", ").join(matchedMethods)); |
100 |
| - return buildDescription(firstMatchedMethod).setMessage(message).addFix(fix.build()).build(); |
| 71 | + var candidateMethods = |
| 72 | + tree.getMembers().stream() |
| 73 | + .filter( |
| 74 | + t -> |
| 75 | + t instanceof MethodTree |
| 76 | + && METHOD_MATCHER.matches((MethodTree) t, state) |
| 77 | + && !isSuppressed(t, state)) |
| 78 | + .map(t -> (MethodTree) t) |
| 79 | + .collect(toImmutableList()); |
| 80 | + |
| 81 | + var fix = |
| 82 | + candidateMethods.stream() |
| 83 | + .flatMap(t -> SuggestedFixes.addModifiers(t, state, Modifier.FINAL).stream()) |
| 84 | + .reduce(SuggestedFix.emptyFix(), SuggestedFix::merge); |
| 85 | + |
| 86 | + if (fix.isEmpty()) { |
| 87 | + return NO_MATCH; |
101 | 88 | }
|
102 |
| - return NO_MATCH; |
| 89 | + return buildDescription(candidateMethods.get(0)) |
| 90 | + .setMessage( |
| 91 | + String.format( |
| 92 | + "Make %s final in AutoValue classes, " |
| 93 | + + "so it is clear to readers that AutoValue is not overriding them", |
| 94 | + candidateMethods.stream().map(t -> t.getName().toString()).collect(joining(", ")))) |
| 95 | + .addFix(fix) |
| 96 | + .build(); |
103 | 97 | }
|
104 | 98 | }
|
0 commit comments