From 011019a20eec1de2bdc699ca81e5465db8d543a9 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 1 Apr 2016 14:00:29 +0200 Subject: KT-11530: when the receiver type of an extension is generic, use subclass instead of subtype check to determine applicability (subtype check doesn't work because type parameter of receiver type is unrelated to type parameter of base class) --- core/src/main/kotlin/Kotlin/DocumentationBuilder.kt | 13 +++++++++++-- core/src/test/kotlin/format/MarkdownFormatTest.kt | 4 ++++ 2 files changed, 15 insertions(+), 2 deletions(-) (limited to 'core/src') diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index 1b6ab3fd..8cead63e 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -309,14 +309,23 @@ class DocumentationBuilder val classDescriptor = extensionFunction.getExtensionClassDescriptor() ?: return@forEach val subclasses = classHierarchy[classDescriptor] ?: return@forEach subclasses.forEach { subclass -> - if (subclass.defaultType.isSubtypeOf(extensionFunction.extensionReceiverParameter!!.type) && - possiblyShadowingFunctions.none { subclass.defaultType.isSubtypeOf(it.extensionReceiverParameter!!.type) }) { + if (subclass.isExtensionApplicable(extensionFunction) && + possiblyShadowingFunctions.none { subclass.isExtensionApplicable(it) }) { refGraph.link(subclass.signature(), extensionFunction.signature(), RefKind.Extension) } } } } + private fun ClassDescriptor.isExtensionApplicable(extensionFunction: CallableMemberDescriptor): Boolean { + val receiverType = extensionFunction.extensionReceiverParameter!!.type + if (receiverType.arguments.any { it.type.constructor.declarationDescriptor is TypeParameterDescriptor }) { + val receiverClass = receiverType.constructor.declarationDescriptor + return receiverClass is ClassDescriptor && DescriptorUtils.isSubclass(this, receiverClass) + } + return defaultType.isSubtypeOf(receiverType) + } + private fun buildClassHierarchy(classes: List): Map> { val result = hashMapOf>() classes.forEach { cls -> diff --git a/core/src/test/kotlin/format/MarkdownFormatTest.kt b/core/src/test/kotlin/format/MarkdownFormatTest.kt index 508790b1..8fe45106 100644 --- a/core/src/test/kotlin/format/MarkdownFormatTest.kt +++ b/core/src/test/kotlin/format/MarkdownFormatTest.kt @@ -218,6 +218,10 @@ class MarkdownFormatTest { verifyMarkdownNodeByName("inheritedExtensions", "Bar") } + @Test fun genericInheritedExtensions() { + verifyMarkdownNodeByName("genericInheritedExtensions", "Bar") + } + @Test fun arrayAverage() { verifyMarkdownNodeByName("arrayAverage", "XArray") } -- cgit