@@ -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
0 commit comments