diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 148c4a44..553a7893 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -57,4 +57,4 @@ If the contribution doesn't meet the above criteria, you may fail our automated ## Maintainers -There are more details about processes and workflow in the [Maintainer's Guide](https://github.com/slackhq/keeper/blob/main/.maintainers_guide.md). \ No newline at end of file +There are more details about processes and workflow in the [Maintainer's Guide](https://github.com/slackhq/keeper/blob/main/.maintainers_guide.md). diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 964ee4ef..284fff51 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -29,4 +29,4 @@ What actually happened #### Attachments: -Logs, screenshots, screencast, sample project, funny gif, etc. \ No newline at end of file +Logs, screenshots, screencast, sample project, funny gif, etc. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 93970b15..f3cde65b 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -10,4 +10,4 @@ assignees: '' Start by telling us what problem you’re trying to solve. Often a solution already exists! Don’t send pull requests to implement significant new features without first getting our support. -Sometimes we leave features out on purpose to keep the project small. \ No newline at end of file +Sometimes we leave features out on purpose to keep the project small. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bbacc6fb..bf105dc5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: fail-fast: false # We want to see all results matrix: java: ['11'] - agp: ['7.1.0', '7.2.0-beta01'] + agp: ['7.1.0', '7.2.0-beta02'] tracerefs: [true, false] job: ['instrumentation', 'plugin'] steps: @@ -47,6 +47,9 @@ jobs: distribution: 'zulu' java-version: ${{ matrix.java }} + - name: Spot check + run: ./gradlew spotlessCheck + - name: Test plugin if: matrix.job == 'plugin' run: ./gradlew -p keeper-gradle-plugin clean check --stacktrace -PkeeperTest.agpVersion=${{ matrix.agp }} diff --git a/.maintainers_guide.md b/.maintainers_guide.md index 2d23f59b..ed1ded75 100644 --- a/.maintainers_guide.md +++ b/.maintainers_guide.md @@ -66,4 +66,4 @@ relevant once again, reopening is great and better than creating a duplicate iss ## Everything else -When in doubt, find the other maintainers and ask. \ No newline at end of file +When in doubt, find the other maintainers and ask. diff --git a/CHANGELOG.md b/CHANGELOG.md index 48823ef4..f4e46b3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -210,7 +210,7 @@ Perf comparisons on the slack app: | inferExternalStagingAndroidTestKeepRulesForKeeper | 14.126s | 11.138s | | jarExternalStagingClassesForKeeper | 10.364s | 6.347s | | jarExternalStagingAndroidTestClassesForKeeper | 4.504s | 2.609s | - + * Keeper now only supports AGP 3.6 or higher. If you still need AGP 3.5.x support, please continue using Keeper 0.2.0 or lower. * Update Kotlin to 1.3.71. @@ -221,7 +221,7 @@ using Keeper 0.2.0 or lower. _2020-02-12_ ### New Variant Filter API [#14](https://github.com/slackhq/keeper/pull/14) -You can specify a variantFilter on the keeper extension to dynamically configure which variants Keeper +You can specify a variantFilter on the keeper extension to dynamically configure which variants Keeper operates on (similar to the Android Gradle Plugin's VariantFilter API). ```groovy @@ -235,8 +235,8 @@ keeper { ``` ### R8 Repository Management Opt-Out [#17](https://github.com/slackhq/keeper/pull/17) -If you don't want Keeper to automatically manage adding R8's maven repo, you can set disable it via -`automaticR8RepoManagement`. Note that you'll need to manually add your own repo that the `keeperR8` +If you don't want Keeper to automatically manage adding R8's maven repo, you can set disable it via +`automaticR8RepoManagement`. Note that you'll need to manually add your own repo that the `keeperR8` configuration can resolve from. ```groovy diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 2d86a841..13462390 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -8,4 +8,4 @@ Our goal is to maintain a safe, helpful and friendly community for everyone, reg This code and related pro`cedures also apply to unacceptable behavior occurring outside the scope of community activities, in all community venues (online and in-person) as well as in all one-on-one communications, and anywhere such behavior has the potential to adversely affect the safety and well-being of community members. -For more information on our code of conduct, please visit [https://slackhq.github.io/code-of-conduct](https://slackhq.github.io/code-of-conduct) \ No newline at end of file +For more information on our code of conduct, please visit [https://slackhq.github.io/code-of-conduct](https://slackhq.github.io/code-of-conduct) diff --git a/RELEASING.md b/RELEASING.md index a79c13f6..ad718ac1 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -9,4 +9,4 @@ Releasing 6. Update the `gradle.properties` to the next SNAPSHOT version. 7. `git commit -am "Prepare next development version."` 8. `git push && git push --tags` - 9. Update the website by running `./deploy_website.sh` \ No newline at end of file + 9. Update the website by running `./deploy_website.sh` diff --git a/build.gradle b/build.gradle index 1c5e22a3..d70c82ed 100644 --- a/build.gradle +++ b/build.gradle @@ -31,6 +31,10 @@ buildscript { } } +plugins { + id("com.diffplug.spotless") version "6.3.0" apply false +} + String resolvedJvmTarget = System.getenv().getOrDefault("ci_java_version", "1.8") allprojects { repositories { @@ -47,3 +51,37 @@ allprojects { } } } + +apply plugin: "com.diffplug.spotless" +spotless { + format("misc") { + target("**/*.md", ".gitignore") + trimTrailingWhitespace() + endWithNewline() + } + String ktlintVersion = "0.44.0" + Map ktlintUserData = ["indent_size": "2", "continuation_indent_size": "2"] + kotlin { + target("**/*.kt") + ktlint(ktlintVersion).userData(ktlintUserData) + trimTrailingWhitespace() + endWithNewline() + licenseHeaderFile(rootProject.file("spotless/copyright.kt")) + targetExclude("**/copyright.kt") + } + kotlinGradle { + target("**/*.kts") + ktlint(ktlintVersion).userData(ktlintUserData) + trimTrailingWhitespace() + endWithNewline() + licenseHeaderFile("spotless/copyright.kt", "(import|plugins|buildscript|dependencies|pluginManagement|rootProject)") + } + java { + target("**/*.java") + googleJavaFormat('1.14.0').reflowLongStrings() + trimTrailingWhitespace() + endWithNewline() + licenseHeaderFile(rootProject.file("spotless/copyright.java")) + targetExclude("**/copyright.java") + } +} diff --git a/gradle.properties b/gradle.properties index 05effeb5..0b85d0aa 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,4 +15,10 @@ # android.useAndroidX=true -kapt.includeCompileClasspath=false + +# For GJF +org.gradle.jvmargs=--add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \ + --add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED \ + --add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED \ + --add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED \ + --add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED diff --git a/keeper-gradle-plugin/build.gradle.kts b/keeper-gradle-plugin/build.gradle.kts index c8d07fe8..48f66cf9 100644 --- a/keeper-gradle-plugin/build.gradle.kts +++ b/keeper-gradle-plugin/build.gradle.kts @@ -1,11 +1,11 @@ /* - * Copyright (C) 2020 Slack Technologies, LLC + * Copyright (C) 2020. Slack Technologies, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -56,9 +56,11 @@ tasks.withType().configureEach { } tasks.withType().configureEach { - beforeTest(closureOf { - logger.lifecycle("Running test: $this") - }) + beforeTest( + closureOf { + logger.lifecycle("Running test: $this") + } + ) } sourceSets { diff --git a/keeper-gradle-plugin/gradle.properties b/keeper-gradle-plugin/gradle.properties index 433a3cf4..cb1b2063 100644 --- a/keeper-gradle-plugin/gradle.properties +++ b/keeper-gradle-plugin/gradle.properties @@ -17,8 +17,6 @@ # For dokka org.gradle.jvmargs=-XX:MaxMetaspaceSize=512m -kapt.include.compile.classpath=false - POM_NAME=Keeper POM_ARTIFACT_ID=keeper POM_PACKAGING=jar diff --git a/keeper-gradle-plugin/settings.gradle.kts b/keeper-gradle-plugin/settings.gradle.kts index e2cba200..bb831984 100644 --- a/keeper-gradle-plugin/settings.gradle.kts +++ b/keeper-gradle-plugin/settings.gradle.kts @@ -1,11 +1,11 @@ /* - * Copyright (C) 2020 Slack Technologies, LLC + * Copyright (C) 2020. Slack Technologies, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - pluginManagement { repositories { google() @@ -22,4 +21,4 @@ pluginManagement { } } -rootProject.name = "keeper-gradle-plugin" \ No newline at end of file +rootProject.name = "keeper-gradle-plugin" diff --git a/keeper-gradle-plugin/src/main/java/com/slack/keeper/InferAndroidTestKeepRules.kt b/keeper-gradle-plugin/src/main/java/com/slack/keeper/InferAndroidTestKeepRules.kt index ac671f97..46af7c5d 100644 --- a/keeper-gradle-plugin/src/main/java/com/slack/keeper/InferAndroidTestKeepRules.kt +++ b/keeper-gradle-plugin/src/main/java/com/slack/keeper/InferAndroidTestKeepRules.kt @@ -1,11 +1,11 @@ /* - * Copyright (C) 2020 Slack Technologies, LLC + * Copyright (C) 2020. Slack Technologies, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.slack.keeper import org.gradle.api.artifacts.Configuration @@ -92,10 +91,12 @@ public abstract class InferAndroidTestKeepRules : JavaExec() { val inputJvmArgs = jvmArgsProperty.get() if (inputJvmArgs.isNotEmpty()) { logger.lifecycle( - "Starting infer exec with jvmArgs ${ - inputJvmArgs.joinToString(", ", prefix = "[", - postfix = "]") - }. If debugging, attach the debugger now." + "Starting infer exec with jvmArgs ${ + inputJvmArgs.joinToString( + ", ", prefix = "[", + postfix = "]" + ) + }. If debugging, attach the debugger now." ) jvmArgs = inputJvmArgs } @@ -111,43 +112,43 @@ public abstract class InferAndroidTestKeepRules : JavaExec() { } private fun genPrintUsesArgs(): List = - listOf( - "--keeprules", - androidJar.get().asFile.absolutePath, - appTargetJar.get().asFile.absolutePath, - androidTestSourceJar.get().asFile.absolutePath - ).also { - // print-uses is using its output to print rules - standardOutput = outputProguardRules.asFile.get().outputStream().buffered() - } + listOf( + "--keeprules", + androidJar.get().asFile.absolutePath, + appTargetJar.get().asFile.absolutePath, + androidTestSourceJar.get().asFile.absolutePath + ).also { + // print-uses is using its output to print rules + standardOutput = outputProguardRules.asFile.get().outputStream().buffered() + } private fun genTraceReferencesArgs(): List = - listOf( - "--keep-rules" to "", - "--lib" to androidJar.get().asFile.absolutePath, - "--lib" to androidTestJar.get().asFile.takeIf { it.exists() }?.absolutePath, - "--target" to appTargetJar.get().asFile.absolutePath, - "--source" to androidTestSourceJar.get().asFile.absolutePath, - "--output" to outputProguardRules.get().asFile.absolutePath - ).map { if (it.second != null) listOf(it.first, it.second) else listOf() } - .reduce { acc, any -> acc + any } - // Add user provided args coming from TraceReferences.arguments after generated ones. - .plus(traceReferencesArgs.getOrElse(listOf())) + listOf( + "--keep-rules" to "", + "--lib" to androidJar.get().asFile.absolutePath, + "--lib" to androidTestJar.get().asFile.takeIf { it.exists() }?.absolutePath, + "--target" to appTargetJar.get().asFile.absolutePath, + "--source" to androidTestSourceJar.get().asFile.absolutePath, + "--output" to outputProguardRules.get().asFile.absolutePath + ).map { if (it.second != null) listOf(it.first, it.second) else listOf() } + .reduce { acc, any -> acc + any } + // Add user provided args coming from TraceReferences.arguments after generated ones. + .plus(traceReferencesArgs.getOrElse(listOf())) public companion object { @Suppress("UNCHECKED_CAST", "UnstableApiUsage") public operator fun invoke( - variantName: String, - androidTestJarProvider: TaskProvider, - releaseClassesJarProvider: TaskProvider, - androidJar: Provider, - androidTestJar: Provider, - automaticallyAddR8Repo: Property, - enableAssertions: Property, - extensionJvmArgs: ListProperty, - traceReferencesEnabled: Property, - traceReferencesArgs: ListProperty, - r8Configuration: Configuration + variantName: String, + androidTestJarProvider: TaskProvider, + releaseClassesJarProvider: TaskProvider, + androidJar: Provider, + androidTestJar: Provider, + automaticallyAddR8Repo: Property, + enableAssertions: Property, + extensionJvmArgs: ListProperty, + traceReferencesEnabled: Property, + traceReferencesArgs: ListProperty, + r8Configuration: Configuration ): InferAndroidTestKeepRules.() -> Unit = { if (automaticallyAddR8Repo.get()) { // This is the maven repo where r8 tagged releases are hosted. Only the r8 artifact is @@ -174,17 +175,21 @@ public abstract class InferAndroidTestKeepRules : JavaExec() { this.traceReferencesEnabled.set(traceReferencesEnabled) this.traceReferencesArgs.set(traceReferencesArgs) outputProguardRules.set( - project.layout.buildDirectory.file( - "${KeeperPlugin.INTERMEDIATES_DIR}/${ - variantName.capitalize(Locale.US) - }/inferredKeepRules.pro")) + project.layout.buildDirectory.file( + "${KeeperPlugin.INTERMEDIATES_DIR}/${ + variantName.capitalize(Locale.US) + }/inferredKeepRules.pro" + ) + ) classpath(r8Configuration) - mainClass.set(this.traceReferencesEnabled.map { enabled -> - when (enabled) { - false -> "com.android.tools.r8.PrintUses" - true -> "com.android.tools.r8.tracereferences.TraceReferences" + mainClass.set( + this.traceReferencesEnabled.map { enabled -> + when (enabled) { + false -> "com.android.tools.r8.PrintUses" + true -> "com.android.tools.r8.tracereferences.TraceReferences" + } } - }) + ) enableAssertionsProperty.set(enableAssertions) } diff --git a/keeper-gradle-plugin/src/main/java/com/slack/keeper/KeeperExtension.kt b/keeper-gradle-plugin/src/main/java/com/slack/keeper/KeeperExtension.kt index 65648f2f..1ea5d104 100644 --- a/keeper-gradle-plugin/src/main/java/com/slack/keeper/KeeperExtension.kt +++ b/keeper-gradle-plugin/src/main/java/com/slack/keeper/KeeperExtension.kt @@ -1,11 +1,11 @@ /* - * Copyright (C) 2020 Slack Technologies, LLC + * Copyright (C) 2020. Slack Technologies, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.slack.keeper import org.gradle.api.Action @@ -87,5 +86,5 @@ public abstract class TraceReferences @Inject constructor(objects: ObjectFactory * with the R8 team. */ public val arguments: ListProperty = objects.listProperty() - .convention(listOf("--map-diagnostics:MissingDefinitionsDiagnostic", "error", "info")) + .convention(listOf("--map-diagnostics:MissingDefinitionsDiagnostic", "error", "info")) } diff --git a/keeper-gradle-plugin/src/main/java/com/slack/keeper/KeeperPlugin.kt b/keeper-gradle-plugin/src/main/java/com/slack/keeper/KeeperPlugin.kt index 100ac1d4..81cb2c1c 100644 --- a/keeper-gradle-plugin/src/main/java/com/slack/keeper/KeeperPlugin.kt +++ b/keeper-gradle-plugin/src/main/java/com/slack/keeper/KeeperPlugin.kt @@ -1,11 +1,11 @@ /* - * Copyright (C) 2020 Slack Technologies, LLC + * Copyright (C) 2020. Slack Technologies, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - @file:Suppress("UnstableApiUsage", "DEPRECATION") package com.slack.keeper @@ -150,7 +149,8 @@ public class KeeperPlugin : Plugin { appComponentsExtension: ApplicationAndroidComponentsExtension, extension: KeeperExtension ) { - appComponentsExtension.onApplicableVariants(project, + appComponentsExtension.onApplicableVariants( + project, appExtension, verifyMinification = false ) { testVariant, appVariant -> @@ -198,7 +198,6 @@ public class KeeperPlugin : Plugin { prefix = "# Source: extra configurations\n" ) - File(diagnosticOutputDir, "patchedL8Rules.pro") .apply { if (exists()) { @@ -247,19 +246,24 @@ public class KeeperPlugin : Plugin { } } - val androidJarRegularFileProvider = layout.file(provider { - resolveAndroidEmbeddedJar(appExtension, appComponentsExtension, "android.jar", - checkIfExisting = true) - }) - val androidTestJarRegularFileProvider = layout.file(provider { - resolveAndroidEmbeddedJar( - appExtension, - appComponentsExtension, - "optional/android.test.base.jar", - checkIfExisting = false - ) - }) - + val androidJarRegularFileProvider = layout.file( + provider { + resolveAndroidEmbeddedJar( + appExtension, appComponentsExtension, "android.jar", + checkIfExisting = true + ) + } + ) + val androidTestJarRegularFileProvider = layout.file( + provider { + resolveAndroidEmbeddedJar( + appExtension, + appComponentsExtension, + "optional/android.test.base.jar", + checkIfExisting = false + ) + } + ) appComponentsExtension.onApplicableVariants( project, @@ -293,7 +297,8 @@ public class KeeperPlugin : Plugin { ) val prop = layout.dir( - inferAndroidTestUsageProvider.flatMap { it.outputProguardRules.asFile }) + inferAndroidTestUsageProvider.flatMap { it.outputProguardRules.asFile } + ) val testProguardFiles = runtimeConfigurationFor(testVariant.name) .proguardFiles() applyGeneratedRules(appVariant.name, prop, testProguardFiles) @@ -309,7 +314,8 @@ public class KeeperPlugin : Plugin { val compileSdkVersion = appExtension.compileSdkVersion ?: error("No compileSdkVersion found") val file = File( - "${appComponentsExtension.sdkComponents.sdkDirectory.get().asFile}/platforms/${compileSdkVersion}/${path}") + "${appComponentsExtension.sdkComponents.sdkDirectory.get().asFile}/platforms/$compileSdkVersion/$path" + ) check(!checkIfExisting || file.exists()) { "No $path found! Expected to find it at: ${file.absolutePath}" } @@ -331,8 +337,8 @@ public class KeeperPlugin : Plugin { if (verifyMinification && !appExtension.buildTypes.getByName(buildType).isMinifyEnabled) { project.logger.error( """ - Keeper is configured to generate keep rules for the "${appVariant.name}" build variant, but the variant doesn't - have minification enabled, so the keep rules will have no effect. To fix this warning, either avoid applying + Keeper is configured to generate keep rules for the "${appVariant.name}" build variant, but the variant doesn't + have minification enabled, so the keep rules will have no effect. To fix this warning, either avoid applying the Keeper plugin when android.testBuildType = $buildType or enable minification on this variant. """.trimIndent() ) @@ -394,9 +400,11 @@ public class KeeperPlugin : Plugin { "$INTERMEDIATES_DIR/${testVariant.name}/diagnostics" ) this.diagnosticsOutputDir.set(diagnosticsDir) - archiveFile.set(outputDir.map { - it.file("classes.jar") - }) + archiveFile.set( + outputDir.map { + it.file("classes.jar") + } + ) } } diff --git a/keeper-gradle-plugin/src/main/java/com/slack/keeper/KeeperVariantMarker.kt b/keeper-gradle-plugin/src/main/java/com/slack/keeper/KeeperVariantMarker.kt index 136a5118..ffe260d1 100644 --- a/keeper-gradle-plugin/src/main/java/com/slack/keeper/KeeperVariantMarker.kt +++ b/keeper-gradle-plugin/src/main/java/com/slack/keeper/KeeperVariantMarker.kt @@ -1,3 +1,18 @@ +/* + * Copyright (C) 2022. Slack Technologies, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.slack.keeper import com.android.build.api.variant.VariantBuilder @@ -21,4 +36,4 @@ public object KeeperVariantMarker /** Shorthand to register Keeper on this variant. */ public fun VariantBuilder.optInToKeeper() { registerExtension(KeeperVariantMarker::class.java, KeeperVariantMarker) -} \ No newline at end of file +} diff --git a/keeper-gradle-plugin/src/main/java/com/slack/keeper/VariantClasspathJar.kt b/keeper-gradle-plugin/src/main/java/com/slack/keeper/VariantClasspathJar.kt index 77e1065f..a51000fe 100644 --- a/keeper-gradle-plugin/src/main/java/com/slack/keeper/VariantClasspathJar.kt +++ b/keeper-gradle-plugin/src/main/java/com/slack/keeper/VariantClasspathJar.kt @@ -1,11 +1,11 @@ /* - * Copyright (C) 2020 Slack Technologies, LLC + * Copyright (C) 2020. Slack Technologies, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - @file:Suppress("UnstableApiUsage") package com.slack.keeper @@ -72,7 +71,7 @@ public abstract class BaseKeeperJarTask : DefaultTask() { protected fun diagnostic(fileName: String, body: () -> String): File? { return if (emitDebugInfo.get()) { - diagnosticsOutputDir.get().file("${fileName}.txt").asFile.apply { + diagnosticsOutputDir.get().file("$fileName.txt").asFile.apply { writeText(body()) } } else { @@ -113,28 +112,28 @@ public abstract class VariantClasspathJar : BaseKeeperJarTask() { ZipArchive(archiveFile.asFile.get().toPath()).use { archive -> // The runtime classpath (i.e. from dependencies) getArtifactFiles() - .forEach { jar -> - appJars.add(jar.canonicalPath) - archive.extractClassesFrom(jar) { - appClasses += it - } + .forEach { jar -> + appJars.add(jar.canonicalPath) + archive.extractClassesFrom(jar) { + appClasses += it } + } // Take the compiled classes classpath.asSequence() - .flatMap { it.classesSequence() } - .forEach { (name, file) -> - appClasses.add(name) - archive.delete(name) - archive.add(BytesSource(file.toPath(), name, Deflater.NO_COMPRESSION)) - } + .flatMap { it.classesSequence() } + .forEach { (name, file) -> + appClasses.add(name) + archive.delete(name) + archive.add(BytesSource(file.toPath(), name, Deflater.NO_COMPRESSION)) + } } appJarsFile.get().asFile.writeText(appJars.sorted().joinToString("\n")) diagnostic("classes") { appClasses.sorted() - .joinToString("\n") + .joinToString("\n") } } } @@ -175,9 +174,9 @@ public abstract class AndroidTestVariantClasspathJar : BaseKeeperJarTask() { val androidTestClasspath = getArtifactFiles() diagnostic("jars") { androidTestClasspath.sortedBy { it.canonicalPath } - .joinToString("\n") { - it.canonicalPath - } + .joinToString("\n") { + it.canonicalPath + } } val distinctAndroidTestClasspath = androidTestClasspath.toMutableSet().apply { @@ -186,30 +185,30 @@ public abstract class AndroidTestVariantClasspathJar : BaseKeeperJarTask() { diagnostic("distinctJars") { distinctAndroidTestClasspath.sortedBy { it.canonicalPath } - .joinToString("\n") { - it.canonicalPath - } + .joinToString("\n") { + it.canonicalPath + } } val androidTestClasses = mutableSetOf() ZipArchive(archiveFile.asFile.get().toPath()).use { archive -> // The runtime classpath (i.e. from dependencies) distinctAndroidTestClasspath - .filter { it.exists() && it.extension == "jar" } - .forEach { jar -> - archive.extractClassesFrom(jar) { - androidTestClasses += it - } + .filter { it.exists() && it.extension == "jar" } + .forEach { jar -> + archive.extractClassesFrom(jar) { + androidTestClasses += it } + } // Take the compiled classes classpath.asSequence() - .flatMap { it.classesSequence() } - .forEach { (name, file) -> - androidTestClasses += name - archive.delete(name) - archive.add(BytesSource(file.toPath(), name, Deflater.NO_COMPRESSION)) - } + .flatMap { it.classesSequence() } + .forEach { (name, file) -> + androidTestClasses += name + archive.delete(name) + archive.add(BytesSource(file.toPath(), name, Deflater.NO_COMPRESSION)) + } } diagnostic("androidTestClasses") { @@ -219,10 +218,10 @@ public abstract class AndroidTestVariantClasspathJar : BaseKeeperJarTask() { // See https://issuetracker.google.com/issues/157583077 for why we do this if (emitDebugInfo.get()) { val duplicateClasses = appJars.asSequence() - .flatMap { jar -> ZipFile(File(jar)).use { it.entries().toList() }.asSequence() } - .map { it.name } - .distinct() - .filterTo(LinkedHashSet()) { it in androidTestClasses } + .flatMap { jar -> ZipFile(File(jar)).use { it.entries().toList() }.asSequence() } + .map { it.name } + .distinct() + .filterTo(LinkedHashSet()) { it in androidTestClasses } // https://github.com/slackhq/keeper/issues/82 duplicateClasses.remove("module-info.class") @@ -231,13 +230,15 @@ public abstract class AndroidTestVariantClasspathJar : BaseKeeperJarTask() { val output = diagnostic("duplicateClasses") { duplicateClasses.sorted().joinToString("\n") } - logger.warn("Duplicate classes found in androidTest APK and app APK! This" + + logger.warn( + "Duplicate classes found in androidTest APK and app APK! This" + " can cause obscure runtime errors during tests due to the app" + " classes being optimized while the androidTest copies of them that are actually used" + " at runtime are not. This usually happens when two different dependencies " + "contribute the same classes and the app configuration only depends on one of them " + "while the androidTest configuration depends on only on the other. " + - "The list of all duplicate classes can be found at file://$output") + "The list of all duplicate classes can be found at file://$output" + ) } } } diff --git a/keeper-gradle-plugin/src/main/java/com/slack/keeper/ZipFlingerExt.kt b/keeper-gradle-plugin/src/main/java/com/slack/keeper/ZipFlingerExt.kt index 2db7a829..2cce2a02 100644 --- a/keeper-gradle-plugin/src/main/java/com/slack/keeper/ZipFlingerExt.kt +++ b/keeper-gradle-plugin/src/main/java/com/slack/keeper/ZipFlingerExt.kt @@ -1,3 +1,18 @@ +/* + * Copyright (C) 2022. Slack Technologies, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.slack.keeper import com.android.zipflinger.ZipArchive @@ -12,9 +27,9 @@ import java.nio.file.Path internal fun File.classesSequence(): Sequence> { val prefix = absolutePath return walkTopDown() - .filter { it.extension == "class" } - .filterNot { "META-INF" in it.name } - .map { it.absolutePath.removePrefix(prefix).removePrefix("/") to it } + .filter { it.extension == "class" } + .filterNot { "META-INF" in it.name } + .map { it.absolutePath.removePrefix(prefix).removePrefix("/") to it } } /** @@ -23,15 +38,15 @@ internal fun File.classesSequence(): Sequence> { internal fun ZipArchive.extractClassesFrom(jar: File, callback: (String) -> Unit) { val jarSource = newZipSource(jar) jarSource.entries() - .filterNot { "META-INF" in it.key } - .forEach { (name, entry) -> - if (!entry.isDirectory && entry.name.endsWith(".class")) { - val entryName = name.removePrefix(".") - callback(entryName) - delete(entryName) - jarSource.select(entryName, name) - } + .filterNot { "META-INF" in it.key } + .forEach { (name, entry) -> + if (!entry.isDirectory && entry.name.endsWith(".class")) { + val entryName = name.removePrefix(".") + callback(entryName) + delete(entryName) + jarSource.select(entryName, name) } + } add(jarSource) } @@ -39,12 +54,12 @@ private fun newZipSource(jar: File): ZipSource { return try { // AGP 4.1/4.2 ZipSource::class.java - .getDeclaredConstructor(File::class.java) - .newInstance(jar) + .getDeclaredConstructor(File::class.java) + .newInstance(jar) } catch (e: NoSuchMethodException) { // AGP/ZipFlinger 7+ ZipSource::class.java - .getDeclaredConstructor(Path::class.java) - .newInstance(jar.toPath()) + .getDeclaredConstructor(Path::class.java) + .newInstance(jar.toPath()) } -} \ No newline at end of file +} diff --git a/keeper-gradle-plugin/src/test/kotlin/com/slack/keeper/Files.kt b/keeper-gradle-plugin/src/test/kotlin/com/slack/keeper/Files.kt index 70be92d9..866c3a09 100644 --- a/keeper-gradle-plugin/src/test/kotlin/com/slack/keeper/Files.kt +++ b/keeper-gradle-plugin/src/test/kotlin/com/slack/keeper/Files.kt @@ -1,11 +1,11 @@ /* - * Copyright (C) 2020 Slack Technologies, LLC + * Copyright (C) 2020. Slack Technologies, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.slack.keeper import com.slack.keeper.SourceFile.JavaSourceFile @@ -50,8 +49,10 @@ internal fun File.newDir(path: String): File { } internal fun File.generatedChild(path: String) = child("build", "intermediates", "keeper", *path.split("/").toTypedArray()) -internal fun File.child(vararg path: String) = File(this, - path.toList().joinToString(File.separator)).apply { +internal fun File.child(vararg path: String) = File( + this, + path.toList().joinToString(File.separator) +).apply { check(exists()) { "Child doesn't exist! Expected $this. Other files in this dir: ${parentFile.listFiles()}" } @@ -65,7 +66,7 @@ internal sealed class SourceFile(val name: String) { } data class KotlinSourceFile( - val fileSpec: FileSpec + val fileSpec: FileSpec ) : SourceFile(fileSpec.members.filterIsInstance().first().name!!) { override fun writeTo(file: File) = fileSpec.writeTo(file) } @@ -76,4 +77,4 @@ internal operator fun File.plusAssign(sourceFile: SourceFile) { } internal fun JavaFile.asSourceFile(): SourceFile = JavaSourceFile(this) -internal fun FileSpec.asSourceFile(): SourceFile = KotlinSourceFile(this) \ No newline at end of file +internal fun FileSpec.asSourceFile(): SourceFile = KotlinSourceFile(this) diff --git a/keeper-gradle-plugin/src/test/kotlin/com/slack/keeper/JavaPoetExt.kt b/keeper-gradle-plugin/src/test/kotlin/com/slack/keeper/JavaPoetExt.kt index 72e9d12a..d7ff4227 100644 --- a/keeper-gradle-plugin/src/test/kotlin/com/slack/keeper/JavaPoetExt.kt +++ b/keeper-gradle-plugin/src/test/kotlin/com/slack/keeper/JavaPoetExt.kt @@ -1,11 +1,11 @@ /* - * Copyright (C) 2020 Slack Technologies, LLC + * Copyright (C) 2020. Slack Technologies, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.slack.keeper import com.squareup.javapoet.JavaFile @@ -21,17 +20,22 @@ import com.squareup.javapoet.MethodSpec import com.squareup.javapoet.TypeSpec import javax.lang.model.element.Modifier.PUBLIC -internal fun javaFile(packageName: String, className: String, - body: TypeSpec.Builder.() -> Unit): SourceFile { - return JavaFile.builder(packageName, - TypeSpec.classBuilder(className) - .addModifiers(PUBLIC) - .apply(body) - .build()) +internal fun javaFile( + packageName: String, + className: String, + body: TypeSpec.Builder.() -> Unit +): SourceFile { + return JavaFile.builder( + packageName, + TypeSpec.classBuilder(className) + .addModifiers(PUBLIC) + .apply(body) .build() - .asSourceFile() + ) + .build() + .asSourceFile() } internal fun TypeSpec.Builder.methodSpec(name: String, body: MethodSpec.Builder.() -> Unit) { addMethod(MethodSpec.methodBuilder(name).addModifiers(PUBLIC).apply(body).build()) -} \ No newline at end of file +} diff --git a/keeper-gradle-plugin/src/test/kotlin/com/slack/keeper/KeeperFunctionalTest.kt b/keeper-gradle-plugin/src/test/kotlin/com/slack/keeper/KeeperFunctionalTest.kt index 1b634edc..f4ecaa4c 100644 --- a/keeper-gradle-plugin/src/test/kotlin/com/slack/keeper/KeeperFunctionalTest.kt +++ b/keeper-gradle-plugin/src/test/kotlin/com/slack/keeper/KeeperFunctionalTest.kt @@ -1,11 +1,11 @@ /* - * Copyright (C) 2020 Slack Technologies, LLC + * Copyright (C) 2020. Slack Technologies, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.slack.keeper import com.google.common.truth.Truth.assertThat @@ -92,13 +91,15 @@ internal class KeeperFunctionalTest(private val minifierType: MinifierType) { * @property keeperExtraConfig Extra [KeeperExtension] configuration. */ enum class MinifierType( - val taskName: String, - val expectedRules: Map?>, - val keeperExtraConfig: KeeperExtraConfig = KeeperExtraConfig.NONE + val taskName: String, + val expectedRules: Map?>, + val keeperExtraConfig: KeeperExtraConfig = KeeperExtraConfig.NONE ) { R8_PRINT_USES("R8", EXPECTED_PRINT_RULES_CONFIG), - R8_TRACE_REFERENCES("R8", EXPECTED_TRACE_REFERENCES_CONFIG, - keeperExtraConfig = KeeperExtraConfig.TRACE_REFERENCES_ENABLED) + R8_TRACE_REFERENCES( + "R8", EXPECTED_TRACE_REFERENCES_CONFIG, + keeperExtraConfig = KeeperExtraConfig.TRACE_REFERENCES_ENABLED + ) } @Rule @@ -114,16 +115,18 @@ internal class KeeperFunctionalTest(private val minifierType: MinifierType) { */ @Test fun standard() { - val (projectDir, proguardConfigOutput) = prepareProject(temporaryFolder, - buildGradleFile("staging", keeperExtraConfig = minifierType.keeperExtraConfig)) + val (projectDir, proguardConfigOutput) = prepareProject( + temporaryFolder, + buildGradleFile("staging", keeperExtraConfig = minifierType.keeperExtraConfig) + ) val result = projectDir.runAsWiredStaging() // Ensure the expected parameterized minifiers ran assertThat(result.resultOf(interpolateR8TaskName("ExternalStaging"))) - .isEqualTo(TaskOutcome.SUCCESS) + .isEqualTo(TaskOutcome.SUCCESS) assertThat(result.resultOf(interpolateR8TaskName("ExternalStagingAndroidTest"))) - .isEqualTo(TaskOutcome.SUCCESS) + .isEqualTo(TaskOutcome.SUCCESS) // Assert we correctly packaged app classes val appJar = projectDir.generatedChild("externalStaging/classes.jar") @@ -139,7 +142,8 @@ internal class KeeperFunctionalTest(private val minifierType: MinifierType) { // Assert we correctly generated rules val generatedRules = projectDir.generatedChild( - "externalStagingAndroidTest/inferredKeepRules.pro") + "externalStagingAndroidTest/inferredKeepRules.pro" + ) assertThat(generatedRules.readText().trim()).isEqualTo( minifierType.expectedRules.map { indentRules(it.key, it.value) }.joinToString("\n") ) @@ -158,11 +162,18 @@ internal class KeeperFunctionalTest(private val minifierType: MinifierType) { // "internalRelease" variant. @Test fun extensionMarker() { - val (projectDir, _) = prepareProject(temporaryFolder, buildGradleFile("release", - androidExtraConfig = AndroidExtraConfig.ONLY_INTERNAL_RELEASE)) + val (projectDir, _) = prepareProject( + temporaryFolder, + buildGradleFile( + "release", + androidExtraConfig = AndroidExtraConfig.ONLY_INTERNAL_RELEASE + ) + ) - val result = runGradle(projectDir, "assembleExternalRelease", "assembleInternalRelease", "-x", - "lintVitalExternalRelease", "-x", "lintVitalInternalRelease") + val result = runGradle( + projectDir, "assembleExternalRelease", "assembleInternalRelease", "-x", + "lintVitalExternalRelease", "-x", "lintVitalInternalRelease" + ) assertThat(result.findTask("jarExternalReleaseAndroidTestClassesForKeeper")).isNull() assertThat(result.findTask("jarExternalReleaseClassesForKeeper")).isNull() assertThat(result.findTask("inferExternalReleaseAndroidTestKeepRulesForKeeper")).isNull() @@ -177,8 +188,13 @@ internal class KeeperFunctionalTest(private val minifierType: MinifierType) { @Test fun extensionMarkerWarning() { // internalDebug variant isn't minified, but the variant is opted into Keeper. - val (projectDir, _) = prepareProject(temporaryFolder, buildGradleFile("debug", - androidExtraConfig = AndroidExtraConfig.ONLY_INTERNAL_DEBUG)) + val (projectDir, _) = prepareProject( + temporaryFolder, + buildGradleFile( + "debug", + androidExtraConfig = AndroidExtraConfig.ONLY_INTERNAL_DEBUG + ) + ) val result = runGradle(projectDir, "assembleInternalDebug") @@ -187,7 +203,8 @@ internal class KeeperFunctionalTest(private val minifierType: MinifierType) { assertThat(result.findTask("jarInternalDebugClassesForKeeper")).isNull() assertThat(result.findTask("inferInternalDebugAndroidTestKeepRulesForKeeper")).isNull() assertThat(result.output).contains( - "Keeper is configured to generate keep rules for the \"internalDebug\" build variant") + "Keeper is configured to generate keep rules for the \"internalDebug\" build variant" + ) } // Ensures that manual R8 repo management works @@ -200,19 +217,20 @@ internal class KeeperFunctionalTest(private val minifierType: MinifierType) { @Test fun duplicateClassesWarning() { val buildFile = buildGradleFile( - testBuildType = "staging", - emitDebugInformation = true, - extraDependencies = mapOf( - "implementation" to "\"org.threeten:threetenbp:1.4.0:no-tzdb\"", - "androidTestImplementation" to "\"org.threeten:threetenbp:1.4.0\"" - ) + testBuildType = "staging", + emitDebugInformation = true, + extraDependencies = mapOf( + "implementation" to "\"org.threeten:threetenbp:1.4.0:no-tzdb\"", + "androidTestImplementation" to "\"org.threeten:threetenbp:1.4.0\"" + ) ) val (projectDir, _) = prepareProject(temporaryFolder, buildFile) projectDir.runSingleTask("jarExternalStagingAndroidTestClassesForKeeper") // Check that we emitted a duplicate classes file val duplicateClasses = projectDir.generatedChild( - "externalStagingAndroidTest/diagnostics/duplicateClasses.txt") + "externalStagingAndroidTest/diagnostics/duplicateClasses.txt" + ) assertThat(duplicateClasses.readText().trim()).isNotEmpty() } @@ -223,18 +241,22 @@ internal class KeeperFunctionalTest(private val minifierType: MinifierType) { private fun File.runSingleTask(name: String): BuildResult { val result = runGradle(this, name, "-x", "lintVitalExternalStaging") assertThat(result.resultOf(name)).isEqualTo( - TaskOutcome.SUCCESS) + TaskOutcome.SUCCESS + ) return result } private fun File.runAsWiredStaging(): BuildResult { val result = runSingleTask("assembleExternalStagingAndroidTest") assertThat(result.resultOf("jarExternalStagingAndroidTestClassesForKeeper")).isEqualTo( - TaskOutcome.SUCCESS) + TaskOutcome.SUCCESS + ) assertThat(result.resultOf("jarExternalStagingClassesForKeeper")).isEqualTo( - TaskOutcome.SUCCESS) + TaskOutcome.SUCCESS + ) assertThat(result.resultOf("inferExternalStagingAndroidTestKeepRulesForKeeper")).isEqualTo( - TaskOutcome.SUCCESS) + TaskOutcome.SUCCESS + ) return result } @@ -242,15 +264,15 @@ internal class KeeperFunctionalTest(private val minifierType: MinifierType) { val extraArgs = args.toMutableList() extraArgs += "--stacktrace" return GradleRunner.create() - .forwardStdOutput(System.out.writer()) - .forwardStdError(System.err.writer()) - .withProjectDir(projectDir) - // TODO eventually test with configuration caching enabled - // https://docs.gradle.org/nightly/userguide/configuration_cache.html#testkit - .withArguments(extraArgs) - .withPluginClasspath() - .withDebug(true) // Tests run in-process and way faster with this enabled - .build() + .forwardStdOutput(System.out.writer()) + .forwardStdError(System.err.writer()) + .withProjectDir(projectDir) + // TODO eventually test with configuration caching enabled + // https://docs.gradle.org/nightly/userguide/configuration_cache.html#testkit + .withArguments(extraArgs) + .withPluginClasspath() + .withDebug(true) // Tests run in-process and way faster with this enabled + .build() } private fun BuildResult.findTask(name: String): BuildTask? { @@ -259,13 +281,14 @@ internal class KeeperFunctionalTest(private val minifierType: MinifierType) { private fun BuildResult.resultOf(name: String): TaskOutcome { return findTask(name)?.outcome - ?: error( - "Could not find task '$name', which is usually an indication that it didn't run. See GradleRunner's printed task graph for more details.") + ?: error( + "Could not find task '$name', which is usually an indication that it didn't run. See GradleRunner's printed task graph for more details." + ) } } private fun String.prefixIfNot(prefix: String) = - if (this.startsWith(prefix)) this else "$prefix$this" + if (this.startsWith(prefix)) this else "$prefix$this" @Language("PROGUARD") private val EXPECTED_TRACE_REFERENCES_CONFIG: Map?> = mapOf( @@ -299,15 +322,15 @@ private val TEST_PROGUARD_RULES = """ internal enum class KeeperExtraConfig(val groovy: String) { NONE(""), TRACE_REFERENCES_ENABLED( - """ + """ traceReferences {} - """.trimIndent() + """.trimIndent() ); } internal enum class AndroidExtraConfig(val groovy: String) { ONLY_EXTERNAL_STAGING( - """ + """ androidComponents { beforeVariants(selector().all()) { variantBuilder -> if (variantBuilder.name == "externalStaging") { @@ -318,10 +341,10 @@ internal enum class AndroidExtraConfig(val groovy: String) { } } } - """.trimIndent() + """.trimIndent() ), ONLY_INTERNAL_RELEASE( - """ + """ androidComponents { beforeVariants(selector().all()) { variantBuilder -> if (variantBuilder.name == "internalRelease") { @@ -332,10 +355,10 @@ internal enum class AndroidExtraConfig(val groovy: String) { } } } - """.trimIndent() + """.trimIndent() ), ONLY_INTERNAL_DEBUG( - """ + """ androidComponents { beforeVariants(selector().all()) { variantBuilder -> if (variantBuilder.name == "internalDebug") { @@ -346,18 +369,18 @@ internal enum class AndroidExtraConfig(val groovy: String) { } } } - """.trimIndent() + """.trimIndent() ); } @Language("groovy") private fun buildGradleFile( - testBuildType: String, - automaticR8RepoManagement: Boolean = true, - keeperExtraConfig: KeeperExtraConfig = KeeperExtraConfig.NONE, - androidExtraConfig: AndroidExtraConfig = AndroidExtraConfig.ONLY_EXTERNAL_STAGING, - emitDebugInformation: Boolean = false, - extraDependencies: Map = emptyMap() + testBuildType: String, + automaticR8RepoManagement: Boolean = true, + keeperExtraConfig: KeeperExtraConfig = KeeperExtraConfig.NONE, + androidExtraConfig: AndroidExtraConfig = AndroidExtraConfig.ONLY_EXTERNAL_STAGING, + emitDebugInformation: Boolean = false, + extraDependencies: Map = emptyMap() ): String { @Suppress("UnnecessaryVariable") @Language("groovy") @@ -405,7 +428,7 @@ private fun buildGradleFile( matchingFallbacks = ['release'] } } - + flavorDimensions "environment" productFlavors { internal { @@ -426,87 +449,93 @@ private fun buildGradleFile( google() mavenCentral() ${ - if (automaticR8RepoManagement) "" else """ + if (automaticR8RepoManagement) "" else """ maven { url = uri("https://storage.googleapis.com/r8-releases/raw") content { includeModule("com.android.tools", "r8") } } - """ + """ } } - + ${androidExtraConfig.groovy} - + keeper { emitDebugInformation.set($emitDebugInformation) automaticR8RepoManagement.set($automaticR8RepoManagement) emitDebugInformation.set($emitDebugInformation) ${keeperExtraConfig.groovy} } - + dependencies { ${extraDependencies.entries.joinToString("\n") { " ${it.key} ${it.value}" }} } -""".trimIndent() + """.trimIndent() return buildScript } private val MAIN_SOURCES = setOf( - // Class that's accessed from the application but not test sources - javaFile("com.slack.keeper.sample", "ApplicationUsedClass") { - methodSpec("applicationCalledMethod") { - addModifiers(STATIC) - addComment("This method is called from the application class") - } - }, - javaFile("com.slack.keeper.sample", "SampleApplication") { - superclass(ClassName.get("android.app", "Application")) - methodSpec("onCreate") { - addAnnotation(Override::class.java) - addStatement("super.onCreate()") - addStatement("\$T.applicationCalledMethod()", - ClassName.get("com.slack.keeper.sample", "ApplicationUsedClass")) - } - }, - // Class that's only accessed from androidTest - javaFile("com.slack.keeper.sample", "TestOnlyClass") { - methodSpec("testOnlyMethod") { - addModifiers(STATIC) - addComment("This method is only called from androidTest sources!") - } - }, - // Class that's only accessed from androidTest - kotlinFile("com.slack.keeper.sample", "TestOnlyKotlinClass") { - funSpec("testOnlyMethod") { - addComment("This method is only called from androidTest sources!") - } - }, - // Class that's unused - javaFile("com.slack.keeper.sample", "UnusedClass") { - methodSpec("unusedMethod") { - addModifiers(STATIC) - addComment("This class and method are completely unused") - } + // Class that's accessed from the application but not test sources + javaFile("com.slack.keeper.sample", "ApplicationUsedClass") { + methodSpec("applicationCalledMethod") { + addModifiers(STATIC) + addComment("This method is called from the application class") + } + }, + javaFile("com.slack.keeper.sample", "SampleApplication") { + superclass(ClassName.get("android.app", "Application")) + methodSpec("onCreate") { + addAnnotation(Override::class.java) + addStatement("super.onCreate()") + addStatement( + "\$T.applicationCalledMethod()", + ClassName.get("com.slack.keeper.sample", "ApplicationUsedClass") + ) + } + }, + // Class that's only accessed from androidTest + javaFile("com.slack.keeper.sample", "TestOnlyClass") { + methodSpec("testOnlyMethod") { + addModifiers(STATIC) + addComment("This method is only called from androidTest sources!") } + }, + // Class that's only accessed from androidTest + kotlinFile("com.slack.keeper.sample", "TestOnlyKotlinClass") { + funSpec("testOnlyMethod") { + addComment("This method is only called from androidTest sources!") + } + }, + // Class that's unused + javaFile("com.slack.keeper.sample", "UnusedClass") { + methodSpec("unusedMethod") { + addModifiers(STATIC) + addComment("This class and method are completely unused") + } + } ) private val ANDROID_TEST_SOURCES = setOf( - // AndroidTest file that uses the TestOnlyClass - javaFile("com.slack.keeper.sample", "TestOnlyClassCaller") { - methodSpec("callTestOnlyMethod") { - addStatement("\$T.testOnlyMethod()", - ClassName.get("com.slack.keeper.sample", "TestOnlyClass")) - } - }, - // AndroidTest file that uses the TestOnlyKotlinClass - kotlinFile("com.slack.keeper.sample", "TestOnlyKotlinClassCaller") { - funSpec("callTestOnlyMethod") { - addStatement("%T.testOnlyMethod()", - KpClassName("com.slack.keeper.sample", "TestOnlyKotlinClass")) - } + // AndroidTest file that uses the TestOnlyClass + javaFile("com.slack.keeper.sample", "TestOnlyClassCaller") { + methodSpec("callTestOnlyMethod") { + addStatement( + "\$T.testOnlyMethod()", + ClassName.get("com.slack.keeper.sample", "TestOnlyClass") + ) } + }, + // AndroidTest file that uses the TestOnlyKotlinClass + kotlinFile("com.slack.keeper.sample", "TestOnlyKotlinClassCaller") { + funSpec("callTestOnlyMethod") { + addStatement( + "%T.testOnlyMethod()", + KpClassName("com.slack.keeper.sample", "TestOnlyKotlinClass") + ) + } + } ) // We include Unit.class here because that allows us to also test that App's transitive dependencies @@ -528,18 +557,22 @@ private fun prepareProject(temporaryFolder: TemporaryFolder, buildFileText: Stri projectDir.newFile("build.gradle").apply { writeText(buildFileText) } projectDir.newFile("proguard-test-rules.pro") { writeText(TEST_PROGUARD_RULES) } projectDir.newFile("src/main/AndroidManifest.xml") { - writeText(""" + writeText( + """ - """.trimIndent()) + """.trimIndent() + ) } projectDir.newFile("src/androidTest/AndroidManifest.xml") { - writeText(""" + writeText( + """ - """.trimIndent()) + """.trimIndent() + ) } val mainSources = projectDir.newDir("src/main/java") @@ -557,12 +590,14 @@ private fun prepareProject(temporaryFolder: TemporaryFolder, buildFileText: Stri // that we can read to verify our generated rules were added. val proguardConfigOutput = projectDir.newFile("proguardConfigOutput.pro") projectDir.newFile("testconfiguration.pro") { - writeText(""" + writeText( + """ -printconfiguration ${proguardConfigOutput.absolutePath} -keep class com.slack.keeper.sample.SampleApplication { *; } # Proguard complains about module-info classes in META-INF -ignorewarnings - """.trimIndent()) + """.trimIndent() + ) } return ProjectData(projectDir, proguardConfigOutput) diff --git a/keeper-gradle-plugin/src/test/kotlin/com/slack/keeper/KotlinPoetExt.kt b/keeper-gradle-plugin/src/test/kotlin/com/slack/keeper/KotlinPoetExt.kt index 3d771d64..ae226fab 100644 --- a/keeper-gradle-plugin/src/test/kotlin/com/slack/keeper/KotlinPoetExt.kt +++ b/keeper-gradle-plugin/src/test/kotlin/com/slack/keeper/KotlinPoetExt.kt @@ -1,11 +1,11 @@ /* - * Copyright (C) 2020 Slack Technologies, LLC + * Copyright (C) 2020. Slack Technologies, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.slack.keeper import com.squareup.kotlinpoet.FileSpec @@ -21,13 +20,16 @@ import com.squareup.kotlinpoet.FunSpec import com.squareup.kotlinpoet.TypeSpec import java.io.File -internal fun kotlinFile(packageName: String, className: String, - body: TypeSpec.Builder.() -> Unit): SourceFile { +internal fun kotlinFile( + packageName: String, + className: String, + body: TypeSpec.Builder.() -> Unit +): SourceFile { return FileSpec.get( - packageName = packageName, - typeSpec = TypeSpec.objectBuilder(className) - .apply(body) - .build() + packageName = packageName, + typeSpec = TypeSpec.objectBuilder(className) + .apply(body) + .build() ).asSourceFile() } @@ -37,4 +39,4 @@ internal fun TypeSpec.Builder.funSpec(name: String, body: FunSpec.Builder.() -> internal operator fun File.plusAssign(fileSpec: FileSpec) { fileSpec.writeTo(this) -} \ No newline at end of file +} diff --git a/sample-libraries/a/src/main/kotlin/com/slack/keeper/example/a/AClass.java b/sample-libraries/a/src/main/kotlin/com/slack/keeper/example/a/AClass.java index 7507e93c..84ffdeda 100644 --- a/sample-libraries/a/src/main/kotlin/com/slack/keeper/example/a/AClass.java +++ b/sample-libraries/a/src/main/kotlin/com/slack/keeper/example/a/AClass.java @@ -1,11 +1,11 @@ /* - * Copyright (C) 2020 Slack Technologies, LLC + * Copyright (C) 2020. Slack Technologies, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.slack.keeper.example.a; import com.slack.keeper.example.b.BClass; diff --git a/sample-libraries/b/src/main/kotlin/com/slack/keeper/example/b/BClass.java b/sample-libraries/b/src/main/kotlin/com/slack/keeper/example/b/BClass.java index ab3e19fe..542c334a 100644 --- a/sample-libraries/b/src/main/kotlin/com/slack/keeper/example/b/BClass.java +++ b/sample-libraries/b/src/main/kotlin/com/slack/keeper/example/b/BClass.java @@ -1,11 +1,11 @@ /* - * Copyright (C) 2020 Slack Technologies, LLC + * Copyright (C) 2020. Slack Technologies, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.slack.keeper.example.b; import com.slack.keeper.example.c.CClass; diff --git a/sample-libraries/c/src/main/kotlin/com/slack/keeper/example/c/CClass.java b/sample-libraries/c/src/main/kotlin/com/slack/keeper/example/c/CClass.java index bf42a84e..21037317 100644 --- a/sample-libraries/c/src/main/kotlin/com/slack/keeper/example/c/CClass.java +++ b/sample-libraries/c/src/main/kotlin/com/slack/keeper/example/c/CClass.java @@ -1,11 +1,11 @@ /* - * Copyright (C) 2020 Slack Technologies, LLC + * Copyright (C) 2020. Slack Technologies, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.slack.keeper.example.c; import okio.ByteString; diff --git a/sample-libraries/c/src/main/kotlin/com/slack/keeper/example/c/TestOnlyCClass.java b/sample-libraries/c/src/main/kotlin/com/slack/keeper/example/c/TestOnlyCClass.java index 38786482..6807190f 100644 --- a/sample-libraries/c/src/main/kotlin/com/slack/keeper/example/c/TestOnlyCClass.java +++ b/sample-libraries/c/src/main/kotlin/com/slack/keeper/example/c/TestOnlyCClass.java @@ -1,11 +1,11 @@ /* - * Copyright (C) 2020 Slack Technologies, LLC + * Copyright (C) 2020. Slack Technologies, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.slack.keeper.example.c; import okio.ByteString; diff --git a/sample/src/androidTest/kotlin/com/slack/keeper/sample/KeeperSampleTest.kt b/sample/src/androidTest/kotlin/com/slack/keeper/sample/KeeperSampleTest.kt index 8e7fe127..87ca56f0 100644 --- a/sample/src/androidTest/kotlin/com/slack/keeper/sample/KeeperSampleTest.kt +++ b/sample/src/androidTest/kotlin/com/slack/keeper/sample/KeeperSampleTest.kt @@ -1,11 +1,11 @@ /* - * Copyright (C) 2020 Slack Technologies, LLC + * Copyright (C) 2020. Slack Technologies, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.slack.keeper.sample import androidx.test.ext.junit.runners.AndroidJUnit4 @@ -30,4 +29,4 @@ class KeeperSampleTest { TestOnlyClassCaller.callTestOnlyMethod() TestOnlyKotlinClassCaller.callTestOnlyMethod() } -} \ No newline at end of file +} diff --git a/sample/src/androidTest/kotlin/com/slack/keeper/sample/TestOnlyCClassCaller.kt b/sample/src/androidTest/kotlin/com/slack/keeper/sample/TestOnlyCClassCaller.kt index 1d906c64..b225d809 100644 --- a/sample/src/androidTest/kotlin/com/slack/keeper/sample/TestOnlyCClassCaller.kt +++ b/sample/src/androidTest/kotlin/com/slack/keeper/sample/TestOnlyCClassCaller.kt @@ -1,11 +1,11 @@ /* - * Copyright (C) 2020 Slack Technologies, LLC + * Copyright (C) 2020. Slack Technologies, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.slack.keeper.sample import com.slack.keeper.example.c.TestOnlyCClass @@ -29,4 +28,4 @@ object TestOnlyCClassCaller { val byteString: ByteString = "Hello C caller! See you in $days day.".encodeUtf8() println(byteString.hex()) } -} \ No newline at end of file +} diff --git a/sample/src/androidTest/kotlin/com/slack/keeper/sample/TestOnlyClassCaller.java b/sample/src/androidTest/kotlin/com/slack/keeper/sample/TestOnlyClassCaller.java index 9c9377de..d472582c 100644 --- a/sample/src/androidTest/kotlin/com/slack/keeper/sample/TestOnlyClassCaller.java +++ b/sample/src/androidTest/kotlin/com/slack/keeper/sample/TestOnlyClassCaller.java @@ -1,11 +1,11 @@ /* - * Copyright (C) 2020 Slack Technologies, LLC + * Copyright (C) 2020. Slack Technologies, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.slack.keeper.sample; /** AndroidTest file that uses the TestOnlyClass. */ diff --git a/sample/src/androidTest/kotlin/com/slack/keeper/sample/TestOnlyKotlinClassCaller.kt b/sample/src/androidTest/kotlin/com/slack/keeper/sample/TestOnlyKotlinClassCaller.kt index 5e260eb6..fda20b09 100644 --- a/sample/src/androidTest/kotlin/com/slack/keeper/sample/TestOnlyKotlinClassCaller.kt +++ b/sample/src/androidTest/kotlin/com/slack/keeper/sample/TestOnlyKotlinClassCaller.kt @@ -1,11 +1,11 @@ /* - * Copyright (C) 2020 Slack Technologies, LLC + * Copyright (C) 2020. Slack Technologies, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.slack.keeper.sample /** AndroidTest file that uses the TestOnlyKotlinClass. */ @@ -21,4 +20,4 @@ object TestOnlyKotlinClassCaller { fun callTestOnlyMethod() { TestOnlyKotlinClass.testOnlyMethod() } -} \ No newline at end of file +} diff --git a/sample/src/main/kotlin/com/slack/keeper/sample/ApplicationUsedClass.java b/sample/src/main/kotlin/com/slack/keeper/sample/ApplicationUsedClass.java index aa7508e2..6ce9099d 100644 --- a/sample/src/main/kotlin/com/slack/keeper/sample/ApplicationUsedClass.java +++ b/sample/src/main/kotlin/com/slack/keeper/sample/ApplicationUsedClass.java @@ -1,11 +1,11 @@ /* - * Copyright (C) 2020 Slack Technologies, LLC + * Copyright (C) 2020. Slack Technologies, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,12 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.slack.keeper.sample; /** Class that's accessed from the application but not test sources. */ public class ApplicationUsedClass { - public static void applicationCalledMethod() { - - } -} \ No newline at end of file + public static void applicationCalledMethod() {} +} diff --git a/sample/src/main/kotlin/com/slack/keeper/sample/SampleApplication.java b/sample/src/main/kotlin/com/slack/keeper/sample/SampleApplication.java index 636f9068..5db3eb04 100644 --- a/sample/src/main/kotlin/com/slack/keeper/sample/SampleApplication.java +++ b/sample/src/main/kotlin/com/slack/keeper/sample/SampleApplication.java @@ -1,11 +1,11 @@ /* - * Copyright (C) 2020 Slack Technologies, LLC + * Copyright (C) 2020. Slack Technologies, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.slack.keeper.sample; import android.app.Application; @@ -23,7 +22,8 @@ import java.time.format.ResolverStyle; public class SampleApplication extends Application { - @Override public void onCreate() { + @Override + public void onCreate() { super.onCreate(); ApplicationUsedClass.applicationCalledMethod(); @@ -32,10 +32,11 @@ public class SampleApplication extends Application { // Regression test for https://github.com/slackhq/keeper/issues/67 @SuppressWarnings("unused") - DateTimeFormatter formatter = new DateTimeFormatterBuilder() - .parseCaseInsensitive() - .appendInstant(9) - .toFormatter() - .withResolverStyle(ResolverStyle.STRICT); + DateTimeFormatter formatter = + new DateTimeFormatterBuilder() + .parseCaseInsensitive() + .appendInstant(9) + .toFormatter() + .withResolverStyle(ResolverStyle.STRICT); } } diff --git a/sample/src/main/kotlin/com/slack/keeper/sample/TestOnlyClass.java b/sample/src/main/kotlin/com/slack/keeper/sample/TestOnlyClass.java index f93cfd99..d595edb9 100644 --- a/sample/src/main/kotlin/com/slack/keeper/sample/TestOnlyClass.java +++ b/sample/src/main/kotlin/com/slack/keeper/sample/TestOnlyClass.java @@ -1,11 +1,11 @@ /* - * Copyright (C) 2020 Slack Technologies, LLC + * Copyright (C) 2020. Slack Technologies, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,12 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.slack.keeper.sample; /** Class that's only accessed from androidTest. */ public class TestOnlyClass { - public static void testOnlyMethod() { - - } + public static void testOnlyMethod() {} } diff --git a/sample/src/main/kotlin/com/slack/keeper/sample/TestOnlyKotlinClass.kt b/sample/src/main/kotlin/com/slack/keeper/sample/TestOnlyKotlinClass.kt index 1bebc203..7ddd0047 100644 --- a/sample/src/main/kotlin/com/slack/keeper/sample/TestOnlyKotlinClass.kt +++ b/sample/src/main/kotlin/com/slack/keeper/sample/TestOnlyKotlinClass.kt @@ -1,11 +1,11 @@ /* - * Copyright (C) 2020 Slack Technologies, LLC + * Copyright (C) 2020. Slack Technologies, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,12 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.slack.keeper.sample /** Class that's only accessed from androidTest. */ object TestOnlyKotlinClass { fun testOnlyMethod() { - } -} \ No newline at end of file +} diff --git a/sample/src/main/kotlin/com/slack/keeper/sample/UnusedClass.java b/sample/src/main/kotlin/com/slack/keeper/sample/UnusedClass.java index 6baf6868..96e9760c 100644 --- a/sample/src/main/kotlin/com/slack/keeper/sample/UnusedClass.java +++ b/sample/src/main/kotlin/com/slack/keeper/sample/UnusedClass.java @@ -1,11 +1,11 @@ /* - * Copyright (C) 2020 Slack Technologies, LLC + * Copyright (C) 2020. Slack Technologies, LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,11 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.slack.keeper.sample; public class UnusedClass { - public static void unusedMethod() { - - } + public static void unusedMethod() {} } diff --git a/spotless/copyright.java b/spotless/copyright.java new file mode 100644 index 00000000..2a70e7c7 --- /dev/null +++ b/spotless/copyright.java @@ -0,0 +1,15 @@ +/* + * Copyright (C) $YEAR. Slack Technologies, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/spotless/copyright.kt b/spotless/copyright.kt new file mode 100644 index 00000000..2a70e7c7 --- /dev/null +++ b/spotless/copyright.kt @@ -0,0 +1,15 @@ +/* + * Copyright (C) $YEAR. Slack Technologies, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */