Skip to content

Commit 27f96dd

Browse files
committed
Chonky boi
1 parent e8e94ac commit 27f96dd

File tree

3 files changed

+435
-9
lines changed

3 files changed

+435
-9
lines changed

gradle-suppressible-error-prone/src/test/groovy/com/palantir/gradle/suppressibleerrorprone/SuppressibleErrorPronePluginIntegrationTest.groovy

Lines changed: 349 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ class SuppressibleErrorPronePluginIntegrationTest extends ConfigurationCacheSpec
9292
errorprone 'com.palantir.suppressible-error-prone:test-error-prone-checks:' + project.findProperty("suppressibleErrorProneVersion")
9393
}
9494
95-
9695
suppressibleErrorProne {
9796
configureEachErrorProneOptions {
9897
// These interfere with some tests, so disable them
@@ -1611,6 +1610,355 @@ class SuppressibleErrorPronePluginIntegrationTest extends ConfigurationCacheSpec
16111610
!output.contains('[RemoveRolloutSuppressions]')
16121611
}
16131612
1613+
def 'errorProneRemoveUnused removes only unused error-prone suppressions, and leaves unknown suppressions untouched'() {
1614+
// language=Java
1615+
writeJavaSourceFileToSourceSets '''
1616+
package app;
1617+
1618+
@SuppressWarnings({"ArrayToString", "UnnecessaryFinal", "InlineTrivialConstant", "NotAnErrorProne", "checkstyle:Bla",})
1619+
public final class App {
1620+
private static final String EMPTY_STRING = "";
1621+
1622+
public static void main(String[] args) {
1623+
new int[3].toString();
1624+
}
1625+
}
1626+
'''.stripIndent(true)
1627+
1628+
when:
1629+
runTasksSuccessfully('compileAllErrorProne', '-PerrorProneRemoveUnused=ArrayToString')
1630+
1631+
then:
1632+
// language=Java
1633+
javaSourceIsSyntacticallyEqualTo '''
1634+
package app;
1635+
1636+
@SuppressWarnings({"ArrayToString", "InlineTrivialConstant", "NotAnErrorProne", "checkstyle:Bla"})
1637+
public final class App {
1638+
private static final String EMPTY_STRING = "";
1639+
1640+
public static void main(String[] args) {
1641+
new int[3].toString();
1642+
}
1643+
}
1644+
'''.stripIndent(true)
1645+
}
1646+
1647+
def 'errorProneRemoveUnused only keeps the closest suppression to a violation'() {
1648+
// language=Java
1649+
writeJavaSourceFileToSourceSets '''
1650+
package app;
1651+
1652+
@SuppressWarnings("InlineTrivialConstant")
1653+
public final class App {
1654+
@SuppressWarnings("InlineTrivialConstant")
1655+
private static final String EMPTY_STRING = "";
1656+
1657+
@SuppressWarnings("InlineTrivialConstant")
1658+
class Inner {
1659+
@SuppressWarnings("InlineTrivialConstant")
1660+
class InnerInner {
1661+
@SuppressWarnings("InlineTrivialConstant")
1662+
class InnerInnerInner {
1663+
private static final String EMPTY = "";
1664+
}
1665+
}
1666+
}
1667+
}
1668+
'''.stripIndent(true)
1669+
1670+
when:
1671+
runTasksSuccessfully('compileAllErrorProne', '-PerrorProneRemoveUnused')
1672+
1673+
then:
1674+
1675+
// language=Java
1676+
javaSourceIsSyntacticallyEqualTo '''
1677+
package app;
1678+
1679+
public final class App {
1680+
@SuppressWarnings("InlineTrivialConstant")
1681+
private static final String EMPTY_STRING = "";
1682+
1683+
class Inner {
1684+
class InnerInner {
1685+
@SuppressWarnings("InlineTrivialConstant")
1686+
class InnerInnerInner {
1687+
private static final String EMPTY = "";
1688+
}
1689+
}
1690+
}
1691+
}
1692+
'''.stripIndent(true)
1693+
}
1694+
1695+
def 'errorProneRemoveUnused handles multiple suppressions on different tree types gracefully'() {
1696+
// Here we test the three types of trees you can suppress — ClassTree, MethodTree, VariableTree
1697+
1698+
// language=Java
1699+
writeJavaSourceFileToSourceSets '''
1700+
package app;
1701+
1702+
@SuppressWarnings({"ArrayEquals", "InlineTrivialConstant"})
1703+
public final class App {
1704+
@SuppressWarnings("InlineTrivialConstant")
1705+
private static final String EMPTY_STRING = "";
1706+
1707+
// Doesn't move an already existing suppression, even if it could be closer to the violation
1708+
@SuppressWarnings({"ArrayEquals", "InlineTrivialConstant"})
1709+
static class Inner {
1710+
@SuppressWarnings("InlineTrivialConstant")
1711+
private static final String EMPTY = "";
1712+
boolean truism = new int[3].equals(new int[3]);
1713+
1714+
@SuppressWarnings("InlineTrivialConstant")
1715+
static class InnerInner {
1716+
@SuppressWarnings({"ArrayEquals", "InlineTrivialConstant"})
1717+
void method() {
1718+
new int[3].equals(new int[3]);
1719+
}
1720+
}
1721+
}
1722+
}
1723+
'''.stripIndent(true)
1724+
1725+
when:
1726+
runTasksSuccessfully('compileAllErrorProne', '-PerrorProneRemoveUnused')
1727+
1728+
then:
1729+
1730+
// language=Java
1731+
javaSourceIsSyntacticallyEqualTo '''
1732+
package app;
1733+
1734+
public final class App {
1735+
@SuppressWarnings("InlineTrivialConstant")
1736+
private static final String EMPTY_STRING = "";
1737+
1738+
// Doesn't move an already existing suppression, even if it could be closer to the violation
1739+
@SuppressWarnings("ArrayEquals")
1740+
static class Inner {
1741+
@SuppressWarnings("InlineTrivialConstant")
1742+
private static final String EMPTY = "";
1743+
1744+
boolean truism = new int[3].equals(new int[3]);
1745+
1746+
static class InnerInner {
1747+
@SuppressWarnings("ArrayEquals")
1748+
void method() {
1749+
new int[3].equals(new int[3]);
1750+
}
1751+
}
1752+
}
1753+
}
1754+
'''.stripIndent(true)
1755+
}
1756+
1757+
def 'errorProneRemoveUnused removes entire SuppressWarnings annotation when all suppressions are unused'() {
1758+
// language=Java
1759+
writeJavaSourceFileToSourceSets '''
1760+
package app;
1761+
1762+
@SuppressWarnings({"UnusedVariable", "ArrayToString"})
1763+
public final class App {
1764+
public static void main(String[] args) {
1765+
System.out.println("No violations here");
1766+
}
1767+
}
1768+
'''.stripIndent(true)
1769+
1770+
when:
1771+
runTasksSuccessfully('compileAllErrorProne', '-PerrorProneRemoveUnused')
1772+
1773+
then:
1774+
// language=Java
1775+
javaSourceIsSyntacticallyEqualTo '''
1776+
package app;
1777+
1778+
public final class App {
1779+
public static void main(String[] args) {
1780+
System.out.println("No violations here");
1781+
}
1782+
}
1783+
'''.stripIndent(true)
1784+
}
1785+
1786+
def 'errorProneRemoveUnused and errorProneSuppress uses existing suppressions if possible'() {
1787+
// language=Java
1788+
writeJavaSourceFileToSourceSets '''
1789+
package app;
1790+
1791+
@SuppressWarnings("InlineTrivialConstant")
1792+
public final class App {
1793+
@SuppressWarnings("InlineTrivialConstant")
1794+
private static final String EMPTY_STRING = "";
1795+
1796+
@SuppressWarnings("InlineTrivialConstant")
1797+
static class Inner {
1798+
@SuppressWarnings("InlineTrivialConstant")
1799+
private static final String EMPTY = "";
1800+
boolean truism = new int[3].equals(new int[3]);
1801+
1802+
@SuppressWarnings("InlineTrivialConstant")
1803+
static class InnerInner {
1804+
@SuppressWarnings({"ArrayEquals", "InlineTrivialConstant"})
1805+
void method() {
1806+
new int[3].equals(new int[3]);
1807+
}
1808+
}
1809+
}
1810+
}
1811+
'''.stripIndent(true)
1812+
1813+
when:
1814+
runTasksSuccessfully('compileAllErrorProne', '-PerrorProneRemoveUnused', '-PerrorProneSuppress')
1815+
1816+
then:
1817+
1818+
// language=Java
1819+
javaSourceIsSyntacticallyEqualTo '''
1820+
package app;
1821+
1822+
public final class App {
1823+
@SuppressWarnings("InlineTrivialConstant")
1824+
private static final String EMPTY_STRING = "";
1825+
1826+
static class Inner {
1827+
@SuppressWarnings("InlineTrivialConstant")
1828+
private static final String EMPTY = "";
1829+
1830+
@SuppressWarnings("for-rollout:ArrayEquals")
1831+
boolean truism = new int[3].equals(new int[3]);
1832+
1833+
static class InnerInner {
1834+
@SuppressWarnings("ArrayEquals")
1835+
void method() {
1836+
new int[3].equals(new int[3]);
1837+
}
1838+
}
1839+
}
1840+
}
1841+
'''.stripIndent(true)
1842+
}
1843+
1844+
def 'errorProneRemoveUnused and errorProneApply applies fixes on previously suppressed elements'() {
1845+
// language=Java
1846+
writeJavaSourceFileToSourceSets '''
1847+
package app;
1848+
@SuppressWarnings({"ArrayEquals", "InlineTrivialConstant"})
1849+
public final class App {
1850+
@SuppressWarnings("InlineTrivialConstant")
1851+
private static final String EMPTY_STRING = "";
1852+
1853+
@SuppressWarnings({"ArrayEquals", "InlineTrivialConstant"})
1854+
static class Inner {
1855+
@SuppressWarnings("InlineTrivialConstant")
1856+
private static final String EMPTY = "";
1857+
boolean truism = new int[3].equals(new int[3]);
1858+
1859+
@SuppressWarnings("InlineTrivialConstant")
1860+
static class InnerInner {
1861+
@SuppressWarnings({"ArrayEquals", "InlineTrivialConstant"})
1862+
void method() {
1863+
new int[3].equals(new int[3]);
1864+
}
1865+
}
1866+
}
1867+
}
1868+
'''.stripIndent(true)
1869+
1870+
when:
1871+
runTasksSuccessfully('compileAllErrorProne', '-PerrorProneRemoveUnused', '-PerrorProneApply=ArrayEquals')
1872+
1873+
then:
1874+
1875+
// language=Java
1876+
javaSourceIsSyntacticallyEqualTo '''
1877+
package app;
1878+
1879+
import java.util.Arrays;
1880+
1881+
public final class App {
1882+
@SuppressWarnings("InlineTrivialConstant")
1883+
private static final String EMPTY_STRING = "";
1884+
1885+
static class Inner {
1886+
@SuppressWarnings("InlineTrivialConstant")
1887+
private static final String EMPTY = "";
1888+
1889+
boolean truism = Arrays.equals(new int[3], new int[3]);
1890+
1891+
static class InnerInner {
1892+
void method() {
1893+
Arrays.equals(new int[3], new int[3]);
1894+
}
1895+
}
1896+
}
1897+
}
1898+
'''.stripIndent(true)
1899+
}
1900+
1901+
def 'errorProneRemoveUnused + errorProneApply + errorProneSuppress applies fixes and suppressions on previously suppressed elements'() {
1902+
// language=Java
1903+
writeJavaSourceFileToSourceSets '''
1904+
package app;
1905+
1906+
@SuppressWarnings("ArrayEquals")
1907+
public final class App {
1908+
private static final String EMPTY_STRING = "";
1909+
1910+
// Although InlineTrivialConstant can be placed lower in the AST hierarchy,
1911+
// we preserve existing suppressions whenever possible rather than move suppressions around.
1912+
// Also, note that we don't add for-rollout here.
1913+
@SuppressWarnings({"ArrayEquals", "InlineTrivialConstant"})
1914+
static class Inner {
1915+
private static final String EMPTY = "";
1916+
boolean truism = new int[3].equals(new int[3]);
1917+
1918+
@SuppressWarnings("InlineTrivialConstant")
1919+
static class InnerInner {
1920+
@SuppressWarnings({"ArrayEquals", "InlineTrivialConstant"})
1921+
void method() {
1922+
new int[3].equals(new int[3]);
1923+
}
1924+
}
1925+
}
1926+
}
1927+
'''.stripIndent(true)
1928+
1929+
when:
1930+
runTasksSuccessfully('compileAllErrorProne', '-PerrorProneRemoveUnused', '-PerrorProneSuppress', '-PerrorProneApply=ArrayEquals')
1931+
1932+
then:
1933+
1934+
// language=Java
1935+
javaSourceIsSyntacticallyEqualTo '''
1936+
package app;
1937+
1938+
import java.util.Arrays;
1939+
1940+
public final class App {
1941+
@SuppressWarnings("for-rollout:InlineTrivialConstant")
1942+
private static final String EMPTY_STRING = "";
1943+
1944+
// Although InlineTrivialConstant can be placed lower in the AST hierarchy,
1945+
// we preserve existing suppressions whenever possible rather than move suppressions around.
1946+
// Also, note that we don't add for-rollout here.
1947+
@SuppressWarnings("InlineTrivialConstant")
1948+
static class Inner {
1949+
private static final String EMPTY = "";
1950+
boolean truism = Arrays.equals(new int[3], new int[3]);
1951+
1952+
static class InnerInner {
1953+
void method() {
1954+
Arrays.equals(new int[3], new int[3]);
1955+
}
1956+
}
1957+
}
1958+
}
1959+
'''.stripIndent(true)
1960+
}
1961+
16141962
def 'error-prone dependencies have versions bound together by a virtual platform'() {
16151963
setup: 'when an error-prone dependency is forced to certain version'
16161964
// language=Gradle

suppressible-error-prone/src/main/java/com/palantir/suppressibleerrorprone/ReportedFixCache.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ final class ReportedFixCache {
4040

4141
public static final Predicate<String> REMOVE_EVERYTHING = bc -> false;
4242
public static final Predicate<String> KEEP_EVERYTHING = bc -> true;
43+
public static final Predicate<String> NOT_AN_ERRORPRONE = suppression -> {
44+
String checkerName = suppression.startsWith(CommonConstants.AUTOMATICALLY_ADDED_PREFIX)
45+
? suppression.substring(CommonConstants.AUTOMATICALLY_ADDED_PREFIX.length())
46+
: suppression;
47+
return !AllErrorprones.allBugcheckerNames().contains(checkerName);
48+
};
4349

4450
ReportedFixCache() {}
4551

@@ -67,6 +73,16 @@ public LazySuppressionFix reportNew(
6773
return cache.put(declaration.getLeaf(), createAndReportFix(declaration, visitorState, filterExisting));
6874
}
6975

76+
/**
77+
* Gets an existing {@code LazySuppressionFix} on {@code declaration}
78+
*/
79+
public LazySuppressionFix getExisting(TreePath declaration) {
80+
if (!cache.containsKey(declaration.getLeaf())) {
81+
throw new IllegalArgumentException("A fix on this declaration must already exists");
82+
}
83+
return cache.get(declaration.getLeaf());
84+
}
85+
7086
private LazySuppressionFix createAndReportFix(
7187
TreePath declaration, VisitorState state, Predicate<String> filterExisting) {
7288
if (!SuppressWarningsUtils.suppressibleTreePath(declaration)) {

0 commit comments

Comments
 (0)