Kapt, Refactoring: Introduce 'KaptOptions'
1. Use 'KaptOptions' for all kapt options, including paths and flags. 2. Use a single 'KAPT_OPTIONS' compiler configuration key for setting all options (using a mutable KaptOptions.Builder). 3. Pass 'KaptOptions' instead of separate flags. 4. Remove 'KaptPaths'. 5. Remove deprecated 'aptOnly' CLI option.
This commit is contained in:
@@ -24,6 +24,7 @@ import com.sun.tools.javac.tree.TreeMaker
|
||||
import com.sun.tools.javac.util.Context
|
||||
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
||||
import org.jetbrains.kotlin.backend.common.output.OutputFile
|
||||
import org.jetbrains.kotlin.base.kapt3.KaptOptions
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.OUTPUT
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil
|
||||
@@ -39,8 +40,11 @@ import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.container.ComponentProvider
|
||||
import org.jetbrains.kotlin.context.ProjectContext
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.kapt3.AptMode.APT_ONLY
|
||||
import org.jetbrains.kotlin.kapt3.AptMode.WITH_COMPILATION
|
||||
import org.jetbrains.kotlin.base.kapt3.AptMode.APT_ONLY
|
||||
import org.jetbrains.kotlin.base.kapt3.AptMode.WITH_COMPILATION
|
||||
import org.jetbrains.kotlin.base.kapt3.DetectMemoryLeaksMode
|
||||
import org.jetbrains.kotlin.base.kapt3.KaptFlag
|
||||
import org.jetbrains.kotlin.base.kapt3.collectJavaSourceFiles
|
||||
import org.jetbrains.kotlin.kapt3.base.*
|
||||
import org.jetbrains.kotlin.kapt3.base.stubs.KaptStubLineInformation.Companion.KAPT_METADATA_EXTENSION
|
||||
import org.jetbrains.kotlin.kapt3.base.util.KaptBaseError
|
||||
@@ -64,31 +68,17 @@ import javax.annotation.processing.Processor
|
||||
import com.sun.tools.javac.util.List as JavacList
|
||||
|
||||
class ClasspathBasedKapt3Extension(
|
||||
paths: KaptPaths,
|
||||
options: Map<String, String>,
|
||||
javacOptions: Map<String, String>,
|
||||
annotationProcessorFqNames: List<String>,
|
||||
aptMode: AptMode,
|
||||
private val useLightAnalysis: Boolean,
|
||||
correctErrorTypes: Boolean,
|
||||
mapDiagnosticLocations: Boolean,
|
||||
strictMode: Boolean,
|
||||
detectMemoryLeaks: Boolean,
|
||||
pluginInitializedTime: Long,
|
||||
options: KaptOptions,
|
||||
logger: MessageCollectorBackedKaptLogger,
|
||||
compilerConfiguration: CompilerConfiguration
|
||||
) : AbstractKapt3Extension(
|
||||
paths, options, javacOptions, annotationProcessorFqNames,
|
||||
aptMode, pluginInitializedTime, logger, correctErrorTypes, mapDiagnosticLocations, strictMode, detectMemoryLeaks,
|
||||
compilerConfiguration
|
||||
) {
|
||||
) : AbstractKapt3Extension(options, logger, compilerConfiguration) {
|
||||
override val analyzePartially: Boolean
|
||||
get() = useLightAnalysis && super.analyzePartially
|
||||
get() = options[KaptFlag.USE_LIGHT_ANALYSIS] && super.analyzePartially
|
||||
|
||||
private var processorLoader: ProcessorLoader? = null
|
||||
|
||||
override fun loadProcessors(): LoadedProcessors {
|
||||
val efficientProcessorLoader = object : ProcessorLoader(paths, annotationProcessorFqNames, logger) {
|
||||
val efficientProcessorLoader = object : ProcessorLoader(options, logger) {
|
||||
override fun doLoadProcessors(classLoader: URLClassLoader): List<Processor> {
|
||||
return ServiceLoaderLite.loadImplementations(Processor::class.java, classLoader)
|
||||
}
|
||||
@@ -122,19 +112,12 @@ class ClasspathBasedKapt3Extension(
|
||||
}
|
||||
|
||||
abstract class AbstractKapt3Extension(
|
||||
val paths: KaptPaths,
|
||||
private val options: Map<String, String>,
|
||||
private val javacOptions: Map<String, String>,
|
||||
val annotationProcessorFqNames: List<String>,
|
||||
private val aptMode: AptMode,
|
||||
private val pluginInitializedTime: Long,
|
||||
val options: KaptOptions,
|
||||
val logger: MessageCollectorBackedKaptLogger,
|
||||
val correctErrorTypes: Boolean,
|
||||
val mapDiagnosticLocations: Boolean,
|
||||
val strictMode: Boolean,
|
||||
val detectMemoryLeaks: Boolean,
|
||||
val compilerConfiguration: CompilerConfiguration
|
||||
) : PartialAnalysisHandlerExtension() {
|
||||
private val pluginInitializedTime: Long = System.currentTimeMillis()
|
||||
|
||||
private var annotationProcessingComplete = false
|
||||
|
||||
private fun setAnnotationProcessingComplete(): Boolean {
|
||||
@@ -155,7 +138,7 @@ abstract class AbstractKapt3Extension(
|
||||
bindingTrace: BindingTrace,
|
||||
componentProvider: ComponentProvider
|
||||
): AnalysisResult? {
|
||||
if (aptMode == APT_ONLY) {
|
||||
if (options.mode == APT_ONLY) {
|
||||
return AnalysisResult.EMPTY
|
||||
}
|
||||
|
||||
@@ -175,7 +158,7 @@ abstract class AbstractKapt3Extension(
|
||||
logger.info { "Initial analysis took ${System.currentTimeMillis() - pluginInitializedTime} ms" }
|
||||
|
||||
val bindingContext = bindingTrace.bindingContext
|
||||
if (aptMode.generateStubs) {
|
||||
if (options.mode.generateStubs) {
|
||||
logger.info { "Kotlin files to compile: " + files.map { it.virtualFile?.name ?: "<in memory ${it.hashCode()}>" } }
|
||||
|
||||
contextForStubGeneration(project, module, bindingContext, files.toList()).use { context ->
|
||||
@@ -183,12 +166,12 @@ abstract class AbstractKapt3Extension(
|
||||
}
|
||||
}
|
||||
|
||||
if (!aptMode.runAnnotationProcessing) return doNotGenerateCode()
|
||||
if (!options.mode.runAnnotationProcessing) return doNotGenerateCode()
|
||||
|
||||
val processors = loadProcessors()
|
||||
if (processors.processors.isEmpty()) return if (aptMode != WITH_COMPILATION) doNotGenerateCode() else null
|
||||
if (processors.processors.isEmpty()) return if (options.mode != WITH_COMPILATION) doNotGenerateCode() else null
|
||||
|
||||
val kaptContext = KaptContext(paths, false, logger, mapDiagnosticLocations, options, javacOptions)
|
||||
val kaptContext = KaptContext(options, false, logger)
|
||||
|
||||
fun handleKaptError(error: KaptError): AnalysisResult {
|
||||
val cause = error.cause
|
||||
@@ -218,22 +201,22 @@ abstract class AbstractKapt3Extension(
|
||||
kaptContext.close()
|
||||
}
|
||||
|
||||
return if (aptMode != WITH_COMPILATION) {
|
||||
return if (options.mode != WITH_COMPILATION) {
|
||||
doNotGenerateCode()
|
||||
} else {
|
||||
AnalysisResult.RetryWithAdditionalJavaRoots(
|
||||
bindingTrace.bindingContext,
|
||||
module,
|
||||
listOf(paths.sourcesOutputDir),
|
||||
listOf(options.sourcesOutputDir),
|
||||
addToEnvironment = true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun runAnnotationProcessing(kaptContext: KaptContext, processors: LoadedProcessors) {
|
||||
if (!aptMode.runAnnotationProcessing) return
|
||||
if (!options.mode.runAnnotationProcessing) return
|
||||
|
||||
val javaSourceFiles = paths.collectJavaSourceFiles()
|
||||
val javaSourceFiles = options.collectJavaSourceFiles()
|
||||
logger.info { "Java source files: " + javaSourceFiles.joinToString { it.canonicalPath } }
|
||||
|
||||
val (annotationProcessingTime) = measureTimeMillis {
|
||||
@@ -242,7 +225,7 @@ abstract class AbstractKapt3Extension(
|
||||
|
||||
logger.info { "Annotation processing took $annotationProcessingTime ms" }
|
||||
|
||||
if (detectMemoryLeaks) {
|
||||
if (options.detectMemoryLeaks != DetectMemoryLeaksMode.NONE) {
|
||||
MemoryLeakDetector.add(processors.classLoader)
|
||||
|
||||
val (leakDetectionTime, leaks) = measureTimeMillis { MemoryLeakDetector.process() }
|
||||
@@ -291,18 +274,13 @@ abstract class AbstractKapt3Extension(
|
||||
logger.info { "Compiled classes: " + compiledClasses.joinToString { it.name } }
|
||||
|
||||
return KaptContextForStubGeneration(
|
||||
paths, false, logger, project, bindingContext, compiledClasses, origins, generationState,
|
||||
mapDiagnosticLocations, options, javacOptions
|
||||
options, false, logger, project, bindingContext,
|
||||
compiledClasses, origins, generationState
|
||||
)
|
||||
}
|
||||
|
||||
private fun generateKotlinSourceStubs(kaptContext: KaptContextForStubGeneration) {
|
||||
val converter = ClassFileToSourceStubConverter(
|
||||
kaptContext,
|
||||
generateNonExistentClass = true,
|
||||
correctErrorTypes = correctErrorTypes,
|
||||
strictMode = strictMode
|
||||
)
|
||||
val converter = ClassFileToSourceStubConverter(kaptContext, generateNonExistentClass = true)
|
||||
|
||||
val (stubGenerationTime, kaptStubs) = measureTimeMillis {
|
||||
converter.convert()
|
||||
@@ -321,7 +299,7 @@ abstract class AbstractKapt3Extension(
|
||||
val className = (stub.defs.first { it is JCTree.JCClassDecl } as JCTree.JCClassDecl).simpleName.toString()
|
||||
|
||||
val packageName = stub.getPackageNameJava9Aware()?.toString() ?: ""
|
||||
val packageDir = if (packageName.isEmpty()) paths.stubsOutputDir else File(paths.stubsOutputDir, packageName.replace('.', '/'))
|
||||
val packageDir = if (packageName.isEmpty()) options.stubsOutputDir else File(options.stubsOutputDir, packageName.replace('.', '/'))
|
||||
packageDir.mkdirs()
|
||||
|
||||
val sourceFile = File(packageDir, "$className.java")
|
||||
@@ -336,7 +314,7 @@ abstract class AbstractKapt3Extension(
|
||||
messageCollector: MessageCollector,
|
||||
converter: ClassFileToSourceStubConverter
|
||||
) {
|
||||
val incrementalDataOutputDir = paths.incrementalDataOutputDir ?: return
|
||||
val incrementalDataOutputDir = options.incrementalDataOutputDir ?: return
|
||||
|
||||
val reportOutputFiles = kaptContext.generationState.configuration.getBoolean(CommonConfigurationKeys.REPORT_OUTPUT_FILES)
|
||||
kaptContext.generationState.factory.writeAll(
|
||||
@@ -344,7 +322,7 @@ abstract class AbstractKapt3Extension(
|
||||
if (!reportOutputFiles) null else fun(file: OutputFile, sources: List<File>, output: File) {
|
||||
val stubFileObject = converter.bindings[file.relativePath.substringBeforeLast(".class", missingDelimiterValue = "")]
|
||||
if (stubFileObject != null) {
|
||||
val stubFile = File(paths.stubsOutputDir, stubFileObject.name)
|
||||
val stubFile = File(options.stubsOutputDir, stubFileObject.name)
|
||||
val lineMappingsFile = File(stubFile.parentFile, stubFile.nameWithoutExtension + KAPT_METADATA_EXTENSION)
|
||||
|
||||
for (outputFile in listOf(stubFile, lineMappingsFile)) {
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.kapt3
|
||||
import com.intellij.mock.MockProject
|
||||
import com.intellij.openapi.project.Project
|
||||
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
||||
import org.jetbrains.kotlin.base.kapt3.*
|
||||
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
|
||||
import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector
|
||||
@@ -38,14 +39,8 @@ import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor
|
||||
import org.jetbrains.kotlin.kapt.cli.KaptCliOption
|
||||
import org.jetbrains.kotlin.kapt.cli.KaptCliOption.Companion.ANNOTATION_PROCESSING_COMPILER_PLUGIN_ID
|
||||
import org.jetbrains.kotlin.kapt.cli.KaptCliOption.*
|
||||
import org.jetbrains.kotlin.kapt3.Kapt3ConfigurationKeys.ANNOTATION_PROCESSOR_CLASSPATH
|
||||
import org.jetbrains.kotlin.kapt3.Kapt3ConfigurationKeys.APT_OPTION
|
||||
import org.jetbrains.kotlin.kapt3.Kapt3ConfigurationKeys.APT_OPTIONS
|
||||
import org.jetbrains.kotlin.kapt3.Kapt3ConfigurationKeys.JAVAC_CLI_OPTIONS
|
||||
import org.jetbrains.kotlin.kapt3.Kapt3ConfigurationKeys.JAVAC_OPTION
|
||||
import org.jetbrains.kotlin.kapt3.base.Kapt
|
||||
import org.jetbrains.kotlin.kapt3.base.KaptPaths
|
||||
import org.jetbrains.kotlin.kapt3.base.log
|
||||
import org.jetbrains.kotlin.kapt3.base.util.KaptLogger
|
||||
import org.jetbrains.kotlin.kapt3.util.MessageCollectorBackedKaptLogger
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
@@ -58,70 +53,7 @@ import java.io.File
|
||||
import java.io.ObjectInputStream
|
||||
import java.util.*
|
||||
|
||||
object Kapt3ConfigurationKeys {
|
||||
val SOURCE_OUTPUT_DIR: CompilerConfigurationKey<String> =
|
||||
CompilerConfigurationKey.create<String>(SOURCE_OUTPUT_DIR_OPTION.description)
|
||||
|
||||
val CLASS_OUTPUT_DIR: CompilerConfigurationKey<String> =
|
||||
CompilerConfigurationKey.create<String>(CLASS_OUTPUT_DIR_OPTION.description)
|
||||
|
||||
val STUBS_OUTPUT_DIR: CompilerConfigurationKey<String> =
|
||||
CompilerConfigurationKey.create<String>(STUBS_OUTPUT_DIR_OPTION.description)
|
||||
|
||||
val INCREMENTAL_DATA_OUTPUT_DIR: CompilerConfigurationKey<String> =
|
||||
CompilerConfigurationKey.create<String>(INCREMENTAL_DATA_OUTPUT_DIR_OPTION.description)
|
||||
|
||||
val ANNOTATION_PROCESSOR_CLASSPATH: CompilerConfigurationKey<List<String>> =
|
||||
CompilerConfigurationKey.create<List<String>>(ANNOTATION_PROCESSOR_CLASSPATH_OPTION.description)
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@Deprecated("Use APT_OPTION instead.")
|
||||
val APT_OPTIONS: CompilerConfigurationKey<String> =
|
||||
CompilerConfigurationKey.create<String>(APT_OPTIONS_OPTION.description)
|
||||
|
||||
val APT_OPTION: CompilerConfigurationKey<Map<String, String>> =
|
||||
CompilerConfigurationKey.create<Map<String, String>>(APT_OPTION_OPTION.description)
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@Deprecated("Use JAVAC_OPTION instead.")
|
||||
val JAVAC_CLI_OPTIONS: CompilerConfigurationKey<String> =
|
||||
CompilerConfigurationKey.create<String>(JAVAC_CLI_OPTIONS_OPTION.description)
|
||||
|
||||
val JAVAC_OPTION: CompilerConfigurationKey<Map<String, String>> =
|
||||
CompilerConfigurationKey.create<Map<String, String>>(JAVAC_OPTION_OPTION.description)
|
||||
|
||||
val ANNOTATION_PROCESSORS: CompilerConfigurationKey<List<String>> =
|
||||
CompilerConfigurationKey.create<List<String>>(ANNOTATION_PROCESSORS_OPTION.description)
|
||||
|
||||
val VERBOSE_MODE: CompilerConfigurationKey<String> =
|
||||
CompilerConfigurationKey.create<String>(VERBOSE_MODE_OPTION.description)
|
||||
|
||||
val INFO_AS_WARNINGS: CompilerConfigurationKey<String> =
|
||||
CompilerConfigurationKey.create<String>(INFO_AS_WARNINGS_OPTION.description)
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@Deprecated("Use APT_MODE instead.")
|
||||
val APT_ONLY: CompilerConfigurationKey<String> =
|
||||
CompilerConfigurationKey.create<String>(APT_ONLY_OPTION.description)
|
||||
|
||||
val APT_MODE: CompilerConfigurationKey<String> =
|
||||
CompilerConfigurationKey.create<String>(APT_MODE_OPTION.description)
|
||||
|
||||
val USE_LIGHT_ANALYSIS: CompilerConfigurationKey<String> =
|
||||
CompilerConfigurationKey.create<String>(USE_LIGHT_ANALYSIS_OPTION.description)
|
||||
|
||||
val CORRECT_ERROR_TYPES: CompilerConfigurationKey<String> =
|
||||
CompilerConfigurationKey.create<String>(CORRECT_ERROR_TYPES_OPTION.description)
|
||||
|
||||
val MAP_DIAGNOSTIC_LOCATIONS: CompilerConfigurationKey<String> =
|
||||
CompilerConfigurationKey.create<String>(MAP_DIAGNOSTIC_LOCATIONS_OPTION.description)
|
||||
|
||||
val STRICT_MODE: CompilerConfigurationKey<String> =
|
||||
CompilerConfigurationKey.create<String>(STRICT_MODE_OPTION.description)
|
||||
|
||||
val DETECT_MEMORY_LEAKS: CompilerConfigurationKey<String> =
|
||||
CompilerConfigurationKey.create<String>(DETECT_MEMORY_LEAKS_OPTION.description)
|
||||
}
|
||||
private val KAPT_OPTIONS = CompilerConfigurationKey.create<KaptOptions.Builder>("Kapt options")
|
||||
|
||||
class Kapt3CommandLineProcessor : CommandLineProcessor {
|
||||
override val pluginId: String = ANNOTATION_PROCESSING_COMPILER_PLUGIN_ID
|
||||
@@ -133,52 +65,61 @@ class Kapt3CommandLineProcessor : CommandLineProcessor {
|
||||
throw CliOptionProcessingException("Unknown option: ${option.optionName}")
|
||||
}
|
||||
|
||||
val kaptOptions = configuration[KAPT_OPTIONS]
|
||||
?: KaptOptions.Builder().also { configuration.put(KAPT_OPTIONS, it) }
|
||||
|
||||
if (option == @Suppress("DEPRECATION") KaptCliOption.CONFIGURATION) {
|
||||
configuration.applyOptionsFrom(decodePluginOptions(value), pluginOptions)
|
||||
} else {
|
||||
kaptOptions.processOption(option, value)
|
||||
}
|
||||
}
|
||||
|
||||
private fun KaptOptions.Builder.processOption(option: KaptCliOption, value: String) {
|
||||
fun setFlag(flag: KaptFlag, value: String) = if (value == "true") flags.add(flag) else flags.remove(flag)
|
||||
|
||||
fun <T : KaptSelector> setSelector(values: Array<T>, rawValue: String, selector: (T) -> Unit) {
|
||||
selector(values.firstOrNull { it.stringValue == rawValue }
|
||||
?: throw CliOptionProcessingException("Unknown value $rawValue for option ${option.optionName}"))
|
||||
}
|
||||
|
||||
fun setKeyValue(rawValue: String, apply: (String, String) -> Unit) {
|
||||
val keyValuePair = rawValue.split('=', limit = 2).takeIf { it.size == 2 }
|
||||
?: throw CliOptionProcessingException("Invalid option format for ${option.optionName}: key=value expected")
|
||||
apply(keyValuePair[0], keyValuePair[1])
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
return when (option) {
|
||||
ANNOTATION_PROCESSOR_CLASSPATH_OPTION -> configuration.appendList(ANNOTATION_PROCESSOR_CLASSPATH, value)
|
||||
ANNOTATION_PROCESSORS_OPTION -> configuration.appendList(
|
||||
Kapt3ConfigurationKeys.ANNOTATION_PROCESSORS, value.split(',').map { it.trim() }.filter { it.isNotEmpty() })
|
||||
APT_OPTIONS_OPTION -> configuration.put(APT_OPTIONS, value)
|
||||
JAVAC_CLI_OPTIONS_OPTION -> configuration.put(JAVAC_CLI_OPTIONS, value)
|
||||
APT_OPTION_OPTION -> configuration.appendMap(APT_OPTION, option, value)
|
||||
JAVAC_OPTION_OPTION -> configuration.appendMap(JAVAC_OPTION, option, value)
|
||||
SOURCE_OUTPUT_DIR_OPTION -> configuration.put(Kapt3ConfigurationKeys.SOURCE_OUTPUT_DIR, value)
|
||||
CLASS_OUTPUT_DIR_OPTION -> configuration.put(Kapt3ConfigurationKeys.CLASS_OUTPUT_DIR, value)
|
||||
STUBS_OUTPUT_DIR_OPTION -> configuration.put(Kapt3ConfigurationKeys.STUBS_OUTPUT_DIR, value)
|
||||
INCREMENTAL_DATA_OUTPUT_DIR_OPTION -> configuration.put(Kapt3ConfigurationKeys.INCREMENTAL_DATA_OUTPUT_DIR, value)
|
||||
VERBOSE_MODE_OPTION -> configuration.put(Kapt3ConfigurationKeys.VERBOSE_MODE, value)
|
||||
APT_ONLY_OPTION -> configuration.put(Kapt3ConfigurationKeys.APT_ONLY, value)
|
||||
APT_MODE_OPTION -> configuration.put(Kapt3ConfigurationKeys.APT_MODE, value)
|
||||
USE_LIGHT_ANALYSIS_OPTION -> configuration.put(Kapt3ConfigurationKeys.USE_LIGHT_ANALYSIS, value)
|
||||
CORRECT_ERROR_TYPES_OPTION -> configuration.put(Kapt3ConfigurationKeys.CORRECT_ERROR_TYPES, value)
|
||||
MAP_DIAGNOSTIC_LOCATIONS_OPTION -> configuration.put(Kapt3ConfigurationKeys.MAP_DIAGNOSTIC_LOCATIONS, value)
|
||||
INFO_AS_WARNINGS_OPTION -> configuration.put(Kapt3ConfigurationKeys.INFO_AS_WARNINGS, value)
|
||||
STRICT_MODE_OPTION -> configuration.put(Kapt3ConfigurationKeys.STRICT_MODE, value)
|
||||
DETECT_MEMORY_LEAKS_OPTION -> configuration.put(Kapt3ConfigurationKeys.DETECT_MEMORY_LEAKS, value)
|
||||
CONFIGURATION -> configuration.applyOptionsFrom(decodePluginOptions(value), pluginOptions)
|
||||
when (option) {
|
||||
SOURCE_OUTPUT_DIR_OPTION -> sourcesOutputDir = File(value)
|
||||
CLASS_OUTPUT_DIR_OPTION -> classesOutputDir = File(value)
|
||||
STUBS_OUTPUT_DIR_OPTION -> stubsOutputDir = File(value)
|
||||
INCREMENTAL_DATA_OUTPUT_DIR_OPTION -> incrementalDataOutputDir = File(value)
|
||||
|
||||
ANNOTATION_PROCESSOR_CLASSPATH_OPTION -> processingClasspath += File(value)
|
||||
ANNOTATION_PROCESSORS_OPTION -> processors.addAll(value.split(',').map { it.trim() }.filter { it.isNotEmpty() })
|
||||
|
||||
APT_OPTION_OPTION -> setKeyValue(value) { k, v -> processingOptions[k] = v }
|
||||
JAVAC_OPTION_OPTION -> setKeyValue(value) { k, v -> javacOptions[k] = v }
|
||||
|
||||
VERBOSE_MODE_OPTION -> setFlag(KaptFlag.VERBOSE, value)
|
||||
USE_LIGHT_ANALYSIS_OPTION -> setFlag(KaptFlag.USE_LIGHT_ANALYSIS, value)
|
||||
CORRECT_ERROR_TYPES_OPTION -> setFlag(KaptFlag.CORRECT_ERROR_TYPES, value)
|
||||
MAP_DIAGNOSTIC_LOCATIONS_OPTION -> setFlag(KaptFlag.MAP_DIAGNOSTIC_LOCATIONS, value)
|
||||
INFO_AS_WARNINGS_OPTION -> setFlag(KaptFlag.INFO_AS_WARNINGS, value)
|
||||
STRICT_MODE_OPTION -> setFlag(KaptFlag.STRICT, value)
|
||||
|
||||
DETECT_MEMORY_LEAKS_OPTION -> setSelector(enumValues<DetectMemoryLeaksMode>(), value) { detectMemoryLeaks = it }
|
||||
APT_MODE_OPTION -> setSelector(enumValues<AptMode>(), value) { mode = it }
|
||||
|
||||
APT_OPTIONS_OPTION -> processingOptions.putAll(decodeMap(value))
|
||||
JAVAC_CLI_OPTIONS_OPTION -> javacOptions.putAll(decodeMap(value))
|
||||
CONFIGURATION -> throw CliOptionProcessingException("${CONFIGURATION.optionName} should be handled earlier")
|
||||
|
||||
TOOLS_JAR_OPTION -> throw CliOptionProcessingException("'${TOOLS_JAR_OPTION.optionName}' is only supported in the kapt CLI tool")
|
||||
}
|
||||
}
|
||||
|
||||
private fun CompilerConfiguration.appendMap(
|
||||
key: CompilerConfigurationKey<Map<String, String>>,
|
||||
option: AbstractCliOption,
|
||||
keyValuePair: String
|
||||
) {
|
||||
val keyValueDecoded = keyValuePair.split('=', limit = 2)
|
||||
if (keyValueDecoded.size != 2) {
|
||||
throw CliOptionProcessingException("Invalid option format for ${option.optionName}: key=value expected")
|
||||
}
|
||||
|
||||
val oldMap = getMap(key)
|
||||
val newMap = (oldMap as? MutableMap<String, String>) ?: oldMap.toMutableMap()
|
||||
|
||||
newMap[keyValueDecoded[0]] = keyValueDecoded[1]
|
||||
put(key, newMap)
|
||||
}
|
||||
}
|
||||
|
||||
class Kapt3ComponentRegistrar : ComponentRegistrar {
|
||||
private fun decodeMap(options: String): Map<String, String> {
|
||||
if (options.isEmpty()) {
|
||||
return emptyMap()
|
||||
@@ -200,115 +141,90 @@ class Kapt3ComponentRegistrar : ComponentRegistrar {
|
||||
|
||||
return map
|
||||
}
|
||||
}
|
||||
|
||||
class Kapt3ComponentRegistrar : ComponentRegistrar {
|
||||
override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) {
|
||||
@Suppress("DEPRECATION")
|
||||
val aptMode = AptMode.parse(configuration.get(Kapt3ConfigurationKeys.APT_MODE) ?: configuration.get(Kapt3ConfigurationKeys.APT_ONLY))
|
||||
val contentRoots = configuration[CLIConfigurationKeys.CONTENT_ROOTS] ?: emptyList()
|
||||
|
||||
val optionsBuilder = (configuration[KAPT_OPTIONS] ?: KaptOptions.Builder()).apply {
|
||||
projectBaseDir = project.basePath?.let(::File)
|
||||
compileClasspath.addAll(contentRoots.filterIsInstance<JvmClasspathRoot>().map { it.file })
|
||||
javaSourceRoots.addAll(contentRoots.filterIsInstance<JavaSourceRoot>().map { it.file })
|
||||
classesOutputDir = classesOutputDir ?: configuration.get(JVMConfigurationKeys.OUTPUT_DIRECTORY)
|
||||
}
|
||||
|
||||
val isVerbose = configuration.get(Kapt3ConfigurationKeys.VERBOSE_MODE) == "true"
|
||||
val infoAsWarnings = configuration.get(Kapt3ConfigurationKeys.INFO_AS_WARNINGS) == "true"
|
||||
val strictMode = configuration.get(Kapt3ConfigurationKeys.STRICT_MODE) == "true"
|
||||
val detectMemoryLeaks = configuration.get(Kapt3ConfigurationKeys.DETECT_MEMORY_LEAKS) != "false"
|
||||
val messageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
|
||||
?: PrintingMessageCollector(System.err, MessageRenderer.PLAIN_FULL_PATHS, isVerbose)
|
||||
val logger = MessageCollectorBackedKaptLogger(isVerbose, infoAsWarnings, messageCollector)
|
||||
?: PrintingMessageCollector(System.err, MessageRenderer.PLAIN_FULL_PATHS, optionsBuilder.flags.contains(KaptFlag.VERBOSE))
|
||||
|
||||
val logger = MessageCollectorBackedKaptLogger(
|
||||
optionsBuilder.flags.contains(KaptFlag.VERBOSE),
|
||||
optionsBuilder.flags.contains(KaptFlag.INFO_AS_WARNINGS),
|
||||
messageCollector
|
||||
)
|
||||
|
||||
if (!optionsBuilder.checkOptions(project, logger, configuration)) {
|
||||
return
|
||||
}
|
||||
|
||||
val options = optionsBuilder.build()
|
||||
|
||||
options.sourcesOutputDir.mkdirs()
|
||||
|
||||
if (options[KaptFlag.VERBOSE]) {
|
||||
logger.info(options.logString())
|
||||
}
|
||||
|
||||
val kapt3AnalysisCompletedHandlerExtension = ClasspathBasedKapt3Extension(options, logger, configuration)
|
||||
|
||||
AnalysisHandlerExtension.registerExtension(project, kapt3AnalysisCompletedHandlerExtension)
|
||||
StorageComponentContainerContributor.registerExtension(project, KaptComponentContributor())
|
||||
}
|
||||
|
||||
private fun KaptOptions.Builder.checkOptions(project: MockProject, logger: KaptLogger, configuration: CompilerConfiguration): Boolean {
|
||||
fun abortAnalysis() = AnalysisHandlerExtension.registerExtension(project, AbortAnalysisHandlerExtension())
|
||||
|
||||
if (!Kapt.checkJavacComponentsAccess(logger)) {
|
||||
abortAnalysis()
|
||||
return
|
||||
if (classesOutputDir == null) {
|
||||
if (configuration.get(JVMConfigurationKeys.OUTPUT_JAR) != null) {
|
||||
logger.error("Kapt does not support specifying JAR file outputs. Please specify the classes output directory explicitly.")
|
||||
abortAnalysis()
|
||||
return false
|
||||
} else {
|
||||
classesOutputDir = configuration.get(JVMConfigurationKeys.OUTPUT_DIRECTORY)
|
||||
}
|
||||
}
|
||||
|
||||
val sourcesOutputDir = configuration.get(Kapt3ConfigurationKeys.SOURCE_OUTPUT_DIR)?.let(::File)
|
||||
val stubsOutputDir = configuration.get(Kapt3ConfigurationKeys.STUBS_OUTPUT_DIR)?.let(::File)
|
||||
val incrementalDataOutputDir = configuration.get(Kapt3ConfigurationKeys.INCREMENTAL_DATA_OUTPUT_DIR)?.let(::File)
|
||||
|
||||
val classFilesOutputDir = configuration.get(Kapt3ConfigurationKeys.CLASS_OUTPUT_DIR)?.let(::File)
|
||||
?: configuration.get(JVMConfigurationKeys.OUTPUT_DIRECTORY)
|
||||
|
||||
if (classFilesOutputDir == null && configuration.get(JVMConfigurationKeys.OUTPUT_JAR) != null) {
|
||||
logger.error("Kapt does not support specifying JAR file outputs. Please specify the classes output directory explicitly.")
|
||||
abortAnalysis()
|
||||
return
|
||||
}
|
||||
|
||||
val annotationProcessors = configuration.get(Kapt3ConfigurationKeys.ANNOTATION_PROCESSORS) ?: emptyList()
|
||||
|
||||
val apClasspath = configuration.get(ANNOTATION_PROCESSOR_CLASSPATH)?.map(::File) ?: emptyList()
|
||||
|
||||
if (apClasspath.isEmpty()) {
|
||||
if (processingClasspath.isEmpty()) {
|
||||
// Skip annotation processing if no annotation processors were provided
|
||||
if (aptMode != AptMode.WITH_COMPILATION) {
|
||||
if (mode != AptMode.WITH_COMPILATION) {
|
||||
abortAnalysis()
|
||||
}
|
||||
return
|
||||
return false
|
||||
}
|
||||
|
||||
if (sourcesOutputDir == null || classFilesOutputDir == null || stubsOutputDir == null) {
|
||||
if (aptMode != AptMode.WITH_COMPILATION) {
|
||||
if (sourcesOutputDir == null || classesOutputDir == null || stubsOutputDir == null) {
|
||||
if (mode != AptMode.WITH_COMPILATION) {
|
||||
val nonExistentOptionName = when {
|
||||
sourcesOutputDir == null -> "Sources output directory"
|
||||
classFilesOutputDir == null -> "Classes output directory"
|
||||
classesOutputDir == null -> "Classes output directory"
|
||||
stubsOutputDir == null -> "Stubs output directory"
|
||||
else -> throw IllegalStateException()
|
||||
}
|
||||
val moduleName = configuration.get(CommonConfigurationKeys.MODULE_NAME)
|
||||
?: configuration.get(JVMConfigurationKeys.MODULES).orEmpty().joinToString()
|
||||
?: configuration.get(JVMConfigurationKeys.MODULES).orEmpty().joinToString()
|
||||
|
||||
logger.warn("$nonExistentOptionName is not specified for $moduleName, skipping annotation processing")
|
||||
abortAnalysis()
|
||||
}
|
||||
return
|
||||
return false
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
val apOptions = decodeMap(configuration.get(APT_OPTIONS).orEmpty()).toMutableMap()
|
||||
configuration.get(APT_OPTION)?.let { apOptions += it }
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
val javacOptions = decodeMap(configuration.get(JAVAC_CLI_OPTIONS).orEmpty()).toMutableMap()
|
||||
configuration.get(JAVAC_OPTION)?.let { javacOptions += it }
|
||||
|
||||
sourcesOutputDir.mkdirs()
|
||||
|
||||
val contentRoots = configuration[CLIConfigurationKeys.CONTENT_ROOTS] ?: emptyList()
|
||||
|
||||
val compileClasspath = contentRoots.filterIsInstance<JvmClasspathRoot>().map { it.file }
|
||||
|
||||
val javaSourceRoots = contentRoots.filterIsInstance<JavaSourceRoot>().map { it.file }
|
||||
|
||||
val useLightAnalysis = configuration.get(Kapt3ConfigurationKeys.USE_LIGHT_ANALYSIS) != "false"
|
||||
val correctErrorTypes = configuration.get(Kapt3ConfigurationKeys.CORRECT_ERROR_TYPES) == "true"
|
||||
val mapDiagnosticLocations = configuration.get(Kapt3ConfigurationKeys.MAP_DIAGNOSTIC_LOCATIONS) == "true"
|
||||
|
||||
val paths = KaptPaths(
|
||||
project.basePath?.let(::File),
|
||||
compileClasspath, apClasspath, javaSourceRoots, sourcesOutputDir, classFilesOutputDir,
|
||||
stubsOutputDir, incrementalDataOutputDir
|
||||
)
|
||||
|
||||
if (isVerbose) {
|
||||
logger.info("Kapt3 is enabled.")
|
||||
logger.info("Annotation processing mode: $aptMode")
|
||||
logger.info("Use light analysis: $useLightAnalysis")
|
||||
logger.info("Correct error types: $correctErrorTypes")
|
||||
logger.info("Map diagnostic locations: $mapDiagnosticLocations")
|
||||
logger.info("Info as warnings: $infoAsWarnings")
|
||||
logger.info("Strict mode: $strictMode")
|
||||
paths.log(logger)
|
||||
logger.info("Annotation processors: " + annotationProcessors.joinToString())
|
||||
logger.info("Javac options: $apOptions")
|
||||
logger.info("AP options: $apOptions")
|
||||
if (!Kapt.checkJavacComponentsAccess(logger)) {
|
||||
abortAnalysis()
|
||||
return false
|
||||
}
|
||||
|
||||
val kapt3AnalysisCompletedHandlerExtension = ClasspathBasedKapt3Extension(
|
||||
paths, apOptions, javacOptions, annotationProcessors,
|
||||
aptMode, useLightAnalysis, correctErrorTypes, mapDiagnosticLocations, strictMode, detectMemoryLeaks,
|
||||
System.currentTimeMillis(), logger, configuration
|
||||
)
|
||||
|
||||
AnalysisHandlerExtension.registerExtension(project, kapt3AnalysisCompletedHandlerExtension)
|
||||
StorageComponentContainerContributor.registerExtension(project, KaptComponentContributor())
|
||||
return true
|
||||
}
|
||||
|
||||
class KaptComponentContributor : StorageComponentContainerContributor {
|
||||
@@ -327,47 +243,23 @@ class Kapt3ComponentRegistrar : ComponentRegistrar {
|
||||
* */
|
||||
private class AbortAnalysisHandlerExtension : AnalysisHandlerExtension {
|
||||
override fun doAnalysis(
|
||||
project: Project,
|
||||
module: ModuleDescriptor,
|
||||
projectContext: ProjectContext,
|
||||
files: Collection<KtFile>,
|
||||
bindingTrace: BindingTrace,
|
||||
componentProvider: ComponentProvider
|
||||
project: Project,
|
||||
module: ModuleDescriptor,
|
||||
projectContext: ProjectContext,
|
||||
files: Collection<KtFile>,
|
||||
bindingTrace: BindingTrace,
|
||||
componentProvider: ComponentProvider
|
||||
): AnalysisResult? {
|
||||
return AnalysisResult.success(bindingTrace.bindingContext, module, shouldGenerateCode = false)
|
||||
}
|
||||
|
||||
override fun analysisCompleted(
|
||||
project: Project,
|
||||
module: ModuleDescriptor,
|
||||
bindingTrace: BindingTrace,
|
||||
files: Collection<KtFile>
|
||||
project: Project,
|
||||
module: ModuleDescriptor,
|
||||
bindingTrace: BindingTrace,
|
||||
files: Collection<KtFile>
|
||||
): AnalysisResult? {
|
||||
return AnalysisResult.success(bindingTrace.bindingContext, module, shouldGenerateCode = false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class AptMode(val optionName: String) {
|
||||
WITH_COMPILATION("compile"),
|
||||
STUBS_AND_APT("stubsAndApt"),
|
||||
STUBS_ONLY("stubs"),
|
||||
APT_ONLY("apt");
|
||||
|
||||
val runAnnotationProcessing
|
||||
get() = this != STUBS_ONLY
|
||||
|
||||
val generateStubs
|
||||
get() = this != APT_ONLY
|
||||
|
||||
companion object {
|
||||
// Supports both deprecated APT_ONLY and new APT_MODE options
|
||||
fun parse(mode: String?): AptMode {
|
||||
return when (mode) {
|
||||
"true" -> STUBS_AND_APT
|
||||
"false" -> WITH_COMPILATION
|
||||
else -> AptMode.values().firstOrNull { it.optionName == mode } ?: WITH_COMPILATION
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-7
@@ -19,9 +19,9 @@ package org.jetbrains.kotlin.kapt3
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.sun.tools.javac.tree.TreeMaker
|
||||
import com.sun.tools.javac.util.Context
|
||||
import org.jetbrains.kotlin.base.kapt3.KaptOptions
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.kapt3.base.KaptContext
|
||||
import org.jetbrains.kotlin.kapt3.base.KaptPaths
|
||||
import org.jetbrains.kotlin.kapt3.base.util.KaptLogger
|
||||
import org.jetbrains.kotlin.kapt3.javac.KaptTreeMaker
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
@@ -29,18 +29,15 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.org.objectweb.asm.tree.ClassNode
|
||||
|
||||
class KaptContextForStubGeneration(
|
||||
paths: KaptPaths,
|
||||
options: KaptOptions,
|
||||
withJdk: Boolean,
|
||||
logger: KaptLogger,
|
||||
val project: Project,
|
||||
val bindingContext: BindingContext,
|
||||
val compiledClasses: List<ClassNode>,
|
||||
val origins: Map<Any, JvmDeclarationOrigin>,
|
||||
val generationState: GenerationState,
|
||||
mapDiagnosticLocations: Boolean,
|
||||
processorOptions: Map<String, String>,
|
||||
javacOptions: Map<String, String> = emptyMap()
|
||||
) : KaptContext(paths, withJdk, logger, mapDiagnosticLocations, processorOptions, javacOptions) {
|
||||
val generationState: GenerationState
|
||||
) : KaptContext(options, withJdk, logger) {
|
||||
private val treeMaker = TreeMaker.instance(context)
|
||||
|
||||
override fun preregisterTreeMaker(context: Context) {
|
||||
|
||||
+9
-9
@@ -24,6 +24,7 @@ import com.sun.tools.javac.tree.JCTree.*
|
||||
import com.sun.tools.javac.tree.TreeMaker
|
||||
import com.sun.tools.javac.tree.TreeScanner
|
||||
import kotlinx.kapt.KaptIgnored
|
||||
import org.jetbrains.kotlin.base.kapt3.KaptFlag
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
@@ -63,12 +64,7 @@ import java.io.File
|
||||
import javax.lang.model.element.ElementKind
|
||||
import com.sun.tools.javac.util.List as JavacList
|
||||
|
||||
class ClassFileToSourceStubConverter(
|
||||
val kaptContext: KaptContextForStubGeneration,
|
||||
val generateNonExistentClass: Boolean,
|
||||
val correctErrorTypes: Boolean,
|
||||
val strictMode: Boolean
|
||||
) {
|
||||
class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGeneration, val generateNonExistentClass: Boolean) {
|
||||
private companion object {
|
||||
private const val VISIBILITY_MODIFIERS = (Opcodes.ACC_PUBLIC or Opcodes.ACC_PRIVATE or Opcodes.ACC_PROTECTED).toLong()
|
||||
private const val MODALITY_MODIFIERS = (Opcodes.ACC_FINAL or Opcodes.ACC_ABSTRACT).toLong()
|
||||
@@ -95,15 +91,19 @@ class ClassFileToSourceStubConverter(
|
||||
|
||||
private val JAVA_KEYWORD_FILTER_REGEX = "[a-z]+".toRegex()
|
||||
|
||||
@Suppress("UselessCallOnNotNull") // nullable toString(), KT-27724
|
||||
private val JAVA_KEYWORDS = Tokens.TokenKind.values()
|
||||
.filter { JAVA_KEYWORD_FILTER_REGEX.matches(it.toString().orEmpty()) }
|
||||
.mapTo(hashSetOf(), Any::toString)
|
||||
}
|
||||
|
||||
private val _bindings = mutableMapOf<String, KaptJavaFileObject>()
|
||||
private val correctErrorTypes = kaptContext.options[KaptFlag.CORRECT_ERROR_TYPES]
|
||||
private val strictMode = kaptContext.options[KaptFlag.STRICT]
|
||||
|
||||
private val mutableBindings = mutableMapOf<String, KaptJavaFileObject>()
|
||||
|
||||
val bindings: Map<String, KaptJavaFileObject>
|
||||
get() = _bindings
|
||||
get() = mutableBindings
|
||||
|
||||
private val typeMapper
|
||||
get() = kaptContext.generationState.typeMapper
|
||||
@@ -193,7 +193,7 @@ class ClassFileToSourceStubConverter(
|
||||
|
||||
KaptJavaFileObject(topLevel, classDeclaration).apply {
|
||||
topLevel.sourcefile = this
|
||||
_bindings[clazz.name] = this
|
||||
mutableBindings[clazz.name] = this
|
||||
}
|
||||
|
||||
postProcess(topLevel)
|
||||
|
||||
+10
-4
@@ -5,10 +5,12 @@
|
||||
|
||||
package org.jetbrains.kotlin.kapt3.util
|
||||
|
||||
import org.jetbrains.kotlin.base.kapt3.KaptFlag
|
||||
import org.jetbrains.kotlin.base.kapt3.KaptFlags
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer.PLAIN_FULL_PATHS
|
||||
import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector
|
||||
import org.jetbrains.kotlin.kapt3.base.util.KaptLogger
|
||||
import java.io.PrintWriter
|
||||
@@ -16,16 +18,20 @@ import java.io.StringWriter
|
||||
|
||||
class MessageCollectorBackedKaptLogger(
|
||||
override val isVerbose: Boolean,
|
||||
infoAsWarnings: Boolean = true,
|
||||
val messageCollector: MessageCollector = PrintingMessageCollector(System.err, MessageRenderer.PLAIN_FULL_PATHS, isVerbose)
|
||||
isInfoAsWarnings: Boolean,
|
||||
val messageCollector: MessageCollector = defaultMessageCollector(isVerbose)
|
||||
) : KaptLogger {
|
||||
constructor(flags: KaptFlags, messageCollector: MessageCollector = defaultMessageCollector(flags[KaptFlag.VERBOSE]))
|
||||
: this(flags[KaptFlag.VERBOSE], flags[KaptFlag.INFO_AS_WARNINGS], messageCollector)
|
||||
|
||||
private companion object {
|
||||
const val PREFIX = "[kapt] "
|
||||
fun defaultMessageCollector(isVerbose: Boolean) = PrintingMessageCollector(System.err, PLAIN_FULL_PATHS, isVerbose)
|
||||
}
|
||||
|
||||
override val errorWriter = makeWriter(ERROR)
|
||||
override val warnWriter = makeWriter(STRONG_WARNING)
|
||||
override val infoWriter = makeWriter(if (infoAsWarnings) WARNING else INFO)
|
||||
override val infoWriter = makeWriter(if (isInfoAsWarnings) WARNING else INFO)
|
||||
|
||||
override fun info(message: String) {
|
||||
if (isVerbose) {
|
||||
|
||||
+24
-34
@@ -16,8 +16,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.kapt3.test
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import org.jetbrains.kotlin.base.kapt3.DetectMemoryLeaksMode
|
||||
import org.jetbrains.kotlin.base.kapt3.KaptOptions
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.codegen.ClassBuilderMode
|
||||
import org.jetbrains.kotlin.codegen.CodegenTestCase
|
||||
@@ -25,9 +26,7 @@ import org.jetbrains.kotlin.codegen.GenerationUtils
|
||||
import org.jetbrains.kotlin.codegen.OriginCollectingClassBuilderFactory
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.kapt3.*
|
||||
import org.jetbrains.kotlin.kapt3.AptMode.STUBS_AND_APT
|
||||
import org.jetbrains.kotlin.kapt3.base.KaptContext
|
||||
import org.jetbrains.kotlin.kapt3.base.KaptPaths
|
||||
import org.jetbrains.kotlin.kapt3.base.LoadedProcessors
|
||||
import org.jetbrains.kotlin.kapt3.javac.KaptJavaFileObject
|
||||
import org.jetbrains.kotlin.kapt3.stubs.ClassFileToSourceStubConverter
|
||||
@@ -59,12 +58,11 @@ abstract class AbstractKotlinKapt3IntegrationTest : CodegenTestCase() {
|
||||
private var _processors: List<Processor>? = null
|
||||
private val processors get() = _processors!!
|
||||
|
||||
private var _options: Map<String, String>? = null
|
||||
private val options get() = _options!!
|
||||
private var mutableOptions: Map<String, String>? = null
|
||||
|
||||
override fun tearDown() {
|
||||
_processors = null
|
||||
_options = null
|
||||
mutableOptions = null
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
@@ -82,7 +80,7 @@ abstract class AbstractKotlinKapt3IntegrationTest : CodegenTestCase() {
|
||||
process: (Set<TypeElement>, RoundEnvironment, ProcessingEnvironment) -> Unit,
|
||||
vararg supportedAnnotations: String
|
||||
) {
|
||||
this._options = options
|
||||
this.mutableOptions = options
|
||||
|
||||
val ktFileName = File(TEST_DATA_DIR, "$name.kt")
|
||||
var started = false
|
||||
@@ -128,18 +126,25 @@ abstract class AbstractKotlinKapt3IntegrationTest : CodegenTestCase() {
|
||||
val javaSources = javaFilesDir?.let { arrayOf(it) } ?: emptyArray()
|
||||
|
||||
val txtFile = File(wholeFile.parentFile, wholeFile.nameWithoutExtension + ".it.txt")
|
||||
val sourceOutputDir = Files.createTempDirectory("kaptRunner").toFile()
|
||||
val stubsDir = Files.createTempDirectory("kaptStubs").toFile()
|
||||
val incrementalDataDir = Files.createTempDirectory("kaptIncrementalData").toFile()
|
||||
|
||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.ALL, *javaSources)
|
||||
|
||||
val project = myEnvironment.project
|
||||
val kapt3Extension = Kapt3ExtensionForTests(
|
||||
project, processors, javaSources.toList(), sourceOutputDir, this.options,
|
||||
stubsOutputDir = stubsDir, incrementalDataOutputDir = incrementalDataDir
|
||||
)
|
||||
|
||||
val options = KaptOptions.Builder().apply {
|
||||
projectBaseDir = project.basePath?.let(::File)
|
||||
compileClasspath.addAll(PathUtil.getJdkClassesRootsFromCurrentJre() + PathUtil.kotlinPathsForIdeaPlugin.stdlibPath)
|
||||
javaSourceRoots.addAll(javaSources)
|
||||
|
||||
sourcesOutputDir = Files.createTempDirectory("kaptRunner").toFile()
|
||||
classesOutputDir = sourcesOutputDir
|
||||
stubsOutputDir = Files.createTempDirectory("kaptStubs").toFile()
|
||||
incrementalDataOutputDir = Files.createTempDirectory("kaptIncrementalData").toFile()
|
||||
|
||||
mutableOptions?.let { processingOptions.putAll(it) }
|
||||
detectMemoryLeaks = DetectMemoryLeaksMode.NONE
|
||||
}.build()
|
||||
|
||||
val kapt3Extension = Kapt3ExtensionForTests(options, processors)
|
||||
AnalysisHandlerExtension.registerExtension(project, kapt3Extension)
|
||||
|
||||
try {
|
||||
@@ -155,28 +160,13 @@ abstract class AbstractKotlinKapt3IntegrationTest : CodegenTestCase() {
|
||||
|
||||
KotlinTestUtils.assertEqualsToFile(txtFile, actual)
|
||||
} finally {
|
||||
sourceOutputDir.deleteRecursively()
|
||||
incrementalDataDir.deleteRecursively()
|
||||
options.sourcesOutputDir.deleteRecursively()
|
||||
options.incrementalDataOutputDir?.deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
protected class Kapt3ExtensionForTests(
|
||||
project: Project,
|
||||
private val processors: List<Processor>,
|
||||
javaSourceRoots: List<File>,
|
||||
outputDir: File,
|
||||
options: Map<String, String>,
|
||||
stubsOutputDir: File,
|
||||
incrementalDataOutputDir: File
|
||||
) : AbstractKapt3Extension(
|
||||
KaptPaths(
|
||||
project.basePath?.let(::File),
|
||||
PathUtil.getJdkClassesRootsFromCurrentJre() + PathUtil.kotlinPathsForIdeaPlugin.stdlibPath,
|
||||
emptyList(), javaSourceRoots, outputDir, outputDir, stubsOutputDir, incrementalDataOutputDir
|
||||
), options, emptyMap(), emptyList(), STUBS_AND_APT, System.currentTimeMillis(),
|
||||
MessageCollectorBackedKaptLogger(true),
|
||||
correctErrorTypes = true, mapDiagnosticLocations = true, strictMode = true, detectMemoryLeaks = false,
|
||||
compilerConfiguration = CompilerConfiguration.EMPTY
|
||||
protected class Kapt3ExtensionForTests(options: KaptOptions, private val processors: List<Processor>) : AbstractKapt3Extension(
|
||||
options, MessageCollectorBackedKaptLogger(options), compilerConfiguration = CompilerConfiguration.EMPTY
|
||||
) {
|
||||
internal var savedStubs: String? = null
|
||||
internal var savedBindings: Map<String, KaptJavaFileObject>? = null
|
||||
|
||||
+55
-30
@@ -24,6 +24,9 @@ import com.sun.tools.javac.tree.JCTree.JCCompilationUnit
|
||||
import com.sun.tools.javac.util.JCDiagnostic
|
||||
import com.sun.tools.javac.util.Log
|
||||
import junit.framework.ComparisonFailure
|
||||
import org.jetbrains.kotlin.base.kapt3.DetectMemoryLeaksMode
|
||||
import org.jetbrains.kotlin.base.kapt3.KaptFlag
|
||||
import org.jetbrains.kotlin.base.kapt3.KaptOptions
|
||||
import org.jetbrains.kotlin.checkers.CheckerTestUtil
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
|
||||
import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector
|
||||
@@ -35,7 +38,6 @@ import org.jetbrains.kotlin.kapt.base.test.JavaKaptContextTest
|
||||
import org.jetbrains.kotlin.kapt3.*
|
||||
import org.jetbrains.kotlin.kapt3.Kapt3ComponentRegistrar.KaptComponentContributor
|
||||
import org.jetbrains.kotlin.kapt3.base.KaptContext
|
||||
import org.jetbrains.kotlin.kapt3.base.KaptPaths
|
||||
import org.jetbrains.kotlin.kapt3.base.doAnnotationProcessing
|
||||
import org.jetbrains.kotlin.kapt3.base.javac.KaptJavaLog
|
||||
import org.jetbrains.kotlin.kapt3.base.parseJavaFiles
|
||||
@@ -57,7 +59,6 @@ import java.nio.file.Files
|
||||
import java.util.*
|
||||
import com.sun.tools.javac.util.List as JavacList
|
||||
|
||||
|
||||
abstract class AbstractKotlinKapt3Test : CodegenTestCase() {
|
||||
companion object {
|
||||
const val FILE_SEPARATOR = "\n\n////////////////////\n\n"
|
||||
@@ -67,8 +68,14 @@ abstract class AbstractKotlinKapt3Test : CodegenTestCase() {
|
||||
val messageCollector = PrintingMessageCollector(ERR_PRINT_STREAM, MessageRenderer.PLAIN_FULL_PATHS, false)
|
||||
}
|
||||
|
||||
val kaptFlags = mutableListOf<KaptFlag>()
|
||||
private val tempFiles = mutableListOf<File>()
|
||||
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
kaptFlags.clear()
|
||||
}
|
||||
|
||||
override fun tearDown() {
|
||||
ERR_BYTE_STREAM.reset()
|
||||
super.tearDown()
|
||||
@@ -81,12 +88,15 @@ abstract class AbstractKotlinKapt3Test : CodegenTestCase() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun createTempDir(prefix: String): File {
|
||||
return Files.createTempDirectory(prefix).toFile().apply { tempFiles += this }
|
||||
}
|
||||
|
||||
override fun loadMultiFiles(files: List<TestFile>) {
|
||||
val project = myEnvironment.project
|
||||
val psiManager = PsiManager.getInstance(project)
|
||||
|
||||
val tmpDir = Files.createTempDirectory("kaptTest").toFile()
|
||||
tempFiles += tmpDir
|
||||
val tmpDir = createTempDir("kaptTest")
|
||||
|
||||
val ktFiles = ArrayList<KtFile>(files.size)
|
||||
for (file in files.sorted()) {
|
||||
@@ -118,7 +128,7 @@ abstract class AbstractKotlinKapt3Test : CodegenTestCase() {
|
||||
val classBuilderFactory = OriginCollectingClassBuilderFactory(ClassBuilderMode.KAPT3)
|
||||
val generationState = GenerationUtils.compileFiles(myFiles.psiFiles, myEnvironment, classBuilderFactory)
|
||||
|
||||
val logger = MessageCollectorBackedKaptLogger(isVerbose = true, messageCollector = messageCollector)
|
||||
val logger = MessageCollectorBackedKaptLogger(isVerbose = true, isInfoAsWarnings = false, messageCollector = messageCollector)
|
||||
|
||||
val javacOptions = wholeFile.getOptionValues("JAVAC_OPTION")
|
||||
.map { opt ->
|
||||
@@ -130,21 +140,25 @@ abstract class AbstractKotlinKapt3Test : CodegenTestCase() {
|
||||
var kaptContext: KaptContext? = null
|
||||
|
||||
try {
|
||||
val sourceOutputDir = Files.createTempDirectory("kaptRunner").toFile()
|
||||
val options = KaptOptions.Builder().apply {
|
||||
projectBaseDir = generationState.project.basePath?.let(::File)
|
||||
compileClasspath.addAll(PathUtil.getJdkClassesRootsFromCurrentJre() + PathUtil.kotlinPathsForIdeaPlugin.stdlibPath)
|
||||
|
||||
val paths = KaptPaths(
|
||||
generationState.project.basePath?.let(::File),
|
||||
compileClasspath = PathUtil.getJdkClassesRootsFromCurrentJre() + PathUtil.kotlinPathsForIdeaPlugin.stdlibPath,
|
||||
annotationProcessingClasspath = emptyList(), javaSourceRoots = emptyList(),
|
||||
sourcesOutputDir = sourceOutputDir, classFilesOutputDir = sourceOutputDir,
|
||||
stubsOutputDir = sourceOutputDir, incrementalDataOutputDir = sourceOutputDir
|
||||
)
|
||||
sourcesOutputDir = createTempDir("kaptRunner")
|
||||
classesOutputDir = sourcesOutputDir
|
||||
stubsOutputDir = sourcesOutputDir
|
||||
incrementalDataOutputDir = sourcesOutputDir
|
||||
|
||||
this.javacOptions.putAll(javacOptions)
|
||||
flags.addAll(kaptFlags)
|
||||
|
||||
detectMemoryLeaks = DetectMemoryLeaksMode.NONE
|
||||
}.build()
|
||||
|
||||
kaptContext = KaptContextForStubGeneration(
|
||||
paths, true,
|
||||
logger, generationState.project, generationState.bindingContext, classBuilderFactory.compiledClasses,
|
||||
classBuilderFactory.origins, generationState, mapDiagnosticLocations = true,
|
||||
processorOptions = emptyMap(), javacOptions = javacOptions
|
||||
options, true, logger,
|
||||
generationState.project, generationState.bindingContext, classBuilderFactory.compiledClasses,
|
||||
classBuilderFactory.origins, generationState
|
||||
)
|
||||
|
||||
javaFiles = files
|
||||
@@ -165,11 +179,9 @@ abstract class AbstractKotlinKapt3Test : CodegenTestCase() {
|
||||
protected fun convert(
|
||||
kaptContext: KaptContextForStubGeneration,
|
||||
javaFiles: List<File>,
|
||||
generateNonExistentClass: Boolean,
|
||||
correctErrorTypes: Boolean,
|
||||
strictMode: Boolean
|
||||
generateNonExistentClass: Boolean
|
||||
): JavacList<JCCompilationUnit> {
|
||||
val converter = ClassFileToSourceStubConverter(kaptContext, generateNonExistentClass, correctErrorTypes, strictMode)
|
||||
val converter = ClassFileToSourceStubConverter(kaptContext, generateNonExistentClass)
|
||||
|
||||
val kaptStubs = converter.convert()
|
||||
val convertedFiles = kaptStubs.map { stub ->
|
||||
@@ -245,18 +257,28 @@ open class AbstractClassFileToSourceStubConverterTest : AbstractKotlinKapt3Test(
|
||||
fun testSuppressWarning() {}
|
||||
|
||||
override fun doTest(filePath: String) {
|
||||
val wholeFile = File(filePath)
|
||||
|
||||
kaptFlags.add(KaptFlag.MAP_DIAGNOSTIC_LOCATIONS)
|
||||
|
||||
if (wholeFile.isOptionSet("CORRECT_ERROR_TYPES")) {
|
||||
kaptFlags.add(KaptFlag.CORRECT_ERROR_TYPES)
|
||||
}
|
||||
|
||||
if (wholeFile.isOptionSet("STRICT_MODE")) {
|
||||
kaptFlags.add(KaptFlag.STRICT)
|
||||
}
|
||||
|
||||
super.doTest(filePath)
|
||||
doTestWithJdk9(AbstractClassFileToSourceStubConverterTest::class.java, filePath)
|
||||
}
|
||||
|
||||
override fun check(kaptContext: KaptContextForStubGeneration, javaFiles: List<File>, txtFile: File, wholeFile: File) {
|
||||
val generateNonExistentClass = wholeFile.isOptionSet("NON_EXISTENT_CLASS")
|
||||
val correctErrorTypes = wholeFile.isOptionSet("CORRECT_ERROR_TYPES")
|
||||
val validate = !wholeFile.isOptionSet("NO_VALIDATION")
|
||||
val strictMode = wholeFile.isOptionSet("STRICT_MODE")
|
||||
val expectedErrors = wholeFile.getRawOptionValues(EXPECTED_ERROR).sorted()
|
||||
|
||||
val convertedFiles = convert(kaptContext, javaFiles, generateNonExistentClass, correctErrorTypes, strictMode)
|
||||
val convertedFiles = convert(kaptContext, javaFiles, generateNonExistentClass)
|
||||
|
||||
kaptContext.javaLog.interceptorData.files = convertedFiles.map { it.sourceFile to it }.toMap()
|
||||
if (validate) kaptContext.compiler.enterTrees(convertedFiles)
|
||||
@@ -309,19 +331,22 @@ open class AbstractClassFileToSourceStubConverterTest : AbstractKotlinKapt3Test(
|
||||
}
|
||||
|
||||
abstract class AbstractKotlinKaptContextTest : AbstractKotlinKapt3Test() {
|
||||
override fun check(kaptContext: KaptContextForStubGeneration, javaFiles: List<File>, txtFile: File, wholeFile: File) {
|
||||
val compilationUnits = convert(
|
||||
kaptContext, javaFiles,
|
||||
generateNonExistentClass = false, correctErrorTypes = true, strictMode = false
|
||||
)
|
||||
override fun doTest(filePath: String?) {
|
||||
kaptFlags.add(KaptFlag.CORRECT_ERROR_TYPES)
|
||||
kaptFlags.add(KaptFlag.STRICT)
|
||||
kaptFlags.add(KaptFlag.MAP_DIAGNOSTIC_LOCATIONS)
|
||||
super.doTest(filePath)
|
||||
}
|
||||
|
||||
override fun check(kaptContext: KaptContextForStubGeneration, javaFiles: List<File>, txtFile: File, wholeFile: File) {
|
||||
val compilationUnits = convert(kaptContext, javaFiles, generateNonExistentClass = false)
|
||||
kaptContext.doAnnotationProcessing(
|
||||
emptyList(),
|
||||
listOf(JavaKaptContextTest.simpleProcessor()),
|
||||
additionalSources = compilationUnits
|
||||
)
|
||||
|
||||
val stubJavaFiles = kaptContext.paths.sourcesOutputDir.walkTopDown().filter { it.isFile && it.extension == "java" }
|
||||
val stubJavaFiles = kaptContext.options.sourcesOutputDir.walkTopDown().filter { it.isFile && it.extension == "java" }
|
||||
val actualRaw = stubJavaFiles.sortedBy { it.name }.joinToString(FILE_SEPARATOR) { it.name + ":\n\n" + it.readText() }
|
||||
val actual = StringUtil.convertLineSeparators(actualRaw.trim({ it <= ' ' })).trimTrailingWhitespacesAndAddNewlineAtEOF()
|
||||
KotlinTestUtils.assertEqualsToFile(txtFile, actual)
|
||||
|
||||
+2
-2
@@ -96,8 +96,8 @@ class KotlinKapt3IntegrationTests : AbstractKotlinKapt3IntegrationTest(), Java9T
|
||||
test(name, "test.MyAnnotation") { _, _, _ ->
|
||||
val kaptExtension = AnalysisHandlerExtension.getInstances(myEnvironment.project).firstIsInstance<Kapt3ExtensionForTests>()
|
||||
|
||||
val stubsOutputDir = kaptExtension.paths.stubsOutputDir
|
||||
val incrementalDataOutputDir = kaptExtension.paths.incrementalDataOutputDir
|
||||
val stubsOutputDir = kaptExtension.options.stubsOutputDir
|
||||
val incrementalDataOutputDir = kaptExtension.options.incrementalDataOutputDir
|
||||
|
||||
val bindings = kaptExtension.savedBindings!!
|
||||
|
||||
|
||||
Reference in New Issue
Block a user