Minor: Fix inspection warnings in 'kotlin-annotation-processing'

This commit is contained in:
Yan Zhulanow
2018-10-19 20:17:27 +03:00
parent 17c02a77c7
commit f19c0c3fb9
17 changed files with 454 additions and 404 deletions
+2
View File
@@ -8,6 +8,8 @@
<w>parceler</w>
<w>repl</w>
<w>uast</w>
<w>unboxed</w>
<w>unmute</w>
</words>
</dictionary>
</component>
@@ -64,18 +64,18 @@ import javax.annotation.processing.Processor
import com.sun.tools.javac.util.List as JavacList
class ClasspathBasedKapt3Extension(
paths: KaptPaths,
options: Map<String, String>,
javacOptions: Map<String, String>,
annotationProcessorFqNames: List<String>,
aptMode: AptMode,
val useLightAnalysis: Boolean,
correctErrorTypes: Boolean,
mapDiagnosticLocations: Boolean,
strictMode: Boolean,
pluginInitializedTime: Long,
logger: MessageCollectorBackedKaptLogger,
compilerConfiguration: CompilerConfiguration
paths: KaptPaths,
options: Map<String, String>,
javacOptions: Map<String, String>,
annotationProcessorFqNames: List<String>,
aptMode: AptMode,
private val useLightAnalysis: Boolean,
correctErrorTypes: Boolean,
mapDiagnosticLocations: Boolean,
strictMode: Boolean,
pluginInitializedTime: Long,
logger: MessageCollectorBackedKaptLogger,
compilerConfiguration: CompilerConfiguration
) : AbstractKapt3Extension(
paths, options, javacOptions, annotationProcessorFqNames,
aptMode, pluginInitializedTime, logger, correctErrorTypes, mapDiagnosticLocations, strictMode,
@@ -91,10 +91,10 @@ class ClasspathBasedKapt3Extension(
}
override fun analysisCompleted(
project: Project,
module: ModuleDescriptor,
bindingTrace: BindingTrace,
files: Collection<KtFile>
project: Project,
module: ModuleDescriptor,
bindingTrace: BindingTrace,
files: Collection<KtFile>
): AnalysisResult? {
try {
return super.analysisCompleted(project, module, bindingTrace, files)
@@ -105,17 +105,17 @@ class ClasspathBasedKapt3Extension(
}
abstract class AbstractKapt3Extension(
val paths: KaptPaths,
val options: Map<String, String>,
val javacOptions: Map<String, String>,
val annotationProcessorFqNames: List<String>,
val aptMode: AptMode,
val pluginInitializedTime: Long,
val logger: MessageCollectorBackedKaptLogger,
val correctErrorTypes: Boolean,
val mapDiagnosticLocations: Boolean,
val strictMode: Boolean,
val compilerConfiguration: CompilerConfiguration
val paths: KaptPaths,
private val options: Map<String, String>,
private val javacOptions: Map<String, String>,
val annotationProcessorFqNames: List<String>,
private val aptMode: AptMode,
private val pluginInitializedTime: Long,
val logger: MessageCollectorBackedKaptLogger,
val correctErrorTypes: Boolean,
val mapDiagnosticLocations: Boolean,
val strictMode: Boolean,
val compilerConfiguration: CompilerConfiguration
) : PartialAnalysisHandlerExtension() {
private var annotationProcessingComplete = false
@@ -127,12 +127,12 @@ abstract class AbstractKapt3Extension(
}
override fun doAnalysis(
project: Project,
module: ModuleDescriptor,
projectContext: ProjectContext,
files: Collection<KtFile>,
bindingTrace: BindingTrace,
componentProvider: ComponentProvider
project: Project,
module: ModuleDescriptor,
projectContext: ProjectContext,
files: Collection<KtFile>,
bindingTrace: BindingTrace,
componentProvider: ComponentProvider
): AnalysisResult? {
if (aptMode == APT_ONLY) {
return AnalysisResult.EMPTY
@@ -142,14 +142,14 @@ abstract class AbstractKapt3Extension(
}
override fun analysisCompleted(
project: Project,
module: ModuleDescriptor,
bindingTrace: BindingTrace,
files: Collection<KtFile>
project: Project,
module: ModuleDescriptor,
bindingTrace: BindingTrace,
files: Collection<KtFile>
): AnalysisResult? {
if (setAnnotationProcessingComplete()) return null
fun doNotGenerateCode() = AnalysisResult.Companion.success(BindingContext.EMPTY, module, shouldGenerateCode = false)
fun doNotGenerateCode() = AnalysisResult.success(BindingContext.EMPTY, module, shouldGenerateCode = false)
logger.info { "Initial analysis took ${System.currentTimeMillis() - pluginInitializedTime} ms" }
@@ -201,10 +201,11 @@ abstract class AbstractKapt3Extension(
doNotGenerateCode()
} else {
AnalysisResult.RetryWithAdditionalJavaRoots(
bindingTrace.bindingContext,
module,
listOf(paths.sourcesOutputDir),
addToEnvironment = true)
bindingTrace.bindingContext,
module,
listOf(paths.sourcesOutputDir),
addToEnvironment = true
)
}
}
@@ -222,24 +223,25 @@ abstract class AbstractKapt3Extension(
}
private fun contextForStubGeneration(
project: Project,
module: ModuleDescriptor,
bindingContext: BindingContext,
files: List<KtFile>
project: Project,
module: ModuleDescriptor,
bindingContext: BindingContext,
files: List<KtFile>
): KaptContextForStubGeneration {
val builderFactory = OriginCollectingClassBuilderFactory(ClassBuilderMode.KAPT3)
val targetId = TargetId(
name = compilerConfiguration[CommonConfigurationKeys.MODULE_NAME] ?: module.name.asString(),
type = "java-production")
name = compilerConfiguration[CommonConfigurationKeys.MODULE_NAME] ?: module.name.asString(),
type = "java-production"
)
val generationState = GenerationState.Builder(
project,
builderFactory,
module,
bindingContext,
files,
compilerConfiguration
project,
builderFactory,
module,
bindingContext,
files,
compilerConfiguration
).targetId(targetId).build()
val (classFilesCompilationTime) = measureTimeMillis {
@@ -294,29 +296,30 @@ abstract class AbstractKapt3Extension(
}
protected open fun saveIncrementalData(
kaptContext: KaptContextForStubGeneration,
messageCollector: MessageCollector,
converter: ClassFileToSourceStubConverter) {
kaptContext: KaptContextForStubGeneration,
messageCollector: MessageCollector,
converter: ClassFileToSourceStubConverter
) {
val incrementalDataOutputDir = paths.incrementalDataOutputDir ?: return
val reportOutputFiles = kaptContext.generationState.configuration.getBoolean(CommonConfigurationKeys.REPORT_OUTPUT_FILES)
kaptContext.generationState.factory.writeAll(
incrementalDataOutputDir,
if (!reportOutputFiles) null else fun(file: OutputFile, sources: List<File>, output: File) {
val stubFileObject = converter.bindings[file.relativePath.substringBeforeLast(".class", missingDelimiterValue = "")]
if (stubFileObject != null) {
val stubFile = File(paths.stubsOutputDir, stubFileObject.name)
val lineMappingsFile = File(stubFile.parentFile, stubFile.nameWithoutExtension + KAPT_METADATA_EXTENSION)
incrementalDataOutputDir,
if (!reportOutputFiles) null else fun(file: OutputFile, sources: List<File>, output: File) {
val stubFileObject = converter.bindings[file.relativePath.substringBeforeLast(".class", missingDelimiterValue = "")]
if (stubFileObject != null) {
val stubFile = File(paths.stubsOutputDir, stubFileObject.name)
val lineMappingsFile = File(stubFile.parentFile, stubFile.nameWithoutExtension + KAPT_METADATA_EXTENSION)
for (file in listOf(stubFile, lineMappingsFile)) {
if (file.exists()) {
messageCollector.report(OUTPUT, OutputMessageUtil.formatOutputMessage(sources, file))
}
for (outputFile in listOf(stubFile, lineMappingsFile)) {
if (outputFile.exists()) {
messageCollector.report(OUTPUT, OutputMessageUtil.formatOutputMessage(sources, outputFile))
}
}
messageCollector.report(OUTPUT, OutputMessageUtil.formatOutputMessage(sources, output))
}
messageCollector.report(OUTPUT, OutputMessageUtil.formatOutputMessage(sources, output))
}
)
}
@@ -346,7 +349,7 @@ private class PrettyWithWorkarounds(private val context: Context, val out: Write
}
}
private inline fun <T> measureTimeMillis(block: () -> T) : Pair<Long, T> {
private inline fun <T> measureTimeMillis(block: () -> T): Pair<Long, T> {
val start = System.currentTimeMillis()
val result = block()
return Pair(System.currentTimeMillis() - start, result)
@@ -74,47 +74,47 @@ import java.util.*
object Kapt3ConfigurationKeys {
val SOURCE_OUTPUT_DIR: CompilerConfigurationKey<String> =
CompilerConfigurationKey.create<String>(SOURCE_OUTPUT_DIR_OPTION.description)
CompilerConfigurationKey.create<String>(SOURCE_OUTPUT_DIR_OPTION.description)
val CLASS_OUTPUT_DIR: CompilerConfigurationKey<String> =
CompilerConfigurationKey.create<String>(CLASS_OUTPUT_DIR_OPTION.description)
CompilerConfigurationKey.create<String>(CLASS_OUTPUT_DIR_OPTION.description)
val STUBS_OUTPUT_DIR: CompilerConfigurationKey<String> =
CompilerConfigurationKey.create<String>(STUBS_OUTPUT_DIR_OPTION.description)
CompilerConfigurationKey.create<String>(STUBS_OUTPUT_DIR_OPTION.description)
val INCREMENTAL_DATA_OUTPUT_DIR: CompilerConfigurationKey<String> =
CompilerConfigurationKey.create<String>(INCREMENTAL_DATA_OUTPUT_DIR_OPTION.description)
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)
CompilerConfigurationKey.create<List<String>>(ANNOTATION_PROCESSOR_CLASSPATH_OPTION.description)
val APT_OPTIONS: CompilerConfigurationKey<String> =
CompilerConfigurationKey.create<String>(APT_OPTIONS_OPTION.description)
CompilerConfigurationKey.create<String>(APT_OPTIONS_OPTION.description)
val JAVAC_CLI_OPTIONS: CompilerConfigurationKey<String> =
CompilerConfigurationKey.create<String>(JAVAC_CLI_OPTIONS_OPTION.description)
CompilerConfigurationKey.create<String>(JAVAC_CLI_OPTIONS_OPTION.description)
val ANNOTATION_PROCESSORS: CompilerConfigurationKey<List<String>> =
CompilerConfigurationKey.create<List<String>>(ANNOTATION_PROCESSORS_OPTION.description)
CompilerConfigurationKey.create<List<String>>(ANNOTATION_PROCESSORS_OPTION.description)
val VERBOSE_MODE: CompilerConfigurationKey<String> =
CompilerConfigurationKey.create<String>(VERBOSE_MODE_OPTION.description)
CompilerConfigurationKey.create<String>(VERBOSE_MODE_OPTION.description)
val INFO_AS_WARNINGS: CompilerConfigurationKey<String> =
CompilerConfigurationKey.create<String>(INFO_AS_WARNINGS_OPTION.description)
CompilerConfigurationKey.create<String>(INFO_AS_WARNINGS_OPTION.description)
@Deprecated("Use APT_MODE instead.")
val APT_ONLY: CompilerConfigurationKey<String> =
CompilerConfigurationKey.create<String>(APT_ONLY_OPTION.description)
CompilerConfigurationKey.create<String>(APT_ONLY_OPTION.description)
val APT_MODE: CompilerConfigurationKey<String> =
CompilerConfigurationKey.create<String>(APT_MODE_OPTION.description)
CompilerConfigurationKey.create<String>(APT_MODE_OPTION.description)
val USE_LIGHT_ANALYSIS: CompilerConfigurationKey<String> =
CompilerConfigurationKey.create<String>(USE_LIGHT_ANALYSIS_OPTION.description)
CompilerConfigurationKey.create<String>(USE_LIGHT_ANALYSIS_OPTION.description)
val CORRECT_ERROR_TYPES: CompilerConfigurationKey<String> =
CompilerConfigurationKey.create<String>(CORRECT_ERROR_TYPES_OPTION.description)
CompilerConfigurationKey.create<String>(CORRECT_ERROR_TYPES_OPTION.description)
val MAP_DIAGNOSTIC_LOCATIONS: CompilerConfigurationKey<String> =
CompilerConfigurationKey.create<String>(MAP_DIAGNOSTIC_LOCATIONS_OPTION.description)
@@ -125,61 +125,81 @@ object Kapt3ConfigurationKeys {
class Kapt3CommandLineProcessor : CommandLineProcessor {
companion object {
val ANNOTATION_PROCESSING_COMPILER_PLUGIN_ID: String = "org.jetbrains.kotlin.kapt3"
const val ANNOTATION_PROCESSING_COMPILER_PLUGIN_ID: String = "org.jetbrains.kotlin.kapt3"
val CONFIGURATION = CliOption("configuration", "<encoded>", "Encoded configuration", required = false)
val SOURCE_OUTPUT_DIR_OPTION: CliOption =
CliOption("sources", "<path>", "Output path for the generated files", required = false)
CliOption("sources", "<path>", "Output path for the generated files", required = false)
val CLASS_OUTPUT_DIR_OPTION: CliOption =
CliOption("classes", "<path>", "Output path for the class files", required = false)
CliOption("classes", "<path>", "Output path for the class files", required = false)
val STUBS_OUTPUT_DIR_OPTION: CliOption =
CliOption("stubs", "<path>", "Output path for the Java stubs", required = false)
CliOption("stubs", "<path>", "Output path for the Java stubs", required = false)
val INCREMENTAL_DATA_OUTPUT_DIR_OPTION: CliOption =
CliOption("incrementalData", "<path>", "Output path for the incremental data", required = false)
CliOption("incrementalData", "<path>", "Output path for the incremental data", required = false)
val ANNOTATION_PROCESSOR_CLASSPATH_OPTION: CliOption =
CliOption("apclasspath", "<classpath>", "Annotation processor classpath",
required = false, allowMultipleOccurrences = true)
CliOption(
"apclasspath", "<classpath>", "Annotation processor classpath",
required = false, allowMultipleOccurrences = true
)
val APT_OPTIONS_OPTION: CliOption =
CliOption("apoptions", "options map", "Encoded annotation processor options",
required = false, allowMultipleOccurrences = false)
CliOption(
"apoptions", "options map", "Encoded annotation processor options",
required = false, allowMultipleOccurrences = false
)
val JAVAC_CLI_OPTIONS_OPTION: CliOption =
CliOption("javacArguments", "javac CLI options map", "Encoded javac CLI options",
required = false, allowMultipleOccurrences = false)
CliOption(
"javacArguments", "javac CLI options map", "Encoded javac CLI options",
required = false, allowMultipleOccurrences = false
)
val ANNOTATION_PROCESSORS_OPTION: CliOption =
CliOption("processors", "<fqname,[fqname2,...]>", "Annotation processor qualified names",
required = false, allowMultipleOccurrences = true)
CliOption(
"processors", "<fqname,[fqname2,...]>", "Annotation processor qualified names",
required = false, allowMultipleOccurrences = true
)
val VERBOSE_MODE_OPTION: CliOption =
CliOption("verbose", "true | false", "Enable verbose output", required = false)
CliOption("verbose", "true | false", "Enable verbose output", required = false)
val INFO_AS_WARNINGS_OPTION: CliOption =
CliOption("infoAsWarnings", "true | false", "Show information messages as warnings", required = false)
CliOption("infoAsWarnings", "true | false", "Show information messages as warnings", required = false)
@Deprecated("Use APT_MODE_OPTION instead.")
val APT_ONLY_OPTION: CliOption =
CliOption("aptOnly", "true | false", "Run only annotation processing, do not compile Kotlin files", required = false)
CliOption("aptOnly", "true | false", "Run only annotation processing, do not compile Kotlin files", required = false)
val APT_MODE_OPTION: CliOption =
CliOption("aptMode", "apt | stubs | stubsAndApt | compile",
"Annotation processing mode: only apt, only stub generation, both, or with the subsequent compilation",
required = false)
CliOption(
"aptMode", "apt | stubs | stubsAndApt | compile",
"Annotation processing mode: only apt, only stub generation, both, or with the subsequent compilation",
required = false
)
val USE_LIGHT_ANALYSIS_OPTION: CliOption =
CliOption("useLightAnalysis", "true | false", "Do not analyze declaration bodies if can", required = false)
CliOption("useLightAnalysis", "true | false", "Do not analyze declaration bodies if can", required = false)
val CORRECT_ERROR_TYPES_OPTION: CliOption =
CliOption("correctErrorTypes", "true | false", "Replace generated or error types with ones from the generated sources", required = false)
CliOption(
"correctErrorTypes",
"true | false",
"Replace generated or error types with ones from the generated sources",
required = false
)
val MAP_DIAGNOSTIC_LOCATIONS_OPTION: CliOption =
CliOption("mapDiagnosticLocations", "true | false", "Map diagnostic reported on kapt stubs to original locations in Kotlin sources", required = false)
CliOption(
"mapDiagnosticLocations",
"true | false",
"Map diagnostic reported on kapt stubs to original locations in Kotlin sources",
required = false
)
val STRICT_MODE_OPTION: CliOption =
CliOption("strict", "true | false", "Show errors on incompatibilities during stub generation", required = false)
@@ -188,10 +208,12 @@ class Kapt3CommandLineProcessor : CommandLineProcessor {
override val pluginId: String = ANNOTATION_PROCESSING_COMPILER_PLUGIN_ID
override val pluginOptions: Collection<CliOption> =
listOf(SOURCE_OUTPUT_DIR_OPTION, ANNOTATION_PROCESSOR_CLASSPATH_OPTION, APT_OPTIONS_OPTION, JAVAC_CLI_OPTIONS_OPTION,
CLASS_OUTPUT_DIR_OPTION, VERBOSE_MODE_OPTION, STUBS_OUTPUT_DIR_OPTION, APT_ONLY_OPTION, APT_MODE_OPTION,
USE_LIGHT_ANALYSIS_OPTION, CORRECT_ERROR_TYPES_OPTION, ANNOTATION_PROCESSORS_OPTION, INCREMENTAL_DATA_OUTPUT_DIR_OPTION,
CONFIGURATION, MAP_DIAGNOSTIC_LOCATIONS_OPTION, INFO_AS_WARNINGS_OPTION, STRICT_MODE_OPTION)
listOf(
SOURCE_OUTPUT_DIR_OPTION, ANNOTATION_PROCESSOR_CLASSPATH_OPTION, APT_OPTIONS_OPTION, JAVAC_CLI_OPTIONS_OPTION,
CLASS_OUTPUT_DIR_OPTION, VERBOSE_MODE_OPTION, STUBS_OUTPUT_DIR_OPTION, APT_ONLY_OPTION, APT_MODE_OPTION,
USE_LIGHT_ANALYSIS_OPTION, CORRECT_ERROR_TYPES_OPTION, ANNOTATION_PROCESSORS_OPTION, INCREMENTAL_DATA_OUTPUT_DIR_OPTION,
CONFIGURATION, MAP_DIAGNOSTIC_LOCATIONS_OPTION, INFO_AS_WARNINGS_OPTION, STRICT_MODE_OPTION
)
override fun processOption(option: CliOption, value: String, configuration: CompilerConfiguration) {
when (option) {
@@ -238,14 +260,13 @@ class Kapt3ComponentRegistrar : ComponentRegistrar {
}
override fun registerProjectComponents(project: MockProject, configuration: CompilerConfiguration) {
val aptMode = AptMode.parse(configuration.get(Kapt3ConfigurationKeys.APT_MODE) ?:
configuration.get(Kapt3ConfigurationKeys.APT_ONLY))
val aptMode = AptMode.parse(configuration.get(Kapt3ConfigurationKeys.APT_MODE) ?: configuration.get(Kapt3ConfigurationKeys.APT_ONLY))
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 messageCollector = configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
?: PrintingMessageCollector(System.err, MessageRenderer.PLAIN_FULL_PATHS, isVerbose)
?: PrintingMessageCollector(System.err, MessageRenderer.PLAIN_FULL_PATHS, isVerbose)
val logger = MessageCollectorBackedKaptLogger(isVerbose, infoAsWarnings, messageCollector)
fun abortAnalysis() = AnalysisHandlerExtension.registerExtension(project, AbortAnalysisHandlerExtension())
@@ -365,7 +386,7 @@ class Kapt3ComponentRegistrar : ComponentRegistrar {
bindingTrace: BindingTrace,
files: Collection<KtFile>
): AnalysisResult? {
return AnalysisResult.Companion.success(bindingTrace.bindingContext, module, shouldGenerateCode = false)
return AnalysisResult.success(bindingTrace.bindingContext, module, shouldGenerateCode = false)
}
}
}
@@ -25,10 +25,10 @@ import javax.lang.model.element.NestingKind
import javax.tools.JavaFileObject
class KaptJavaFileObject(
val compilationUnit: JCTree.JCCompilationUnit,
val clazz: JCTree.JCClassDecl,
val file: File? = null,
val timestamp: Long = System.currentTimeMillis()
val compilationUnit: JCTree.JCCompilationUnit,
val clazz: JCTree.JCClassDecl,
val file: File? = null,
val timestamp: Long = System.currentTimeMillis()
) : JavaFileObject {
override fun toString() = "${javaClass.simpleName}[$name]"
@@ -38,6 +38,7 @@ class KaptTreeMaker(context: Context, kaptContext: KaptContextForStubGeneration)
val nameTable: Name.Table = Names.instance(context).table
@Suppress("FunctionName")
fun Type(type: Type): JCTree.JCExpression {
convertBuiltinType(type)?.let { return it }
if (type.sort == ARRAY) {
@@ -46,14 +47,17 @@ class KaptTreeMaker(context: Context, kaptContext: KaptContextForStubGeneration)
return FqName(type.internalName)
}
@Suppress("FunctionName")
fun FqName(internalOrFqName: String): JCTree.JCExpression {
val path = getQualifiedName(internalOrFqName).convertSpecialFqName().split('.')
assert(path.isNotEmpty())
return FqName(path)
}
@Suppress("FunctionName")
fun FqName(fqName: FqName) = FqName(fqName.pathSegments().map { it.asString() })
@Suppress("FunctionName")
private fun FqName(path: List<String>): JCTree.JCExpression {
if (path.size == 1) return SimpleName(path.single())
@@ -162,6 +166,7 @@ class KaptTreeMaker(context: Context, kaptContext: KaptContextForStubGeneration)
return TypeIdent(typeTag)
}
@Suppress("FunctionName")
fun SimpleName(name: String): JCTree.JCExpression = Ident(name(name))
fun name(name: String): Name = nameTable.fromString(name)
@@ -63,31 +63,31 @@ import javax.lang.model.element.ElementKind
import com.sun.tools.javac.util.List as JavacList
class ClassFileToSourceStubConverter(
val kaptContext: KaptContextForStubGeneration,
val generateNonExistentClass: Boolean,
val correctErrorTypes: Boolean,
val strictMode: Boolean
val kaptContext: KaptContextForStubGeneration,
val generateNonExistentClass: Boolean,
val correctErrorTypes: Boolean,
val strictMode: Boolean
) {
private companion object {
private val VISIBILITY_MODIFIERS = (Opcodes.ACC_PUBLIC or Opcodes.ACC_PRIVATE or Opcodes.ACC_PROTECTED).toLong()
private val MODALITY_MODIFIERS = (Opcodes.ACC_FINAL or Opcodes.ACC_ABSTRACT).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 val CLASS_MODIFIERS = VISIBILITY_MODIFIERS or MODALITY_MODIFIERS or
private const val CLASS_MODIFIERS = VISIBILITY_MODIFIERS or MODALITY_MODIFIERS or
(Opcodes.ACC_DEPRECATED or Opcodes.ACC_INTERFACE or Opcodes.ACC_ANNOTATION or Opcodes.ACC_ENUM or Opcodes.ACC_STATIC).toLong()
private val METHOD_MODIFIERS = VISIBILITY_MODIFIERS or MODALITY_MODIFIERS or
private const val METHOD_MODIFIERS = VISIBILITY_MODIFIERS or MODALITY_MODIFIERS or
(Opcodes.ACC_DEPRECATED or Opcodes.ACC_SYNCHRONIZED or Opcodes.ACC_NATIVE or Opcodes.ACC_STATIC or Opcodes.ACC_STRICT).toLong()
private val FIELD_MODIFIERS = VISIBILITY_MODIFIERS or MODALITY_MODIFIERS or
private const val FIELD_MODIFIERS = VISIBILITY_MODIFIERS or MODALITY_MODIFIERS or
(Opcodes.ACC_VOLATILE or Opcodes.ACC_TRANSIENT or Opcodes.ACC_ENUM or Opcodes.ACC_STATIC).toLong()
private val PARAMETER_MODIFIERS = FIELD_MODIFIERS or Flags.PARAMETER or Flags.VARARGS or Opcodes.ACC_FINAL.toLong()
private const val PARAMETER_MODIFIERS = FIELD_MODIFIERS or Flags.PARAMETER or Flags.VARARGS or Opcodes.ACC_FINAL.toLong()
private val BLACKLISTED_ANNOTATIONS = listOf(
"java.lang.Deprecated", "kotlin.Deprecated", // Deprecated annotations
"java.lang.Synthetic",
"synthetic.kotlin.jvm.GeneratedByJvmOverloads", // kapt3-related annotation for marking JvmOverloads-generated methods
"kotlin.jvm." // Kotlin annotations from runtime
"java.lang.Deprecated", "kotlin.Deprecated", // Deprecated annotations
"java.lang.Synthetic",
"synthetic.kotlin.jvm.GeneratedByJvmOverloads", // kapt3-related annotation for marking JvmOverloads-generated methods
"kotlin.jvm." // Kotlin annotations from runtime
)
private val NON_EXISTENT_CLASS_NAME = FqName("error.NonExistentClass")
@@ -95,8 +95,8 @@ class ClassFileToSourceStubConverter(
private val JAVA_KEYWORD_FILTER_REGEX = "[a-z]+".toRegex()
private val JAVA_KEYWORDS = Tokens.TokenKind.values()
.filter { JAVA_KEYWORD_FILTER_REGEX.matches(it.toString().orEmpty()) }
.mapTo(hashSetOf(), Any::toString)
.filter { JAVA_KEYWORD_FILTER_REGEX.matches(it.toString().orEmpty()) }
.mapTo(hashSetOf(), Any::toString)
}
private val _bindings = mutableMapOf<String, KaptJavaFileObject>()
@@ -130,12 +130,13 @@ class ClassFileToSourceStubConverter(
private fun generateNonExistentClass(): JCCompilationUnit {
val nonExistentClass = treeMaker.ClassDef(
treeMaker.Modifiers((Flags.PUBLIC or Flags.FINAL).toLong()),
treeMaker.name(NON_EXISTENT_CLASS_NAME.shortName().asString()),
JavacList.nil(),
null,
JavacList.nil(),
JavacList.nil())
treeMaker.Modifiers((Flags.PUBLIC or Flags.FINAL).toLong()),
treeMaker.name(NON_EXISTENT_CLASS_NAME.shortName().asString()),
JavacList.nil(),
null,
JavacList.nil(),
JavacList.nil()
)
val topLevel = treeMaker.TopLevelJava9Aware(treeMaker.FqName(NON_EXISTENT_CLASS_NAME.parent()), JavacList.of(nonExistentClass))
@@ -145,7 +146,7 @@ class ClassFileToSourceStubConverter(
return topLevel
}
class KaptStub(val file: JCCompilationUnit, val kaptMetadata: ByteArray? = null) {
class KaptStub(val file: JCCompilationUnit, private val kaptMetadata: ByteArray? = null) {
fun writeMetadataIfNeeded(forSource: File) {
if (kaptMetadata == null) {
return
@@ -166,7 +167,7 @@ class ClassFileToSourceStubConverter(
val descriptor = origin.descriptor ?: return null
// Nested classes will be processed during the outer classes conversion
if ((descriptor as? ClassDescriptor)?.isNested ?: false) return null
if ((descriptor as? ClassDescriptor)?.isNested == true) return null
val lineMappings = KaptLineMappingCollector(kaptContext)
@@ -245,7 +246,7 @@ class ClassFileToSourceStubConverter(
val shortName = importedFqName.shortName()
if (shortName.asString() == classDeclaration.simpleName.toString()) continue
val importedReference = resolveImportReference@ run {
val importedReference = /* resolveImportReference */ run {
val referenceExpression = getReferenceExpression(importDirective.importedReference) ?: return@run null
val bindingContext = kaptContext.bindingContext
@@ -283,10 +284,10 @@ class ClassFileToSourceStubConverter(
* Returns false for the inner classes or if the origin for the class was not found.
*/
private fun convertClass(
clazz: ClassNode,
lineMappings: KaptLineMappingCollector,
packageFqName: String,
isTopLevel: Boolean
clazz: ClassNode,
lineMappings: KaptLineMappingCollector,
packageFqName: String,
isTopLevel: Boolean
): JCClassDecl? {
if (isSynthetic(clazz.access)) return null
if (!checkIfValidTypeName(clazz, Type.getObjectType(clazz.name))) return null
@@ -300,14 +301,16 @@ class ClassFileToSourceStubConverter(
val isEnum = clazz.isEnum()
val isAnnotation = clazz.isAnnotation()
val modifiers = convertModifiers(flags,
if (isEnum) ElementKind.ENUM else ElementKind.CLASS,
packageFqName, clazz.visibleAnnotations, clazz.invisibleAnnotations, descriptor.annotations)
val modifiers = convertModifiers(
flags,
if (isEnum) ElementKind.ENUM else ElementKind.CLASS,
packageFqName, clazz.visibleAnnotations, clazz.invisibleAnnotations, descriptor.annotations
)
val isDefaultImpls = clazz.name.endsWith("${descriptor.name.asString()}\$DefaultImpls")
&& isPublic(clazz.access) && isFinal(clazz.access)
&& descriptor is ClassDescriptor
&& descriptor.kind == ClassKind.INTERFACE
&& isPublic(clazz.access) && isFinal(clazz.access)
&& descriptor is ClassDescriptor
&& descriptor.kind == ClassKind.INTERFACE
// DefaultImpls without any contents don't have INNERCLASS'es inside it (and inside the parent interface)
if (isDefaultImpls && (isTopLevel || (clazz.fields.isNullOrEmpty() && clazz.methods.isNullOrEmpty()))) {
@@ -357,12 +360,15 @@ class ClassFileToSourceStubConverter(
val def = data.correspondingClass?.let { convertClass(it, lineMappings, packageFqName, false) }
convertField(data.field, clazz, lineMappings, packageFqName, treeMaker.NewClass(
convertField(
data.field, clazz, lineMappings, packageFqName, treeMaker.NewClass(
/* enclosing = */ null,
/* typeArgs = */ JavacList.nil(),
/* clazz = */ treeMaker.Ident(treeMaker.name(data.field.name)),
/* args = */ args,
/* def = */ def))
/* def = */ def
)
)
}
val fields = mapJList<FieldNode, JCTree>(clazz.fields) {
@@ -390,12 +396,13 @@ class ClassFileToSourceStubConverter(
val superTypes = calculateSuperTypes(clazz, genericType)
return treeMaker.ClassDef(
modifiers,
treeMaker.name(simpleName),
genericType.typeParameters,
superTypes.superClass,
superTypes.interfaces,
enumValues + fields + methods + nestedClasses).keepKdocComments(clazz)
modifiers,
treeMaker.name(simpleName),
genericType.typeParameters,
superTypes.superClass,
superTypes.interfaces,
enumValues + fields + methods + nestedClasses
).keepKdocComments(clazz)
}
private class ClassSupertypes(val superClass: JCExpression?, val interfaces: JavacList<JCExpression>)
@@ -456,7 +463,7 @@ class ClassFileToSourceStubConverter(
val (resolvedAsClasses, otherSuperTypes) = resolvedSuperTypes
.partition {
it.second?.isError == false
&& (it.second?.constructor?.declarationDescriptor as? ClassDescriptor)?.kind == ClassKind.CLASS
&& (it.second?.constructor?.declarationDescriptor as? ClassDescriptor)?.kind == ClassKind.CLASS
}
if (resolvedAsClasses.size > 1) {
@@ -526,8 +533,8 @@ class ClassFileToSourceStubConverter(
// Java forbids outer and inner class names to be the same. Check if the names are different
private tailrec fun doesInnerClassNameConflictWithOuter(
clazz: ClassNode,
outerClass: ClassNode? = findContainingClassNode(clazz)
clazz: ClassNode,
outerClass: ClassNode? = findContainingClassNode(clazz)
): Boolean {
if (outerClass == null) return false
if (treeMaker.getSimpleName(clazz) == treeMaker.getSimpleName(outerClass)) return true
@@ -559,11 +566,11 @@ class ClassFileToSourceStubConverter(
}
private fun convertField(
field: FieldNode,
containingClass: ClassNode,
lineMappings: KaptLineMappingCollector,
packageFqName: String,
explicitInitializer: JCExpression? = null
field: FieldNode,
containingClass: ClassNode,
lineMappings: KaptLineMappingCollector,
packageFqName: String,
explicitInitializer: JCExpression? = null
): JCVariableDecl? {
if (isSynthetic(field.access) || isIgnored(field.invisibleAnnotations)) return null
// not needed anymore
@@ -606,8 +613,8 @@ class ClassFileToSourceStubConverter(
val value = field.value
val initializer = explicitInitializer
?: convertValueOfPrimitiveTypeOrString(value)
?: if (isFinal(field.access)) convertLiteralExpression(getDefaultValue(type)) else null
?: convertValueOfPrimitiveTypeOrString(value)
?: if (isFinal(field.access)) convertLiteralExpression(getDefaultValue(type)) else null
lineMappings.registerField(containingClass, field)
@@ -615,16 +622,16 @@ class ClassFileToSourceStubConverter(
}
private fun convertMethod(
method: MethodNode,
containingClass: ClassNode,
lineMappings: KaptLineMappingCollector,
packageFqName: String
method: MethodNode,
containingClass: ClassNode,
lineMappings: KaptLineMappingCollector,
packageFqName: String
): JCMethodDecl? {
if (isIgnored(method.invisibleAnnotations)) return null
val descriptor = kaptContext.origins[method]?.descriptor as? CallableDescriptor ?: return null
val isAnnotationHolderForProperty = descriptor is PropertyDescriptor && isSynthetic(method.access)
&& isStatic(method.access) && method.name.endsWith("\$annotations")
&& isStatic(method.access) && method.name.endsWith("\$annotations")
if (isSynthetic(method.access) && !isAnnotationHolderForProperty) return null
@@ -641,11 +648,12 @@ class ClassFileToSourceStubConverter(
if (!isValidIdentifier(name, canBeConstructor = isConstructor)) return null
val modifiers = convertModifiers(
if (containingClass.isEnum() && isConstructor)
(method.access.toLong() and VISIBILITY_MODIFIERS.inv())
else
method.access.toLong(),
ElementKind.METHOD, packageFqName, visibleAnnotations, method.invisibleAnnotations, descriptor.annotations)
if (containingClass.isEnum() && isConstructor)
(method.access.toLong() and VISIBILITY_MODIFIERS.inv())
else
method.access.toLong(),
ElementKind.METHOD, packageFqName, visibleAnnotations, method.invisibleAnnotations, descriptor.annotations
)
val asmReturnType = Type.getReturnType(method.desc)
val jcReturnType = if (isConstructor) null else treeMaker.Type(asmReturnType)
@@ -665,14 +673,15 @@ class ClassFileToSourceStubConverter(
val varargs = if (lastParameter && isArrayType && method.isVarargs()) Flags.VARARGS else 0L
val modifiers = convertModifiers(
info.flags or varargs or Flags.PARAMETER,
ElementKind.PARAMETER,
packageFqName,
info.visibleAnnotations,
info.invisibleAnnotations,
Annotations.EMPTY /* TODO */)
info.flags or varargs or Flags.PARAMETER,
ElementKind.PARAMETER,
packageFqName,
info.visibleAnnotations,
info.invisibleAnnotations,
Annotations.EMPTY /* TODO */
)
val name = info.name.takeIf { isValidIdentifier(it) } ?: "p${index}_" + info.name.hashCode().ushr(1)
val name = info.name.takeIf { isValidIdentifier(it) } ?: ("p" + index + "_" + info.name.hashCode().ushr(1))
val type = treeMaker.Type(info.type)
treeMaker.VarDef(modifiers, treeMaker.name(name), type, null)
}
@@ -680,8 +689,8 @@ class ClassFileToSourceStubConverter(
val exceptionTypes = mapJList(method.exceptions) { treeMaker.FqName(it) }
val valueParametersFromDescriptor = descriptor.valueParameters
val (genericSignature, returnType) = extractMethodSignatureTypes(
descriptor, exceptionTypes, jcReturnType, method, parameters, valueParametersFromDescriptor)
val (genericSignature, returnType) =
extractMethodSignatureTypes(descriptor, exceptionTypes, jcReturnType, method, parameters, valueParametersFromDescriptor)
val defaultValue = method.annotationDefault?.let { convertLiteralExpression(it) }
@@ -718,9 +727,9 @@ class ClassFileToSourceStubConverter(
lineMappings.registerMethod(containingClass, method)
return treeMaker.MethodDef(
modifiers, treeMaker.name(name), returnType, genericSignature.typeParameters,
genericSignature.parameterTypes, genericSignature.exceptionTypes,
body, defaultValue
modifiers, treeMaker.name(name), returnType, genericSignature.typeParameters,
genericSignature.parameterTypes, genericSignature.exceptionTypes,
body, defaultValue
).keepKdocComments(method).keepSignature(lineMappings, method)
}
@@ -730,36 +739,34 @@ class ClassFileToSourceStubConverter(
}
private fun extractMethodSignatureTypes(
descriptor: CallableDescriptor,
exceptionTypes: JavacList<JCExpression>,
jcReturnType: JCExpression?, method: MethodNode,
parameters: JavacList<JCVariableDecl>,
valueParametersFromDescriptor: List<ValueParameterDescriptor>
descriptor: CallableDescriptor,
exceptionTypes: JavacList<JCExpression>,
jcReturnType: JCExpression?, method: MethodNode,
parameters: JavacList<JCVariableDecl>,
valueParametersFromDescriptor: List<ValueParameterDescriptor>
): Pair<SignatureParser.MethodGenericSignature, JCExpression?> {
val genericSignature = signatureParser.parseMethodSignature(
method.signature, parameters, exceptionTypes, jcReturnType,
nonErrorParameterTypeProvider = { index, lazyType ->
if (descriptor is PropertySetterDescriptor && valueParametersFromDescriptor.size == 1 && index == 0) {
getNonErrorType(descriptor.correspondingProperty.returnType, METHOD_PARAMETER_TYPE,
ktTypeProvider = {
val setterOrigin = (kaptContext.origins[method]?.element as? KtCallableDeclaration)
?.takeIf { it !is KtFunction }
method.signature, parameters, exceptionTypes, jcReturnType,
nonErrorParameterTypeProvider = { index, lazyType ->
if (descriptor is PropertySetterDescriptor && valueParametersFromDescriptor.size == 1 && index == 0) {
getNonErrorType(descriptor.correspondingProperty.returnType, METHOD_PARAMETER_TYPE,
ktTypeProvider = {
val setterOrigin = (kaptContext.origins[method]?.element as? KtCallableDeclaration)
?.takeIf { it !is KtFunction }
setterOrigin?.typeReference
},
ifNonError = { lazyType() })
}
else if (descriptor is FunctionDescriptor && valueParametersFromDescriptor.size == parameters.size) {
getNonErrorType(valueParametersFromDescriptor[index].type, METHOD_PARAMETER_TYPE,
ktTypeProvider = {
(kaptContext.origins[method]?.element as? KtFunction)?.valueParameters?.get(index)?.typeReference
},
ifNonError = { lazyType() })
}
else {
lazyType()
}
})
setterOrigin?.typeReference
},
ifNonError = { lazyType() })
} else if (descriptor is FunctionDescriptor && valueParametersFromDescriptor.size == parameters.size) {
getNonErrorType(valueParametersFromDescriptor[index].type, METHOD_PARAMETER_TYPE,
ktTypeProvider = {
(kaptContext.origins[method]?.element as? KtFunction)?.valueParameters?.get(index)?.typeReference
},
ifNonError = { lazyType() })
} else {
lazyType()
}
})
val returnType = getNonErrorType(
descriptor.returnType, RETURN_TYPE,
@@ -779,10 +786,10 @@ class ClassFileToSourceStubConverter(
}
private inline fun <T : JCExpression?> getNonErrorType(
type: KotlinType?,
kind: ErrorTypeCorrector.TypeKind,
ktTypeProvider: () -> KtTypeReference?,
ifNonError: () -> T
type: KotlinType?,
kind: ErrorTypeCorrector.TypeKind,
ktTypeProvider: () -> KtTypeReference?,
ifNonError: () -> T
): T {
if (!correctErrorTypes) {
return ifNonError()
@@ -802,8 +809,8 @@ class ClassFileToSourceStubConverter(
if (nonErrorType is JCFieldAccess) {
val qualifier = nonErrorType.selected
if (nonErrorType.name.toString() == NON_EXISTENT_CLASS_NAME.shortName().asString()
&& qualifier is JCIdent
&& qualifier.name.toString() == NON_EXISTENT_CLASS_NAME.parent().asString()
&& qualifier is JCIdent
&& qualifier.name.toString() == NON_EXISTENT_CLASS_NAME.parent().asString()
) {
@Suppress("UNCHECKED_CAST")
return treeMaker.FqName("java.lang.Object") as T
@@ -834,25 +841,25 @@ class ClassFileToSourceStubConverter(
@Suppress("NOTHING_TO_INLINE")
private inline fun convertModifiers(
access: Int,
kind: ElementKind,
packageFqName: String,
visibleAnnotations: List<AnnotationNode>?,
invisibleAnnotations: List<AnnotationNode>?,
descriptorAnnotations: Annotations
access: Int,
kind: ElementKind,
packageFqName: String,
visibleAnnotations: List<AnnotationNode>?,
invisibleAnnotations: List<AnnotationNode>?,
descriptorAnnotations: Annotations
): JCModifiers = convertModifiers(access.toLong(), kind, packageFqName, visibleAnnotations, invisibleAnnotations, descriptorAnnotations)
private fun convertModifiers(
access: Long,
kind: ElementKind,
packageFqName: String,
visibleAnnotations: List<AnnotationNode>?,
invisibleAnnotations: List<AnnotationNode>?,
descriptorAnnotations: Annotations
access: Long,
kind: ElementKind,
packageFqName: String,
visibleAnnotations: List<AnnotationNode>?,
invisibleAnnotations: List<AnnotationNode>?,
descriptorAnnotations: Annotations
): JCModifiers {
fun convertAndAdd(list: JavacList<JCAnnotation>, anno: AnnotationNode): JavacList<JCAnnotation> {
val annotationDescriptor = descriptorAnnotations.singleOrNull { checkIfAnnotationValueMatches(anno, AnnotationValue(it)) }
val annotationTree = convertAnnotation(anno, packageFqName, annotationDescriptor) ?: return list
fun convertAndAdd(list: JavacList<JCAnnotation>, annotation: AnnotationNode): JavacList<JCAnnotation> {
val annotationDescriptor = descriptorAnnotations.singleOrNull { checkIfAnnotationValueMatches(annotation, AnnotationValue(it)) }
val annotationTree = convertAnnotation(annotation, packageFqName, annotationDescriptor) ?: return list
return list.prepend(annotationTree)
}
@@ -871,10 +878,10 @@ class ClassFileToSourceStubConverter(
}
private fun convertAnnotation(
annotation: AnnotationNode,
packageFqName: String? = "",
annotationDescriptor: AnnotationDescriptor? = null,
filtered: Boolean = true
annotation: AnnotationNode,
packageFqName: String? = "",
annotationDescriptor: AnnotationDescriptor? = null,
filtered: Boolean = true
): JCAnnotation? {
val annotationType = Type.getType(annotation.desc)
val fqName = treeMaker.getQualifiedName(annotationType)
@@ -885,9 +892,9 @@ class ClassFileToSourceStubConverter(
val ktAnnotation = (annotationDescriptor?.source as? PsiSourceElement)?.psi as? KtAnnotationEntry
val argMapping = ktAnnotation?.calleeExpression
?.getResolvedCall(kaptContext.bindingContext)?.valueArguments
?.mapKeys { it.key.name.asString() }
?: emptyMap()
?.getResolvedCall(kaptContext.bindingContext)?.valueArguments
?.mapKeys { it.key.name.asString() }
?: emptyMap()
val useSimpleName = '.' in fqName && fqName.substringBeforeLast('.', "") == packageFqName
@@ -922,7 +929,7 @@ class ClassFileToSourceStubConverter(
val args = value?.arguments?.mapNotNull { it.getArgumentExpression() } ?: emptyList()
val singleArg = args.singleOrNull()
if (constantValue.isOfPrimiviteType()) {
if (constantValue.isOfPrimitiveType()) {
// Do not inline primitive constants
tryParseReferenceToIntConstant(singleArg)?.let { return it }
}
@@ -1115,7 +1122,7 @@ class ClassFileToSourceStubConverter(
}
}
private fun Any?.isOfPrimiviteType(): Boolean = when(this) {
private fun Any?.isOfPrimitiveType(): Boolean = when (this) {
is Boolean, is Byte, is Int, is Long, is Short, is Char, is Float, is Double -> true
else -> false
}
@@ -37,9 +37,9 @@ import org.jetbrains.kotlin.types.*
private typealias SubstitutionMap = Map<String, Pair<KtTypeParameter, KtTypeProjection>>
class ErrorTypeCorrector(
private val converter: ClassFileToSourceStubConverter,
private val typeKind: TypeKind,
file: KtFile
private val converter: ClassFileToSourceStubConverter,
private val typeKind: TypeKind,
file: KtFile
) {
private val defaultType = converter.treeMaker.FqName(Object::class.java.name)
@@ -54,7 +54,7 @@ class ErrorTypeCorrector(
val importedFqName = importDirective.importedFqName ?: continue
val importedReference = getReferenceExpression(importDirective.importedReference)
?.let { bindingContext[BindingContext.REFERENCE_TARGET, it] }
?.let { bindingContext[BindingContext.REFERENCE_TARGET, it] }
if (importedReference is CallableDescriptor) continue
@@ -90,40 +90,47 @@ class ErrorTypeCorrector(
val baseExpression: JCTree.JCExpression
if (target is TypeAliasDescriptor) {
val typeAlias = target.source.getPsi() as? KtTypeAlias
val actualType = typeAlias?.getTypeReference() ?: return convert(target.expandedType)
return convert(actualType, typeAlias.getSubstitutions(type))
} else if (target is ClassConstructorDescriptor) {
val asmType = converter.kaptContext.generationState.typeMapper
.mapType(target.constructedClass.defaultType, null, TypeMappingMode.GENERIC_ARGUMENT)
baseExpression = converter.treeMaker.Type(asmType)
} else if (target is ClassDescriptor) {
// We only get here if some type were an error type. In other words, 'type' is either an error type or its argument,
// so it's impossible it to be unboxed primitive.
val asmType = converter.kaptContext.generationState.typeMapper.mapType(target.defaultType, null, TypeMappingMode.GENERIC_ARGUMENT)
baseExpression = converter.treeMaker.Type(asmType)
} else {
val referencedName = type.referencedName ?: return defaultType
val qualifier = type.qualifier
if (qualifier == null) {
if (referencedName in substitutions) {
val (typeParameter, projection) = substitutions.getValue(referencedName)
return convertTypeProjection(projection, typeParameter.variance, emptyMap())
}
aliasedImports[referencedName]?.let { return it }
when (target) {
is TypeAliasDescriptor -> {
val typeAlias = target.source.getPsi() as? KtTypeAlias
val actualType = typeAlias?.getTypeReference() ?: return convert(target.expandedType)
return convert(actualType, typeAlias.getSubstitutions(type))
}
is ClassConstructorDescriptor -> {
val asmType = converter.kaptContext.generationState.typeMapper
.mapType(target.constructedClass.defaultType, null, TypeMappingMode.GENERIC_ARGUMENT)
baseExpression = when {
qualifier != null -> {
val qualifierType = convertUserType(qualifier, substitutions)
if (qualifierType === defaultType) return defaultType // Do not allow to use 'defaultType' as a qualifier
treeMaker.Select(qualifierType, treeMaker.name(referencedName))
baseExpression = converter.treeMaker.Type(asmType)
}
is ClassDescriptor -> {
// We only get here if some type were an error type. In other words, 'type' is either an error type or its argument,
// so it's impossible it to be unboxed primitive.
val asmType = converter.kaptContext.generationState.typeMapper
.mapType(target.defaultType, null, TypeMappingMode.GENERIC_ARGUMENT)
baseExpression = converter.treeMaker.Type(asmType)
}
else -> {
val referencedName = type.referencedName ?: return defaultType
val qualifier = type.qualifier
if (qualifier == null) {
if (referencedName in substitutions) {
val (typeParameter, projection) = substitutions.getValue(referencedName)
return convertTypeProjection(projection, typeParameter.variance, emptyMap())
}
aliasedImports[referencedName]?.let { return it }
}
baseExpression = when {
qualifier != null -> {
val qualifierType = convertUserType(qualifier, substitutions)
if (qualifierType === defaultType) return defaultType // Do not allow to use 'defaultType' as a qualifier
treeMaker.Select(qualifierType, treeMaker.name(referencedName))
}
else -> treeMaker.SimpleName(referencedName)
}
else -> treeMaker.SimpleName(referencedName)
}
}
@@ -147,8 +154,7 @@ class ErrorTypeCorrector(
val variance = if (typeArgument != null && typeParameter != null) {
KotlinTypeMapper.getVarianceForWildcard(typeParameter, typeArgument, typeMappingMode)
}
else {
} else {
null
}
@@ -157,9 +163,9 @@ class ErrorTypeCorrector(
}
private fun convertTypeProjection(
projection: KtTypeProjection,
variance: Variance?,
substitutions: SubstitutionMap
projection: KtTypeProjection,
variance: Variance?,
substitutions: SubstitutionMap
): JCTree.JCExpression {
fun unbounded() = treeMaker.Wildcard(treeMaker.TypeBoundKind(BoundKind.UNBOUND), null)
@@ -183,10 +189,6 @@ class ErrorTypeCorrector(
}
}
private fun convertTypeProjection() {
}
private fun convertFunctionType(type: KtFunctionType, substitutions: SubstitutionMap): JCTree.JCExpression {
val receiverType = type.receiverTypeReference
var parameterTypes = mapJList(type.parameters) { convert(it.typeReference, substitutions) }
@@ -207,8 +209,8 @@ class ErrorTypeCorrector(
if (typeParameters.size != arguments.size) {
val kaptContext = converter.kaptContext
kaptContext.compiler.log.report(
kaptContext.kaptError("${typeParameters.size} parameters are expected but ${arguments.size} passed"))
val error = kaptContext.kaptError("${typeParameters.size} parameters are expected but ${arguments.size} passed")
kaptContext.compiler.log.report(error)
return emptyMap()
}
@@ -87,7 +87,7 @@ class KDocCommentKeeper(private val kaptContext: KaptContextForStubGeneration) {
&& descriptor is PropertyAccessorDescriptor
&& kaptContext.bindingContext[BindingContext.BACKING_FIELD_REQUIRED, descriptor.correspondingProperty] == true
) {
// Do not place the smae documentation on backing field and property accessors
// Do not place documentation on backing field and property accessors
return
}
@@ -47,8 +47,8 @@ class KaptLineMappingCollector(private val kaptContext: KaptContextForStubGenera
register(field, clazz.name + "#" + field.name)
}
fun registerSignature(decl: JCTree.JCMethodDecl, method: MethodNode) {
signatureInfo[decl.getJavacSignature()] = method.name + method.desc
fun registerSignature(declaration: JCTree.JCMethodDecl, method: MethodNode) {
signatureInfo[declaration.getJavacSignature()] = method.name + method.desc
}
private fun register(asmNode: Any, fqName: String) {
@@ -92,24 +92,24 @@ private class SignatureNode(val kind: ElementKind, val name: String? = null) {
val children: MutableList<SignatureNode> = SmartList<SignatureNode>()
}
class SignatureParser(val treeMaker: KaptTreeMaker) {
class SignatureParser(private val treeMaker: KaptTreeMaker) {
class ClassGenericSignature(
val typeParameters: JavacList<JCTypeParameter>,
val superClass: JCExpression,
val interfaces: JavacList<JCExpression>
val typeParameters: JavacList<JCTypeParameter>,
val superClass: JCExpression,
val interfaces: JavacList<JCExpression>
)
class MethodGenericSignature(
val typeParameters: JavacList<JCTypeParameter>,
val parameterTypes: JavacList<JCVariableDecl>,
val exceptionTypes: JavacList<JCExpression>,
val returnType: JCExpression?
val typeParameters: JavacList<JCTypeParameter>,
val parameterTypes: JavacList<JCVariableDecl>,
val exceptionTypes: JavacList<JCExpression>,
val returnType: JCExpression?
)
fun parseClassSignature(
signature: String?,
rawSuperClass: JCExpression,
rawInterfaces: JavacList<JCExpression>
signature: String?,
rawSuperClass: JCExpression,
rawInterfaces: JavacList<JCExpression>
): ClassGenericSignature {
if (signature == null) {
return ClassGenericSignature(JavacList.nil(), rawSuperClass, rawInterfaces)
@@ -128,11 +128,11 @@ class SignatureParser(val treeMaker: KaptTreeMaker) {
}
fun parseMethodSignature(
signature: String?,
rawParameters: JavacList<JCVariableDecl>,
rawExceptionTypes: JavacList<JCExpression>,
rawReturnType: JCExpression?,
nonErrorParameterTypeProvider: (Int, () -> JCExpression) -> JCExpression
signature: String?,
rawParameters: JavacList<JCVariableDecl>,
rawExceptionTypes: JavacList<JCExpression>,
rawReturnType: JCExpression?,
nonErrorParameterTypeProvider: (Int, () -> JCExpression) -> JCExpression
): MethodGenericSignature {
if (signature == null) {
val parameters = mapJListIndexed(rawParameters) { index, it ->
@@ -164,8 +164,8 @@ class SignatureParser(val treeMaker: KaptTreeMaker) {
}
fun parseFieldSignature(
signature: String?,
rawType: JCExpression
signature: String?,
rawType: JCExpression
): JCExpression {
if (signature == null) return rawType
@@ -208,8 +208,9 @@ class SignatureParser(val treeMaker: KaptTreeMaker) {
for (innerClass in innerClasses) {
expression = makeExpressionForClassTypeWithArguments(
treeMaker.Select(expression, treeMaker.name(innerClass.name!!)),
innerClass.children)
treeMaker.Select(expression, treeMaker.name(innerClass.name!!)),
innerClass.children
)
}
expression
@@ -273,12 +274,12 @@ private fun SignatureNode.split(l1: MutableList<SignatureNode>, e1: ElementKind,
}
private fun SignatureNode.split(
l1: MutableList<SignatureNode>,
e1: ElementKind,
l2: MutableList<SignatureNode>,
e2: ElementKind,
l3: MutableList<SignatureNode>,
e3: ElementKind
l1: MutableList<SignatureNode>,
e1: ElementKind,
l2: MutableList<SignatureNode>,
e2: ElementKind,
l3: MutableList<SignatureNode>,
e3: ElementKind
) {
for (child in children) {
val kind = child.kind
@@ -292,14 +293,14 @@ private fun SignatureNode.split(
}
private fun SignatureNode.split(
l1: MutableList<SignatureNode>,
e1: ElementKind,
l2: MutableList<SignatureNode>,
e2: ElementKind,
l3: MutableList<SignatureNode>,
e3: ElementKind,
l4: MutableList<SignatureNode>,
e4: ElementKind
l1: MutableList<SignatureNode>,
e1: ElementKind,
l2: MutableList<SignatureNode>,
e2: ElementKind,
l3: MutableList<SignatureNode>,
e3: ElementKind,
l4: MutableList<SignatureNode>,
e4: ElementKind
) {
for (child in children) {
val kind = child.kind
@@ -27,11 +27,12 @@ import org.jetbrains.org.objectweb.asm.tree.MethodNode
import java.util.*
internal class ParameterInfo(
val flags: Long,
val name: String,
val type: Type,
val visibleAnnotations: List<AnnotationNode>?,
val invisibleAnnotations: List<AnnotationNode>?)
val flags: Long,
val name: String,
val type: Type,
val visibleAnnotations: List<AnnotationNode>?,
val invisibleAnnotations: List<AnnotationNode>?
)
internal fun MethodNode.getParametersInfo(containingClass: ClassNode): List<ParameterInfo> {
val localVariables = this.localVariables ?: emptyList()
@@ -63,7 +64,7 @@ internal fun MethodNode.getParametersInfo(containingClass: ClassNode): List<Para
// @JvmOverloads constructors and ordinary methods don't have "this" local variable
name = name ?: localVariables.getOrNull(index + localVariableIndexOffset)?.name
?: "p${index - startParameterIndex}"
?: "p${index - startParameterIndex}"
// Property setters has bad parameter names
if (name.startsWith("<") && name.endsWith(">")) {
@@ -20,7 +20,7 @@ class MessageCollectorBackedKaptLogger(
val messageCollector: MessageCollector = PrintingMessageCollector(System.err, MessageRenderer.PLAIN_FULL_PATHS, isVerbose)
) : KaptLogger {
private companion object {
val PREFIX = "[kapt] "
const val PREFIX = "[kapt] "
}
override val errorWriter = makeWriter(ERROR)
@@ -21,7 +21,10 @@ import org.jetbrains.kotlin.cli.common.messages.GroupingMessageCollector
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import java.io.Writer
class MessageCollectorBackedWriter(val messageCollector: MessageCollector, val severity: CompilerMessageSeverity) : Writer() {
class MessageCollectorBackedWriter(
private val messageCollector: MessageCollector,
private val severity: CompilerMessageSeverity
) : Writer() {
override fun write(buffer: CharArray, offset: Int, length: Int) {
val message = String(buffer, offset, length).trim().trim('\n', '\r')
if (message.isNotEmpty()) {
@@ -26,7 +26,6 @@ import org.jetbrains.org.objectweb.asm.tree.MethodNode
internal fun isEnum(access: Int) = (access and Opcodes.ACC_ENUM) != 0
internal fun isPublic(access: Int) = (access and Opcodes.ACC_PUBLIC) != 0
internal fun isSynthetic(access: Int) = (access and Opcodes.ACC_SYNTHETIC) != 0
internal fun isPrivate(access: Int) = (access and Opcodes.ACC_PRIVATE) != 0
internal fun isFinal(access: Int) = (access and Opcodes.ACC_FINAL) != 0
internal fun isStatic(access: Int) = (access and Opcodes.ACC_STATIC) != 0
internal fun isAbstract(access: Int) = (access and Opcodes.ACC_ABSTRACT) != 0
@@ -40,13 +39,13 @@ internal fun <T> List<T>?.isNullOrEmpty() = this == null || this.isEmpty()
internal fun MethodNode.isJvmOverloadsGenerated(): Boolean {
return (invisibleAnnotations?.any { it.isJvmOverloadsGenerated() } ?: false)
|| (visibleAnnotations?.any { it.isJvmOverloadsGenerated() } ?: false)
|| (visibleAnnotations?.any { it.isJvmOverloadsGenerated() } ?: false)
}
// Constant from DefaultParameterValueSubstitutor can't be used in Maven build because of ProGuard
// rename this as well
private val ANNOTATION_TYPE_DESCRIPTOR_FOR_JVMOVERLOADS_GENERATED_METHODS: String =
Type.getObjectType("synthetic/kotlin/jvm/GeneratedByJvmOverloads").descriptor
Type.getObjectType("synthetic/kotlin/jvm/GeneratedByJvmOverloads").descriptor
private fun AnnotationNode.isJvmOverloadsGenerated(): Boolean {
return this.desc == ANNOTATION_TYPE_DESCRIPTOR_FOR_JVMOVERLOADS_GENERATED_METHODS
@@ -68,22 +68,22 @@ abstract class AbstractKotlinKapt3IntegrationTest : CodegenTestCase() {
}
protected open fun test(
name: String,
vararg supportedAnnotations: String,
options: Map<String, String> = emptyMap(),
process: (Set<TypeElement>, RoundEnvironment, ProcessingEnvironment) -> Unit
name: String,
vararg supportedAnnotations: String,
options: Map<String, String> = emptyMap(),
process: (Set<TypeElement>, RoundEnvironment, ProcessingEnvironment) -> Unit
) = testAP(true, name, options, process, *supportedAnnotations)
protected fun testAP(
shouldRun: Boolean,
name: String,
options: Map<String, String>,
process: (Set<TypeElement>, RoundEnvironment, ProcessingEnvironment) -> Unit,
vararg supportedAnnotations: String
private fun testAP(
shouldRun: Boolean,
name: String,
options: Map<String, String>,
process: (Set<TypeElement>, RoundEnvironment, ProcessingEnvironment) -> Unit,
vararg supportedAnnotations: String
) {
this._options = options
val ktFileName = File(TEST_DATA_DIR, name + ".kt")
val ktFileName = File(TEST_DATA_DIR, "$name.kt")
var started = false
val processor = object : Processor {
lateinit var processingEnv: ProcessingEnvironment
@@ -103,10 +103,10 @@ abstract class AbstractKotlinKapt3IntegrationTest : CodegenTestCase() {
}
override fun getCompletions(
element: Element?,
annotation: AnnotationMirror?,
member: ExecutableElement?,
userText: String?
element: Element?,
annotation: AnnotationMirror?,
member: ExecutableElement?,
userText: String?
): Iterable<Completion>? {
return emptyList()
}
@@ -134,8 +134,10 @@ abstract class AbstractKotlinKapt3IntegrationTest : CodegenTestCase() {
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.ALL, *javaSources)
val project = myEnvironment.project
val kapt3Extension = Kapt3ExtensionForTests(project, processors, javaSources.toList(), sourceOutputDir, this.options,
stubsOutputDir = stubsDir, incrementalDataOutputDir = incrementalDataDir)
val kapt3Extension = Kapt3ExtensionForTests(
project, processors, javaSources.toList(), sourceOutputDir, this.options,
stubsOutputDir = stubsDir, incrementalDataOutputDir = incrementalDataDir
)
AnalysisHandlerExtension.registerExtension(project, kapt3Extension)
@@ -146,9 +148,9 @@ abstract class AbstractKotlinKapt3IntegrationTest : CodegenTestCase() {
GenerationUtils.compileFiles(myFiles.psiFiles, myEnvironment, classBuilderFactory).factory
val actualRaw = kapt3Extension.savedStubs ?: error("Stubs were not saved")
val actual = StringUtil.convertLineSeparators(actualRaw.trim({ it <= ' ' }))
.trimTrailingWhitespacesAndAddNewlineAtEOF()
.let { AbstractClassFileToSourceStubConverterTest.removeMetadataAnnotationContents(it) }
val actual = StringUtil.convertLineSeparators(actualRaw.trim { it <= ' ' })
.trimTrailingWhitespacesAndAddNewlineAtEOF()
.let { AbstractClassFileToSourceStubConverterTest.removeMetadataAnnotationContents(it) }
KotlinTestUtils.assertEqualsToFile(txtFile, actual)
} finally {
@@ -158,13 +160,13 @@ abstract class AbstractKotlinKapt3IntegrationTest : CodegenTestCase() {
}
protected class Kapt3ExtensionForTests(
project: Project,
private val processors: List<Processor>,
javaSourceRoots: List<File>,
outputDir: File,
options: Map<String, String>,
stubsOutputDir: File,
incrementalDataOutputDir: File
project: Project,
private val processors: List<Processor>,
javaSourceRoots: List<File>,
outputDir: File,
options: Map<String, String>,
stubsOutputDir: File,
incrementalDataOutputDir: File
) : AbstractKapt3Extension(
KaptPaths(
project.basePath?.let(::File),
@@ -186,17 +188,17 @@ abstract class AbstractKotlinKapt3IntegrationTest : CodegenTestCase() {
}
this.savedStubs = stubs
.map { it.file.prettyPrint(kaptContext.context) }
.sorted()
.joinToString(AbstractKotlinKapt3Test.FILE_SEPARATOR)
.map { it.file.prettyPrint(kaptContext.context) }
.sorted()
.joinToString(AbstractKotlinKapt3Test.FILE_SEPARATOR)
super.saveStubs(kaptContext, stubs)
}
override fun saveIncrementalData(
kaptContext: KaptContextForStubGeneration,
messageCollector: MessageCollector,
converter: ClassFileToSourceStubConverter
kaptContext: KaptContextForStubGeneration,
messageCollector: MessageCollector,
converter: ClassFileToSourceStubConverter
) {
if (this.savedBindings != null) {
error("Bindings are already saved")
@@ -208,7 +208,7 @@ abstract class AbstractKotlinKapt3Test : CodegenTestCase() {
lines.filter { it.startsWith("// $name") }.toList()
}
protected fun File.getOptionValues(name: String) = getRawOptionValues(name).map { it.drop("// ".length + name.length).trim() }
private fun File.getOptionValues(name: String) = getRawOptionValues(name).map { it.drop("// ".length + name.length).trim() }
protected abstract fun check(
kaptContext: KaptContextForStubGeneration,
@@ -31,15 +31,17 @@ import javax.lang.model.element.TypeElement
class KotlinKapt3IntegrationTests : AbstractKotlinKapt3IntegrationTest(), Java9TestLauncher {
override fun test(
name: String,
vararg supportedAnnotations: String,
options: Map<String, String>,
process: (Set<TypeElement>, RoundEnvironment, ProcessingEnvironment) -> Unit
name: String,
vararg supportedAnnotations: String,
options: Map<String, String>,
process: (Set<TypeElement>, RoundEnvironment, ProcessingEnvironment) -> Unit
) {
super.test(name, *supportedAnnotations, options = options, process = process)
doTestWithJdk9(SingleJUnitTestRunner::class.java,
KotlinKapt3IntegrationTests::class.java.name + "#test" + getTestName(false))
doTestWithJdk9(
SingleJUnitTestRunner::class.java,
KotlinKapt3IntegrationTests::class.java.name + "#test" + getTestName(false)
)
}
@Test
@@ -51,7 +53,7 @@ class KotlinKapt3IntegrationTests : AbstractKotlinKapt3IntegrationTest(), Java9T
}
@Test
fun testComments() = test("Simple", "test.MyAnnotation") { set, roundEnv, env ->
fun testComments() = test("Simple", "test.MyAnnotation") { _, _, env ->
fun commentOf(className: String) = env.elementUtils.getDocComment(env.elementUtils.getTypeElement(className))
assert(commentOf("test.Simple") == " * KDoc comment.\n")
@@ -73,19 +75,21 @@ class KotlinKapt3IntegrationTests : AbstractKotlinKapt3IntegrationTest(), Java9T
}
@Test
fun testStubsAndIncrementalDataForNestedClasses() = bindingsTest("NestedClasses") { stubsOutputDir, incrementalDataOutputDir, bindings ->
assert(File(stubsOutputDir, "test/Simple.java").exists())
assert(!File(stubsOutputDir, "test/Simple/InnerClass.java").exists())
fun testStubsAndIncrementalDataForNestedClasses() {
bindingsTest("NestedClasses") { stubsOutputDir, incrementalDataOutputDir, bindings ->
assert(File(stubsOutputDir, "test/Simple.java").exists())
assert(!File(stubsOutputDir, "test/Simple/InnerClass.java").exists())
assert(File(incrementalDataOutputDir, "test/Simple.class").exists())
assert(File(incrementalDataOutputDir, "test/Simple\$Companion.class").exists())
assert(File(incrementalDataOutputDir, "test/Simple\$InnerClass.class").exists())
assert(File(incrementalDataOutputDir, "test/Simple\$NestedClass.class").exists())
assert(File(incrementalDataOutputDir, "test/Simple\$NestedClass\$NestedNestedClass.class").exists())
assert(File(incrementalDataOutputDir, "test/Simple.class").exists())
assert(File(incrementalDataOutputDir, "test/Simple\$Companion.class").exists())
assert(File(incrementalDataOutputDir, "test/Simple\$InnerClass.class").exists())
assert(File(incrementalDataOutputDir, "test/Simple\$NestedClass.class").exists())
assert(File(incrementalDataOutputDir, "test/Simple\$NestedClass\$NestedNestedClass.class").exists())
assert(bindings.any { it.key == "test/Simple" && it.value.name == "test/Simple.java" })
assert(bindings.none { it.key.contains("Companion") })
assert(bindings.none { it.key.contains("InnerClass") })
assert(bindings.any { it.key == "test/Simple" && it.value.name == "test/Simple.java" })
assert(bindings.none { it.key.contains("Companion") })
assert(bindings.none { it.key.contains("InnerClass") })
}
}
private fun bindingsTest(name: String, test: (File, File, Map<String, KaptJavaFileObject>) -> Unit) {
@@ -103,8 +107,8 @@ class KotlinKapt3IntegrationTests : AbstractKotlinKapt3IntegrationTest(), Java9T
@Test
fun testOptions() = test(
"Simple", "test.MyAnnotation",
options = mapOf("firstKey" to "firstValue", "secondKey" to "")
"Simple", "test.MyAnnotation",
options = mapOf("firstKey" to "firstValue", "secondKey" to "")
) { _, _, env ->
val options = env.options
assertEquals("firstValue", options["firstKey"])
@@ -117,11 +121,11 @@ class KotlinKapt3IntegrationTests : AbstractKotlinKapt3IntegrationTest(), Java9T
val annotatedElements = roundEnv.getElementsAnnotatedWith(set.single())
assertEquals(1, annotatedElements.size)
val constructors = annotatedElements
.first()
.enclosedElements
.filter { it.kind == ElementKind.CONSTRUCTOR }
.map { it as ExecutableElement }
.sortedBy { it.parameters.size }
.first()
.enclosedElements
.filter { it.kind == ElementKind.CONSTRUCTOR }
.map { it as ExecutableElement }
.sortedBy { it.parameters.size }
assertEquals(2, constructors.size)
assertEquals(2, constructors[0].parameters.size)
assertEquals(3, constructors[1].parameters.size)