Kapt: Do not write references to anonymous classes to stubs & metadata (#KT-25374)
This commit is contained in:
+13
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* 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.resolve
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
interface DeclarationSignatureAnonymousTypeTransformer {
|
||||
fun transformAnonymousType(descriptor: DeclarationDescriptorWithVisibility, type: KotlinType): KotlinType?
|
||||
}
|
||||
@@ -88,6 +88,7 @@ public class DescriptorResolver {
|
||||
private final TypeApproximator typeApproximator;
|
||||
private final DeclarationReturnTypeSanitizer declarationReturnTypeSanitizer;
|
||||
private final DataFlowValueFactory dataFlowValueFactory;
|
||||
private final Iterable<DeclarationSignatureAnonymousTypeTransformer> anonymousTypeTransformers;
|
||||
|
||||
public DescriptorResolver(
|
||||
@NotNull AnnotationResolver annotationResolver,
|
||||
@@ -106,7 +107,8 @@ public class DescriptorResolver {
|
||||
@NotNull Project project,
|
||||
@NotNull TypeApproximator approximator,
|
||||
@NotNull DeclarationReturnTypeSanitizer declarationReturnTypeSanitizer,
|
||||
@NotNull DataFlowValueFactory dataFlowValueFactory
|
||||
@NotNull DataFlowValueFactory dataFlowValueFactory,
|
||||
@NotNull Iterable<DeclarationSignatureAnonymousTypeTransformer> anonymousTypeTransformers
|
||||
) {
|
||||
this.annotationResolver = annotationResolver;
|
||||
this.builtIns = builtIns;
|
||||
@@ -125,6 +127,7 @@ public class DescriptorResolver {
|
||||
typeApproximator = approximator;
|
||||
this.declarationReturnTypeSanitizer = declarationReturnTypeSanitizer;
|
||||
this.dataFlowValueFactory = dataFlowValueFactory;
|
||||
this.anonymousTypeTransformers = anonymousTypeTransformers;
|
||||
}
|
||||
|
||||
public List<KotlinType> resolveSupertypes(
|
||||
@@ -977,8 +980,16 @@ public class DescriptorResolver {
|
||||
@NotNull DeclarationDescriptorWithVisibility descriptor,
|
||||
@NotNull KtDeclaration declaration,
|
||||
@NotNull KotlinType type,
|
||||
@NotNull BindingTrace trace
|
||||
@NotNull BindingTrace trace,
|
||||
@NotNull Iterable<DeclarationSignatureAnonymousTypeTransformer> anonymousTypeTransformers
|
||||
) {
|
||||
for (DeclarationSignatureAnonymousTypeTransformer transformer : anonymousTypeTransformers) {
|
||||
KotlinType transformedType = transformer.transformAnonymousType(descriptor, type);
|
||||
if (transformedType != null) {
|
||||
return transformedType;
|
||||
}
|
||||
}
|
||||
|
||||
ClassifierDescriptor classifier = type.getConstructor().getDeclarationDescriptor();
|
||||
if (classifier == null || !DescriptorUtils.isAnonymousObject(classifier) || DescriptorUtils.isLocal(descriptor)) {
|
||||
return type;
|
||||
@@ -996,7 +1007,6 @@ public class DescriptorResolver {
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
private PropertySetterDescriptor resolvePropertySetterDescriptor(
|
||||
@NotNull LexicalScope scopeWithTypeParameters,
|
||||
@@ -1159,7 +1169,7 @@ public class DescriptorResolver {
|
||||
return wrappedTypeFactory.createRecursionIntolerantDeferredType(trace, () -> {
|
||||
PreliminaryDeclarationVisitor.Companion.createForDeclaration(function, trace, languageVersionSettings);
|
||||
KotlinType type = expressionTypingServices.getBodyExpressionType(trace, scope, dataFlowInfo, function, functionDescriptor);
|
||||
KotlinType publicType = transformAnonymousTypeIfNeeded(functionDescriptor, function, type, trace);
|
||||
KotlinType publicType = transformAnonymousTypeIfNeeded(functionDescriptor, function, type, trace, anonymousTypeTransformers);
|
||||
UnwrappedType approximatedType = typeApproximator.approximateDeclarationType(publicType, false, languageVersionSettings);
|
||||
KotlinType sanitizedType = declarationReturnTypeSanitizer.sanitizeReturnType(approximatedType, wrappedTypeFactory, trace, languageVersionSettings);
|
||||
functionsTypingVisitor.checkTypesForReturnStatements(function, trace, sanitizedType);
|
||||
|
||||
+3
-2
@@ -31,7 +31,8 @@ class VariableTypeAndInitializerResolver(
|
||||
private val wrappedTypeFactory: WrappedTypeFactory,
|
||||
private val typeApproximator: TypeApproximator,
|
||||
private val declarationReturnTypeSanitizer: DeclarationReturnTypeSanitizer,
|
||||
private val languageVersionSettings: LanguageVersionSettings
|
||||
private val languageVersionSettings: LanguageVersionSettings,
|
||||
private val anonymousTypeTransformers: Iterable<DeclarationSignatureAnonymousTypeTransformer>
|
||||
) {
|
||||
companion object {
|
||||
@JvmField
|
||||
@@ -82,7 +83,7 @@ class VariableTypeAndInitializerResolver(
|
||||
)
|
||||
val initializerType =
|
||||
resolveInitializerType(scopeForInitializer, variable.initializer!!, dataFlowInfo, trace, local)
|
||||
transformAnonymousTypeIfNeeded(variableDescriptor, variable, initializerType, trace)
|
||||
transformAnonymousTypeIfNeeded(variableDescriptor, variable, initializerType, trace, anonymousTypeTransformers)
|
||||
}
|
||||
|
||||
else -> resolveInitializerType(scopeForInitializer, variable.initializer!!, dataFlowInfo, trace, local)
|
||||
|
||||
+46
-20
@@ -1,6 +1,7 @@
|
||||
package org.jetbrains.kotlin.gradle
|
||||
|
||||
import org.jetbrains.kotlin.gradle.util.isLegacyAndroidGradleVersion
|
||||
import org.jetbrains.kotlin.gradle.util.getFileByName
|
||||
import org.jetbrains.kotlin.gradle.util.modify
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import org.junit.Test
|
||||
@@ -126,29 +127,32 @@ open class Kapt3AndroidIT : Kapt3BaseIT() {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testICWithAnonymousClasses() {
|
||||
val project = Project("icAnonymousTypes", directoryPrefix = "kapt2")
|
||||
setupDataBinding(project, null)
|
||||
|
||||
project.build("assembleDebug") {
|
||||
assertSuccessful()
|
||||
assertKaptSuccessful()
|
||||
}
|
||||
|
||||
val aKt = project.projectDir.getFileByName("a.kt").also { assert(it.exists()) }
|
||||
aKt.modify {
|
||||
assert(it.contains("CrashMe2(1000)"))
|
||||
it.replace("CrashMe2(1000)", "CrashMe2(2000)")
|
||||
}
|
||||
|
||||
project.build("assembleDebug") {
|
||||
assertSuccessful()
|
||||
assertKaptSuccessful()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
open fun testDatabinding() {
|
||||
val project = Project("android-databinding", directoryPrefix = "kapt2")
|
||||
|
||||
if (!isLegacyAndroidGradleVersion(androidGradlePluginVersion)) {
|
||||
project.setupWorkingDir()
|
||||
|
||||
// With new AGP, there's no need in the Databinding kapt dependency:
|
||||
project.gradleBuildScript("app").modify {
|
||||
it.lines().filterNot {
|
||||
it.contains("kapt \"com.android.databinding:compiler")
|
||||
}.joinToString("\n")
|
||||
}
|
||||
|
||||
// Workaround for KT-24915
|
||||
project.gradleBuildScript("app").appendText(
|
||||
"\n" + """
|
||||
afterEvaluate {
|
||||
kaptDebugKotlin.dependsOn dataBindingExportFeaturePackageIdsDebug
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
setupDataBinding(project, "app")
|
||||
|
||||
project.build("assembleDebug") {
|
||||
assertSuccessful()
|
||||
@@ -165,4 +169,26 @@ open class Kapt3AndroidIT : Kapt3BaseIT() {
|
||||
assertNotContains("The following options were not recognized by any processor")
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupDataBinding(project: Project, projectName: String?) {
|
||||
if (!isLegacyAndroidGradleVersion(androidGradlePluginVersion)) {
|
||||
project.setupWorkingDir()
|
||||
|
||||
// With new AGP, there's no need in the Databinding kapt dependency:
|
||||
project.gradleBuildScript(projectName).modify {
|
||||
it.lines().filterNot {
|
||||
it.contains("kapt \"com.android.databinding:compiler")
|
||||
}.joinToString("\n")
|
||||
}
|
||||
|
||||
// Workaround for KT-24915
|
||||
project.gradleBuildScript(projectName).appendText(
|
||||
"\n" + """
|
||||
afterEvaluate {
|
||||
kaptDebugKotlin.dependsOn dataBindingExportFeaturePackageIdsDebug
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenLocal()
|
||||
jcenter()
|
||||
maven { url 'https://maven.google.com' }
|
||||
}
|
||||
dependencies {
|
||||
classpath "com.android.tools.build:gradle:$android_tools_version"
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
|
||||
android {
|
||||
compileSdkVersion 27
|
||||
buildToolsVersion "27.0.3"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "org.kotlinlang.test"
|
||||
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 27
|
||||
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
|
||||
dataBinding {
|
||||
enabled true
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
jcenter()
|
||||
maven { url 'https://maven.google.com' }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
kapt "com.android.databinding:compiler:$android_tools_version"
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.example.databinding">
|
||||
|
||||
<application android:label="test">
|
||||
<activity android:name=".MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package test
|
||||
|
||||
class CrashMe {
|
||||
private val crashMe = object : CrashMe2(1000) {
|
||||
// empty
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package test
|
||||
|
||||
abstract class CrashMe2(value: Long) {
|
||||
val crashMe2 = object : Any() {
|
||||
// empty
|
||||
}
|
||||
}
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent" android:layout_height="match_parent"
|
||||
android:orientation="vertical"/>
|
||||
</layout>
|
||||
@@ -33,8 +33,11 @@ import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.CompilerConfigurationKey
|
||||
import org.jetbrains.kotlin.config.JVMConfigurationKeys
|
||||
import org.jetbrains.kotlin.container.ComponentProvider
|
||||
import org.jetbrains.kotlin.container.StorageComponentContainer
|
||||
import org.jetbrains.kotlin.container.useInstance
|
||||
import org.jetbrains.kotlin.context.ProjectContext
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor
|
||||
import org.jetbrains.kotlin.kapt3.Kapt3CommandLineProcessor.Companion.ANNOTATION_PROCESSORS_OPTION
|
||||
import org.jetbrains.kotlin.kapt3.Kapt3CommandLineProcessor.Companion.ANNOTATION_PROCESSOR_CLASSPATH_OPTION
|
||||
import org.jetbrains.kotlin.kapt3.Kapt3CommandLineProcessor.Companion.APT_MODE_OPTION
|
||||
@@ -59,7 +62,9 @@ import org.jetbrains.kotlin.kapt3.base.log
|
||||
import org.jetbrains.kotlin.kapt3.util.MessageCollectorBackedKaptLogger
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.TargetPlatform
|
||||
import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisHandlerExtension
|
||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
|
||||
import org.jetbrains.kotlin.utils.decodePluginOptions
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.File
|
||||
@@ -314,6 +319,19 @@ class Kapt3ComponentRegistrar : ComponentRegistrar {
|
||||
)
|
||||
|
||||
AnalysisHandlerExtension.registerExtension(project, kapt3AnalysisCompletedHandlerExtension)
|
||||
StorageComponentContainerContributor.registerExtension(project, KaptComponentContributor())
|
||||
}
|
||||
|
||||
class KaptComponentContributor : StorageComponentContainerContributor {
|
||||
override fun registerModuleComponents(
|
||||
container: StorageComponentContainer,
|
||||
platform: TargetPlatform,
|
||||
moduleDescriptor: ModuleDescriptor
|
||||
) {
|
||||
if (platform != JvmPlatform) return
|
||||
container.useInstance(KaptAnonymousTypeTransformer())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* This extension simply disables both code analysis and code generation.
|
||||
@@ -340,6 +358,7 @@ class Kapt3ComponentRegistrar : ComponentRegistrar {
|
||||
return AnalysisResult.Companion.success(bindingTrace.bindingContext, module, shouldGenerateCode = false)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
enum class AptMode {
|
||||
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility
|
||||
import org.jetbrains.kotlin.resolve.DeclarationSignatureAnonymousTypeTransformer
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.isAnonymousObject
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
||||
import org.jetbrains.kotlin.types.replace
|
||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||
import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
|
||||
|
||||
class KaptAnonymousTypeTransformer : DeclarationSignatureAnonymousTypeTransformer {
|
||||
override fun transformAnonymousType(descriptor: DeclarationDescriptorWithVisibility, type: KotlinType): KotlinType? {
|
||||
if (DescriptorUtils.isLocal(descriptor))
|
||||
return type
|
||||
|
||||
return convertPossiblyAnonymousType(type)
|
||||
}
|
||||
|
||||
private fun convertPossiblyAnonymousType(type: KotlinType): KotlinType {
|
||||
val declaration = type.constructor.declarationDescriptor as? ClassDescriptor ?: return type
|
||||
|
||||
if (KotlinBuiltIns.isArray(type)) {
|
||||
val elementTypeProjection = type.arguments.singleOrNull()
|
||||
if (elementTypeProjection != null && !elementTypeProjection.isStarProjection) {
|
||||
return type.builtIns.getArrayType(
|
||||
elementTypeProjection.projectionKind,
|
||||
convertPossiblyAnonymousType(elementTypeProjection.type)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val actualType = when {
|
||||
isAnonymousObject(declaration) -> findMostSuitableParentForAnonymousType(declaration)
|
||||
else -> type
|
||||
}
|
||||
|
||||
if (actualType.arguments.isEmpty()) return actualType
|
||||
|
||||
val arguments = actualType.arguments.map { typeArg ->
|
||||
if (typeArg.isStarProjection)
|
||||
return@map typeArg
|
||||
|
||||
TypeProjectionImpl(typeArg.projectionKind, convertPossiblyAnonymousType(typeArg.type))
|
||||
}
|
||||
|
||||
return actualType.replace(newArguments = arguments)
|
||||
}
|
||||
|
||||
private fun findMostSuitableParentForAnonymousType(descriptor: ClassDescriptor): KotlinType {
|
||||
descriptor.getSuperClassNotAny()?.let { return it.defaultType }
|
||||
|
||||
val sortedSuperTypes = descriptor.typeConstructor.supertypes
|
||||
.sortedBy { it.constructor.declarationDescriptor?.name?.asString() ?: "" }
|
||||
|
||||
for (candidate in sortedSuperTypes) {
|
||||
if (!candidate.isAnyOrNullableAny())
|
||||
return candidate
|
||||
}
|
||||
|
||||
return descriptor.builtIns.anyType
|
||||
}
|
||||
}
|
||||
-137
@@ -1,137 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.kapt3.stubs
|
||||
|
||||
import com.sun.tools.javac.code.BoundKind
|
||||
import com.sun.tools.javac.tree.JCTree
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.kapt3.base.mapJList
|
||||
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
||||
import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.isAnonymousObject
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.types.replace
|
||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||
|
||||
class AnonymousTypeHandler(private val converter: ClassFileToSourceStubConverter) {
|
||||
fun <T : JCTree.JCExpression?> getNonAnonymousType(descriptor: DeclarationDescriptor?, f: () -> T): T {
|
||||
val classType = when (descriptor) {
|
||||
is ClassDescriptor -> descriptor.defaultType
|
||||
is CallableDescriptor -> descriptor.returnType
|
||||
else -> null
|
||||
} ?: return f()
|
||||
|
||||
return getNonAnonymousType(classType, f)
|
||||
}
|
||||
|
||||
fun <T : JCTree.JCExpression?> getNonAnonymousType(type: KotlinType, f: () -> T): T {
|
||||
if (!checkIfAnonymousRecursively(type)) return f()
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return convertKotlinType(convertPossiblyAnonymousType(type)) as T
|
||||
}
|
||||
|
||||
private fun checkIfAnonymousRecursively(type: KotlinType): Boolean {
|
||||
val declaration = type.constructor.declarationDescriptor as? ClassDescriptor ?: return false
|
||||
if (isAnonymousObject(declaration)) return true
|
||||
return type.arguments.any {
|
||||
if (it.isStarProjection) return@any false
|
||||
checkIfAnonymousRecursively(it.type)
|
||||
}
|
||||
}
|
||||
|
||||
private fun convertPossiblyAnonymousType(type: KotlinType): KotlinType {
|
||||
val declaration = type.constructor.declarationDescriptor as? ClassDescriptor ?: return type
|
||||
|
||||
if (KotlinBuiltIns.isArray(type)) {
|
||||
val elementTypeProjection = type.arguments.singleOrNull()
|
||||
if (elementTypeProjection != null && !elementTypeProjection.isStarProjection) {
|
||||
return type.builtIns.getArrayType(
|
||||
elementTypeProjection.projectionKind,
|
||||
convertPossiblyAnonymousType(elementTypeProjection.type)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val actualType = when {
|
||||
isAnonymousObject(declaration) -> findMostSuitableParentForAnonymousType(declaration)
|
||||
else -> type
|
||||
}
|
||||
|
||||
if (actualType.arguments.isEmpty()) return actualType
|
||||
|
||||
val arguments = actualType.arguments.map { typeArg ->
|
||||
if (typeArg.isStarProjection) return@map typeArg
|
||||
TypeProjectionImpl(typeArg.projectionKind, convertPossiblyAnonymousType(typeArg.type))
|
||||
}
|
||||
|
||||
return actualType.replace(arguments)
|
||||
}
|
||||
|
||||
private fun findMostSuitableParentForAnonymousType(descriptor: ClassDescriptor): KotlinType {
|
||||
descriptor.getSuperClassNotAny()?.let { return it.defaultType }
|
||||
|
||||
val sortedSuperTypes = descriptor.typeConstructor.supertypes
|
||||
.sortedBy { it.constructor.declarationDescriptor?.name?.asString() ?: "" }
|
||||
|
||||
for (candidate in sortedSuperTypes) {
|
||||
if (!candidate.isAnyOrNullableAny()) return candidate
|
||||
}
|
||||
|
||||
return descriptor.builtIns.anyType
|
||||
}
|
||||
|
||||
private fun convertKotlinType(type: KotlinType): JCTree.JCExpression {
|
||||
val treeMaker = converter.treeMaker
|
||||
|
||||
if (KotlinBuiltIns.isArray(type)) {
|
||||
val elementTypeProjection = type.arguments.single()
|
||||
|
||||
val elementType = if (elementTypeProjection.isStarProjection || elementTypeProjection.projectionKind == Variance.IN_VARIANCE) {
|
||||
type.builtIns.anyType
|
||||
} else {
|
||||
elementTypeProjection.type
|
||||
}
|
||||
|
||||
return treeMaker.TypeArray(convertKotlinType(elementType))
|
||||
}
|
||||
|
||||
val typeMapper = converter.kaptContext.generationState.typeMapper
|
||||
|
||||
// Primitive types can't be anonymous, so if we get here, we want to map a class type or its generic argument
|
||||
val selfType = treeMaker.Type(typeMapper.mapType(type, null, TypeMappingMode.GENERIC_ARGUMENT))
|
||||
if (type.arguments.isEmpty()) return selfType
|
||||
|
||||
return treeMaker.TypeApply(selfType, mapJList(type.arguments) { projection ->
|
||||
if (projection.isStarProjection) return@mapJList treeMaker.Wildcard(treeMaker.TypeBoundKind(BoundKind.UNBOUND), null)
|
||||
|
||||
val renderedArg = convertKotlinType(projection.type)
|
||||
when (projection.projectionKind) {
|
||||
Variance.INVARIANT -> renderedArg
|
||||
Variance.OUT_VARIANCE -> treeMaker.Wildcard(treeMaker.TypeBoundKind(BoundKind.EXTENDS), renderedArg)
|
||||
Variance.IN_VARIANCE -> treeMaker.Wildcard(treeMaker.TypeBoundKind(BoundKind.SUPER), renderedArg)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
+22
-24
@@ -107,8 +107,6 @@ class ClassFileToSourceStubConverter(
|
||||
|
||||
private val signatureParser = SignatureParser(treeMaker)
|
||||
|
||||
private val anonymousTypeHandler = AnonymousTypeHandler(this)
|
||||
|
||||
private val kdocCommentKeeper = KDocCommentKeeper(kaptContext)
|
||||
|
||||
private var done = false
|
||||
@@ -479,16 +477,16 @@ class ClassFileToSourceStubConverter(
|
||||
val typeExpression = if (isEnum(field.access))
|
||||
treeMaker.SimpleName(treeMaker.getQualifiedName(type).substringAfterLast('.'))
|
||||
else
|
||||
anonymousTypeHandler.getNonAnonymousType(descriptor) {
|
||||
getNonErrorType((descriptor as? CallableDescriptor)?.returnType, RETURN_TYPE,
|
||||
ktTypeProvider = {
|
||||
val fieldOrigin = (kaptContext.origins[field]?.element as? KtCallableDeclaration)
|
||||
?.takeIf { it !is KtFunction }
|
||||
getNonErrorType(
|
||||
(descriptor as? CallableDescriptor)?.returnType, RETURN_TYPE,
|
||||
ktTypeProvider = {
|
||||
val fieldOrigin = (kaptContext.origins[field]?.element as? KtCallableDeclaration)
|
||||
?.takeIf { it !is KtFunction }
|
||||
|
||||
fieldOrigin?.typeReference
|
||||
},
|
||||
ifNonError = { signatureParser.parseFieldSignature(field.signature, treeMaker.Type(type)) })
|
||||
}
|
||||
fieldOrigin?.typeReference
|
||||
},
|
||||
ifNonError = { signatureParser.parseFieldSignature(field.signature, treeMaker.Type(type)) }
|
||||
)
|
||||
|
||||
val value = field.value
|
||||
|
||||
@@ -646,19 +644,19 @@ class ClassFileToSourceStubConverter(
|
||||
}
|
||||
})
|
||||
|
||||
val returnType = anonymousTypeHandler.getNonAnonymousType(descriptor) {
|
||||
getNonErrorType(descriptor.returnType, RETURN_TYPE,
|
||||
ktTypeProvider = {
|
||||
val element = kaptContext.origins[method]?.element
|
||||
when (element) {
|
||||
is KtFunction -> element.typeReference
|
||||
is KtProperty -> if (descriptor is PropertyGetterDescriptor) element.typeReference else null
|
||||
is KtParameter -> if (descriptor is PropertyGetterDescriptor) element.typeReference else null
|
||||
else -> null
|
||||
}
|
||||
},
|
||||
ifNonError = { genericSignature.returnType })
|
||||
}
|
||||
val returnType = getNonErrorType(
|
||||
descriptor.returnType, RETURN_TYPE,
|
||||
ktTypeProvider = {
|
||||
val element = kaptContext.origins[method]?.element
|
||||
when (element) {
|
||||
is KtFunction -> element.typeReference
|
||||
is KtProperty -> if (descriptor is PropertyGetterDescriptor) element.typeReference else null
|
||||
is KtParameter -> if (descriptor is PropertyGetterDescriptor) element.typeReference else null
|
||||
else -> null
|
||||
}
|
||||
},
|
||||
ifNonError = { genericSignature.returnType }
|
||||
)
|
||||
|
||||
return Pair(genericSignature, returnType)
|
||||
}
|
||||
|
||||
+5
-1
@@ -30,7 +30,9 @@ import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor
|
||||
import org.jetbrains.kotlin.kapt3.*
|
||||
import org.jetbrains.kotlin.kapt3.Kapt3ComponentRegistrar.KaptComponentContributor
|
||||
import org.jetbrains.kotlin.kapt3.base.KaptContext
|
||||
import org.jetbrains.kotlin.kapt3.base.KaptPaths
|
||||
import org.jetbrains.kotlin.kapt3.base.doAnnotationProcessing
|
||||
@@ -105,7 +107,9 @@ abstract class AbstractKotlinKapt3Test : CodegenTestCase() {
|
||||
addAnnotationProcessingRuntimeLibrary(myEnvironment)
|
||||
|
||||
// Use light analysis mode in tests
|
||||
AnalysisHandlerExtension.registerExtension(myEnvironment.project, PartialAnalysisHandlerExtension())
|
||||
val project = myEnvironment.project
|
||||
AnalysisHandlerExtension.registerExtension(project, PartialAnalysisHandlerExtension())
|
||||
StorageComponentContainerContributor.registerExtension(project, KaptComponentContributor())
|
||||
|
||||
loadMultiFiles(files)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user