diff options
Diffstat (limited to 'compiler-plugin/src/main/kotlin/com/google/devtools/ksp/KotlinSymbolProcessingPlugin.kt')
-rw-r--r-- | compiler-plugin/src/main/kotlin/com/google/devtools/ksp/KotlinSymbolProcessingPlugin.kt | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/KotlinSymbolProcessingPlugin.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/KotlinSymbolProcessingPlugin.kt new file mode 100644 index 00000000..9d2c400b --- /dev/null +++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/KotlinSymbolProcessingPlugin.kt @@ -0,0 +1,96 @@ +/* + * Copyright 2020 Google LLC + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * + * 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 + * + * 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.google.devtools.ksp + +import com.google.devtools.ksp.processing.impl.MessageCollectorBasedKSPLogger +import com.intellij.core.CoreApplicationEnvironment +import com.intellij.mock.MockProject +import com.intellij.psi.PsiTreeChangeAdapter +import com.intellij.psi.PsiTreeChangeListener +import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys +import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot +import org.jetbrains.kotlin.compiler.plugin.AbstractCliOption +import org.jetbrains.kotlin.compiler.plugin.CliOptionProcessingException +import org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor +import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar +import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi +import org.jetbrains.kotlin.config.CommonConfigurationKeys +import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.config.CompilerConfigurationKey +import org.jetbrains.kotlin.config.KotlinCompilerVersion +import org.jetbrains.kotlin.config.languageVersionSettings +import org.jetbrains.kotlin.config.toKotlinVersion +import org.jetbrains.kotlin.resolve.extensions.AnalysisHandlerExtension + +private val KSP_OPTIONS = CompilerConfigurationKey.create<KspOptions.Builder>("Ksp options") + +@ExperimentalCompilerApi +class KotlinSymbolProcessingCommandLineProcessor : CommandLineProcessor { + override val pluginId = "com.google.devtools.ksp.symbol-processing" + + override val pluginOptions: Collection<AbstractCliOption> = KspCliOption.values().asList() + + override fun processOption(option: AbstractCliOption, value: String, configuration: CompilerConfiguration) { + if (option !is KspCliOption) { + throw CliOptionProcessingException("Unknown option: ${option.optionName}") + } + + val kspOptions = configuration[KSP_OPTIONS] + ?: KspOptions.Builder().also { configuration.put(KSP_OPTIONS, it) } + kspOptions.processOption(option, value) + } +} + +// Changes here may break some third party libraries like Kotlin Compile Testing, where the compiler is invoked in +// another way. Do our best to notify them when changing this. +// +// Third party libraries: +// https://github.com/tschuchortdev/kotlin-compile-testing +@Suppress("DEPRECATION") +@ExperimentalCompilerApi +class KotlinSymbolProcessingComponentRegistrar : ComponentRegistrar { + override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) { + val contentRoots = configuration[CLIConfigurationKeys.CONTENT_ROOTS] ?: emptyList() + val options = configuration[KSP_OPTIONS]?.apply { + javaSourceRoots.addAll(contentRoots.filterIsInstance<JavaSourceRoot>().map { it.file }) + languageVersion = configuration.languageVersionSettings.languageVersion.toKotlinVersion() + apiVersion = configuration.languageVersionSettings.apiVersion.toKotlinVersion() + compilerVersion = KotlinCompilerVersion.getVersion().toKotlinVersion() + }?.build() ?: return + val messageCollector = configuration.get(CLIConfigurationKeys.ORIGINAL_MESSAGE_COLLECTOR_KEY) + ?: throw IllegalStateException("ksp: message collector not found!") + val wrappedMessageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY) + ?: throw IllegalStateException("ksp: message collector not found!") + val logger = MessageCollectorBasedKSPLogger( + messageCollector, wrappedMessageCollector, options.allWarningsAsErrors + ) + if (options.processingClasspath.isNotEmpty()) { + if (options.withCompilation && options.incremental) { + throw IllegalStateException("ksp: `incremental` is incompatible with `withCompilation`.") + } + val kotlinSymbolProcessingHandlerExtension = KotlinSymbolProcessingExtension(options, logger) + AnalysisHandlerExtension.registerExtension(project, kotlinSymbolProcessingHandlerExtension) + configuration.put(CommonConfigurationKeys.LOOKUP_TRACKER, DualLookupTracker()) + + // Dummy extension point; Required by dropPsiCaches(). + CoreApplicationEnvironment.registerExtensionPoint( + project.extensionArea, PsiTreeChangeListener.EP.name, PsiTreeChangeAdapter::class.java + ) + } + } +} |