Skip to content
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

Move KSP to an independent Gradle task #130

Merged
merged 1 commit into from
Oct 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,6 @@ class KotlinSymbolProcessingExtension(

abstract class AbstractKotlinSymbolProcessingExtension(val options: KspOptions, val logger: KSPLogger, val testMode: Boolean) :
AnalysisHandlerExtension {
private var completed = false

override fun doAnalysis(
project: Project,
module: ModuleDescriptor,
Expand All @@ -69,9 +67,6 @@ abstract class AbstractKotlinSymbolProcessingExtension(val options: KspOptions,
bindingTrace: BindingTrace,
componentProvider: ComponentProvider
): AnalysisResult? {
if (completed)
return null

val psiManager = PsiManager.getInstance(project)
val localFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL)
val javaFiles = options.javaSourceRoots
Expand Down Expand Up @@ -101,7 +96,7 @@ abstract class AbstractKotlinSymbolProcessingExtension(val options: KspOptions,

KSObjectCacheManager.clear()

return AnalysisResult.success(BindingContext.EMPTY, module, shouldGenerateCode = false)
return AnalysisResult.EMPTY
}

abstract fun loadProcessors(): List<SymbolProcessor>
Expand All @@ -112,21 +107,7 @@ abstract class AbstractKotlinSymbolProcessingExtension(val options: KspOptions,
bindingTrace: BindingTrace,
files: Collection<KtFile>
): AnalysisResult? {
if (completed)
return null

completed = true

if (testMode)
return null

return AnalysisResult.RetryWithAdditionalRoots(
BindingContext.EMPTY,
module,
listOf(options.javaOutputDir),
listOf(options.kotlinOutputDir),
addToEnvironment = true
)
return AnalysisResult.success(BindingContext.EMPTY, module, shouldGenerateCode = false)
}

private var annotationProcessingComplete = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,17 +65,6 @@ class KotlinSymbolProcessingCommandLineProcessor : CommandLineProcessor {

class KotlinSymbolProcessingComponentRegistrar : ComponentRegistrar {
override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) {
// Don't bother with KAPT tasks.
// There is no way to pass KSP options to compileKotlin only. Have to workaround here.
val outputDir = configuration[JVMConfigurationKeys.OUTPUT_DIRECTORY]
val kaptOutputDirs = listOf(
listOf("tmp", "kapt3", "stubs"),
listOf("tmp", "kapt3", "incrementalData"),
listOf("tmp", "kapt3", "incApCache")
).map { File(it.joinToString(File.separator)) }
if (kaptOutputDirs.any { outputDir?.parentFile?.endsWith(it) == true })
return

val contentRoots = configuration[CLIConfigurationKeys.CONTENT_ROOTS] ?: emptyList()
val options = configuration[KSP_OPTIONS]?.apply {
javaSourceRoots.addAll(contentRoots.filterIsInstance<JavaSourceRoot>().map { it.file })
Expand Down
2 changes: 2 additions & 0 deletions gradle-plugin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ plugins {

dependencies {
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin-api:$kotlinBaseVersion")
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinBaseVersion")
compileOnly("org.jetbrains.kotlin:kotlin-compiler:$kotlinBaseVersion")

compileOnly(gradleApi())

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.google.devtools.ksp.gradle;

import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation;
import org.jetbrains.kotlin.gradle.tasks.KotlinCompileTaskData;

// FIXME: Ask upstream to open these API
public class InternalTrampoline {
public static void KotlinCompileTaskData_register(String taskName, KotlinCompilation<?> kotlinCompilation) {
KotlinCompileTaskData kotlinCompileTaskData = KotlinCompileTaskData.Companion.register(taskName, kotlinCompilation);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import com.google.devtools.ksp.gradle.KspGradleSubplugin.Companion.getKspKotlinO
import com.google.devtools.ksp.gradle.KspGradleSubplugin.Companion.getKspResourceOutputDir
import java.io.File
import javax.inject.Inject
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

class KspGradleSubplugin @Inject internal constructor(private val registry: ToolingModelBuilderRegistry) : Plugin<Project> {
companion object {
Expand Down Expand Up @@ -67,6 +68,8 @@ class KspGradleSubplugin @Inject internal constructor(private val registry: Tool
class KspKotlinGradleSubplugin : KotlinGradleSubplugin<AbstractCompile> {
companion object {
const val KSP_ARTIFACT_NAME = "symbol-processing"
const val KSP_PLUGIN_ID = "com.google.devtools.ksp.symbol-processing"

}

override fun isApplicable(project: Project, task: AbstractCompile) = KspGradleSubplugin.isEnabled(project)
Expand All @@ -88,8 +91,6 @@ class KspKotlinGradleSubplugin : KotlinGradleSubplugin<AbstractCompile> {

kotlinCompile.dependsOn(kspConfiguration.buildDependencies)

kotlinCompile.setProperty("incremental", false)

val options = mutableListOf<SubpluginOption>()

options += FilesSubpluginOption("apclasspath", kspConfiguration)
Expand All @@ -114,10 +115,47 @@ class KspKotlinGradleSubplugin : KotlinGradleSubplugin<AbstractCompile> {
javaCompile.source(generatedJavaSources)
}

return options
val kspTaskName = kotlinCompile.name.replaceFirst("compile", "ksp")
InternalTrampoline.KotlinCompileTaskData_register(kspTaskName, kotlinCompilation)

val kspTaskProvider = project.tasks.register(kspTaskName, KspTask::class.java) { kspTask ->
kspTask.setDestinationDir(File(project.buildDir, "generated/ksp"))
kspTask.mapClasspath { kotlinCompile.classpath }
kspTask.options = options
}.apply {
configure {
kotlinCompilation?.allKotlinSourceSets?.forEach { sourceSet -> it.source(sourceSet.kotlin) }
}
}

kotlinCompile.dependsOn(kspTaskProvider)
kotlinCompile.source(kotlinOutputDir, javaOutputDir)

return emptyList()
}

override fun getCompilerPluginId() = "com.google.devtools.ksp.symbol-processing"
override fun getCompilerPluginId() = KSP_PLUGIN_ID
override fun getPluginArtifact(): SubpluginArtifact =
SubpluginArtifact(groupId = "com.google.devtools.ksp", artifactId = KSP_ARTIFACT_NAME, version = javaClass.`package`.implementationVersion)
}

open class KspTask : KotlinCompile() {
lateinit var options: List<SubpluginOption>

init {
// kotlinc's incremental compilation isn't compatible with symbol processing in a few ways:
// * It doesn't consider private / internal changes when computing dirty sets.
// * It compiles iteratively; Sources can be compiled in different rounds.
incremental = false
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR description says it was reenabled but this seems to suggest it's not?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incremental compilation is back on in the compilation Gradle task, but incremental processing is off in the new ksp specific Gradle task, as the later is still under construction :-)

}

override fun setupCompilerArgs(
args: org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments,
defaultsOnly: Boolean,
ignoreClasspathResolutionErrors: Boolean
) {
fun SubpluginOption.toArg() = "plugin:${KspKotlinGradleSubplugin.KSP_PLUGIN_ID}:${key}=${value}"
super.setupCompilerArgs(args, defaultsOnly, ignoreClasspathResolutionErrors)
args.pluginOptions = (options.map { it.toArg() } + args.pluginOptions!!).toTypedArray()
}
}