|
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