
.kotlin.kotlin-annotation-processing.1.4.21-2.source-code.KaptCli.kt Maven / Gradle / Ivy
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:JvmName("KaptCli")
package org.jetbrains.kotlin.kapt.cli
import com.intellij.util.PathUtil
import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.cli.common.ExitCode
import org.jetbrains.kotlin.cli.common.arguments.ArgumentParseErrors
import org.jetbrains.kotlin.cli.common.arguments.preprocessCommandLineArguments
import org.jetbrains.kotlin.cli.common.arguments.validateArguments
import org.jetbrains.kotlin.cli.common.messages.*
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
import org.jetbrains.kotlin.cli.jvm.modules.isAtLeastJava9
import org.jetbrains.kotlin.kapt.cli.CliToolOption.Format.*
import java.io.File
import kotlin.system.exitProcess
fun main(args: Array) {
val messageCollector = PrintingMessageCollector(System.err, MessageRenderer.PLAIN_RELATIVE_PATHS, false)
if (args.isEmpty() || args.contains("-help")) {
printHelp()
return
}
val kaptTransformed = transformArgs(args.asList(), messageCollector, false)
if (messageCollector.hasErrors()) {
exitProcess(ExitCode.COMPILATION_ERROR.code)
}
K2JVMCompiler.main(kaptTransformed.toTypedArray())
}
@TestOnly
internal fun transformArgs(args: List, messageCollector: MessageCollector, isTest: Boolean): List {
val parseErrors = ArgumentParseErrors()
val kotlincTransformed = preprocessCommandLineArguments(args, parseErrors)
val errorMessage = validateArguments(parseErrors)
if (errorMessage != null) {
messageCollector.report(CompilerMessageSeverity.ERROR, errorMessage)
return emptyList()
}
return try {
transformKaptToolArgs(kotlincTransformed, messageCollector, isTest)
} catch (e: IllegalArgumentException) {
messageCollector.report(CompilerMessageSeverity.ERROR, e.localizedMessage)
emptyList()
}
}
private const val KAPT_COMPILER_PLUGIN_JAR_NAME = "kotlin-annotation-processing.jar"
private fun transformKaptToolArgs(args: List, messageCollector: MessageCollector, isTest: Boolean): List {
val transformed = mutableListOf()
if (!isTest) {
val kaptCompilerPluginFile = findKaptCompilerPlugin()
?: throw IllegalStateException("Can't find $KAPT_COMPILER_PLUGIN_JAR_NAME")
transformed += "-Xplugin=${kaptCompilerPluginFile.absolutePath}"
}
var toolsJarPassed = false
var aptModePassed = false
var kaptVerboseModePassed = false
data class Option(val cliToolOption: CliToolOption, val pluginOption: KaptCliOption)
val cliOptions = KaptCliOption.values().mapNotNull { Option(it.cliToolOption ?: return@mapNotNull null, it) }
val iterator = args.asIterable().iterator()
loop@ while (iterator.hasNext()) {
val arg = iterator.next()
if (arg == "--") {
transformed += arg
iterator.forEach { transformed += it }
break
}
if (arg == "-help") {
throw IllegalStateException("-help option should be already processed")
}
val option = cliOptions.firstOrNull { it.cliToolOption.matches(arg) }
if (option == null) {
transformed += arg
continue
}
val transformedOption = option.cliToolOption.transform(arg)
when (option.pluginOption) {
KaptCliOption.TOOLS_JAR_OPTION -> {
// TOOLS_JAR option is not passed as other compiler plugin options.
// It is only used in kapt-cli, and we add a -Xplugin compiler option instead.
toolsJarPassed = true
transformed.add(0, "-Xplugin=$transformedOption")
continue@loop
}
KaptCliOption.APT_MODE_OPTION -> aptModePassed = true
KaptCliOption.VERBOSE_MODE_OPTION -> kaptVerboseModePassed = true
else -> {}
}
transformed += kaptArg(option.pluginOption, transformedOption)
}
if (!aptModePassed) {
transformed.addAll(0, kaptArg(KaptCliOption.APT_MODE_OPTION, "compile"))
}
if (!isTest && !isAtLeastJava9() && !areJavacComponentsAvailable() && !toolsJarPassed) {
val toolsJarFile = findToolsJar()
?: argError("'tools.jar' location should be specified (${KaptCliOption.TOOLS_JAR_OPTION.cliToolOption!!.name}=)")
transformed.add(0, "-Xplugin=" + toolsJarFile.absolutePath)
}
if (kaptVerboseModePassed) {
messageCollector.report(CompilerMessageSeverity.INFO, "Options passed to kotlinc: " + transformed.joinToString(" "))
}
return transformed
}
private fun CliToolOption.matches(arg: String) = when (format) {
FLAG, VALUE -> arg.startsWith(name + "=")
KEY_VALUE -> arg.startsWith(name + ":")
}
private fun CliToolOption.transform(arg: String): String {
val optionName = name
return when (format) {
FLAG -> {
fun err(): Nothing = argError("Invalid option format, should be $optionName=true/false")
if (arg.length < (optionName.length + 2)) err()
arg.drop(optionName.length + 1).takeIf { it == "true" || it == "false" } ?: err()
}
VALUE -> {
fun err(): Nothing = argError("Invalid option format, should be $optionName=")
if (arg.length < (optionName.length + 2)) err()
arg.drop(optionName.length + 1)
}
KEY_VALUE -> {
fun err(): Nothing = argError("Invalid option format, should be $optionName:=")
if (arg.length < (optionName.length + 3) || arg[optionName.length] != ':') err()
arg.drop(optionName.length + 1).takeIf { it.contains('=') } ?: err()
}
}
}
private fun kaptArg(option: KaptCliOption, value: String): List {
return listOf("-P", "plugin:" + KaptCliOption.ANNOTATION_PROCESSING_COMPILER_PLUGIN_ID + ":" + option.optionName + "=" + value)
}
private fun argError(text: String): Nothing {
throw IllegalArgumentException(text)
}
private fun findKaptCompilerPlugin(): File? {
val pathToThisJar = File(PathUtil.getJarPathForClass(CliToolOption::class.java))
if (pathToThisJar.extension.toLowerCase() != "jar") {
return null
}
return File(pathToThisJar.parentFile, KAPT_COMPILER_PLUGIN_JAR_NAME).takeIf { it.exists() }
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy