diff --git a/src/functionalTest/groovy/com/github/spotbugs/snom/ExtensionFunctionalTest.groovy b/src/functionalTest/groovy/com/github/spotbugs/snom/ExtensionFunctionalTest.groovy index b9286b26..4bc466c9 100644 --- a/src/functionalTest/groovy/com/github/spotbugs/snom/ExtensionFunctionalTest.groovy +++ b/src/functionalTest/groovy/com/github/spotbugs/snom/ExtensionFunctionalTest.groovy @@ -106,6 +106,30 @@ spotbugs { assertTrue(result.getOutput().contains(filter.getAbsolutePath())) } + def "can use baselineFile"() { + setup: + File baseline = new File(rootDir, "baseline.xml") + buildFile << """ +spotbugs { + baselineFile = file('baseline.xml') +}""" + baseline << """ + +""" + when: + def result = GradleRunner.create() + .withProjectDir(rootDir) + .withArguments('spotbugsMain', '--debug') + .withPluginClasspath() + .withGradleVersion(version) + .build() + + then: + assertEquals(SUCCESS, result.task(":spotbugsMain").outcome) + assertTrue(result.getOutput().contains("-excludeBugs")) + assertTrue(result.getOutput().contains(baseline.getAbsolutePath())) + } + def "can use visitors"() { setup: buildFile << """ diff --git a/src/functionalTest/groovy/com/github/spotbugs/snom/StandardFunctionalTest.groovy b/src/functionalTest/groovy/com/github/spotbugs/snom/StandardFunctionalTest.groovy index 455f6930..c809d827 100644 --- a/src/functionalTest/groovy/com/github/spotbugs/snom/StandardFunctionalTest.groovy +++ b/src/functionalTest/groovy/com/github/spotbugs/snom/StandardFunctionalTest.groovy @@ -642,4 +642,73 @@ public class SimpleTest { where: isWorkerApi << [true, false] } + + @Unroll + def 'ignore bugs from baseline file (Worker API? #isWorkerApi)'() { + given: + def badCode = new File(rootDir, 'src/main/java/Bar.java') + badCode << ''' + |public class Bar { + | public int unreadField = 42; // warning: URF_UNREAD_FIELD + |} + |'''.stripMargin() + def baseline = new File(rootDir, 'baseline.xml') + baseline << ''' + + + Unread public/protected field + Unread public/protected field: Bar.unreadField + + + At Bar.java:[lines 2-3] + + In class Bar + + + + In Bar.java + + Field Bar.unreadField + + + At Bar.java:[line 3] + + + + Dodgy code + + + Unread public/protected field + + + Champ non lu + + + '''.stripMargin() + buildFile << """ +spotbugs { + baselineFile = file('baseline.xml') +}""" + + when: + def arguments = [':spotbugsMain'] + if(!isWorkerApi) { + arguments.add('-Pcom.github.spotbugs.snom.worker=false') + } + def runner = GradleRunner.create() + .withProjectDir(rootDir) + .withArguments(arguments) + .withPluginClasspath() + .forwardOutput() + .withGradleVersion(version) + .withDebug(true) + + def result = runner.build() + + then: + result.task(':spotbugsMain').outcome == TaskOutcome.SUCCESS + + where: + isWorkerApi << [true, false] + } } diff --git a/src/main/groovy/com/github/spotbugs/snom/SpotBugsExtension.groovy b/src/main/groovy/com/github/spotbugs/snom/SpotBugsExtension.groovy index 22b1e746..20a41460 100644 --- a/src/main/groovy/com/github/spotbugs/snom/SpotBugsExtension.groovy +++ b/src/main/groovy/com/github/spotbugs/snom/SpotBugsExtension.groovy @@ -112,6 +112,12 @@ class SpotBugsExtension { */ @NonNull final RegularFileProperty excludeFilter; + /** + * Property to set the baseline file. This file is a Spotbugs result file, and all bugs reported in this file will not be + * reported in the final output. + */ + @NonNull + final RegularFileProperty baselineFile; /** * Property to specify the target classes for analysis. Default value is empty that means all classes are analyzed. */ @@ -162,6 +168,7 @@ class SpotBugsExtension { reportsDir = objects.directoryProperty() includeFilter = objects.fileProperty() excludeFilter = objects.fileProperty() + baselineFile = objects.fileProperty() onlyAnalyze = objects.listProperty(String); projectName = objects.property(String); release = objects.property(String); diff --git a/src/main/groovy/com/github/spotbugs/snom/SpotBugsTask.groovy b/src/main/groovy/com/github/spotbugs/snom/SpotBugsTask.groovy index a706fdfd..e4f183a6 100644 --- a/src/main/groovy/com/github/spotbugs/snom/SpotBugsTask.groovy +++ b/src/main/groovy/com/github/spotbugs/snom/SpotBugsTask.groovy @@ -171,6 +171,15 @@ class SpotBugsTask extends DefaultTask implements VerificationTask { @PathSensitive(PathSensitivity.RELATIVE) @NonNull final RegularFileProperty excludeFilter; + /** + * Property to set the baseline file. This file is a Spotbugs result file, and all bugs reported in this file will not be + * reported in the final output. + */ + @Optional + @InputFile + @PathSensitive(PathSensitivity.RELATIVE) + @NonNull + final RegularFileProperty baselineFile; /** * Property to specify the target classes for analysis. Default value is empty that means all classes are analyzed. */ @@ -306,6 +315,7 @@ class SpotBugsTask extends DefaultTask implements VerificationTask { }); includeFilter = objects.fileProperty() excludeFilter = objects.fileProperty() + baselineFile = objects.fileProperty() onlyAnalyze = objects.listProperty(String); projectName = objects.property(String); release = objects.property(String); @@ -333,6 +343,7 @@ class SpotBugsTask extends DefaultTask implements VerificationTask { reportsDir.convention(extension.reportsDir) includeFilter.convention(extension.includeFilter) excludeFilter.convention(extension.excludeFilter) + baselineFile.convention(extension.baselineFile) onlyAnalyze.convention(extension.onlyAnalyze) projectName.convention(extension.projectName.map({p -> String.format("%s (%s)", p, getName())})) release.convention(extension.release) diff --git a/src/main/groovy/com/github/spotbugs/snom/internal/SpotBugsRunner.java b/src/main/groovy/com/github/spotbugs/snom/internal/SpotBugsRunner.java index 3540578d..f8792420 100644 --- a/src/main/groovy/com/github/spotbugs/snom/internal/SpotBugsRunner.java +++ b/src/main/groovy/com/github/spotbugs/snom/internal/SpotBugsRunner.java @@ -100,6 +100,10 @@ protected List buildArguments(SpotBugsTask task) { args.add("-exclude"); args.add(task.getExcludeFilter().get().getAsFile().getAbsolutePath()); } + if (task.getBaselineFile().isPresent() && task.getBaselineFile().get() != null) { + args.add("-excludeBugs"); + args.add(task.getBaselineFile().get().getAsFile().getAbsolutePath()); + } if (task.getOnlyAnalyze().isPresent() && !task.getOnlyAnalyze().get().isEmpty()) { args.add("-onlyAnalyze"); args.add(task.getOnlyAnalyze().get().stream().collect(Collectors.joining(",")));