1 package org.robolectric.gradle 2 3 import com.android.SdkConstants.DOT_JAVA 4 import com.android.SdkConstants.FD_GENERATED 5 import com.android.SdkConstants.FD_MAIN 6 import com.android.SdkConstants.SRC_FOLDER 7 import java.io.File 8 import java.util.jar.JarFile 9 import org.gradle.api.Plugin 10 import org.gradle.api.Project 11 import org.gradle.api.tasks.compile.JavaCompile 12 import org.gradle.api.tasks.javadoc.Javadoc 13 import org.gradle.jvm.tasks.Jar 14 import org.gradle.kotlin.dsl.create 15 import org.gradle.kotlin.dsl.extra 16 import org.gradle.kotlin.dsl.named 17 import org.gradle.kotlin.dsl.provideDelegate 18 import org.gradle.kotlin.dsl.withType 19 20 class ShadowsPlugin : Plugin<Project> { applynull21 override fun apply(project: Project) { 22 project.pluginManager.apply("idea") 23 24 val shadows = project.extensions.create<ShadowsPluginExtension>("shadows") 25 26 project.dependencies.add("annotationProcessor", project.project(":processor")) 27 28 // Write generated Java into its own dir. See https://github.com/gradle/gradle/issues/4956 29 val generatedSrcDir = 30 project.layout.buildDirectory.dir("$FD_GENERATED/$SRC_FOLDER/apt/$FD_MAIN") 31 32 project.tasks.named<JavaCompile>("compileJava").configure { 33 options.generatedSourceOutputDirectory.set(generatedSrcDir) 34 35 doFirst { 36 val jsonDocsDir = project.layout.buildDirectory.dir("docs/json").get().asFile 37 val sdks = project.rootProject.layout.buildDirectory.file("sdks.txt").get().asFile 38 39 with(options.compilerArgs) { 40 add("-Aorg.robolectric.annotation.processing.jsonDocsEnabled=true") 41 add("-Aorg.robolectric.annotation.processing.jsonDocsDir=$jsonDocsDir") 42 add("-Aorg.robolectric.annotation.processing.shadowPackage=${shadows.packageName}") 43 add("-Aorg.robolectric.annotation.processing.sdkCheckMode=${shadows.sdkCheckMode}") 44 add("-Aorg.robolectric.annotation.processing.sdks=$sdks") 45 } 46 } 47 } 48 49 // Include the generated sources in the Javadoc jar 50 project.tasks.named<Javadoc>("javadoc").configure { source(generatedSrcDir) } 51 52 // Verify that we have the apt-generated files in our Javadoc and sources jars 53 project.tasks.named<Jar>("javadocJar").configure { 54 doLast { 55 val shadowPackageNameDir = shadows.packageName.replace('.', '/') 56 checkForFile(archiveFile.get().asFile, "$shadowPackageNameDir/Shadows.html") 57 } 58 } 59 60 project.tasks.named<Jar>("sourcesJar").configure { 61 from(generatedSrcDir) 62 doLast { 63 val shadowPackageNameDir = shadows.packageName.replace('.', '/') 64 checkForFile(archiveFile.get().asFile, "$shadowPackageNameDir/Shadows$DOT_JAVA") 65 } 66 } 67 68 var configAnnotationProcessing: List<Project> by project.rootProject.extra 69 configAnnotationProcessing += project 70 71 // Prevents sporadic compilation error: 72 // 'Bad service configuration file, or exception thrown while constructing 73 // Processor object: javax.annotation.processing.Processor: Error reading 74 // configuration file' 75 // 76 // See https://discuss.gradle.org/t/gradle-not-compiles-with-solder-tooling-jar/7583/20 77 project.tasks.withType<JavaCompile>().configureEach { options.isFork = true } 78 } 79 80 abstract class ShadowsPluginExtension { 81 abstract var packageName: String 82 var sdkCheckMode: String = "WARN" 83 } 84 85 private companion object { checkForFilenull86 private fun checkForFile(jar: File, name: String) { 87 val hasFile = JarFile(jar).entries().asSequence().any { it.name == name } 88 89 check(hasFile) { "Missing file $name in $jar" } 90 } 91 } 92 } 93