aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorDmitry Jemerov <yole@jetbrains.com>2016-04-01 14:00:29 +0200
committerDmitry Jemerov <yole@jetbrains.com>2016-04-01 14:00:29 +0200
commit011019a20eec1de2bdc699ca81e5465db8d543a9 (patch)
treedf748eb347a1a84270f6802b4755b6a42273b4af /core
parent792ae5c4099c7a37815888cd1313404375453eea (diff)
downloaddokka-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.kt13
-rw-r--r--core/src/test/kotlin/format/MarkdownFormatTest.kt4
-rw-r--r--core/testdata/format/genericInheritedExtensions.kt11
-rw-r--r--core/testdata/format/genericInheritedExtensions.md21
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&lt;T&gt;&nbsp;:&nbsp;[Foo](test/-foo/index)&lt;T&gt;`
+
+
+
+### Constructors
+
+
+| [&lt;init&gt;](test/-bar/-init-) | `Bar()` |
+
+
+### Extension Functions
+
+
+| [first](test/first) | `fun &lt;T&gt; [Foo](test/-foo/index)&lt;T&gt;.first(): Unit` |
+| [second](test/second) | `fun &lt;T&gt; [Bar](test/-bar/index)&lt;T&gt;.second(): Unit` |
+