diff --git a/README.md b/README.md index 4c0073b..3750701 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ The plugin supports various static analysis tools for Java, Kotlin and Android p * [`Checkstyle`](docs/tools/checkstyle.md) * [`PMD`](docs/tools/pmd.md) * [`FindBugs`](docs/tools/findbugs.md) + * [`SpotBugs`](docs/tools/spotbugs.md) * [`Detekt`](docs/tools/detekt.md) * [`Android Lint`](docs/tools/android_lint.md) * [`KtLint`](docs/tools/ktlint.md) @@ -31,7 +32,6 @@ Please note that the tools availability depends on the project the plugin is app ### Tools in-consideration - * `Spotbugs` [#142](https://github.com/novoda/gradle-static-analysis-plugin/issues/142) * `CPD (Duplicate Code Detection) ` [#150](https://github.com/novoda/gradle-static-analysis-plugin/issues/150) * `error-prone` [#151](https://github.com/novoda/gradle-static-analysis-plugin/issues/151) * `Jetbrains IDEA Inspections` [#152](https://github.com/novoda/gradle-static-analysis-plugin/issues/152) @@ -80,6 +80,7 @@ staticAnalysis { checkstyle { } pmd { } findbugs { } + spotbugs { } detekt { } lintOptions { } } @@ -89,7 +90,7 @@ This will enable all the tools with their default settings and create `evaluateV [advanced usage](docs/advanced-usage.md) and to the [supported tools](docs/supported-tools.md) pages. ## Sample app -There are two sample Android projects available, one consisting of a regular app - available [here](https://github.com/novoda/gradle-static-analysis-plugin/tree/master/sample) - and the other comprising a multi-module setup available [here](https://github.com/novoda/gradle-static-analysis-plugin/tree/master/sample-multi-module). Both sample projects showcase a setup featuring Checkstyle, FindBugs, PMD, Lint and Detekt. +There are two sample Android projects available, one consisting of a regular app - available [here](https://github.com/novoda/gradle-static-analysis-plugin/tree/master/sample) - and the other comprising a multi-module setup available [here](https://github.com/novoda/gradle-static-analysis-plugin/tree/master/sample-multi-module). Both sample projects showcase a setup featuring Checkstyle, FindBugs, SpotBugs, PMD, Lint, Ktlint and Detekt. ## Snapshots [![CI status](https://ci.novoda.com/buildStatus/icon?job=gradle-static-analysis-plugin-snapshot)](https://ci.novoda.com/job/gradle-static-analysis-plugin-snapshot/lastBuild/console) [![Download from Bintray](https://api.bintray.com/packages/novoda-oss/snapshots/gradle-static-analysis-plugin/images/download.svg)](https://bintray.com/novoda-oss/snapshots/gradle-static-analysis-plugin/_latestVersion) diff --git a/docs/supported-tools.md b/docs/supported-tools.md index 40905bd..8cff379 100644 --- a/docs/supported-tools.md +++ b/docs/supported-tools.md @@ -8,6 +8,7 @@ Tool | Java | Android
(Java) | Kotlin | Android
(Kotlin) [`Checkstyle`](https://checkstyle.sourceforge.net) | :white_check_mark: | :white_check_mark: | — | — [`PMD`](https://pmd.github.io) | :white_check_mark: | :white_check_mark: | — | — [`FindBugs`](http://findbugs.sourceforge.net/) | :white_check_mark: | :white_check_mark: | — | — +[`SpotBugs`](https://spotbugs.github.io/) | :white_check_mark: | :white_check_mark: | — | — [`Detekt`](https://github.com/arturbosch/detekt) | — | — | :white_check_mark: | :white_check_mark: [`Android Lint`](https://developer.android.com/studio/write/lint.html) | — | :white_check_mark:️ | — | :white_check_mark:️ [`KtLint`](https://github.com/shyiko/ktlint) | — | — | :white_check_mark:️ | :white_check_mark:️ @@ -22,6 +23,7 @@ For additional informations and tips on how to obtain advanced behaviours with t * [Checkstyle](tools/checkstyle.md) * [PMD](tools/pmd.md) * [Findbugs](tools/findbugs.md) + * [SpotBugs](tools/spotbugs.md) * [Android Lint](tools/android_lint.md) * [KtLint](tools/ktlint.md) * [Example configurations](#example-configurations) @@ -40,6 +42,7 @@ staticAnalysis { checkstyle {} pmd {} findbugs {} + spotbugs {} lintOptions {} detekt {} ktlint {} diff --git a/docs/tools/spotbugs.md b/docs/tools/spotbugs.md new file mode 100644 index 0000000..2303074 --- /dev/null +++ b/docs/tools/spotbugs.md @@ -0,0 +1,29 @@ +# SpotBugs +[SpotBugs](https://spotbugs.github.io/) is a static analysis tool that looks for potential bugs in Java code. It does not support Kotlin. +It can be used in both pure Java, and Android Java projects. It then only makes sense to have SpotBugs enabled if you have Java code in your project. +The plugin only runs SpotBugs on projects that contain the Java or the Android plugin. + +## Table of contents + * [Configure SpotBugs](#configure-spotbugs) + * [SpotBugs in mixed-language projects](#spotbugs-in-mixed-language-projects) + +--- + +## Configure SpotBugs +Enabling and configuring SpotBugs for a project is done through the `spotbugs` closure: + +```gradle +spotbugs { + toolVersion // Optional string, the latest SpotBugs release (currently 4.0.0-beta4) + excludeFilter // A file containing the SpotBugs exclusions, e.g., teamPropsFile('static-analysis/spotbugs-excludes.xml') + htmlReportEnabled true // Control whether html report generation should be enabled. `true` by default. + includeVariants { variant -> ... } // A closure to determine which variants (only for Android) to include +} +``` + +(assuming you're using the Novoda scaffolding system, see [Example configurations](#example-configurations) for more details) + +For more information about SpotBugs rules, refer to the [official website](https://spotbugs.readthedocs.io/en/latest/bugDescriptions.html). + +## SpotBugs in mixed-language projects +If your project mixes Java and Kotlin code, you will need to exclude your Kotlin files by using `excludeFilter` diff --git a/plugin/src/main/groovy/com/novoda/staticanalysis/StaticAnalysisPlugin.groovy b/plugin/src/main/groovy/com/novoda/staticanalysis/StaticAnalysisPlugin.groovy index 2e3de10..36f1719 100644 --- a/plugin/src/main/groovy/com/novoda/staticanalysis/StaticAnalysisPlugin.groovy +++ b/plugin/src/main/groovy/com/novoda/staticanalysis/StaticAnalysisPlugin.groovy @@ -7,6 +7,7 @@ import com.novoda.staticanalysis.internal.findbugs.FindbugsConfigurator import com.novoda.staticanalysis.internal.ktlint.KtlintConfigurator import com.novoda.staticanalysis.internal.lint.LintConfigurator import com.novoda.staticanalysis.internal.pmd.PmdConfigurator +import com.novoda.staticanalysis.internal.spotbugs.SpotBugsConfigurator import org.gradle.api.NamedDomainObjectContainer import org.gradle.api.Plugin import org.gradle.api.Project @@ -42,6 +43,7 @@ class StaticAnalysisPlugin implements Plugin { CheckstyleConfigurator.create(project, violationsContainer, evaluateViolations), PmdConfigurator.create(project, violationsContainer, evaluateViolations), FindbugsConfigurator.create(project, violationsContainer, evaluateViolations), + SpotBugsConfigurator.create(project, violationsContainer, evaluateViolations), DetektConfigurator.create(project, violationsContainer, evaluateViolations), KtlintConfigurator.create(project, violationsContainer, evaluateViolations), LintConfigurator.create(project, violationsContainer, evaluateViolations) diff --git a/plugin/src/main/groovy/com/novoda/staticanalysis/internal/spotbugs/SpotBugsConfigurator.groovy b/plugin/src/main/groovy/com/novoda/staticanalysis/internal/spotbugs/SpotBugsConfigurator.groovy new file mode 100644 index 0000000..75b199d --- /dev/null +++ b/plugin/src/main/groovy/com/novoda/staticanalysis/internal/spotbugs/SpotBugsConfigurator.groovy @@ -0,0 +1,171 @@ +package com.novoda.staticanalysis.internal.spotbugs + +import com.novoda.staticanalysis.StaticAnalysisExtension +import com.novoda.staticanalysis.Violations +import com.novoda.staticanalysis.internal.Configurator +import com.novoda.staticanalysis.internal.VariantFilter +import com.novoda.staticanalysis.internal.findbugs.CollectFindbugsViolationsTask +import com.novoda.staticanalysis.internal.findbugs.GenerateFindBugsHtmlReport +import org.gradle.api.* +import org.gradle.api.tasks.SourceTask + +import static com.novoda.staticanalysis.internal.Exceptions.handleException +import static com.novoda.staticanalysis.internal.TasksCompat.createTask + +class SpotBugsConfigurator implements Configurator { + + private static final String SPOTBUGS_PLUGIN = 'com.github.spotbugs' + private static final String SPOTBUGS_NOT_APPLIED = "The SpotBugs plugin is configured but not applied. Please apply the plugin: $SPOTBUGS_PLUGIN in your build script." + private static final String SPOTBUGS_CONFIGURATION_ERROR = "A problem occurred while configuring SpotBugs." + + private final Project project + private final Violations violations + private final Task evaluateViolations + private final VariantFilter variantFilter + protected boolean htmlReportEnabled = true + protected boolean configured = false + + static SpotBugsConfigurator create(Project project, + NamedDomainObjectContainer violationsContainer, + Task evaluateViolations) { + Violations violations = violationsContainer.maybeCreate('SpotBugs') + return new SpotBugsConfigurator(project, violations, evaluateViolations) + } + + SpotBugsConfigurator(Project project, Violations violations, Task evaluateViolations) { + this.project = project + this.violations = violations + this.evaluateViolations = evaluateViolations + this.variantFilter = new VariantFilter(project) + } + + @Override + void execute() { + project.extensions.findByType(StaticAnalysisExtension).ext.spotbugs = { Closure config -> + if (!project.plugins.hasPlugin(SPOTBUGS_PLUGIN)) { + throw new GradleException(SPOTBUGS_NOT_APPLIED) + } + + configureSpotBugsExtension(config) + + project.plugins.withId('com.android.application') { + configureAndroidWithVariants(variantFilter.filteredApplicationVariants) + } + project.plugins.withId('com.android.library') { + configureAndroidWithVariants(variantFilter.filteredLibraryVariants) + } + project.plugins.withId('java') { + configureJavaProject() + } + } + } + + private void configureSpotBugsExtension(Closure config) { + try { + def spotbugs = project.spotbugs + spotbugs.ext.includeVariants = { Closure filter -> + variantFilter.includeVariantsFilter = filter + } + spotbugs.ext.htmlReportEnabled = { boolean enabled -> this.htmlReportEnabled = enabled } + config.delegate = spotbugs + config.resolveStrategy = Closure.DELEGATE_FIRST + config() + } catch (Exception exception) { + handleException(SPOTBUGS_CONFIGURATION_ERROR, exception) + } + } + + protected void configureAndroidWithVariants(DomainObjectSet variants) { + if (configured) return + + variants.all { configureVariant(it) } + variantFilter.filteredTestVariants.all { configureVariant(it) } + variantFilter.filteredUnitTestVariants.all { configureVariant(it) } + configured = true + } + + private void configureVariant(variant) { + createToolTaskForAndroid(variant) + def collectViolations = createCollectViolations(getToolTaskNameFor(variant), violations) + evaluateViolations.dependsOn collectViolations + } + + private void createToolTaskForAndroid(variant) { + createTask(project, getToolTaskNameFor(variant), Class.forName('com.github.spotbugs.SpotBugsTask')) { SourceTask task -> + def javaCompile = javaCompile(variant) + def androidSourceDirs = variant.sourceSets.collect { + it.javaDirectories + }.flatten() + task.description = "Run SpotBugs analysis for ${variant.name} classes" + task.setSource(androidSourceDirs) + task.classpath = javaCompile.classpath + task.extraArgs '-auxclasspath', androidJar + task.conventionMapping.map("classes") { + project.fileTree(javaCompile.destinationDir) + } + task.dependsOn javaCompile + } + } + + private void configureJavaProject() { + if (configured) return + + project.sourceSets.all { sourceSet -> + def collectViolations = createCollectViolations(getToolTaskNameFor(sourceSet), violations) + evaluateViolations.dependsOn collectViolations + } + configured = true + } + + private def createCollectViolations(String taskName, Violations violations) { + if (htmlReportEnabled) { + createHtmlReportTask(taskName) + } + createTask(project, "collect${taskName.capitalize()}Violations", CollectFindbugsViolationsTask) { task -> + def spotbugs = project.tasks[taskName] as SourceTask + configureToolTask(spotbugs) + task.xmlReportFile = spotbugs.reports.xml.destination + task.violations = violations + + if (htmlReportEnabled) { + task.dependsOn project.tasks["generate${taskName.capitalize()}HtmlReport"] + } else { + task.dependsOn spotbugs + } + } + } + + private void createHtmlReportTask(String taskName) { + createTask(project, "generate${taskName.capitalize()}HtmlReport", GenerateFindBugsHtmlReport) { GenerateFindBugsHtmlReport task -> + def spotbugs = project.tasks[taskName] + task.xmlReportFile = spotbugs.reports.xml.destination + task.htmlReportFile = new File(task.xmlReportFile.absolutePath - '.xml' + '.html') + task.classpath = spotbugs.spotbugsClasspath + task.dependsOn spotbugs + } + } + + private static void configureToolTask(SourceTask task) { + task.group = 'verification' + task.exclude '**/*.kt' + task.ignoreFailures = true + task.reports.xml.enabled = true + task.reports.html.enabled = false + } + + private static String getToolTaskNameFor(named) { + "spotbugs${named.name.capitalize()}" + } + + private static def javaCompile(variant) { + if (variant.hasProperty('javaCompileProvider')) { + variant.javaCompileProvider.get() + } else { + variant.javaCompile + } + } + + private def getAndroidJar() { + "${project.android.sdkDirectory}/platforms/${project.android.compileSdkVersion}/android.jar" + } +} diff --git a/plugin/src/test/groovy/com/novoda/staticanalysis/internal/spotbugs/SpotBugsIntegrationTest.groovy b/plugin/src/test/groovy/com/novoda/staticanalysis/internal/spotbugs/SpotBugsIntegrationTest.groovy new file mode 100644 index 0000000..b3df238 --- /dev/null +++ b/plugin/src/test/groovy/com/novoda/staticanalysis/internal/spotbugs/SpotBugsIntegrationTest.groovy @@ -0,0 +1,195 @@ +package com.novoda.staticanalysis.internal.spotbugs + +import com.google.common.truth.Truth +import com.novoda.test.TestProject +import com.novoda.test.TestProjectRule +import org.gradle.testkit.runner.TaskOutcome +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.Parameterized + +import static com.novoda.test.Fixtures.Findbugs.* +import static com.novoda.test.LogsSubject.assertThat + +@RunWith(Parameterized.class) +class SpotBugsIntegrationTest { + + @Parameterized.Parameters(name = "{0}") + static Iterable rules() { + return [TestProjectRule.forJavaProject(), TestProjectRule.forAndroidProject()] + } + + @Rule + public final TestProjectRule projectRule + + SpotBugsIntegrationTest(TestProjectRule projectRule) { + this.projectRule = projectRule + } + + @Test + void shouldFailBuildWhenSpotBugsWarningsOverTheThreshold() { + TestProject.Result result = createProjectWith() + .withSourceSet('debug', SOURCES_WITH_LOW_VIOLATION, SOURCES_WITH_MEDIUM_VIOLATION) + .withPenalty('''{ + maxErrors = 0 + maxWarnings = 1 + }''') + .withToolsConfig('spotbugs {}') + .buildAndFail('check') + + assertThat(result.logs).containsLimitExceeded(0, 1) + assertThat(result.logs).containsSpotBugsViolations(0, 2, + result.buildFileUrl('reports/spotbugs/debug.html')) + } + + @Test + void shouldFailBuildAfterSecondRunWhenSpotBugsWarningsStillOverTheThreshold() { + def project = createProjectWith() + .withSourceSet('debug', SOURCES_WITH_LOW_VIOLATION, SOURCES_WITH_MEDIUM_VIOLATION) + .withPenalty('''{ + maxErrors = 0 + maxWarnings = 1 + }''') + .withToolsConfig('spotbugs {}') + + TestProject.Result result = project.buildAndFail('check') + + assertThat(result.logs).containsLimitExceeded(0, 1) + assertThat(result.logs).containsSpotBugsViolations(0, 2, + result.buildFileUrl('reports/spotbugs/debug.html')) + + result = project.buildAndFail('check') + + assertThat(result.logs).containsLimitExceeded(0, 1) + assertThat(result.logs).containsSpotBugsViolations(0, 2, + result.buildFileUrl('reports/spotbugs/debug.html')) + } + + @Test + void shouldDetectMoreWarningsWhenEffortIsMaxAndReportLevelIsLow() { + TestProject.Result result = createProjectWith() + .withSourceSet('debug', SOURCES_WITH_LOW_VIOLATION, SOURCES_WITH_MEDIUM_VIOLATION) + .withPenalty('''{ + maxErrors = 0 + maxWarnings = 1 + }''') + .withToolsConfig("spotbugs { effort = 'max' \n reportLevel = 'low'}") + .buildAndFail('check') + + assertThat(result.logs).containsLimitExceeded(0, 2) + assertThat(result.logs).containsSpotBugsViolations(0, 3, + result.buildFileUrl('reports/spotbugs/debug.html')) + } + + @Test + void shouldFailBuildWhenSpotBugsErrorsOverTheThreshold() { + TestProject.Result result = createProjectWith() + .withSourceSet('debug', SOURCES_WITH_HIGH_VIOLATION) + .withPenalty('''{ + maxErrors = 0 + maxWarnings = 0 + }''') + .withToolsConfig('spotbugs {}') + .buildAndFail('check') + + assertThat(result.logs).containsLimitExceeded(1, 0) + assertThat(result.logs).containsSpotBugsViolations(1, 0, + result.buildFileUrl('reports/spotbugs/debug.html')) + } + + @Test + void shouldNotFailBuildWhenNoSpotBugsWarningsOrErrorsEncounteredAndNoThresholdTrespassed() { + TestProject.Result result = createProjectWith() + .withPenalty('''{ + maxErrors = 0 + maxWarnings = 0 + }''') + .withToolsConfig('spotbugs {}') + .build('check') + + assertThat(result.logs).doesNotContainLimitExceeded() + assertThat(result.logs).doesNotContainSpotBugsViolations() + } + + @Test + void shouldNotFailBuildWhenSpotBugsWarningsAndErrorsEncounteredAndNoThresholdTrespassed() { + TestProject.Result result = createProjectWith() + .withSourceSet('debug', SOURCES_WITH_LOW_VIOLATION, SOURCES_WITH_MEDIUM_VIOLATION) + .withSourceSet('release', SOURCES_WITH_HIGH_VIOLATION) + .withPenalty('''{ + maxErrors = 10 + maxWarnings = 10 + }''') + .withToolsConfig('spotbugs {}') + .build('check') + + assertThat(result.logs).doesNotContainLimitExceeded() + assertThat(result.logs).containsSpotBugsViolations(1, 2, + result.buildFileUrl('reports/spotbugs/debug.html'), + result.buildFileUrl('reports/spotbugs/release.html')) + } + + @Test + void shouldNotFailBuildWhenSpotBugsConfiguredToNotIgnoreFailures() { + createProjectWith() + .withSourceSet('debug', SOURCES_WITH_LOW_VIOLATION, SOURCES_WITH_MEDIUM_VIOLATION) + .withSourceSet('release', SOURCES_WITH_HIGH_VIOLATION) + .withPenalty('''{ + maxErrors = 10 + maxWarnings = 10 + }''') + .withToolsConfig('spotbugs { ignoreFailures = false }') + .build('check') + } + + @Test + void shouldNotFailBuildWhenSpotBugsIsConfiguredMultipleTimes() { + createProjectWith() + .withSourceSet('main', SOURCES_WITH_LOW_VIOLATION) + .withPenalty('none') + .withToolsConfig(""" + spotbugs { } + spotbugs { + effort = "max" + } + """) + .build('check') + } + + @Test + void shouldBeUpToDateWhenCheckTaskRunsAgain() { + def project = createProjectWith() + .withSourceSet('debug', SOURCES_WITH_LOW_VIOLATION, SOURCES_WITH_MEDIUM_VIOLATION) + .withSourceSet('release', SOURCES_WITH_HIGH_VIOLATION) + .withPenalty('''{ + maxErrors = 10 + maxWarnings = 10 + }''') + .withToolsConfig('spotbugs {}') + + project.build('check') + + def result = project.build('check') + + Truth.assertThat(result.outcome(':spotbugsDebug')).isEqualTo(TaskOutcome.UP_TO_DATE) + Truth.assertThat(result.outcome(':generateSpotbugsDebugHtmlReport')).isEqualTo(TaskOutcome.UP_TO_DATE) + } + + @Test + void shouldNotGenerateHtmlWhenDisabled() { + def result = createProjectWith() + .withSourceSet('main', SOURCES_WITH_LOW_VIOLATION) + .withToolsConfig('''spotbugs { + htmlReportEnabled false + }''') + .build('check') + + Truth.assertThat(result.tasksPaths).doesNotContain(':generateSpotBugsDebugHtmlReport') + } + + private TestProject createProjectWith() { + projectRule.newProject() + .withPlugin('com.github.spotbugs', "2.0.0") + } +} diff --git a/plugin/src/test/groovy/com/novoda/test/LogsSubject.groovy b/plugin/src/test/groovy/com/novoda/test/LogsSubject.groovy index 35fb1e9..9f56360 100644 --- a/plugin/src/test/groovy/com/novoda/test/LogsSubject.groovy +++ b/plugin/src/test/groovy/com/novoda/test/LogsSubject.groovy @@ -17,6 +17,7 @@ class LogsSubject extends Subject { private static final String CHECKSTYLE_VIOLATIONS_FOUND = 'Checkstyle violations found' private static final String PMD_VIOLATIONS_FOUND = 'PMD violations found' private static final String FINDBUGS_VIOLATIONS_FOUND = 'Findbugs violations found' + private static final String SPOTBUGS_VIOLATIONS_FOUND = 'SpotBugs violations found' private static final String DETEKT_VIOLATIONS_FOUND = 'Detekt violations found' private static final String KTLINT_VIOLATIONS_FOUND = 'ktlint violations found' private static final String LINT_VIOLATIONS_FOUND = 'Lint violations found' @@ -68,6 +69,10 @@ class LogsSubject extends Subject { outputSubject.doesNotContain(FINDBUGS_VIOLATIONS_FOUND) } + public void doesNotContainSpotBugsViolations() { + outputSubject.doesNotContain(SPOTBUGS_VIOLATIONS_FOUND) + } + public void doesNotContainDetektViolations() { outputSubject.doesNotContain(DETEKT_VIOLATIONS_FOUND) } @@ -92,6 +97,10 @@ class LogsSubject extends Subject { containsToolViolations(FINDBUGS_VIOLATIONS_FOUND, errors, warnings, reportUrls) } + public void containsSpotBugsViolations(int errors, int warnings, String... reportUrls) { + containsToolViolations(SPOTBUGS_VIOLATIONS_FOUND, errors, warnings, reportUrls) + } + public void containsDetektViolations(int errors, int warnings, String... reportUrls) { containsToolViolations(DETEKT_VIOLATIONS_FOUND, errors, warnings, reportUrls) } diff --git a/sample-multi-module/build.gradle b/sample-multi-module/build.gradle index 73afee0..61e4532 100644 --- a/sample-multi-module/build.gradle +++ b/sample-multi-module/build.gradle @@ -11,6 +11,7 @@ buildscript { classpath 'com.novoda:gradle-static-analysis-plugin:local' classpath 'io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.0.0-RC14' classpath 'org.jlleitschuh.gradle:ktlint-gradle:9.0.0' + classpath "gradle.plugin.com.github.spotbugs:spotbugs-gradle-plugin:2.0.0" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/sample-multi-module/core/src/main/java/com/novoda/staticanalysisplugin/sample/SomeJavaClass.java b/sample-multi-module/core/src/main/java/com/novoda/staticanalysisplugin/sample/SomeJavaClass.java index 2fd1406..28bd695 100644 --- a/sample-multi-module/core/src/main/java/com/novoda/staticanalysisplugin/sample/SomeJavaClass.java +++ b/sample-multi-module/core/src/main/java/com/novoda/staticanalysisplugin/sample/SomeJavaClass.java @@ -1,4 +1,18 @@ package com.novoda.staticanalysisplugin.sample; public class SomeJavaClass { + + private void THIS_IS_A_VERY_VERY_VERY_LONG_NAME_FOR_A_METHOD_IT_IS_IN_FACT_VERY_LONG_INDEED_NO_NEED_TO_COUNT_THE_NUMBER_OF_CHARACTERS_YOU_CAN_CLEARLY_SEE_THIS_IS_WAY_LONGER_THAN_IT_SHOULD(int duration) { + // no-op + } + + public static class Internal { + + public void impossibleCast() { + final Object doubleValue = Double.valueOf(1.0); + final Long value = (Long) doubleValue; + System.out.println(" - " + value); + } + + } } diff --git a/sample-multi-module/team-props/static-analysis.gradle b/sample-multi-module/team-props/static-analysis.gradle index 3d7b7c7..aefa67f 100644 --- a/sample-multi-module/team-props/static-analysis.gradle +++ b/sample-multi-module/team-props/static-analysis.gradle @@ -1,6 +1,7 @@ apply plugin: 'com.novoda.static-analysis' apply plugin: 'io.gitlab.arturbosch.detekt' apply plugin: 'org.jlleitschuh.gradle.ktlint' +apply plugin: 'com.github.spotbugs' staticAnalysis { @@ -27,6 +28,11 @@ staticAnalysis { includeVariants { variant -> variant.name.contains('debug') } } + spotbugs { + excludeFilter rootProject.file('team-props/findbugs-excludes.xml') + includeVariants { variant -> variant.name.contains('debug') } + } + lintOptions { lintConfig rootProject.file('team-props/lint-config.xml') checkReleaseBuilds false diff --git a/sample/app/build.gradle b/sample/app/build.gradle index a49ab7f..320a155 100755 --- a/sample/app/build.gradle +++ b/sample/app/build.gradle @@ -1,6 +1,7 @@ plugins { id 'io.gitlab.arturbosch.detekt' - id "org.jlleitschuh.gradle.ktlint" + id 'org.jlleitschuh.gradle.ktlint' + id 'com.github.spotbugs' } apply plugin: 'com.android.application' @@ -51,6 +52,11 @@ staticAnalysis { includeVariants { variant -> variant.name.contains('debug') } } + spotbugs { + excludeFilter rootProject.file('team-props/findbugs-excludes.xml') + includeVariants { variant -> variant.name.contains('debug') } + } + lintOptions { lintConfig rootProject.file('team-props/lint-config.xml') checkReleaseBuilds false diff --git a/sample/build.gradle b/sample/build.gradle index a784b83..a2f6efa 100755 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -11,6 +11,7 @@ buildscript { classpath 'com.novoda:gradle-static-analysis-plugin:local' classpath 'io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.0.0-RC14' classpath 'org.jlleitschuh.gradle:ktlint-gradle:9.0.0' + classpath "gradle.plugin.com.github.spotbugs:spotbugs-gradle-plugin:2.0.0" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } }