From d932b66d837b08cd04d8c0992984609984cafb70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Burstr=C3=B6m?= Date: Thu, 14 May 2020 16:23:46 +0200 Subject: [PATCH] feat: Create SpotBugs tasks for both Android apps and libs By looping over the variants, it is possible to associate each of them with a given SpotBugs task. Each variant has a compilation task that can be hooked up. --- .../snom/AndroidFunctionalTest.groovy | 19 +++--- .../snom/internal/SpotBugsTaskFactory.java | 62 +++++++++++-------- 2 files changed, 48 insertions(+), 33 deletions(-) diff --git a/src/functionalTest/groovy/com/github/spotbugs/snom/AndroidFunctionalTest.groovy b/src/functionalTest/groovy/com/github/spotbugs/snom/AndroidFunctionalTest.groovy index 48d05f5cf..bfea1ca29 100644 --- a/src/functionalTest/groovy/com/github/spotbugs/snom/AndroidFunctionalTest.groovy +++ b/src/functionalTest/groovy/com/github/spotbugs/snom/AndroidFunctionalTest.groovy @@ -19,6 +19,7 @@ import org.gradle.testkit.runner.GradleRunner import org.gradle.util.GradleVersion import org.junit.jupiter.api.BeforeEach import spock.lang.Ignore +import spock.lang.Requires import spock.lang.Specification import static org.gradle.testkit.runner.TaskOutcome.SUCCESS @@ -35,8 +36,8 @@ class AndroidFunctionalTest extends Specification { buildFile = new File(rootDir, 'build.gradle') } - @Ignore("need to install Android SDK") - def "can generate spotbugsMain depending on classes task"() { + @Requires({env['ANDROID_SDK_ROOT']}) + def "can generate spotbugsRelease depending on variant compilation task"() { given: "a Gradle project to build an Android app" GradleRunner runner = GradleRunner.create() @@ -57,7 +58,7 @@ buildscript { """ runner.pluginClasspath.forEach({ file -> buildFile << """ - classpath '${file.absolutePath}' + classpath files('${file.absolutePath}') """ }) buildFile << """ @@ -83,7 +84,7 @@ android { } """ - File sourceDir = rootDir.toPath().resolve("src").resolve("main").resolve("java").toFile() + File sourceDir = new File(rootDir, "src/main/java") sourceDir.mkdirs() File sourceFile = new File(sourceDir, "Foo.java") sourceFile << """ @@ -92,15 +93,19 @@ public class Foo { System.out.println("Hello, SpotBugs!"); } } +""" + File manifestFile = new File(rootDir, "src/main/AndroidManifest.xml") + manifestFile << """ + """ - when: "the spotbugsMain task is executed" + when: "the spotbugsRelease task is executed" BuildResult result = runner - .withArguments(":spotbugsMain") + .withArguments(":spotbugsRelease", '-s') .withGradleVersion(version) .build() then: "gradle runs spotbugsMain successfully" - assertEquals(SUCCESS, result.task(":spotbugsMain").outcome) + assertEquals(SUCCESS, result.task(":spotbugsRelease").outcome) } } diff --git a/src/main/groovy/com/github/spotbugs/snom/internal/SpotBugsTaskFactory.java b/src/main/groovy/com/github/spotbugs/snom/internal/SpotBugsTaskFactory.java index a6d8ade68..64a33a361 100644 --- a/src/main/groovy/com/github/spotbugs/snom/internal/SpotBugsTaskFactory.java +++ b/src/main/groovy/com/github/spotbugs/snom/internal/SpotBugsTaskFactory.java @@ -13,12 +13,17 @@ */ package com.github.spotbugs.snom.internal; -import com.android.build.gradle.tasks.AndroidJavaCompile; +import com.android.build.gradle.AppExtension; +import com.android.build.gradle.BaseExtension; +import com.android.build.gradle.LibraryExtension; +import com.android.build.gradle.api.BaseVariant; import com.github.spotbugs.snom.SpotBugsTask; import org.gradle.api.Action; +import org.gradle.api.DomainObjectSet; import org.gradle.api.Project; import org.gradle.api.plugins.JavaBasePlugin; import org.gradle.api.plugins.JavaPluginConvention; +import org.gradle.api.tasks.compile.JavaCompile; import org.gradle.util.GUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -63,30 +68,35 @@ private void generateForJava(Project project, Action confi private void generateForAndroid( Project project, Action configurationAction) { - project - .getPlugins() - .withId( - "com.android.application", - plugin -> - project - .getTasks() - .withType(AndroidJavaCompile.class) - .all( - task -> { - String name = GUtil.toLowerCamelCase("spotbugs " + task.getVariantName()); - log.debug("Creating SpotBugsTask for {}", task); - project - .getTasks() - .register( - name, - SpotBugsTask.class, - spotbugsTask -> { - spotbugsTask.setSourceDirs(task.getSource()); - spotbugsTask.setClassDirs( - task.getOutputDirectory().getAsFileTree()); - spotbugsTask.setAuxClassPaths(task.getClasspath()); - configurationAction.execute(spotbugsTask); - }); - })); + if (project.getPlugins().hasPlugin("com.android.base")) { + + final BaseExtension baseExtension = project.getExtensions().getByType(BaseExtension.class); + DomainObjectSet variants; + if (baseExtension instanceof AppExtension) { + variants = ((AppExtension) baseExtension).getApplicationVariants(); + } else if (baseExtension instanceof LibraryExtension) { + variants = ((LibraryExtension) baseExtension).getLibraryVariants(); + } else { + throw new RuntimeException("Unrecognized Android extension " + baseExtension); + } + variants.all( + (BaseVariant variant) -> { + String spotbugsTaskName = GUtil.toLowerCamelCase("spotbugs " + variant.getName()); + log.debug("Creating SpotBugsTask for {}", variant.getName()); + project + .getTasks() + .register( + spotbugsTaskName, + SpotBugsTask.class, + spotbugsTask -> { + final JavaCompile javaCompile = variant.getJavaCompileProvider().get(); + spotbugsTask.setSourceDirs(javaCompile.getSource()); + spotbugsTask.setClassDirs(project.files(javaCompile.getDestinationDir())); + spotbugsTask.setAuxClassPaths(javaCompile.getClasspath()); + spotbugsTask.dependsOn(javaCompile); + configurationAction.execute(spotbugsTask); + }); + }); + } } }