Skip to content

Conversation

@kelvinou01
Copy link
Contributor

Before this PR

After this PR

==COMMIT_MSG==
==COMMIT_MSG==

Possible downsides?

@changelog-app
Copy link

changelog-app bot commented Sep 29, 2025

Generate changelog in changelog/@unreleased

Type (Select exactly one)

  • Feature (Adding new functionality)
  • Improvement (Improving existing functionality)
  • Fix (Fixing an issue with existing functionality)
  • Break (Creating a new major version by breaking public APIs)
  • Deprecation (Removing functionality in a non-breaking way)
  • Migration (Automatically moving data/functionality to a new system)

Description

-PerrorProneRemoveUnused implementation (works with suppress and apply): remove unused suppressions on every encountered compilation unit

Check the box to generate changelog(s)

  • Generate changelog entry

private final List<String> existingSuppressions;
private final String suffix;
private final Set<String> newSuppressions;
private final Set<String> desiredSuppressions;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This implicitly uses a listener/accumulator pattern, like error-prone's DescriptionListener. Maybe make this explicit

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that it's a mutable set?

}

/**
* Only these trees are suppressible, as per
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This cond is too loose! See #160

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to be careful here. We've decided that suppressible-error-prone will not put suppressions in certain locations, but if we're removing unused human suppressions they may be in these locations. This may complicate things somewhat.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Especially as we might want to "move" for-rollout: suppressions to be in a more specific location (eg because we changed up some errorprone logic), but we probably don't want to do this to human authored suppressions unless we need to (eg someone suppresses a whole class to stop loads of errors - we probably want to keep this).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we probably don't want to do this to human authored suppressions unless we need to

yep, RemoveUnusedMode has tests for this specific case

@kelvinou01 kelvinou01 changed the title -PerrorProneRemoveUnused implementation (works with suppress and apply): remove unused suppressions on every encountered compilation unit -PerrorProneRemoveUnused implementation (works with suppress and apply): remove unused suppressions on every encountered compilation unit in VisitorStateModifications Sep 29, 2025
Comment on lines 1587 to 1644
def 'errorProneRemoveUnused + errorProneApply + errorProneSuppress applies fixes and suppressions on previously suppressed elements'() {
// language=Java
writeJavaSourceFileToSourceSets '''
package app;
@SuppressWarnings("ArrayEquals")
public final class App {
private static final String EMPTY_STRING = "";

// Although InlineTrivialConstant can be placed lower in the AST hierarchy,
// we preserve existing suppressions whenever possible rather than move suppressions around.
// Also, note that we don't add for-rollout here.
@SuppressWarnings({"ArrayEquals", "InlineTrivialConstant"})
static class Inner {
private static final String EMPTY = "";
boolean truism = new int[3].equals(new int[3]);

@SuppressWarnings("InlineTrivialConstant")
static class InnerInner {
@SuppressWarnings({"ArrayEquals", "InlineTrivialConstant"})
void method() {
new int[3].equals(new int[3]);
}
}
}
}
'''.stripIndent(true)
when:
runTasksSuccessfully('compileAllErrorProne', '-PerrorProneRemoveUnused', '-PerrorProneSuppress', '-PerrorProneApply=ArrayEquals')
then:
// language=Java
resultIsSyntacticallyEqualTo '''
package app;
import java.util.Arrays;

public final class App {
@SuppressWarnings("for-rollout:InlineTrivialConstant")
private static final String EMPTY_STRING = "";

// Although InlineTrivialConstant can be placed lower in the AST hierarchy,
// we preserve existing suppressions whenever possible rather than move suppressions around.
// Also, note that we don't add for-rollout here.
@SuppressWarnings("InlineTrivialConstant")
static class Inner {
private static final String EMPTY = "";
boolean truism = Arrays.equals(new int[3], new int[3]);

static class InnerInner {
void method() {
Arrays.equals(new int[3], new int[3]);
}
}
}
}
'''.stripIndent(true)
}
Copy link
Contributor Author

@kelvinou01 kelvinou01 Sep 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚨 TLDR of what this PR enables

* <p>This class uses bytecode manipulation to patch {@code SuppressibleTreePathScanner::isSuppressed}
* to respect the ErrorProneOptions setting.
*/
final class SuppressibleTreePathScannerClassVisitor extends ClassVisitor {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed in person, we should try to get the issue fixed in error-prone before resorting to further asm modification.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, lets see how the PR does

google/error-prone#5255

return description;
}

Set<String> modes = visitorState.errorProneOptions().getFlags().getSetOrEmpty("SuppressibleErrorProne:Mode");
Copy link
Contributor

@CRogers CRogers Sep 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mmm, putting the mode in here kinda odd, especially as we could be in multiple modes. just realised this is a Set, but maybe we could have a nice abstract here - would need to think about this more.

…e into okelvin/remove-apply-suppress

# Conflicts:
#	gradle-suppressible-error-prone/src/test/groovy/com/palantir/gradle/suppressibleerrorprone/SuppressibleErrorPronePluginIntegrationTest.groovy
#	suppressible-error-prone/src/main/java/com/palantir/suppressibleerrorprone/RemoveRolloutSuppressions.java
#	suppressible-error-prone/src/main/java/com/palantir/suppressibleerrorprone/SuppressWarningsUtils.java
#	versions.lock
#	versions.props
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants