diff options
author | Dmitry Jemerov <yole@jetbrains.com> | 2016-04-01 14:00:29 +0200 |
---|---|---|
committer | Dmitry Jemerov <yole@jetbrains.com> | 2016-04-01 14:00:29 +0200 |
commit | 011019a20eec1de2bdc699ca81e5465db8d543a9 (patch) | |
tree | df748eb347a1a84270f6802b4755b6a42273b4af /core | |
parent | 792ae5c4099c7a37815888cd1313404375453eea (diff) | |
download | dokka-011019a20eec1de2bdc699ca81e5465db8d543a9.tar.gz dokka-011019a20eec1de2bdc699ca81e5465db8d543a9.tar.bz2 dokka-011019a20eec1de2bdc699ca81e5465db8d543a9.zip |
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)
Diffstat (limited to 'core')
-rw-r--r-- | core/src/main/kotlin/Kotlin/DocumentationBuilder.kt | 13 | ||||
-rw-r--r-- | core/src/test/kotlin/format/MarkdownFormatTest.kt | 4 | ||||
-rw-r--r-- | core/testdata/format/genericInheritedExtensions.kt | 11 | ||||
-rw-r--r-- | core/testdata/format/genericInheritedExtensions.md | 21 |
4 files changed, 47 insertions, 2 deletions
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<ClassDescriptor>): Map<ClassDescriptor, List<ClassDescriptor>> { val result = hashMapOf<ClassDescriptor, MutableList<ClassDescriptor>>() 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") } diff --git a/core/testdata/format/genericInheritedExtensions.kt b/core/testdata/format/genericInheritedExtensions.kt new file mode 100644 index 00000000..4c07e1e5 --- /dev/null +++ b/core/testdata/format/genericInheritedExtensions.kt @@ -0,0 +1,11 @@ +open class Foo<T> + +class Bar<T> : Foo<T>() + +fun <T> Foo<T>.first() { + +} + +fun <T> Bar<T>.second() { + +} diff --git a/core/testdata/format/genericInheritedExtensions.md b/core/testdata/format/genericInheritedExtensions.md new file mode 100644 index 00000000..e02683a9 --- /dev/null +++ b/core/testdata/format/genericInheritedExtensions.md @@ -0,0 +1,21 @@ +[test](test/index) / [Bar](test/-bar/index) + + +# Bar + +`class Bar<T> : [Foo](test/-foo/index)<T>` + + + +### Constructors + + +| [<init>](test/-bar/-init-) | `Bar()` | + + +### Extension Functions + + +| [first](test/first) | `fun <T> [Foo](test/-foo/index)<T>.first(): Unit` | +| [second](test/second) | `fun <T> [Bar](test/-bar/index)<T>.second(): Unit` | + |