-
Notifications
You must be signed in to change notification settings - Fork 81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Start KSP dual implementation #722
Changes from 9 commits
d7e63ad
e9e7b99
2337b75
b7ee29f
cad1b65
e6ac598
a030d15
6e11193
c6d5775
14cf287
78815d3
c513b73
6e223db
4ed03de
d51fc90
074d5cb
31ae236
1eb9653
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,28 @@ | ||
package com.squareup.anvil.compiler.internal.testing | ||
|
||
import com.google.auto.value.processor.AutoAnnotationProcessor | ||
import com.google.devtools.ksp.processing.SymbolProcessorProvider | ||
import com.squareup.anvil.annotations.ExperimentalAnvilApi | ||
import com.squareup.anvil.compiler.AnvilCommandLineProcessor | ||
import com.squareup.anvil.compiler.AnvilComponentRegistrar | ||
import com.squareup.anvil.compiler.api.CodeGenerator | ||
import com.squareup.anvil.compiler.internal.testing.AnvilCompilationMode.Embedded | ||
import com.squareup.anvil.compiler.internal.testing.AnvilCompilationMode.Ksp | ||
import com.tschuchort.compiletesting.KotlinCompilation | ||
import com.tschuchort.compiletesting.KotlinCompilation.Result | ||
import com.tschuchort.compiletesting.PluginOption | ||
import com.tschuchort.compiletesting.SourceFile | ||
import com.tschuchort.compiletesting.addPreviousResultToClasspath | ||
import com.tschuchort.compiletesting.kspArgs | ||
import com.tschuchort.compiletesting.kspWithCompilation | ||
import com.tschuchort.compiletesting.symbolProcessorProviders | ||
import dagger.internal.codegen.ComponentProcessor | ||
import org.intellij.lang.annotations.Language | ||
import org.jetbrains.kotlin.config.JvmTarget | ||
import java.io.File | ||
import java.io.OutputStream | ||
import java.nio.file.Files | ||
import java.util.Locale | ||
import java.util.ServiceLoader | ||
|
||
/** | ||
* A simple API over a [KotlinCompilation] with extra configuration support for Anvil. | ||
|
@@ -37,7 +44,7 @@ public class AnvilCompilation internal constructor( | |
generateDaggerFactoriesOnly: Boolean = false, | ||
disableComponentMerging: Boolean = false, | ||
enableExperimentalAnvilApis: Boolean = true, | ||
codeGenerators: List<CodeGenerator> = emptyList(), | ||
mode: AnvilCompilationMode = Embedded(emptyList()), | ||
enableAnvil: Boolean = true, | ||
) = apply { | ||
checkNotCompiled() | ||
|
@@ -48,41 +55,68 @@ public class AnvilCompilation internal constructor( | |
if (!enableAnvil) return@apply | ||
|
||
kotlinCompilation.apply { | ||
val anvilComponentRegistrar = AnvilComponentRegistrar() | ||
// Deprecation tracked in https://github.com/square/anvil/issues/672 | ||
@Suppress("DEPRECATION") | ||
componentRegistrars = listOf( | ||
AnvilComponentRegistrar().also { it.addCodeGenerators(codeGenerators) } | ||
) | ||
componentRegistrars = listOf(anvilComponentRegistrar) | ||
if (enableDaggerAnnotationProcessor) { | ||
annotationProcessors = listOf(ComponentProcessor(), AutoAnnotationProcessor()) | ||
} | ||
|
||
val anvilCommandLineProcessor = AnvilCommandLineProcessor() | ||
commandLineProcessors = listOf(anvilCommandLineProcessor) | ||
|
||
pluginOptions = listOf( | ||
PluginOption( | ||
pluginId = anvilCommandLineProcessor.pluginId, | ||
optionName = "src-gen-dir", | ||
optionValue = File(workingDir, "build/anvil").absolutePath | ||
), | ||
pluginOptions = mutableListOf( | ||
PluginOption( | ||
pluginId = anvilCommandLineProcessor.pluginId, | ||
optionName = "generate-dagger-factories", | ||
optionValue = generateDaggerFactories.toString() | ||
), | ||
PluginOption( | ||
pluginId = anvilCommandLineProcessor.pluginId, | ||
optionName = "generate-dagger-factories-only", | ||
optionValue = generateDaggerFactoriesOnly.toString() | ||
optionName = "disable-component-merging", | ||
optionValue = disableComponentMerging.toString() | ||
), | ||
PluginOption( | ||
pluginId = anvilCommandLineProcessor.pluginId, | ||
optionName = "disable-component-merging", | ||
optionValue = disableComponentMerging.toString() | ||
optionName = "compilation-mode", | ||
optionValue = mode.type.name.lowercase(Locale.US) | ||
) | ||
) | ||
|
||
when (mode) { | ||
is Embedded -> { | ||
anvilComponentRegistrar.addCodeGenerators(mode.codeGenerators) | ||
pluginOptions += | ||
listOf( | ||
PluginOption( | ||
pluginId = anvilCommandLineProcessor.pluginId, | ||
optionName = "src-gen-dir", | ||
optionValue = File(workingDir, "build/anvil").absolutePath | ||
), | ||
PluginOption( | ||
pluginId = anvilCommandLineProcessor.pluginId, | ||
optionName = "generate-dagger-factories", | ||
optionValue = generateDaggerFactories.toString() | ||
), | ||
PluginOption( | ||
pluginId = anvilCommandLineProcessor.pluginId, | ||
optionName = "generate-dagger-factories-only", | ||
optionValue = generateDaggerFactoriesOnly.toString() | ||
) | ||
) | ||
} | ||
is Ksp -> { | ||
symbolProcessorProviders += buildList { | ||
addAll( | ||
ServiceLoader.load( | ||
SymbolProcessorProvider::class.java, | ||
SymbolProcessorProvider::class.java.classLoader | ||
) | ||
) | ||
addAll(mode.symbolProcessorProviders) | ||
} | ||
kspWithCompilation = true | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is how we force KSP to compile in-process during the kotlinc invocation, just for testing. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Maybe worth adding this as a code comment? Unless that's already documented on the KCT side There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's on the kdoc iirc There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added one in |
||
kspArgs["generate-dagger-factories"] = generateDaggerFactories.toString() | ||
kspArgs["generate-dagger-factories-only"] = generateDaggerFactoriesOnly.toString() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we not use PluginOption for these still / why is there this API difference for KSP? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. KSP uses its own API yeah. Modeled after how annotation processing options are |
||
} | ||
} | ||
|
||
if (enableExperimentalAnvilApis) { | ||
kotlincArguments += listOf( | ||
"-opt-in=kotlin.RequiresOptIn", | ||
|
@@ -202,11 +236,11 @@ public fun compileAnvil( | |
workingDir: File? = null, | ||
enableExperimentalAnvilApis: Boolean = true, | ||
previousCompilationResult: Result? = null, | ||
codeGenerators: List<CodeGenerator> = emptyList(), | ||
mode: AnvilCompilationMode = Embedded(emptyList()), | ||
moduleName: String? = null, | ||
jvmTarget: JvmTarget? = null, | ||
block: Result.() -> Unit = { }, | ||
): Result { | ||
block: KotlinCompilation.Result.() -> Unit = { }, | ||
): KotlinCompilation.Result { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: Any reason to make these There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because kotlin.Result is an implicit import and they cause issues. This is why I changed the name (and updated in the KCT update PR) |
||
return AnvilCompilation() | ||
.apply { | ||
kotlinCompilation.apply { | ||
|
@@ -234,7 +268,7 @@ public fun compileAnvil( | |
generateDaggerFactoriesOnly = generateDaggerFactoriesOnly, | ||
disableComponentMerging = disableComponentMerging, | ||
enableExperimentalAnvilApis = enableExperimentalAnvilApis, | ||
codeGenerators = codeGenerators, | ||
mode = mode, | ||
) | ||
.compile(*sources) | ||
.also(block) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package com.squareup.anvil.compiler.internal.testing | ||
|
||
import com.google.devtools.ksp.processing.SymbolProcessorProvider | ||
import com.squareup.anvil.compiler.api.CodeGenerator | ||
import com.squareup.anvil.compiler.internal.testing.AnvilCompilationMode.Type.EMBEDDED | ||
import com.squareup.anvil.compiler.internal.testing.AnvilCompilationMode.Type.KSP | ||
|
||
sealed class AnvilCompilationMode(val type: Type) { | ||
enum class Type { | ||
EMBEDDED, KSP | ||
} | ||
|
||
data class Embedded( | ||
val codeGenerators: List<CodeGenerator> = emptyList() | ||
) : AnvilCompilationMode(EMBEDDED) | ||
data class Ksp( | ||
val symbolProcessorProviders: List<SymbolProcessorProvider> = emptyList() | ||
) : AnvilCompilationMode(KSP) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,10 @@ internal const val disableComponentMergingName = "disable-component-merging" | |
internal val disableComponentMergingKey = | ||
CompilerConfigurationKey.create<Boolean>("anvil $disableComponentMergingName") | ||
|
||
internal const val compilationModeName = "compilation-mode" | ||
internal val compilationModeKey = | ||
CompilerConfigurationKey.create<String>("anvil $compilationModeName") | ||
|
||
/** | ||
* Parses arguments from the Gradle plugin for the compiler plugin. | ||
*/ | ||
|
@@ -34,7 +38,7 @@ class AnvilCommandLineProcessor : CommandLineProcessor { | |
optionName = srcGenDirName, | ||
valueDescription = "<file-path>", | ||
description = "Path to directory in which Anvil specific code should be generated", | ||
required = true, | ||
required = false, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this optional now? Do we lose the ability to configure this with KSP? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't need it at all in KSP |
||
allowMultipleOccurrences = false | ||
), | ||
CliOption( | ||
|
@@ -61,6 +65,13 @@ class AnvilCommandLineProcessor : CommandLineProcessor { | |
"@MergeComponent or @MergeSubcomponent.", | ||
required = false, | ||
allowMultipleOccurrences = false | ||
), | ||
CliOption( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added this option so we could correctly gate the modes, but have not wired it up in the gradle plugin yet. I figure we can wait on that until everything's fully implemented |
||
optionName = compilationModeName, | ||
valueDescription = "<embedded|ksp>", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you add constants for both of these values? Looks like we could probably utilize the existing types you created in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extracted in 4ed03de |
||
description = "Controls whether Anvil is running as an embedded plugin or as KSP.", | ||
required = false, | ||
allowMultipleOccurrences = false | ||
) | ||
) | ||
|
||
|
@@ -77,6 +88,8 @@ class AnvilCommandLineProcessor : CommandLineProcessor { | |
configuration.put(generateDaggerFactoriesOnlyKey, value.toBoolean()) | ||
disableComponentMergingName -> | ||
configuration.put(disableComponentMergingKey, value.toBoolean()) | ||
compilationModeName -> | ||
configuration.put(compilationModeKey, value) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you know if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It does not validate There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added some + a stronger typed parsing in 4ed03de |
||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I gated these off now that they may not be necessary in all compilations