From 86fd4da5676d836644d292b3c7f562e25aa20d92 Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Fri, 3 Apr 2020 20:08:23 +0300 Subject: [PATCH] [UAST] Fix mapping types containing type aliases #KT-27935 Fixed --- .../kotlin/codegen/state/KotlinTypeMapper.kt | 5 ++-- .../kotlin/codegen/state/typeMappingUtil.kt | 17 +++++++----- ...irOldFrontendDiagnosticsTestGenerated.java | 5 ++++ .../jvm/codegen/MethodSignatureMapper.kt | 8 ++++-- ...eAliasIsUsedAsATypeArgumentInOtherAlias.kt | 4 +++ ...AliasIsUsedAsATypeArgumentInOtherAlias.txt | 4 +++ .../checkers/DiagnosticsTestGenerated.java | 5 ++++ .../DiagnosticsUsingJavacTestGenerated.java | 5 ++++ .../kotlin/load/kotlin/TypeMappingMode.kt | 26 +++++++++++++++++-- .../load/kotlin/typeSignatureMapping.kt | 4 +++ .../internal/kotlinInternalUastUtils.kt | 2 +- ...eAliasExpansionWithOtherAliasInArgument.kt | 5 ++++ ...sExpansionWithOtherAliasInArgument.log.txt | 18 +++++++++++++ ...pansionWithOtherAliasInArgument.render.txt | 8 ++++++ .../tests/SimpleKotlinRenderLogTest.kt | 3 +++ 15 files changed, 106 insertions(+), 13 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/typealias/typeAliasIsUsedAsATypeArgumentInOtherAlias.kt create mode 100644 compiler/testData/diagnostics/tests/typealias/typeAliasIsUsedAsATypeArgumentInOtherAlias.txt create mode 100644 plugins/uast-kotlin/testData/TypeAliasExpansionWithOtherAliasInArgument.kt create mode 100644 plugins/uast-kotlin/testData/TypeAliasExpansionWithOtherAliasInArgument.log.txt create mode 100644 plugins/uast-kotlin/testData/TypeAliasExpansionWithOtherAliasInArgument.render.txt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.kt index b951ae1cff6..a4ae550fa5a 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.kt @@ -200,7 +200,8 @@ class KotlinTypeMapper @JvmOverloads constructor( return mapType(returnType, sw, TypeMappingMode.getModeForReturnTypeNoGeneric(isAnnotationMethod)) } - val typeMappingModeFromAnnotation = extractTypeMappingModeFromAnnotation(descriptor, returnType, isAnnotationMethod) + val typeMappingModeFromAnnotation = + extractTypeMappingModeFromAnnotation(descriptor, returnType, isAnnotationMethod, mapTypeAliases = false) if (typeMappingModeFromAnnotation != null) { return mapType(returnType, sw, typeMappingModeFromAnnotation) } @@ -1020,7 +1021,7 @@ class KotlinTypeMapper @JvmOverloads constructor( } val typeMappingMode = - extractTypeMappingModeFromAnnotation(callableDescriptor, type, isForAnnotationParameter = false) + extractTypeMappingModeFromAnnotation(callableDescriptor, type, isForAnnotationParameter = false, mapTypeAliases = false) ?: if (callableDescriptor.isMethodWithDeclarationSiteWildcards && type.arguments.isNotEmpty()) { TypeMappingMode.GENERIC_ARGUMENT // Render all wildcards } else { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/typeMappingUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/typeMappingUtil.kt index 9f4d75b97d2..662c77bfe26 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/typeMappingUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/typeMappingUtil.kt @@ -93,7 +93,8 @@ fun TypeMappingMode.updateArgumentModeFromAnnotations( return TypeMappingMode.createWithConstantDeclarationSiteWildcardsMode( skipDeclarationSiteWildcards = it, isForAnnotationParameter = isForAnnotationParameter, - needInlineClassWrapping = needInlineClassWrapping + needInlineClassWrapping = needInlineClassWrapping, + mapTypeAliases = mapTypeAliases ) } @@ -102,7 +103,8 @@ fun TypeMappingMode.updateArgumentModeFromAnnotations( skipDeclarationSiteWildcards = false, isForAnnotationParameter = isForAnnotationParameter, fallbackMode = this, - needInlineClassWrapping = needInlineClassWrapping + needInlineClassWrapping = needInlineClassWrapping, + mapTypeAliases = mapTypeAliases ) } @@ -112,16 +114,18 @@ fun TypeMappingMode.updateArgumentModeFromAnnotations( internal fun extractTypeMappingModeFromAnnotation( callableDescriptor: CallableDescriptor?, outerType: KotlinType, - isForAnnotationParameter: Boolean + isForAnnotationParameter: Boolean, + mapTypeAliases: Boolean ): TypeMappingMode? = SimpleClassicTypeSystemContext.extractTypeMappingModeFromAnnotation( - callableDescriptor?.suppressWildcardsMode(), outerType, isForAnnotationParameter + callableDescriptor?.suppressWildcardsMode(), outerType, isForAnnotationParameter, mapTypeAliases ) fun TypeSystemCommonBackendContext.extractTypeMappingModeFromAnnotation( callableSuppressWildcardsMode: Boolean?, outerType: KotlinTypeMarker, - isForAnnotationParameter: Boolean + isForAnnotationParameter: Boolean, + mapTypeAliases: Boolean ): TypeMappingMode? { val suppressWildcards = outerType.suppressWildcardsMode(this) ?: callableSuppressWildcardsMode ?: return null @@ -131,7 +135,8 @@ fun TypeSystemCommonBackendContext.extractTypeMappingModeFromAnnotation( return TypeMappingMode.createWithConstantDeclarationSiteWildcardsMode( skipDeclarationSiteWildcards = suppressWildcards, isForAnnotationParameter = isForAnnotationParameter, - needInlineClassWrapping = !outerType.typeConstructor().isInlineClass() + needInlineClassWrapping = !outerType.typeConstructor().isInlineClass(), + mapTypeAliases = mapTypeAliases ) } diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java index 301d6482c92..2ba444407ab 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java @@ -24028,6 +24028,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte runTest("compiler/testData/diagnostics/tests/typealias/typeAliasInvisibleObject.kt"); } + @TestMetadata("typeAliasIsUsedAsATypeArgumentInOtherAlias.kt") + public void testTypeAliasIsUsedAsATypeArgumentInOtherAlias() throws Exception { + runTest("compiler/testData/diagnostics/tests/typealias/typeAliasIsUsedAsATypeArgumentInOtherAlias.kt"); + } + @TestMetadata("typeAliasNotNull.kt") public void testTypeAliasNotNull() throws Exception { runTest("compiler/testData/diagnostics/tests/typealias/typeAliasNotNull.kt"); diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/MethodSignatureMapper.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/MethodSignatureMapper.kt index 19e0b3bf88e..20dbeda55b7 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/MethodSignatureMapper.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/MethodSignatureMapper.kt @@ -159,7 +159,9 @@ class MethodSignatureMapper(private val context: JvmBackendContext) { } val typeMappingModeFromAnnotation = - typeSystem.extractTypeMappingModeFromAnnotation(declaration.suppressWildcardsMode(), returnType, isAnnotationMethod) + typeSystem.extractTypeMappingModeFromAnnotation( + declaration.suppressWildcardsMode(), returnType, isAnnotationMethod, mapTypeAliases = false + ) if (typeMappingModeFromAnnotation != null) { return typeMapper.mapType(returnType, typeMappingModeFromAnnotation, sw) } @@ -259,7 +261,9 @@ class MethodSignatureMapper(private val context: JvmBackendContext) { } val mode = with(typeSystem) { - extractTypeMappingModeFromAnnotation(declaration.suppressWildcardsMode(), type, isForAnnotationParameter = false) + extractTypeMappingModeFromAnnotation( + declaration.suppressWildcardsMode(), type, isForAnnotationParameter = false, mapTypeAliases = false + ) ?: if (declaration.isMethodWithDeclarationSiteWildcards && type.argumentsCount() != 0) { TypeMappingMode.GENERIC_ARGUMENT // Render all wildcards } else { diff --git a/compiler/testData/diagnostics/tests/typealias/typeAliasIsUsedAsATypeArgumentInOtherAlias.kt b/compiler/testData/diagnostics/tests/typealias/typeAliasIsUsedAsATypeArgumentInOtherAlias.kt new file mode 100644 index 00000000000..29b48b3a2c5 --- /dev/null +++ b/compiler/testData/diagnostics/tests/typealias/typeAliasIsUsedAsATypeArgumentInOtherAlias.kt @@ -0,0 +1,4 @@ +// FIR_IDENTICAL + +typealias A = String +typealias My = (Map) -> Unit \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/typealias/typeAliasIsUsedAsATypeArgumentInOtherAlias.txt b/compiler/testData/diagnostics/tests/typealias/typeAliasIsUsedAsATypeArgumentInOtherAlias.txt new file mode 100644 index 00000000000..39097fdb9e5 --- /dev/null +++ b/compiler/testData/diagnostics/tests/typealias/typeAliasIsUsedAsATypeArgumentInOtherAlias.txt @@ -0,0 +1,4 @@ +package + +public typealias A = kotlin.String +public typealias My = (kotlin.collections.Map) -> kotlin.Unit diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index c3c801688c1..5ea99bee7e6 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -24110,6 +24110,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali runTest("compiler/testData/diagnostics/tests/typealias/typeAliasInvisibleObject.kt"); } + @TestMetadata("typeAliasIsUsedAsATypeArgumentInOtherAlias.kt") + public void testTypeAliasIsUsedAsATypeArgumentInOtherAlias() throws Exception { + runTest("compiler/testData/diagnostics/tests/typealias/typeAliasIsUsedAsATypeArgumentInOtherAlias.kt"); + } + @TestMetadata("typeAliasNotNull.kt") public void testTypeAliasNotNull() throws Exception { runTest("compiler/testData/diagnostics/tests/typealias/typeAliasNotNull.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 8db5b07f886..ade8fd0e75d 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -24030,6 +24030,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/typealias/typeAliasInvisibleObject.kt"); } + @TestMetadata("typeAliasIsUsedAsATypeArgumentInOtherAlias.kt") + public void testTypeAliasIsUsedAsATypeArgumentInOtherAlias() throws Exception { + runTest("compiler/testData/diagnostics/tests/typealias/typeAliasIsUsedAsATypeArgumentInOtherAlias.kt"); + } + @TestMetadata("typeAliasNotNull.kt") public void testTypeAliasNotNull() throws Exception { runTest("compiler/testData/diagnostics/tests/typealias/typeAliasNotNull.kt"); diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/TypeMappingMode.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/TypeMappingMode.kt index 7ae51774d80..c76a575bfb7 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/TypeMappingMode.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/TypeMappingMode.kt @@ -19,7 +19,8 @@ class TypeMappingMode private constructor( private val genericArgumentMode: TypeMappingMode? = null, val kotlinCollectionsToJavaCollections: Boolean = true, private val genericContravariantArgumentMode: TypeMappingMode? = genericArgumentMode, - private val genericInvariantArgumentMode: TypeMappingMode? = genericArgumentMode + private val genericInvariantArgumentMode: TypeMappingMode? = genericArgumentMode, + val mapTypeAliases: Boolean = false ) { companion object { /** @@ -28,6 +29,13 @@ class TypeMappingMode private constructor( @JvmField val GENERIC_ARGUMENT = TypeMappingMode() + /** + * kotlin.Int is mapped to Ljava/lang/Integer; + * Type aliases are mapped to their expanded form + */ + @JvmField + val GENERIC_ARGUMENT_UAST = TypeMappingMode(mapTypeAliases = true) + /** * see KotlinTypeMapper.forceBoxedReturnType() * This configuration should be called only for method return type @@ -41,6 +49,18 @@ class TypeMappingMode private constructor( @JvmField val DEFAULT = TypeMappingMode(genericArgumentMode = GENERIC_ARGUMENT, needPrimitiveBoxing = false, needInlineClassWrapping = false) + /** + * kotlin.Int is mapped to I + * Type aliases are mapped to their expanded form + */ + @JvmField + val DEFAULT_UAST = TypeMappingMode( + genericArgumentMode = GENERIC_ARGUMENT_UAST, + needPrimitiveBoxing = false, + needInlineClassWrapping = false, + mapTypeAliases = true + ) + /** * kotlin.Int is mapped to I * inline class Foo(val x: Int) is mapped to LFoo; @@ -133,12 +153,14 @@ class TypeMappingMode private constructor( skipDeclarationSiteWildcards: Boolean, isForAnnotationParameter: Boolean, needInlineClassWrapping: Boolean, + mapTypeAliases: Boolean, fallbackMode: TypeMappingMode? = null ) = TypeMappingMode( isForAnnotationParameter = isForAnnotationParameter, skipDeclarationSiteWildcards = skipDeclarationSiteWildcards, genericArgumentMode = fallbackMode, - needInlineClassWrapping = needInlineClassWrapping + needInlineClassWrapping = needInlineClassWrapping, + mapTypeAliases = mapTypeAliases ) } diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/typeSignatureMapping.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/typeSignatureMapping.kt index edf2754a9ec..df15f4b635f 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/typeSignatureMapping.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/kotlin/typeSignatureMapping.kt @@ -173,6 +173,10 @@ fun mapType( return type } + descriptor is TypeAliasDescriptor && mode.mapTypeAliases -> { + return mapType(descriptor.expandedType, factory, mode, typeMappingConfiguration, descriptorTypeWriter, writeGenericType) + } + else -> throw UnsupportedOperationException("Unknown type $kotlinType") } } diff --git a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/kotlinInternalUastUtils.kt b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/kotlinInternalUastUtils.kt index e52d13fcb49..fadc9497882 100644 --- a/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/kotlinInternalUastUtils.kt +++ b/plugins/uast-kotlin/src/org/jetbrains/uast/kotlin/internal/kotlinInternalUastUtils.kt @@ -285,7 +285,7 @@ internal fun KotlinType.toPsiType(lightDeclaration: PsiModifierListOwner?, conte .getLanguageVersionSettings(context) val signatureWriter = BothSignatureWriter(BothSignatureWriter.Mode.TYPE) - val typeMappingMode = if (boxed) TypeMappingMode.GENERIC_ARGUMENT else TypeMappingMode.DEFAULT + val typeMappingMode = if (boxed) TypeMappingMode.GENERIC_ARGUMENT_UAST else TypeMappingMode.DEFAULT_UAST val approximatedType = TypeApproximator(this.builtIns).approximateDeclarationType(this, true, languageVersionSettings) typeMapper.mapType(approximatedType, signatureWriter, typeMappingMode) diff --git a/plugins/uast-kotlin/testData/TypeAliasExpansionWithOtherAliasInArgument.kt b/plugins/uast-kotlin/testData/TypeAliasExpansionWithOtherAliasInArgument.kt new file mode 100644 index 00000000000..39d33c38e6b --- /dev/null +++ b/plugins/uast-kotlin/testData/TypeAliasExpansionWithOtherAliasInArgument.kt @@ -0,0 +1,5 @@ +typealias A = String +typealias My = (Map) -> Unit + +fun My.foo(x: My): My? = null +fun Map.bar(x: Map): Map? = null diff --git a/plugins/uast-kotlin/testData/TypeAliasExpansionWithOtherAliasInArgument.log.txt b/plugins/uast-kotlin/testData/TypeAliasExpansionWithOtherAliasInArgument.log.txt new file mode 100644 index 00000000000..b78a173daca --- /dev/null +++ b/plugins/uast-kotlin/testData/TypeAliasExpansionWithOtherAliasInArgument.log.txt @@ -0,0 +1,18 @@ +UFile (package = ) + UClass (name = TypeAliasExpansionWithOtherAliasInArgumentKt) + UMethod (name = foo) + UParameter (name = $this$foo) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UParameter (name = x) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UBlockExpression + UReturnExpression + ULiteralExpression (value = null) + UMethod (name = bar) + UParameter (name = $this$bar) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UParameter (name = x) + UAnnotation (fqName = org.jetbrains.annotations.NotNull) + UBlockExpression + UReturnExpression + ULiteralExpression (value = null) diff --git a/plugins/uast-kotlin/testData/TypeAliasExpansionWithOtherAliasInArgument.render.txt b/plugins/uast-kotlin/testData/TypeAliasExpansionWithOtherAliasInArgument.render.txt new file mode 100644 index 00000000000..15f95397c7e --- /dev/null +++ b/plugins/uast-kotlin/testData/TypeAliasExpansionWithOtherAliasInArgument.render.txt @@ -0,0 +1,8 @@ +public final class TypeAliasExpansionWithOtherAliasInArgumentKt { + public static final fun foo(@org.jetbrains.annotations.NotNull $this$foo: kotlin.jvm.functions.Function1,kotlin.Unit>, @org.jetbrains.annotations.NotNull x: kotlin.jvm.functions.Function1,kotlin.Unit>) : kotlin.jvm.functions.Function1,kotlin.Unit> { + return null + } + public static final fun bar(@org.jetbrains.annotations.NotNull $this$bar: java.util.Map, @org.jetbrains.annotations.NotNull x: java.util.Map) : java.util.Map { + return null + } +} diff --git a/plugins/uast-kotlin/tests/SimpleKotlinRenderLogTest.kt b/plugins/uast-kotlin/tests/SimpleKotlinRenderLogTest.kt index 70e9e95f944..eb3e0c5b251 100644 --- a/plugins/uast-kotlin/tests/SimpleKotlinRenderLogTest.kt +++ b/plugins/uast-kotlin/tests/SimpleKotlinRenderLogTest.kt @@ -150,6 +150,9 @@ class SimpleKotlinRenderLogTest : AbstractKotlinUastTest(), AbstractKotlinRender @Test fun testNonTrivialIdentifiers() = doTest("NonTrivialIdentifiers") + + @Test + fun testTypeAliasExpansionWithOtherAliasInArgument() = doTest("TypeAliasExpansionWithOtherAliasInArgument") } fun withForceUInjectionHostValue(call: () -> Unit) {