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:
+1
-1
@@ -94,7 +94,7 @@ public class KaptJVMCompilerMojo extends K2JVMCompileMojo {
|
|||||||
) {
|
) {
|
||||||
List<KaptOption> options = new ArrayList<>();
|
List<KaptOption> options = new ArrayList<>();
|
||||||
|
|
||||||
options.add(new KaptOption("aptOnly", true));
|
options.add(new KaptOption("aptMode", "stubsAndApt"));
|
||||||
options.add(new KaptOption("useLightAnalysis", useLightAnalysis));
|
options.add(new KaptOption("useLightAnalysis", useLightAnalysis));
|
||||||
options.add(new KaptOption("correctErrorTypes", correctErrorTypes));
|
options.add(new KaptOption("correctErrorTypes", correctErrorTypes));
|
||||||
options.add(new KaptOption("mapDiagnosticLocations", mapDiagnosticLocations));
|
options.add(new KaptOption("mapDiagnosticLocations", mapDiagnosticLocations));
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.kapt3.base
|
package org.jetbrains.kotlin.kapt3.base
|
||||||
|
|
||||||
import com.sun.tools.javac.util.Context
|
import com.sun.tools.javac.util.Context
|
||||||
|
import org.jetbrains.kotlin.base.kapt3.*
|
||||||
import org.jetbrains.kotlin.kapt3.base.util.KaptLogger
|
import org.jetbrains.kotlin.kapt3.base.util.KaptLogger
|
||||||
import org.jetbrains.kotlin.kapt3.base.util.WriterBackedKaptLogger
|
import org.jetbrains.kotlin.kapt3.base.util.WriterBackedKaptLogger
|
||||||
import org.jetbrains.kotlin.kapt3.base.util.info
|
import org.jetbrains.kotlin.kapt3.base.util.info
|
||||||
@@ -16,32 +17,26 @@ object Kapt {
|
|||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
fun kapt(
|
fun kaptFlags(rawFlags: Set<String>): KaptFlags {
|
||||||
paths: KaptPaths,
|
return KaptFlags.fromSet(KaptFlag.values().filterTo(mutableSetOf()) { it.name in rawFlags })
|
||||||
isVerbose: Boolean,
|
}
|
||||||
mapDiagnosticLocations: Boolean,
|
|
||||||
annotationProcessorFqNames: List<String>,
|
@JvmStatic
|
||||||
processorOptions: Map<String, String>,
|
@Suppress("unused")
|
||||||
javacOptions: Map<String, String>
|
fun kapt(options: KaptOptions): Boolean {
|
||||||
): Boolean {
|
val logger = WriterBackedKaptLogger(options[KaptFlag.VERBOSE])
|
||||||
val logger = WriterBackedKaptLogger(isVerbose)
|
|
||||||
|
|
||||||
if (!Kapt.checkJavacComponentsAccess(logger)) {
|
if (!Kapt.checkJavacComponentsAccess(logger)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
val kaptContext = KaptContext(paths, false, logger, mapDiagnosticLocations, processorOptions, javacOptions)
|
val kaptContext = KaptContext(options, false, logger)
|
||||||
|
|
||||||
logger.info { "Kapt3 is enabled (stand-alone mode)." }
|
logger.info { options.logString("stand-alone mode") }
|
||||||
logger.info { "Map diagnostic locations: $mapDiagnosticLocations" }
|
|
||||||
paths.log(logger)
|
|
||||||
logger.info { "Javac options: $javacOptions" }
|
|
||||||
logger.info { "AP options: $processorOptions" }
|
|
||||||
|
|
||||||
val javaSourceFiles = paths.collectJavaSourceFiles()
|
val javaSourceFiles = options.collectJavaSourceFiles()
|
||||||
logger.info { "Java source files: " + javaSourceFiles.joinToString { it.canonicalPath } }
|
|
||||||
|
|
||||||
val processorLoader = ProcessorLoader(paths, annotationProcessorFqNames, logger)
|
val processorLoader = ProcessorLoader(options, logger)
|
||||||
|
|
||||||
processorLoader.use {
|
processorLoader.use {
|
||||||
val processors = processorLoader.loadProcessors(findClassLoaderWithJavac())
|
val processors = processorLoader.loadProcessors(findClassLoaderWithJavac())
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import com.sun.tools.javac.main.Option
|
|||||||
import com.sun.tools.javac.util.Context
|
import com.sun.tools.javac.util.Context
|
||||||
import com.sun.tools.javac.util.Log
|
import com.sun.tools.javac.util.Log
|
||||||
import com.sun.tools.javac.util.Options
|
import com.sun.tools.javac.util.Options
|
||||||
|
import org.jetbrains.kotlin.base.kapt3.KaptFlag
|
||||||
|
import org.jetbrains.kotlin.base.kapt3.KaptOptions
|
||||||
import org.jetbrains.kotlin.kapt3.base.javac.KaptJavaCompiler
|
import org.jetbrains.kotlin.kapt3.base.javac.KaptJavaCompiler
|
||||||
import org.jetbrains.kotlin.kapt3.base.javac.KaptJavaFileManager
|
import org.jetbrains.kotlin.kapt3.base.javac.KaptJavaFileManager
|
||||||
import org.jetbrains.kotlin.kapt3.base.javac.KaptJavaLog
|
import org.jetbrains.kotlin.kapt3.base.javac.KaptJavaLog
|
||||||
@@ -21,18 +23,11 @@ import java.io.Closeable
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.tools.JavaFileManager
|
import javax.tools.JavaFileManager
|
||||||
|
|
||||||
open class KaptContext(
|
open class KaptContext(val options: KaptOptions, val withJdk: Boolean, val logger: KaptLogger) : Closeable {
|
||||||
val paths: KaptPaths,
|
|
||||||
val withJdk: Boolean,
|
|
||||||
val logger: KaptLogger,
|
|
||||||
private val mapDiagnosticLocations: Boolean,
|
|
||||||
processorOptions: Map<String, String>,
|
|
||||||
javacOptions: Map<String, String> = emptyMap()
|
|
||||||
) : Closeable {
|
|
||||||
val context = Context()
|
val context = Context()
|
||||||
val compiler: KaptJavaCompiler
|
val compiler: KaptJavaCompiler
|
||||||
val fileManager: KaptJavaFileManager
|
val fileManager: KaptJavaFileManager
|
||||||
val options: Options
|
private val javacOptions: Options
|
||||||
val javaLog: KaptJavaLog
|
val javaLog: KaptJavaLog
|
||||||
|
|
||||||
protected open fun preregisterTreeMaker(context: Context) {}
|
protected open fun preregisterTreeMaker(context: Context) {}
|
||||||
@@ -41,8 +36,8 @@ open class KaptContext(
|
|||||||
val interceptorData = KaptJavaLog.DiagnosticInterceptorData()
|
val interceptorData = KaptJavaLog.DiagnosticInterceptorData()
|
||||||
context.put(Log.logKey, Context.Factory<Log> { newContext ->
|
context.put(Log.logKey, Context.Factory<Log> { newContext ->
|
||||||
KaptJavaLog(
|
KaptJavaLog(
|
||||||
paths.projectBaseDir, newContext, logger.errorWriter, logger.warnWriter, logger.infoWriter,
|
options.projectBaseDir, newContext, logger.errorWriter, logger.warnWriter, logger.infoWriter,
|
||||||
interceptorData, mapDiagnosticLocations
|
interceptorData, options[KaptFlag.MAP_DIAGNOSTIC_LOCATIONS]
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -56,13 +51,13 @@ open class KaptContext(
|
|||||||
|
|
||||||
KaptJavaCompiler.preRegister(context)
|
KaptJavaCompiler.preRegister(context)
|
||||||
|
|
||||||
options = Options.instance(context).apply {
|
javacOptions = Options.instance(context).apply {
|
||||||
for ((key, value) in processorOptions) {
|
for ((key, value) in options.processingOptions) {
|
||||||
val option = if (value.isEmpty()) "-A$key" else "-A$key=$value"
|
val option = if (value.isEmpty()) "-A$key" else "-A$key=$value"
|
||||||
put(option, option) // key == value: it's intentional
|
put(option, option) // key == value: it's intentional
|
||||||
}
|
}
|
||||||
|
|
||||||
for ((key, value) in javacOptions) {
|
for ((key, value) in options.javacOptions) {
|
||||||
if (value.isNotEmpty()) {
|
if (value.isNotEmpty()) {
|
||||||
put(key, value)
|
put(key, value)
|
||||||
} else {
|
} else {
|
||||||
@@ -82,26 +77,26 @@ open class KaptContext(
|
|||||||
}
|
}
|
||||||
|
|
||||||
putJavacOption("CLASSPATH", "CLASS_PATH",
|
putJavacOption("CLASSPATH", "CLASS_PATH",
|
||||||
paths.compileClasspath.joinToString(File.pathSeparator) { it.canonicalPath })
|
options.compileClasspath.joinToString(File.pathSeparator) { it.canonicalPath })
|
||||||
|
|
||||||
@Suppress("SpellCheckingInspection")
|
@Suppress("SpellCheckingInspection")
|
||||||
putJavacOption("PROCESSORPATH", "PROCESSOR_PATH",
|
putJavacOption("PROCESSORPATH", "PROCESSOR_PATH",
|
||||||
paths.annotationProcessingClasspath.joinToString(File.pathSeparator) { it.canonicalPath })
|
options.processingClasspath.joinToString(File.pathSeparator) { it.canonicalPath })
|
||||||
|
|
||||||
put(Option.S, paths.sourcesOutputDir.canonicalPath)
|
put(Option.S, options.sourcesOutputDir.canonicalPath)
|
||||||
put(Option.D, paths.classFilesOutputDir.canonicalPath)
|
put(Option.D, options.classesOutputDir.canonicalPath)
|
||||||
put(Option.ENCODING, "UTF-8")
|
put(Option.ENCODING, "UTF-8")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (logger.isVerbose) {
|
if (logger.isVerbose) {
|
||||||
logger.info("All Javac options: " + options.keySet().associateBy({ it }) { key -> options[key] ?: "" })
|
logger.info("All Javac options: " + javacOptions.keySet().associateBy({ it }) { key -> javacOptions[key] ?: "" })
|
||||||
}
|
}
|
||||||
|
|
||||||
fileManager = context.get(JavaFileManager::class.java) as KaptJavaFileManager
|
fileManager = context.get(JavaFileManager::class.java) as KaptJavaFileManager
|
||||||
|
|
||||||
if (isJava9OrLater()) {
|
if (isJava9OrLater()) {
|
||||||
for (option in Option.getJavacFileManagerOptions()) {
|
for (option in Option.getJavacFileManagerOptions()) {
|
||||||
val value = options.get(option) ?: continue
|
val value = javacOptions.get(option) ?: continue
|
||||||
fileManager.handleOptionJavac9(option, value)
|
fileManager.handleOptionJavac9(option, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.base.kapt3
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
import java.nio.file.Files
|
||||||
|
|
||||||
|
class KaptOptions(
|
||||||
|
val projectBaseDir: File?,
|
||||||
|
val compileClasspath: List<File>,
|
||||||
|
val javaSourceRoots: List<File>,
|
||||||
|
|
||||||
|
val sourcesOutputDir: File,
|
||||||
|
val classesOutputDir: File,
|
||||||
|
val stubsOutputDir: File,
|
||||||
|
val incrementalDataOutputDir: File?,
|
||||||
|
|
||||||
|
val processingClasspath: List<File>,
|
||||||
|
val processors: List<String>,
|
||||||
|
|
||||||
|
val processingOptions: Map<String, String>,
|
||||||
|
val javacOptions: Map<String, String>,
|
||||||
|
|
||||||
|
val flags: KaptFlags,
|
||||||
|
|
||||||
|
val mode: AptMode,
|
||||||
|
val detectMemoryLeaks: DetectMemoryLeaksMode
|
||||||
|
) : KaptFlags {
|
||||||
|
override fun get(flag: KaptFlag) = flags[flag]
|
||||||
|
|
||||||
|
class Builder {
|
||||||
|
var projectBaseDir: File? = null
|
||||||
|
val compileClasspath: MutableList<File> = mutableListOf()
|
||||||
|
val javaSourceRoots: MutableList<File> = mutableListOf()
|
||||||
|
|
||||||
|
var sourcesOutputDir: File? = null
|
||||||
|
var classesOutputDir: File? = null
|
||||||
|
var stubsOutputDir: File? = null
|
||||||
|
var incrementalDataOutputDir: File? = null
|
||||||
|
|
||||||
|
val processingClasspath: MutableList<File> = mutableListOf()
|
||||||
|
val processors: MutableList<String> = mutableListOf()
|
||||||
|
|
||||||
|
val processingOptions: MutableMap<String, String> = mutableMapOf()
|
||||||
|
val javacOptions: MutableMap<String, String> = mutableMapOf()
|
||||||
|
|
||||||
|
val flags: MutableSet<KaptFlag> = mutableSetOf(KaptFlag.USE_LIGHT_ANALYSIS)
|
||||||
|
|
||||||
|
var mode: AptMode = AptMode.WITH_COMPILATION
|
||||||
|
var detectMemoryLeaks: DetectMemoryLeaksMode = DetectMemoryLeaksMode.DEFAULT
|
||||||
|
|
||||||
|
fun build(): KaptOptions {
|
||||||
|
val sourcesOutputDir = this.sourcesOutputDir ?: error("'sourcesOutputDir' must be set")
|
||||||
|
val classesOutputDir = this.classesOutputDir ?: error("'classesOutputDir' must be set")
|
||||||
|
val stubsOutputDir = this.stubsOutputDir ?: error("'stubsOutputDir' must be set")
|
||||||
|
|
||||||
|
return KaptOptions(
|
||||||
|
projectBaseDir, compileClasspath, javaSourceRoots,
|
||||||
|
sourcesOutputDir, classesOutputDir, stubsOutputDir, incrementalDataOutputDir,
|
||||||
|
processingClasspath, processors, processingOptions, javacOptions, KaptFlags.fromSet(flags),
|
||||||
|
mode, detectMemoryLeaks
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface KaptFlags {
|
||||||
|
operator fun get(flag: KaptFlag): Boolean
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun fromSet(flags: Set<KaptFlag>) = object : KaptFlags {
|
||||||
|
override fun get(flag: KaptFlag) = flag in flags
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object Empty : KaptFlags {
|
||||||
|
override fun get(flag: KaptFlag) = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class KaptFlag(val description: String) {
|
||||||
|
VERBOSE("Verbose mode"),
|
||||||
|
INFO_AS_WARNINGS("Info as warnings"),
|
||||||
|
USE_LIGHT_ANALYSIS("Use light analysis"),
|
||||||
|
CORRECT_ERROR_TYPES("Correct error types"),
|
||||||
|
MAP_DIAGNOSTIC_LOCATIONS("Map diagnostic locations"),
|
||||||
|
STRICT("Strict mode");
|
||||||
|
}
|
||||||
|
|
||||||
|
interface KaptSelector {
|
||||||
|
val stringValue: String
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class DetectMemoryLeaksMode(override val stringValue: String) : KaptSelector {
|
||||||
|
DEFAULT("default"), PARANOID("paranoid"), NONE("none")
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class AptMode(override val stringValue: String) : KaptSelector {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
fun KaptOptions.collectJavaSourceFiles(): List<File> {
|
||||||
|
return (javaSourceRoots + stubsOutputDir)
|
||||||
|
.sortedBy { Files.isSymbolicLink(it.toPath()) } // Get non-symbolic paths first
|
||||||
|
.flatMap { root -> root.walk().filter { it.isFile && it.extension == "java" }.toList() }
|
||||||
|
.sortedBy { Files.isSymbolicLink(it.toPath()) } // This time is for .java files
|
||||||
|
.distinctBy { it.canonicalPath }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun KaptOptions.logString(additionalInfo: String = "") = buildString {
|
||||||
|
val additionalInfoRendered = if (additionalInfo.isEmpty()) "" else " ($additionalInfo)"
|
||||||
|
appendln("Kapt3 is enabled$additionalInfoRendered.")
|
||||||
|
|
||||||
|
appendln("Annotation processing mode: ${mode.stringValue}")
|
||||||
|
appendln("Memory leak detection mode: ${detectMemoryLeaks.stringValue}")
|
||||||
|
KaptFlag.values().forEach { appendln(it.description + ": " + this@logString[it]) }
|
||||||
|
|
||||||
|
appendln("Project base dir: $projectBaseDir")
|
||||||
|
appendln("Compile classpath: " + compileClasspath.joinToString())
|
||||||
|
appendln("Java source roots: " + javaSourceRoots.joinToString())
|
||||||
|
|
||||||
|
appendln("Sources output directory: $sourcesOutputDir")
|
||||||
|
appendln("Class files output directory: $classesOutputDir")
|
||||||
|
appendln("Stubs output directory: $stubsOutputDir")
|
||||||
|
appendln("Incremental data output directory: $incrementalDataOutputDir")
|
||||||
|
|
||||||
|
appendln("Annotation processing classpath: " + processingClasspath.joinToString())
|
||||||
|
appendln("Annotation processors: " + processors.joinToString())
|
||||||
|
|
||||||
|
appendln("AP options: $processingOptions")
|
||||||
|
appendln("Javac options: $javacOptions")
|
||||||
|
}
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
|
||||||
* that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.kapt3.base
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.kapt3.base.util.KaptLogger
|
|
||||||
import java.io.File
|
|
||||||
import java.nio.file.Files
|
|
||||||
|
|
||||||
class KaptPaths(
|
|
||||||
val projectBaseDir: File?,
|
|
||||||
compileClasspath: List<File>,
|
|
||||||
annotationProcessingClasspath: List<File>,
|
|
||||||
val javaSourceRoots: List<File>,
|
|
||||||
val sourcesOutputDir: File,
|
|
||||||
val classFilesOutputDir: File,
|
|
||||||
val stubsOutputDir: File,
|
|
||||||
val incrementalDataOutputDir: File?
|
|
||||||
) {
|
|
||||||
val compileClasspath = compileClasspath.distinct()
|
|
||||||
val annotationProcessingClasspath = annotationProcessingClasspath.distinct()
|
|
||||||
|
|
||||||
fun collectJavaSourceFiles(): List<File> {
|
|
||||||
return (javaSourceRoots + stubsOutputDir)
|
|
||||||
.sortedBy { Files.isSymbolicLink(it.toPath()) } // Get non-symbolic paths first
|
|
||||||
.flatMap { root -> root.walk().filter { it.isFile && it.extension == "java" }.toList() }
|
|
||||||
.sortedBy { Files.isSymbolicLink(it.toPath()) } // This time is for .java files
|
|
||||||
.distinctBy { it.canonicalPath }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun KaptPaths.log(logger: KaptLogger) {
|
|
||||||
if (!logger.isVerbose) return
|
|
||||||
|
|
||||||
logger.info("Project base dir: $projectBaseDir")
|
|
||||||
logger.info("Compile classpath: ${compileClasspath.joinToString()}")
|
|
||||||
logger.info("Annotation processing classpath: ${annotationProcessingClasspath.joinToString()}")
|
|
||||||
logger.info("Java source roots: ${javaSourceRoots.joinToString()}")
|
|
||||||
logger.info("Sources output directory: $sourcesOutputDir")
|
|
||||||
logger.info("Class files output directory: $classFilesOutputDir")
|
|
||||||
logger.info("Stubs output directory: $stubsOutputDir")
|
|
||||||
logger.info("Incremental data output directory: $incrementalDataOutputDir")
|
|
||||||
}
|
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.kapt3.base
|
package org.jetbrains.kotlin.kapt3.base
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.base.kapt3.KaptOptions
|
||||||
import org.jetbrains.kotlin.kapt3.base.util.KaptLogger
|
import org.jetbrains.kotlin.kapt3.base.util.KaptLogger
|
||||||
import org.jetbrains.kotlin.kapt3.base.util.info
|
import org.jetbrains.kotlin.kapt3.base.util.info
|
||||||
import java.io.Closeable
|
import java.io.Closeable
|
||||||
@@ -16,23 +17,19 @@ import javax.annotation.processing.Processor
|
|||||||
|
|
||||||
class LoadedProcessors(val processors: List<Processor>, val classLoader: ClassLoader)
|
class LoadedProcessors(val processors: List<Processor>, val classLoader: ClassLoader)
|
||||||
|
|
||||||
open class ProcessorLoader(
|
open class ProcessorLoader(private val options: KaptOptions, private val logger: KaptLogger) : Closeable {
|
||||||
private val paths: KaptPaths,
|
|
||||||
private val annotationProcessorFqNames: List<String>,
|
|
||||||
private val logger: KaptLogger
|
|
||||||
) : Closeable {
|
|
||||||
private var annotationProcessingClassLoader: URLClassLoader? = null
|
private var annotationProcessingClassLoader: URLClassLoader? = null
|
||||||
|
|
||||||
fun loadProcessors(parentClassLoader: ClassLoader = ClassLoader.getSystemClassLoader()): LoadedProcessors {
|
fun loadProcessors(parentClassLoader: ClassLoader = ClassLoader.getSystemClassLoader()): LoadedProcessors {
|
||||||
clearJarURLCache()
|
clearJarURLCache()
|
||||||
|
|
||||||
val classpath = (paths.annotationProcessingClasspath + paths.compileClasspath).distinct()
|
val classpath = (options.processingClasspath + options.compileClasspath).distinct()
|
||||||
val classLoader = URLClassLoader(classpath.map { it.toURI().toURL() }.toTypedArray(), parentClassLoader)
|
val classLoader = URLClassLoader(classpath.map { it.toURI().toURL() }.toTypedArray(), parentClassLoader)
|
||||||
this.annotationProcessingClassLoader = classLoader
|
this.annotationProcessingClassLoader = classLoader
|
||||||
|
|
||||||
val processors = if (annotationProcessorFqNames.isNotEmpty()) {
|
val processors = if (options.processors.isNotEmpty()) {
|
||||||
logger.info("Annotation processor class names are set, skip AP discovery")
|
logger.info("Annotation processor class names are set, skip AP discovery")
|
||||||
annotationProcessorFqNames.mapNotNull { tryLoadProcessor(it, classLoader) }
|
options.processors.mapNotNull { tryLoadProcessor(it, classLoader) }
|
||||||
} else {
|
} else {
|
||||||
logger.info("Need to discovery annotation processors in the AP classpath")
|
logger.info("Need to discovery annotation processors in the AP classpath")
|
||||||
doLoadProcessors(classLoader)
|
doLoadProcessors(classLoader)
|
||||||
|
|||||||
@@ -6,8 +6,10 @@
|
|||||||
package org.jetbrains.kotlin.kapt.base.test
|
package org.jetbrains.kotlin.kapt.base.test
|
||||||
|
|
||||||
import junit.framework.TestCase
|
import junit.framework.TestCase
|
||||||
|
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.kapt3.base.KaptContext
|
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.doAnnotationProcessing
|
||||||
import org.jetbrains.kotlin.kapt3.base.util.KaptBaseError
|
import org.jetbrains.kotlin.kapt3.base.util.KaptBaseError
|
||||||
import org.jetbrains.kotlin.kapt3.base.util.WriterBackedKaptLogger
|
import org.jetbrains.kotlin.kapt3.base.util.WriterBackedKaptLogger
|
||||||
@@ -49,22 +51,20 @@ class JavaKaptContextTest : TestCase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun doAnnotationProcessing(javaSourceFile: File, processor: Processor, outputDir: File) {
|
private fun doAnnotationProcessing(javaSourceFile: File, processor: Processor, outputDir: File) {
|
||||||
KaptContext(
|
val options = KaptOptions.Builder().apply {
|
||||||
KaptPaths(
|
projectBaseDir = javaSourceFile.parentFile
|
||||||
projectBaseDir = javaSourceFile.parentFile,
|
|
||||||
compileClasspath = emptyList(),
|
sourcesOutputDir = outputDir
|
||||||
annotationProcessingClasspath = emptyList(),
|
classesOutputDir = outputDir
|
||||||
javaSourceRoots = emptyList(),
|
stubsOutputDir = outputDir
|
||||||
sourcesOutputDir = outputDir,
|
incrementalDataOutputDir = outputDir
|
||||||
classFilesOutputDir = outputDir,
|
|
||||||
stubsOutputDir = outputDir,
|
flags.add(KaptFlag.MAP_DIAGNOSTIC_LOCATIONS)
|
||||||
incrementalDataOutputDir = outputDir
|
detectMemoryLeaks = DetectMemoryLeaksMode.NONE
|
||||||
),
|
}.build()
|
||||||
withJdk = true,
|
|
||||||
logger = WriterBackedKaptLogger(isVerbose = true),
|
val logger = WriterBackedKaptLogger(isVerbose = true)
|
||||||
mapDiagnosticLocations = true,
|
KaptContext(options, true, logger).doAnnotationProcessing(listOf(javaSourceFile), listOf(processor))
|
||||||
processorOptions = emptyMap()
|
|
||||||
).doAnnotationProcessing(listOf(javaSourceFile), listOf(processor))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -6,7 +6,8 @@
|
|||||||
package org.jetbrains.kotlin.kapt.base.test
|
package org.jetbrains.kotlin.kapt.base.test
|
||||||
|
|
||||||
import junit.framework.TestCase
|
import junit.framework.TestCase
|
||||||
import org.jetbrains.kotlin.kapt3.base.KaptPaths
|
import org.jetbrains.kotlin.base.kapt3.KaptOptions
|
||||||
|
import org.jetbrains.kotlin.base.kapt3.collectJavaSourceFiles
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
@@ -36,16 +37,12 @@ class KaptPathsTest : TestCase() {
|
|||||||
|
|
||||||
val javaRoots = listOf(simpleJava, symlinkToOtherJava, symlinkToNotJava, symlinkToJavaRootDir, javaRootDir)
|
val javaRoots = listOf(simpleJava, symlinkToOtherJava, symlinkToNotJava, symlinkToJavaRootDir, javaRootDir)
|
||||||
|
|
||||||
val paths = KaptPaths(
|
val paths = KaptOptions.Builder().apply {
|
||||||
projectBaseDir = null,
|
javaSourceRoots.addAll(javaRoots)
|
||||||
compileClasspath = emptyList(),
|
sourcesOutputDir = outputDir
|
||||||
annotationProcessingClasspath = emptyList(),
|
classesOutputDir = outputDir
|
||||||
javaSourceRoots = javaRoots,
|
stubsOutputDir = outputDir
|
||||||
sourcesOutputDir = outputDir,
|
}.build()
|
||||||
classFilesOutputDir = outputDir,
|
|
||||||
stubsOutputDir = outputDir,
|
|
||||||
incrementalDataOutputDir = null
|
|
||||||
)
|
|
||||||
|
|
||||||
val javaSourceFiles = paths.collectJavaSourceFiles()
|
val javaSourceFiles = paths.collectJavaSourceFiles()
|
||||||
|
|
||||||
|
|||||||
@@ -149,10 +149,7 @@ enum class KaptCliOption(
|
|||||||
APT_OPTIONS_OPTION("apoptions", "options map", "Encoded annotation processor options", false),
|
APT_OPTIONS_OPTION("apoptions", "options map", "Encoded annotation processor options", false),
|
||||||
|
|
||||||
@Deprecated("Do not use in CLI")
|
@Deprecated("Do not use in CLI")
|
||||||
JAVAC_CLI_OPTIONS_OPTION("javacArguments", "javac CLI options map", "Encoded javac CLI options", false),
|
JAVAC_CLI_OPTIONS_OPTION("javacArguments", "javac CLI options map", "Encoded javac CLI options", false);
|
||||||
|
|
||||||
@Deprecated("Use APT_MODE_OPTION instead.")
|
|
||||||
APT_ONLY_OPTION("aptOnly", "true | false", "Run only annotation processing, do not compile Kotlin files");
|
|
||||||
|
|
||||||
override val required: Boolean = false
|
override val required: Boolean = false
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import com.sun.tools.javac.tree.TreeMaker
|
|||||||
import com.sun.tools.javac.util.Context
|
import com.sun.tools.javac.util.Context
|
||||||
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
||||||
import org.jetbrains.kotlin.backend.common.output.OutputFile
|
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.CompilerMessageSeverity.OUTPUT
|
||||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||||
import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil
|
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.container.ComponentProvider
|
||||||
import org.jetbrains.kotlin.context.ProjectContext
|
import org.jetbrains.kotlin.context.ProjectContext
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
import org.jetbrains.kotlin.kapt3.AptMode.APT_ONLY
|
import org.jetbrains.kotlin.base.kapt3.AptMode.APT_ONLY
|
||||||
import org.jetbrains.kotlin.kapt3.AptMode.WITH_COMPILATION
|
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.*
|
||||||
import org.jetbrains.kotlin.kapt3.base.stubs.KaptStubLineInformation.Companion.KAPT_METADATA_EXTENSION
|
import org.jetbrains.kotlin.kapt3.base.stubs.KaptStubLineInformation.Companion.KAPT_METADATA_EXTENSION
|
||||||
import org.jetbrains.kotlin.kapt3.base.util.KaptBaseError
|
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
|
import com.sun.tools.javac.util.List as JavacList
|
||||||
|
|
||||||
class ClasspathBasedKapt3Extension(
|
class ClasspathBasedKapt3Extension(
|
||||||
paths: KaptPaths,
|
options: KaptOptions,
|
||||||
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,
|
|
||||||
logger: MessageCollectorBackedKaptLogger,
|
logger: MessageCollectorBackedKaptLogger,
|
||||||
compilerConfiguration: CompilerConfiguration
|
compilerConfiguration: CompilerConfiguration
|
||||||
) : AbstractKapt3Extension(
|
) : AbstractKapt3Extension(options, logger, compilerConfiguration) {
|
||||||
paths, options, javacOptions, annotationProcessorFqNames,
|
|
||||||
aptMode, pluginInitializedTime, logger, correctErrorTypes, mapDiagnosticLocations, strictMode, detectMemoryLeaks,
|
|
||||||
compilerConfiguration
|
|
||||||
) {
|
|
||||||
override val analyzePartially: Boolean
|
override val analyzePartially: Boolean
|
||||||
get() = useLightAnalysis && super.analyzePartially
|
get() = options[KaptFlag.USE_LIGHT_ANALYSIS] && super.analyzePartially
|
||||||
|
|
||||||
private var processorLoader: ProcessorLoader? = null
|
private var processorLoader: ProcessorLoader? = null
|
||||||
|
|
||||||
override fun loadProcessors(): LoadedProcessors {
|
override fun loadProcessors(): LoadedProcessors {
|
||||||
val efficientProcessorLoader = object : ProcessorLoader(paths, annotationProcessorFqNames, logger) {
|
val efficientProcessorLoader = object : ProcessorLoader(options, logger) {
|
||||||
override fun doLoadProcessors(classLoader: URLClassLoader): List<Processor> {
|
override fun doLoadProcessors(classLoader: URLClassLoader): List<Processor> {
|
||||||
return ServiceLoaderLite.loadImplementations(Processor::class.java, classLoader)
|
return ServiceLoaderLite.loadImplementations(Processor::class.java, classLoader)
|
||||||
}
|
}
|
||||||
@@ -122,19 +112,12 @@ class ClasspathBasedKapt3Extension(
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract class AbstractKapt3Extension(
|
abstract class AbstractKapt3Extension(
|
||||||
val paths: KaptPaths,
|
val options: KaptOptions,
|
||||||
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 logger: MessageCollectorBackedKaptLogger,
|
val logger: MessageCollectorBackedKaptLogger,
|
||||||
val correctErrorTypes: Boolean,
|
|
||||||
val mapDiagnosticLocations: Boolean,
|
|
||||||
val strictMode: Boolean,
|
|
||||||
val detectMemoryLeaks: Boolean,
|
|
||||||
val compilerConfiguration: CompilerConfiguration
|
val compilerConfiguration: CompilerConfiguration
|
||||||
) : PartialAnalysisHandlerExtension() {
|
) : PartialAnalysisHandlerExtension() {
|
||||||
|
private val pluginInitializedTime: Long = System.currentTimeMillis()
|
||||||
|
|
||||||
private var annotationProcessingComplete = false
|
private var annotationProcessingComplete = false
|
||||||
|
|
||||||
private fun setAnnotationProcessingComplete(): Boolean {
|
private fun setAnnotationProcessingComplete(): Boolean {
|
||||||
@@ -155,7 +138,7 @@ abstract class AbstractKapt3Extension(
|
|||||||
bindingTrace: BindingTrace,
|
bindingTrace: BindingTrace,
|
||||||
componentProvider: ComponentProvider
|
componentProvider: ComponentProvider
|
||||||
): AnalysisResult? {
|
): AnalysisResult? {
|
||||||
if (aptMode == APT_ONLY) {
|
if (options.mode == APT_ONLY) {
|
||||||
return AnalysisResult.EMPTY
|
return AnalysisResult.EMPTY
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,7 +158,7 @@ abstract class AbstractKapt3Extension(
|
|||||||
logger.info { "Initial analysis took ${System.currentTimeMillis() - pluginInitializedTime} ms" }
|
logger.info { "Initial analysis took ${System.currentTimeMillis() - pluginInitializedTime} ms" }
|
||||||
|
|
||||||
val bindingContext = bindingTrace.bindingContext
|
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()}>" } }
|
logger.info { "Kotlin files to compile: " + files.map { it.virtualFile?.name ?: "<in memory ${it.hashCode()}>" } }
|
||||||
|
|
||||||
contextForStubGeneration(project, module, bindingContext, files.toList()).use { context ->
|
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()
|
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 {
|
fun handleKaptError(error: KaptError): AnalysisResult {
|
||||||
val cause = error.cause
|
val cause = error.cause
|
||||||
@@ -218,22 +201,22 @@ abstract class AbstractKapt3Extension(
|
|||||||
kaptContext.close()
|
kaptContext.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
return if (aptMode != WITH_COMPILATION) {
|
return if (options.mode != WITH_COMPILATION) {
|
||||||
doNotGenerateCode()
|
doNotGenerateCode()
|
||||||
} else {
|
} else {
|
||||||
AnalysisResult.RetryWithAdditionalJavaRoots(
|
AnalysisResult.RetryWithAdditionalJavaRoots(
|
||||||
bindingTrace.bindingContext,
|
bindingTrace.bindingContext,
|
||||||
module,
|
module,
|
||||||
listOf(paths.sourcesOutputDir),
|
listOf(options.sourcesOutputDir),
|
||||||
addToEnvironment = true
|
addToEnvironment = true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun runAnnotationProcessing(kaptContext: KaptContext, processors: LoadedProcessors) {
|
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 } }
|
logger.info { "Java source files: " + javaSourceFiles.joinToString { it.canonicalPath } }
|
||||||
|
|
||||||
val (annotationProcessingTime) = measureTimeMillis {
|
val (annotationProcessingTime) = measureTimeMillis {
|
||||||
@@ -242,7 +225,7 @@ abstract class AbstractKapt3Extension(
|
|||||||
|
|
||||||
logger.info { "Annotation processing took $annotationProcessingTime ms" }
|
logger.info { "Annotation processing took $annotationProcessingTime ms" }
|
||||||
|
|
||||||
if (detectMemoryLeaks) {
|
if (options.detectMemoryLeaks != DetectMemoryLeaksMode.NONE) {
|
||||||
MemoryLeakDetector.add(processors.classLoader)
|
MemoryLeakDetector.add(processors.classLoader)
|
||||||
|
|
||||||
val (leakDetectionTime, leaks) = measureTimeMillis { MemoryLeakDetector.process() }
|
val (leakDetectionTime, leaks) = measureTimeMillis { MemoryLeakDetector.process() }
|
||||||
@@ -291,18 +274,13 @@ abstract class AbstractKapt3Extension(
|
|||||||
logger.info { "Compiled classes: " + compiledClasses.joinToString { it.name } }
|
logger.info { "Compiled classes: " + compiledClasses.joinToString { it.name } }
|
||||||
|
|
||||||
return KaptContextForStubGeneration(
|
return KaptContextForStubGeneration(
|
||||||
paths, false, logger, project, bindingContext, compiledClasses, origins, generationState,
|
options, false, logger, project, bindingContext,
|
||||||
mapDiagnosticLocations, options, javacOptions
|
compiledClasses, origins, generationState
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateKotlinSourceStubs(kaptContext: KaptContextForStubGeneration) {
|
private fun generateKotlinSourceStubs(kaptContext: KaptContextForStubGeneration) {
|
||||||
val converter = ClassFileToSourceStubConverter(
|
val converter = ClassFileToSourceStubConverter(kaptContext, generateNonExistentClass = true)
|
||||||
kaptContext,
|
|
||||||
generateNonExistentClass = true,
|
|
||||||
correctErrorTypes = correctErrorTypes,
|
|
||||||
strictMode = strictMode
|
|
||||||
)
|
|
||||||
|
|
||||||
val (stubGenerationTime, kaptStubs) = measureTimeMillis {
|
val (stubGenerationTime, kaptStubs) = measureTimeMillis {
|
||||||
converter.convert()
|
converter.convert()
|
||||||
@@ -321,7 +299,7 @@ abstract class AbstractKapt3Extension(
|
|||||||
val className = (stub.defs.first { it is JCTree.JCClassDecl } as JCTree.JCClassDecl).simpleName.toString()
|
val className = (stub.defs.first { it is JCTree.JCClassDecl } as JCTree.JCClassDecl).simpleName.toString()
|
||||||
|
|
||||||
val packageName = stub.getPackageNameJava9Aware()?.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()
|
packageDir.mkdirs()
|
||||||
|
|
||||||
val sourceFile = File(packageDir, "$className.java")
|
val sourceFile = File(packageDir, "$className.java")
|
||||||
@@ -336,7 +314,7 @@ abstract class AbstractKapt3Extension(
|
|||||||
messageCollector: MessageCollector,
|
messageCollector: MessageCollector,
|
||||||
converter: ClassFileToSourceStubConverter
|
converter: ClassFileToSourceStubConverter
|
||||||
) {
|
) {
|
||||||
val incrementalDataOutputDir = paths.incrementalDataOutputDir ?: return
|
val incrementalDataOutputDir = options.incrementalDataOutputDir ?: return
|
||||||
|
|
||||||
val reportOutputFiles = kaptContext.generationState.configuration.getBoolean(CommonConfigurationKeys.REPORT_OUTPUT_FILES)
|
val reportOutputFiles = kaptContext.generationState.configuration.getBoolean(CommonConfigurationKeys.REPORT_OUTPUT_FILES)
|
||||||
kaptContext.generationState.factory.writeAll(
|
kaptContext.generationState.factory.writeAll(
|
||||||
@@ -344,7 +322,7 @@ abstract class AbstractKapt3Extension(
|
|||||||
if (!reportOutputFiles) null else fun(file: OutputFile, sources: List<File>, output: File) {
|
if (!reportOutputFiles) null else fun(file: OutputFile, sources: List<File>, output: File) {
|
||||||
val stubFileObject = converter.bindings[file.relativePath.substringBeforeLast(".class", missingDelimiterValue = "")]
|
val stubFileObject = converter.bindings[file.relativePath.substringBeforeLast(".class", missingDelimiterValue = "")]
|
||||||
if (stubFileObject != null) {
|
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)
|
val lineMappingsFile = File(stubFile.parentFile, stubFile.nameWithoutExtension + KAPT_METADATA_EXTENSION)
|
||||||
|
|
||||||
for (outputFile in listOf(stubFile, lineMappingsFile)) {
|
for (outputFile in listOf(stubFile, lineMappingsFile)) {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.kapt3
|
|||||||
import com.intellij.mock.MockProject
|
import com.intellij.mock.MockProject
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import org.jetbrains.kotlin.analyzer.AnalysisResult
|
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.CLIConfigurationKeys
|
||||||
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
|
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
|
||||||
import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector
|
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
|
||||||
import org.jetbrains.kotlin.kapt.cli.KaptCliOption.Companion.ANNOTATION_PROCESSING_COMPILER_PLUGIN_ID
|
import org.jetbrains.kotlin.kapt.cli.KaptCliOption.Companion.ANNOTATION_PROCESSING_COMPILER_PLUGIN_ID
|
||||||
import org.jetbrains.kotlin.kapt.cli.KaptCliOption.*
|
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.Kapt
|
||||||
import org.jetbrains.kotlin.kapt3.base.KaptPaths
|
import org.jetbrains.kotlin.kapt3.base.util.KaptLogger
|
||||||
import org.jetbrains.kotlin.kapt3.base.log
|
|
||||||
import org.jetbrains.kotlin.kapt3.util.MessageCollectorBackedKaptLogger
|
import org.jetbrains.kotlin.kapt3.util.MessageCollectorBackedKaptLogger
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||||
@@ -58,70 +53,7 @@ import java.io.File
|
|||||||
import java.io.ObjectInputStream
|
import java.io.ObjectInputStream
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
object Kapt3ConfigurationKeys {
|
private val KAPT_OPTIONS = CompilerConfigurationKey.create<KaptOptions.Builder>("Kapt options")
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
class Kapt3CommandLineProcessor : CommandLineProcessor {
|
class Kapt3CommandLineProcessor : CommandLineProcessor {
|
||||||
override val pluginId: String = ANNOTATION_PROCESSING_COMPILER_PLUGIN_ID
|
override val pluginId: String = ANNOTATION_PROCESSING_COMPILER_PLUGIN_ID
|
||||||
@@ -133,52 +65,61 @@ class Kapt3CommandLineProcessor : CommandLineProcessor {
|
|||||||
throw CliOptionProcessingException("Unknown option: ${option.optionName}")
|
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")
|
@Suppress("DEPRECATION")
|
||||||
return when (option) {
|
when (option) {
|
||||||
ANNOTATION_PROCESSOR_CLASSPATH_OPTION -> configuration.appendList(ANNOTATION_PROCESSOR_CLASSPATH, value)
|
SOURCE_OUTPUT_DIR_OPTION -> sourcesOutputDir = File(value)
|
||||||
ANNOTATION_PROCESSORS_OPTION -> configuration.appendList(
|
CLASS_OUTPUT_DIR_OPTION -> classesOutputDir = File(value)
|
||||||
Kapt3ConfigurationKeys.ANNOTATION_PROCESSORS, value.split(',').map { it.trim() }.filter { it.isNotEmpty() })
|
STUBS_OUTPUT_DIR_OPTION -> stubsOutputDir = File(value)
|
||||||
APT_OPTIONS_OPTION -> configuration.put(APT_OPTIONS, value)
|
INCREMENTAL_DATA_OUTPUT_DIR_OPTION -> incrementalDataOutputDir = File(value)
|
||||||
JAVAC_CLI_OPTIONS_OPTION -> configuration.put(JAVAC_CLI_OPTIONS, value)
|
|
||||||
APT_OPTION_OPTION -> configuration.appendMap(APT_OPTION, option, value)
|
ANNOTATION_PROCESSOR_CLASSPATH_OPTION -> processingClasspath += File(value)
|
||||||
JAVAC_OPTION_OPTION -> configuration.appendMap(JAVAC_OPTION, option, value)
|
ANNOTATION_PROCESSORS_OPTION -> processors.addAll(value.split(',').map { it.trim() }.filter { it.isNotEmpty() })
|
||||||
SOURCE_OUTPUT_DIR_OPTION -> configuration.put(Kapt3ConfigurationKeys.SOURCE_OUTPUT_DIR, value)
|
|
||||||
CLASS_OUTPUT_DIR_OPTION -> configuration.put(Kapt3ConfigurationKeys.CLASS_OUTPUT_DIR, value)
|
APT_OPTION_OPTION -> setKeyValue(value) { k, v -> processingOptions[k] = v }
|
||||||
STUBS_OUTPUT_DIR_OPTION -> configuration.put(Kapt3ConfigurationKeys.STUBS_OUTPUT_DIR, value)
|
JAVAC_OPTION_OPTION -> setKeyValue(value) { k, v -> javacOptions[k] = v }
|
||||||
INCREMENTAL_DATA_OUTPUT_DIR_OPTION -> configuration.put(Kapt3ConfigurationKeys.INCREMENTAL_DATA_OUTPUT_DIR, value)
|
|
||||||
VERBOSE_MODE_OPTION -> configuration.put(Kapt3ConfigurationKeys.VERBOSE_MODE, value)
|
VERBOSE_MODE_OPTION -> setFlag(KaptFlag.VERBOSE, value)
|
||||||
APT_ONLY_OPTION -> configuration.put(Kapt3ConfigurationKeys.APT_ONLY, value)
|
USE_LIGHT_ANALYSIS_OPTION -> setFlag(KaptFlag.USE_LIGHT_ANALYSIS, value)
|
||||||
APT_MODE_OPTION -> configuration.put(Kapt3ConfigurationKeys.APT_MODE, value)
|
CORRECT_ERROR_TYPES_OPTION -> setFlag(KaptFlag.CORRECT_ERROR_TYPES, value)
|
||||||
USE_LIGHT_ANALYSIS_OPTION -> configuration.put(Kapt3ConfigurationKeys.USE_LIGHT_ANALYSIS, value)
|
MAP_DIAGNOSTIC_LOCATIONS_OPTION -> setFlag(KaptFlag.MAP_DIAGNOSTIC_LOCATIONS, value)
|
||||||
CORRECT_ERROR_TYPES_OPTION -> configuration.put(Kapt3ConfigurationKeys.CORRECT_ERROR_TYPES, value)
|
INFO_AS_WARNINGS_OPTION -> setFlag(KaptFlag.INFO_AS_WARNINGS, value)
|
||||||
MAP_DIAGNOSTIC_LOCATIONS_OPTION -> configuration.put(Kapt3ConfigurationKeys.MAP_DIAGNOSTIC_LOCATIONS, value)
|
STRICT_MODE_OPTION -> setFlag(KaptFlag.STRICT, 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 -> setSelector(enumValues<DetectMemoryLeaksMode>(), value) { detectMemoryLeaks = it }
|
||||||
DETECT_MEMORY_LEAKS_OPTION -> configuration.put(Kapt3ConfigurationKeys.DETECT_MEMORY_LEAKS, value)
|
APT_MODE_OPTION -> setSelector(enumValues<AptMode>(), value) { mode = it }
|
||||||
CONFIGURATION -> configuration.applyOptionsFrom(decodePluginOptions(value), pluginOptions)
|
|
||||||
|
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")
|
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> {
|
private fun decodeMap(options: String): Map<String, String> {
|
||||||
if (options.isEmpty()) {
|
if (options.isEmpty()) {
|
||||||
return emptyMap()
|
return emptyMap()
|
||||||
@@ -200,115 +141,90 @@ class Kapt3ComponentRegistrar : ComponentRegistrar {
|
|||||||
|
|
||||||
return map
|
return map
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Kapt3ComponentRegistrar : ComponentRegistrar {
|
||||||
override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) {
|
override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) {
|
||||||
@Suppress("DEPRECATION")
|
val contentRoots = configuration[CLIConfigurationKeys.CONTENT_ROOTS] ?: emptyList()
|
||||||
val aptMode = AptMode.parse(configuration.get(Kapt3ConfigurationKeys.APT_MODE) ?: configuration.get(Kapt3ConfigurationKeys.APT_ONLY))
|
|
||||||
|
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)
|
val messageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
|
||||||
?: PrintingMessageCollector(System.err, MessageRenderer.PLAIN_FULL_PATHS, isVerbose)
|
?: PrintingMessageCollector(System.err, MessageRenderer.PLAIN_FULL_PATHS, optionsBuilder.flags.contains(KaptFlag.VERBOSE))
|
||||||
val logger = MessageCollectorBackedKaptLogger(isVerbose, infoAsWarnings, messageCollector)
|
|
||||||
|
|
||||||
|
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())
|
fun abortAnalysis() = AnalysisHandlerExtension.registerExtension(project, AbortAnalysisHandlerExtension())
|
||||||
|
|
||||||
if (!Kapt.checkJavacComponentsAccess(logger)) {
|
if (classesOutputDir == null) {
|
||||||
abortAnalysis()
|
if (configuration.get(JVMConfigurationKeys.OUTPUT_JAR) != null) {
|
||||||
return
|
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)
|
if (processingClasspath.isEmpty()) {
|
||||||
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()) {
|
|
||||||
// Skip annotation processing if no annotation processors were provided
|
// Skip annotation processing if no annotation processors were provided
|
||||||
if (aptMode != AptMode.WITH_COMPILATION) {
|
if (mode != AptMode.WITH_COMPILATION) {
|
||||||
abortAnalysis()
|
abortAnalysis()
|
||||||
}
|
}
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sourcesOutputDir == null || classFilesOutputDir == null || stubsOutputDir == null) {
|
if (sourcesOutputDir == null || classesOutputDir == null || stubsOutputDir == null) {
|
||||||
if (aptMode != AptMode.WITH_COMPILATION) {
|
if (mode != AptMode.WITH_COMPILATION) {
|
||||||
val nonExistentOptionName = when {
|
val nonExistentOptionName = when {
|
||||||
sourcesOutputDir == null -> "Sources output directory"
|
sourcesOutputDir == null -> "Sources output directory"
|
||||||
classFilesOutputDir == null -> "Classes output directory"
|
classesOutputDir == null -> "Classes output directory"
|
||||||
stubsOutputDir == null -> "Stubs output directory"
|
stubsOutputDir == null -> "Stubs output directory"
|
||||||
else -> throw IllegalStateException()
|
else -> throw IllegalStateException()
|
||||||
}
|
}
|
||||||
val moduleName = configuration.get(CommonConfigurationKeys.MODULE_NAME)
|
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")
|
logger.warn("$nonExistentOptionName is not specified for $moduleName, skipping annotation processing")
|
||||||
abortAnalysis()
|
abortAnalysis()
|
||||||
}
|
}
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
if (!Kapt.checkJavacComponentsAccess(logger)) {
|
||||||
val apOptions = decodeMap(configuration.get(APT_OPTIONS).orEmpty()).toMutableMap()
|
abortAnalysis()
|
||||||
configuration.get(APT_OPTION)?.let { apOptions += it }
|
return false
|
||||||
|
|
||||||
@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")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val kapt3AnalysisCompletedHandlerExtension = ClasspathBasedKapt3Extension(
|
return true
|
||||||
paths, apOptions, javacOptions, annotationProcessors,
|
|
||||||
aptMode, useLightAnalysis, correctErrorTypes, mapDiagnosticLocations, strictMode, detectMemoryLeaks,
|
|
||||||
System.currentTimeMillis(), logger, configuration
|
|
||||||
)
|
|
||||||
|
|
||||||
AnalysisHandlerExtension.registerExtension(project, kapt3AnalysisCompletedHandlerExtension)
|
|
||||||
StorageComponentContainerContributor.registerExtension(project, KaptComponentContributor())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class KaptComponentContributor : StorageComponentContainerContributor {
|
class KaptComponentContributor : StorageComponentContainerContributor {
|
||||||
@@ -327,47 +243,23 @@ class Kapt3ComponentRegistrar : ComponentRegistrar {
|
|||||||
* */
|
* */
|
||||||
private class AbortAnalysisHandlerExtension : AnalysisHandlerExtension {
|
private class AbortAnalysisHandlerExtension : AnalysisHandlerExtension {
|
||||||
override fun doAnalysis(
|
override fun doAnalysis(
|
||||||
project: Project,
|
project: Project,
|
||||||
module: ModuleDescriptor,
|
module: ModuleDescriptor,
|
||||||
projectContext: ProjectContext,
|
projectContext: ProjectContext,
|
||||||
files: Collection<KtFile>,
|
files: Collection<KtFile>,
|
||||||
bindingTrace: BindingTrace,
|
bindingTrace: BindingTrace,
|
||||||
componentProvider: ComponentProvider
|
componentProvider: ComponentProvider
|
||||||
): AnalysisResult? {
|
): AnalysisResult? {
|
||||||
return AnalysisResult.success(bindingTrace.bindingContext, module, shouldGenerateCode = false)
|
return AnalysisResult.success(bindingTrace.bindingContext, module, shouldGenerateCode = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun analysisCompleted(
|
override fun analysisCompleted(
|
||||||
project: Project,
|
project: Project,
|
||||||
module: ModuleDescriptor,
|
module: ModuleDescriptor,
|
||||||
bindingTrace: BindingTrace,
|
bindingTrace: BindingTrace,
|
||||||
files: Collection<KtFile>
|
files: Collection<KtFile>
|
||||||
): AnalysisResult? {
|
): AnalysisResult? {
|
||||||
return AnalysisResult.success(bindingTrace.bindingContext, module, shouldGenerateCode = false)
|
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.intellij.openapi.project.Project
|
||||||
import com.sun.tools.javac.tree.TreeMaker
|
import com.sun.tools.javac.tree.TreeMaker
|
||||||
import com.sun.tools.javac.util.Context
|
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.codegen.state.GenerationState
|
||||||
import org.jetbrains.kotlin.kapt3.base.KaptContext
|
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.base.util.KaptLogger
|
||||||
import org.jetbrains.kotlin.kapt3.javac.KaptTreeMaker
|
import org.jetbrains.kotlin.kapt3.javac.KaptTreeMaker
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
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
|
import org.jetbrains.org.objectweb.asm.tree.ClassNode
|
||||||
|
|
||||||
class KaptContextForStubGeneration(
|
class KaptContextForStubGeneration(
|
||||||
paths: KaptPaths,
|
options: KaptOptions,
|
||||||
withJdk: Boolean,
|
withJdk: Boolean,
|
||||||
logger: KaptLogger,
|
logger: KaptLogger,
|
||||||
val project: Project,
|
val project: Project,
|
||||||
val bindingContext: BindingContext,
|
val bindingContext: BindingContext,
|
||||||
val compiledClasses: List<ClassNode>,
|
val compiledClasses: List<ClassNode>,
|
||||||
val origins: Map<Any, JvmDeclarationOrigin>,
|
val origins: Map<Any, JvmDeclarationOrigin>,
|
||||||
val generationState: GenerationState,
|
val generationState: GenerationState
|
||||||
mapDiagnosticLocations: Boolean,
|
) : KaptContext(options, withJdk, logger) {
|
||||||
processorOptions: Map<String, String>,
|
|
||||||
javacOptions: Map<String, String> = emptyMap()
|
|
||||||
) : KaptContext(paths, withJdk, logger, mapDiagnosticLocations, processorOptions, javacOptions) {
|
|
||||||
private val treeMaker = TreeMaker.instance(context)
|
private val treeMaker = TreeMaker.instance(context)
|
||||||
|
|
||||||
override fun preregisterTreeMaker(context: 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.TreeMaker
|
||||||
import com.sun.tools.javac.tree.TreeScanner
|
import com.sun.tools.javac.tree.TreeScanner
|
||||||
import kotlinx.kapt.KaptIgnored
|
import kotlinx.kapt.KaptIgnored
|
||||||
|
import org.jetbrains.kotlin.base.kapt3.KaptFlag
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
@@ -63,12 +64,7 @@ import java.io.File
|
|||||||
import javax.lang.model.element.ElementKind
|
import javax.lang.model.element.ElementKind
|
||||||
import com.sun.tools.javac.util.List as JavacList
|
import com.sun.tools.javac.util.List as JavacList
|
||||||
|
|
||||||
class ClassFileToSourceStubConverter(
|
class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGeneration, val generateNonExistentClass: Boolean) {
|
||||||
val kaptContext: KaptContextForStubGeneration,
|
|
||||||
val generateNonExistentClass: Boolean,
|
|
||||||
val correctErrorTypes: Boolean,
|
|
||||||
val strictMode: Boolean
|
|
||||||
) {
|
|
||||||
private companion object {
|
private companion object {
|
||||||
private const val VISIBILITY_MODIFIERS = (Opcodes.ACC_PUBLIC or Opcodes.ACC_PRIVATE or Opcodes.ACC_PROTECTED).toLong()
|
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()
|
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()
|
private val JAVA_KEYWORD_FILTER_REGEX = "[a-z]+".toRegex()
|
||||||
|
|
||||||
|
@Suppress("UselessCallOnNotNull") // nullable toString(), KT-27724
|
||||||
private val JAVA_KEYWORDS = Tokens.TokenKind.values()
|
private val JAVA_KEYWORDS = Tokens.TokenKind.values()
|
||||||
.filter { JAVA_KEYWORD_FILTER_REGEX.matches(it.toString().orEmpty()) }
|
.filter { JAVA_KEYWORD_FILTER_REGEX.matches(it.toString().orEmpty()) }
|
||||||
.mapTo(hashSetOf(), Any::toString)
|
.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>
|
val bindings: Map<String, KaptJavaFileObject>
|
||||||
get() = _bindings
|
get() = mutableBindings
|
||||||
|
|
||||||
private val typeMapper
|
private val typeMapper
|
||||||
get() = kaptContext.generationState.typeMapper
|
get() = kaptContext.generationState.typeMapper
|
||||||
@@ -193,7 +193,7 @@ class ClassFileToSourceStubConverter(
|
|||||||
|
|
||||||
KaptJavaFileObject(topLevel, classDeclaration).apply {
|
KaptJavaFileObject(topLevel, classDeclaration).apply {
|
||||||
topLevel.sourcefile = this
|
topLevel.sourcefile = this
|
||||||
_bindings[clazz.name] = this
|
mutableBindings[clazz.name] = this
|
||||||
}
|
}
|
||||||
|
|
||||||
postProcess(topLevel)
|
postProcess(topLevel)
|
||||||
|
|||||||
+10
-4
@@ -5,10 +5,12 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.kapt3.util
|
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.CompilerMessageSeverity.*
|
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
|
||||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
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.cli.common.messages.PrintingMessageCollector
|
||||||
import org.jetbrains.kotlin.kapt3.base.util.KaptLogger
|
import org.jetbrains.kotlin.kapt3.base.util.KaptLogger
|
||||||
import java.io.PrintWriter
|
import java.io.PrintWriter
|
||||||
@@ -16,16 +18,20 @@ import java.io.StringWriter
|
|||||||
|
|
||||||
class MessageCollectorBackedKaptLogger(
|
class MessageCollectorBackedKaptLogger(
|
||||||
override val isVerbose: Boolean,
|
override val isVerbose: Boolean,
|
||||||
infoAsWarnings: Boolean = true,
|
isInfoAsWarnings: Boolean,
|
||||||
val messageCollector: MessageCollector = PrintingMessageCollector(System.err, MessageRenderer.PLAIN_FULL_PATHS, isVerbose)
|
val messageCollector: MessageCollector = defaultMessageCollector(isVerbose)
|
||||||
) : KaptLogger {
|
) : KaptLogger {
|
||||||
|
constructor(flags: KaptFlags, messageCollector: MessageCollector = defaultMessageCollector(flags[KaptFlag.VERBOSE]))
|
||||||
|
: this(flags[KaptFlag.VERBOSE], flags[KaptFlag.INFO_AS_WARNINGS], messageCollector)
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
const val PREFIX = "[kapt] "
|
const val PREFIX = "[kapt] "
|
||||||
|
fun defaultMessageCollector(isVerbose: Boolean) = PrintingMessageCollector(System.err, PLAIN_FULL_PATHS, isVerbose)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val errorWriter = makeWriter(ERROR)
|
override val errorWriter = makeWriter(ERROR)
|
||||||
override val warnWriter = makeWriter(STRONG_WARNING)
|
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) {
|
override fun info(message: String) {
|
||||||
if (isVerbose) {
|
if (isVerbose) {
|
||||||
|
|||||||
+24
-34
@@ -16,8 +16,9 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.kapt3.test
|
package org.jetbrains.kotlin.kapt3.test
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import com.intellij.openapi.util.text.StringUtil
|
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.cli.common.messages.MessageCollector
|
||||||
import org.jetbrains.kotlin.codegen.ClassBuilderMode
|
import org.jetbrains.kotlin.codegen.ClassBuilderMode
|
||||||
import org.jetbrains.kotlin.codegen.CodegenTestCase
|
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.codegen.OriginCollectingClassBuilderFactory
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
import org.jetbrains.kotlin.kapt3.*
|
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.KaptContext
|
||||||
import org.jetbrains.kotlin.kapt3.base.KaptPaths
|
|
||||||
import org.jetbrains.kotlin.kapt3.base.LoadedProcessors
|
import org.jetbrains.kotlin.kapt3.base.LoadedProcessors
|
||||||
import org.jetbrains.kotlin.kapt3.javac.KaptJavaFileObject
|
import org.jetbrains.kotlin.kapt3.javac.KaptJavaFileObject
|
||||||
import org.jetbrains.kotlin.kapt3.stubs.ClassFileToSourceStubConverter
|
import org.jetbrains.kotlin.kapt3.stubs.ClassFileToSourceStubConverter
|
||||||
@@ -59,12 +58,11 @@ abstract class AbstractKotlinKapt3IntegrationTest : CodegenTestCase() {
|
|||||||
private var _processors: List<Processor>? = null
|
private var _processors: List<Processor>? = null
|
||||||
private val processors get() = _processors!!
|
private val processors get() = _processors!!
|
||||||
|
|
||||||
private var _options: Map<String, String>? = null
|
private var mutableOptions: Map<String, String>? = null
|
||||||
private val options get() = _options!!
|
|
||||||
|
|
||||||
override fun tearDown() {
|
override fun tearDown() {
|
||||||
_processors = null
|
_processors = null
|
||||||
_options = null
|
mutableOptions = null
|
||||||
super.tearDown()
|
super.tearDown()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +80,7 @@ abstract class AbstractKotlinKapt3IntegrationTest : CodegenTestCase() {
|
|||||||
process: (Set<TypeElement>, RoundEnvironment, ProcessingEnvironment) -> Unit,
|
process: (Set<TypeElement>, RoundEnvironment, ProcessingEnvironment) -> Unit,
|
||||||
vararg supportedAnnotations: String
|
vararg supportedAnnotations: String
|
||||||
) {
|
) {
|
||||||
this._options = options
|
this.mutableOptions = options
|
||||||
|
|
||||||
val ktFileName = File(TEST_DATA_DIR, "$name.kt")
|
val ktFileName = File(TEST_DATA_DIR, "$name.kt")
|
||||||
var started = false
|
var started = false
|
||||||
@@ -128,18 +126,25 @@ abstract class AbstractKotlinKapt3IntegrationTest : CodegenTestCase() {
|
|||||||
val javaSources = javaFilesDir?.let { arrayOf(it) } ?: emptyArray()
|
val javaSources = javaFilesDir?.let { arrayOf(it) } ?: emptyArray()
|
||||||
|
|
||||||
val txtFile = File(wholeFile.parentFile, wholeFile.nameWithoutExtension + ".it.txt")
|
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)
|
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.ALL, *javaSources)
|
||||||
|
|
||||||
val project = myEnvironment.project
|
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)
|
AnalysisHandlerExtension.registerExtension(project, kapt3Extension)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -155,28 +160,13 @@ abstract class AbstractKotlinKapt3IntegrationTest : CodegenTestCase() {
|
|||||||
|
|
||||||
KotlinTestUtils.assertEqualsToFile(txtFile, actual)
|
KotlinTestUtils.assertEqualsToFile(txtFile, actual)
|
||||||
} finally {
|
} finally {
|
||||||
sourceOutputDir.deleteRecursively()
|
options.sourcesOutputDir.deleteRecursively()
|
||||||
incrementalDataDir.deleteRecursively()
|
options.incrementalDataOutputDir?.deleteRecursively()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected class Kapt3ExtensionForTests(
|
protected class Kapt3ExtensionForTests(options: KaptOptions, private val processors: List<Processor>) : AbstractKapt3Extension(
|
||||||
project: Project,
|
options, MessageCollectorBackedKaptLogger(options), compilerConfiguration = CompilerConfiguration.EMPTY
|
||||||
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
|
|
||||||
) {
|
) {
|
||||||
internal var savedStubs: String? = null
|
internal var savedStubs: String? = null
|
||||||
internal var savedBindings: Map<String, KaptJavaFileObject>? = 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.JCDiagnostic
|
||||||
import com.sun.tools.javac.util.Log
|
import com.sun.tools.javac.util.Log
|
||||||
import junit.framework.ComparisonFailure
|
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.checkers.CheckerTestUtil
|
||||||
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
|
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
|
||||||
import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector
|
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.*
|
||||||
import org.jetbrains.kotlin.kapt3.Kapt3ComponentRegistrar.KaptComponentContributor
|
import org.jetbrains.kotlin.kapt3.Kapt3ComponentRegistrar.KaptComponentContributor
|
||||||
import org.jetbrains.kotlin.kapt3.base.KaptContext
|
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.doAnnotationProcessing
|
||||||
import org.jetbrains.kotlin.kapt3.base.javac.KaptJavaLog
|
import org.jetbrains.kotlin.kapt3.base.javac.KaptJavaLog
|
||||||
import org.jetbrains.kotlin.kapt3.base.parseJavaFiles
|
import org.jetbrains.kotlin.kapt3.base.parseJavaFiles
|
||||||
@@ -57,7 +59,6 @@ import java.nio.file.Files
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
import com.sun.tools.javac.util.List as JavacList
|
import com.sun.tools.javac.util.List as JavacList
|
||||||
|
|
||||||
|
|
||||||
abstract class AbstractKotlinKapt3Test : CodegenTestCase() {
|
abstract class AbstractKotlinKapt3Test : CodegenTestCase() {
|
||||||
companion object {
|
companion object {
|
||||||
const val FILE_SEPARATOR = "\n\n////////////////////\n\n"
|
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 messageCollector = PrintingMessageCollector(ERR_PRINT_STREAM, MessageRenderer.PLAIN_FULL_PATHS, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val kaptFlags = mutableListOf<KaptFlag>()
|
||||||
private val tempFiles = mutableListOf<File>()
|
private val tempFiles = mutableListOf<File>()
|
||||||
|
|
||||||
|
override fun setUp() {
|
||||||
|
super.setUp()
|
||||||
|
kaptFlags.clear()
|
||||||
|
}
|
||||||
|
|
||||||
override fun tearDown() {
|
override fun tearDown() {
|
||||||
ERR_BYTE_STREAM.reset()
|
ERR_BYTE_STREAM.reset()
|
||||||
super.tearDown()
|
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>) {
|
override fun loadMultiFiles(files: List<TestFile>) {
|
||||||
val project = myEnvironment.project
|
val project = myEnvironment.project
|
||||||
val psiManager = PsiManager.getInstance(project)
|
val psiManager = PsiManager.getInstance(project)
|
||||||
|
|
||||||
val tmpDir = Files.createTempDirectory("kaptTest").toFile()
|
val tmpDir = createTempDir("kaptTest")
|
||||||
tempFiles += tmpDir
|
|
||||||
|
|
||||||
val ktFiles = ArrayList<KtFile>(files.size)
|
val ktFiles = ArrayList<KtFile>(files.size)
|
||||||
for (file in files.sorted()) {
|
for (file in files.sorted()) {
|
||||||
@@ -118,7 +128,7 @@ abstract class AbstractKotlinKapt3Test : CodegenTestCase() {
|
|||||||
val classBuilderFactory = OriginCollectingClassBuilderFactory(ClassBuilderMode.KAPT3)
|
val classBuilderFactory = OriginCollectingClassBuilderFactory(ClassBuilderMode.KAPT3)
|
||||||
val generationState = GenerationUtils.compileFiles(myFiles.psiFiles, myEnvironment, classBuilderFactory)
|
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")
|
val javacOptions = wholeFile.getOptionValues("JAVAC_OPTION")
|
||||||
.map { opt ->
|
.map { opt ->
|
||||||
@@ -130,21 +140,25 @@ abstract class AbstractKotlinKapt3Test : CodegenTestCase() {
|
|||||||
var kaptContext: KaptContext? = null
|
var kaptContext: KaptContext? = null
|
||||||
|
|
||||||
try {
|
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(
|
sourcesOutputDir = createTempDir("kaptRunner")
|
||||||
generationState.project.basePath?.let(::File),
|
classesOutputDir = sourcesOutputDir
|
||||||
compileClasspath = PathUtil.getJdkClassesRootsFromCurrentJre() + PathUtil.kotlinPathsForIdeaPlugin.stdlibPath,
|
stubsOutputDir = sourcesOutputDir
|
||||||
annotationProcessingClasspath = emptyList(), javaSourceRoots = emptyList(),
|
incrementalDataOutputDir = sourcesOutputDir
|
||||||
sourcesOutputDir = sourceOutputDir, classFilesOutputDir = sourceOutputDir,
|
|
||||||
stubsOutputDir = sourceOutputDir, incrementalDataOutputDir = sourceOutputDir
|
this.javacOptions.putAll(javacOptions)
|
||||||
)
|
flags.addAll(kaptFlags)
|
||||||
|
|
||||||
|
detectMemoryLeaks = DetectMemoryLeaksMode.NONE
|
||||||
|
}.build()
|
||||||
|
|
||||||
kaptContext = KaptContextForStubGeneration(
|
kaptContext = KaptContextForStubGeneration(
|
||||||
paths, true,
|
options, true, logger,
|
||||||
logger, generationState.project, generationState.bindingContext, classBuilderFactory.compiledClasses,
|
generationState.project, generationState.bindingContext, classBuilderFactory.compiledClasses,
|
||||||
classBuilderFactory.origins, generationState, mapDiagnosticLocations = true,
|
classBuilderFactory.origins, generationState
|
||||||
processorOptions = emptyMap(), javacOptions = javacOptions
|
|
||||||
)
|
)
|
||||||
|
|
||||||
javaFiles = files
|
javaFiles = files
|
||||||
@@ -165,11 +179,9 @@ abstract class AbstractKotlinKapt3Test : CodegenTestCase() {
|
|||||||
protected fun convert(
|
protected fun convert(
|
||||||
kaptContext: KaptContextForStubGeneration,
|
kaptContext: KaptContextForStubGeneration,
|
||||||
javaFiles: List<File>,
|
javaFiles: List<File>,
|
||||||
generateNonExistentClass: Boolean,
|
generateNonExistentClass: Boolean
|
||||||
correctErrorTypes: Boolean,
|
|
||||||
strictMode: Boolean
|
|
||||||
): JavacList<JCCompilationUnit> {
|
): JavacList<JCCompilationUnit> {
|
||||||
val converter = ClassFileToSourceStubConverter(kaptContext, generateNonExistentClass, correctErrorTypes, strictMode)
|
val converter = ClassFileToSourceStubConverter(kaptContext, generateNonExistentClass)
|
||||||
|
|
||||||
val kaptStubs = converter.convert()
|
val kaptStubs = converter.convert()
|
||||||
val convertedFiles = kaptStubs.map { stub ->
|
val convertedFiles = kaptStubs.map { stub ->
|
||||||
@@ -245,18 +257,28 @@ open class AbstractClassFileToSourceStubConverterTest : AbstractKotlinKapt3Test(
|
|||||||
fun testSuppressWarning() {}
|
fun testSuppressWarning() {}
|
||||||
|
|
||||||
override fun doTest(filePath: String) {
|
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)
|
super.doTest(filePath)
|
||||||
doTestWithJdk9(AbstractClassFileToSourceStubConverterTest::class.java, filePath)
|
doTestWithJdk9(AbstractClassFileToSourceStubConverterTest::class.java, filePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun check(kaptContext: KaptContextForStubGeneration, javaFiles: List<File>, txtFile: File, wholeFile: File) {
|
override fun check(kaptContext: KaptContextForStubGeneration, javaFiles: List<File>, txtFile: File, wholeFile: File) {
|
||||||
val generateNonExistentClass = wholeFile.isOptionSet("NON_EXISTENT_CLASS")
|
val generateNonExistentClass = wholeFile.isOptionSet("NON_EXISTENT_CLASS")
|
||||||
val correctErrorTypes = wholeFile.isOptionSet("CORRECT_ERROR_TYPES")
|
|
||||||
val validate = !wholeFile.isOptionSet("NO_VALIDATION")
|
val validate = !wholeFile.isOptionSet("NO_VALIDATION")
|
||||||
val strictMode = wholeFile.isOptionSet("STRICT_MODE")
|
|
||||||
val expectedErrors = wholeFile.getRawOptionValues(EXPECTED_ERROR).sorted()
|
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()
|
kaptContext.javaLog.interceptorData.files = convertedFiles.map { it.sourceFile to it }.toMap()
|
||||||
if (validate) kaptContext.compiler.enterTrees(convertedFiles)
|
if (validate) kaptContext.compiler.enterTrees(convertedFiles)
|
||||||
@@ -309,19 +331,22 @@ open class AbstractClassFileToSourceStubConverterTest : AbstractKotlinKapt3Test(
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract class AbstractKotlinKaptContextTest : AbstractKotlinKapt3Test() {
|
abstract class AbstractKotlinKaptContextTest : AbstractKotlinKapt3Test() {
|
||||||
override fun check(kaptContext: KaptContextForStubGeneration, javaFiles: List<File>, txtFile: File, wholeFile: File) {
|
override fun doTest(filePath: String?) {
|
||||||
val compilationUnits = convert(
|
kaptFlags.add(KaptFlag.CORRECT_ERROR_TYPES)
|
||||||
kaptContext, javaFiles,
|
kaptFlags.add(KaptFlag.STRICT)
|
||||||
generateNonExistentClass = false, correctErrorTypes = true, strictMode = false
|
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(
|
kaptContext.doAnnotationProcessing(
|
||||||
emptyList(),
|
emptyList(),
|
||||||
listOf(JavaKaptContextTest.simpleProcessor()),
|
listOf(JavaKaptContextTest.simpleProcessor()),
|
||||||
additionalSources = compilationUnits
|
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 actualRaw = stubJavaFiles.sortedBy { it.name }.joinToString(FILE_SEPARATOR) { it.name + ":\n\n" + it.readText() }
|
||||||
val actual = StringUtil.convertLineSeparators(actualRaw.trim({ it <= ' ' })).trimTrailingWhitespacesAndAddNewlineAtEOF()
|
val actual = StringUtil.convertLineSeparators(actualRaw.trim({ it <= ' ' })).trimTrailingWhitespacesAndAddNewlineAtEOF()
|
||||||
KotlinTestUtils.assertEqualsToFile(txtFile, actual)
|
KotlinTestUtils.assertEqualsToFile(txtFile, actual)
|
||||||
|
|||||||
+2
-2
@@ -96,8 +96,8 @@ class KotlinKapt3IntegrationTests : AbstractKotlinKapt3IntegrationTest(), Java9T
|
|||||||
test(name, "test.MyAnnotation") { _, _, _ ->
|
test(name, "test.MyAnnotation") { _, _, _ ->
|
||||||
val kaptExtension = AnalysisHandlerExtension.getInstances(myEnvironment.project).firstIsInstance<Kapt3ExtensionForTests>()
|
val kaptExtension = AnalysisHandlerExtension.getInstances(myEnvironment.project).firstIsInstance<Kapt3ExtensionForTests>()
|
||||||
|
|
||||||
val stubsOutputDir = kaptExtension.paths.stubsOutputDir
|
val stubsOutputDir = kaptExtension.options.stubsOutputDir
|
||||||
val incrementalDataOutputDir = kaptExtension.paths.incrementalDataOutputDir
|
val incrementalDataOutputDir = kaptExtension.options.incrementalDataOutputDir
|
||||||
|
|
||||||
val bindings = kaptExtension.savedBindings!!
|
val bindings = kaptExtension.savedBindings!!
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user