-
Notifications
You must be signed in to change notification settings - Fork 1
Fix removeUnused mode not loading plugin checks and alt names #278
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
Generate changelog in
|
082b6c1 to
e507d60
Compare
✅ Successfully generated changelog entry!Need to regenerate?Simply interact with the changelog bot comment again to regenerate these entries. 📋Changelog Preview🐛 Fixes
|
| '''.stripIndent(true) | ||
|
|
||
| when: | ||
| runTasksSuccessfully('compileAllErrorProne', '-PerrorProneRemoveUnused=ArrayToString') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RemoveUnused doesn't take arguments — this argument was being ignored
aldexis
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to have a look, but I'm not familiar enough with the remove unused logic to confidently review the actual logic changes. Best to have @CRogers have an eye on this as well
| @BugPattern( | ||
| severity = BugPattern.SeverityLevel.ERROR, | ||
| summary = "This check is meant only for testing suppressible-error-prone functionality") | ||
| public final class ShouldNotReturn extends BugChecker implements MethodTreeMatcher { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you use this anywhere?
| ServiceLoader.load(BugChecker.class).stream().map(ServiceLoader.Provider::get); | ||
| Stream<String> pluginCheckNames = | ||
| StreamEx.of(pluginChecks).flatMap(bugchecker -> bugchecker.allNames().stream()); | ||
| private static Supplier<Map<String, Set<String>>> canonicalToAllNames = VisitorState.memoize(state -> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| private static Supplier<Map<String, Set<String>>> canonicalToAllNames = VisitorState.memoize(state -> { | |
| private static final Supplier<Map<String, Set<String>>> canonicalToAllNames = VisitorState.memoize(state -> { |
|
|
||
| public static Set<String> allBugcheckerNames() { | ||
| return cachedAllBugcheckerNames.get(); | ||
| private static Supplier<Set<String>> allNames = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| private static Supplier<Set<String>> allNames = | |
| private static final Supplier<Set<String>> allNames = |
| .flatMap(entry -> entry.getValue().stream()) | ||
| .collect(Collectors.toSet())); | ||
|
|
||
| private static Supplier<Map<String, Set<String>>> nameToPossibleCanonicalNames = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| private static Supplier<Map<String, Set<String>>> nameToPossibleCanonicalNames = | |
| private static final Supplier<Map<String, Set<String>>> nameToPossibleCanonicalNames = |
| .flatMap(entry -> entry.getValue().stream()) | ||
| .collect(Collectors.toSet())); | ||
|
|
||
| private static Supplier<Map<String, Set<String>>> nameToPossibleCanonicalNames = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to have multiple checks share the same alt name? I imagine so, though it's also pretty surprising
| declaration, state, suppression -> !AllErrorprones.allBugcheckerNames(state) | ||
| .contains(suppression)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You were previously removing the for-rollout prefix and aren't doing so anymore. Is that intentional?
| String existingSuppression = AnnotationUtils.annotationStringValues( | ||
| SuppressWarningsUtils.getSuppressWarnings(declaration) | ||
| .get()) | ||
| .filter(suppression -> allNames.contains(SuppressWarningsUtils.stripForRollout(suppression))) | ||
| .collect(MoreCollectors.first()) | ||
| .get(); | ||
| FIXES.getExisting(declaration).addSuppression(existingSuppression); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't you keep all the ones that might already exist, rather than just the first one? (especially the non-rollout ones)
| String existingSuppression = AnnotationUtils.annotationStringValues( | ||
| SuppressWarningsUtils.getSuppressWarnings(declaration) | ||
| .get()) | ||
| .filter(suppression -> allNames.contains(SuppressWarningsUtils.stripForRollout(suppression))) | ||
| .collect(MoreCollectors.first()) | ||
| .get(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this leverage suppressionsOn in some way?
| .map(Provider::get) | ||
| .collect(Collectors.toList()); | ||
| EntryStream<String, Set<String>> pluginCheckNames = | ||
| StreamEx.of(pluginChecks).mapToEntry(BugChecker::canonicalName, BugChecker::allNames); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BugChecker#allNames will return for-rollout:Name if we've patched the errorprone classes in the artifact transform.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which may be what we want...
| // Use the same classloader that Error Prone was loaded from to avoid classloader skew | ||
| // when using Error Prone plugins together with the Error Prone javac plugin. | ||
| JavacProcessingEnvironment processingEnvironment = JavacProcessingEnvironment.instance(state.context); | ||
| ClassLoader loader = processingEnvironment.getProcessorClassLoader(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if there's any real difference between this and state.getClass().getClassLoader()? The latter does not require interacting with so many compiler APIs or module imports.
Before this PR
A few bugs in suppressible-error-prone:
After this PR
==COMMIT_MSG==
Fix removeUnused mode not loading plugin checks and alt names
==COMMIT_MSG==
Possible downsides?
Probably next PR: RemoveUnused should not remove human-made suppressions. For example, a human-made suppression on SafeLoggingPropagation for a method which is safe to log. RemoveUnused + Apply should not remove the suppression and add the
@Unsafeannotation.If needed, human-authored suppressions can be removed on an allow-list basis. But the correct and performant removal of robot-added suppressions should be the focus here.