aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Formats/StructuredFormatService.kt34
-rw-r--r--src/Kotlin/DocumentationBuilder.kt23
-rw-r--r--src/Model/DocumentationNode.kt2
-rw-r--r--test/data/classes/indirectOverride.kt9
-rw-r--r--test/data/format/overridingFunction.kt7
-rw-r--r--test/data/format/overridingFunction.md13
-rw-r--r--test/src/format/MarkdownFormatTest.kt8
-rw-r--r--test/src/model/ClassTest.kt16
8 files changed, 101 insertions, 11 deletions
diff --git a/src/Formats/StructuredFormatService.kt b/src/Formats/StructuredFormatService.kt
index 3f505e37..bfb69d1d 100644
--- a/src/Formats/StructuredFormatService.kt
+++ b/src/Formats/StructuredFormatService.kt
@@ -119,23 +119,35 @@ public abstract class StructuredFormatService(val locationService: LocationServi
for ((summary, items) in breakdownBySummary) {
items.forEach {
appendBlockCode(to, formatText(location, languageService.render(it)))
- val deprecation = it.deprecation
- if (deprecation != null) {
- val deprecationParameter = deprecation.details(DocumentationNode.Kind.Parameter).firstOrNull()
- val deprecationValue = deprecationParameter?.details(DocumentationNode.Kind.Value)?.firstOrNull()
- if (deprecationValue != null) {
- to.append(formatStrong("Deprecated: "))
- appendLine(to, formatText(deprecationValue.name.trim("\"")))
- } else {
- appendLine(to, formatStrong("Deprecated"))
- }
- }
+ it.appendOverrides(to)
+ it.appendDeprecation(to)
}
appendLine(to, summary)
appendLine(to)
}
}
+ private fun DocumentationNode.appendOverrides(to: StringBuilder) {
+ overrides.forEach {
+ to.append("Overrides ")
+ val location = locationService.relativeLocation(this, it, extension)
+ appendLine(to, formatLink(FormatLink(it.owner!!.name + "." + it.name, location)))
+ }
+ }
+
+ private fun DocumentationNode.appendDeprecation(to: StringBuilder) {
+ if (deprecation != null) {
+ val deprecationParameter = deprecation!!.details(DocumentationNode.Kind.Parameter).firstOrNull()
+ val deprecationValue = deprecationParameter?.details(DocumentationNode.Kind.Value)?.firstOrNull()
+ if (deprecationValue != null) {
+ to.append(formatStrong("Deprecated: "))
+ appendLine(to, formatText(deprecationValue.name.trim("\"")))
+ } else {
+ appendLine(to, formatStrong("Deprecated"))
+ }
+ }
+ }
+
fun appendLocation(location: Location, to: StringBuilder, nodes: Iterable<DocumentationNode>) {
val breakdownByName = nodes.groupBy { node -> node.name }
for ((name, items) in breakdownByName) {
diff --git a/src/Kotlin/DocumentationBuilder.kt b/src/Kotlin/DocumentationBuilder.kt
index 892a462e..0b978370 100644
--- a/src/Kotlin/DocumentationBuilder.kt
+++ b/src/Kotlin/DocumentationBuilder.kt
@@ -412,6 +412,14 @@ class DocumentationBuilder(val session: ResolveSession, val options: Documentati
}
}
+ val descriptor = nodeToDescriptor[node]
+ if (descriptor is FunctionDescriptor) {
+ val overrides = descriptor.getOverriddenDescriptors();
+ overrides?.forEach {
+ addOverrideLink(node, it)
+ }
+ }
+
resolveContentLinks(node, node.content)
for (child in node.members) {
@@ -422,6 +430,21 @@ class DocumentationBuilder(val session: ResolveSession, val options: Documentati
}
}
+ /**
+ * Add an override link from a function node to the node corresponding to the specified descriptor.
+ * Note that this descriptor may be contained in a class where the function is not actually overridden
+ * (just inherited from the parent), so we need to go further up the override chain to find a function
+ * which exists in the code and for which we do have a documentation node.
+ */
+ private fun addOverrideLink(node: DocumentationNode, overriddenDescriptor: FunctionDescriptor) {
+ val overriddenNode = descriptorToNode[overriddenDescriptor.getOriginal()]
+ if (overriddenNode != null) {
+ node.addReferenceTo(overriddenNode, DocumentationReference.Kind.Override)
+ } else {
+ overriddenDescriptor.getOverriddenDescriptors().forEach { addOverrideLink(node, it) }
+ }
+ }
+
fun getResolutionScope(node: DocumentationNode): DeclarationDescriptor {
val descriptor = nodeToDescriptor[node] ?: throw IllegalArgumentException("Node is not known to this context")
return descriptor
diff --git a/src/Model/DocumentationNode.kt b/src/Model/DocumentationNode.kt
index 635d1db9..6e707cce 100644
--- a/src/Model/DocumentationNode.kt
+++ b/src/Model/DocumentationNode.kt
@@ -28,6 +28,8 @@ public open class DocumentationNode(val name: String,
get() = references(DocumentationReference.Kind.Extension).map { it.to }
public val inheritors: List<DocumentationNode>
get() = references(DocumentationReference.Kind.Inheritor).map { it.to }
+ public val overrides: List<DocumentationNode>
+ get() = references(DocumentationReference.Kind.Override).map { it.to }
public val links: List<DocumentationNode>
get() = references(DocumentationReference.Kind.Link).map { it.to }
public val annotations: List<DocumentationNode>
diff --git a/test/data/classes/indirectOverride.kt b/test/data/classes/indirectOverride.kt
new file mode 100644
index 00000000..8d091b80
--- /dev/null
+++ b/test/data/classes/indirectOverride.kt
@@ -0,0 +1,9 @@
+abstract class C() {
+ abstract fun foo()
+}
+
+abstract class D(): C()
+
+class E(): D() {
+ override fun foo() {}
+}
diff --git a/test/data/format/overridingFunction.kt b/test/data/format/overridingFunction.kt
new file mode 100644
index 00000000..d7329489
--- /dev/null
+++ b/test/data/format/overridingFunction.kt
@@ -0,0 +1,7 @@
+open class C() {
+ open fun f() {}
+}
+
+class D(): C() {
+ override fun f() {}
+}
diff --git a/test/data/format/overridingFunction.md b/test/data/format/overridingFunction.md
new file mode 100644
index 00000000..b53b3e13
--- /dev/null
+++ b/test/data/format/overridingFunction.md
@@ -0,0 +1,13 @@
+[test](out.md) / [](out.md) / [D](out.md) / [f](out.md)
+
+
+# f
+
+
+```
+fun f(): Unit
+```
+
+Overrides [C.f](out.md)
+
+
diff --git a/test/src/format/MarkdownFormatTest.kt b/test/src/format/MarkdownFormatTest.kt
index f7fc6da0..580acd7c 100644
--- a/test/src/format/MarkdownFormatTest.kt
+++ b/test/src/format/MarkdownFormatTest.kt
@@ -61,4 +61,12 @@ public class MarkdownFormatTest {
markdownService.appendNodes(tempLocation, output, model.members.single().members)
}
}
+
+ Test fun overridingFunction() {
+ verifyOutput("test/data/format/overridingFunction.kt", ".md") { model, output ->
+ val classMembers = model.members.single().members.first { it.name == "D" }.members
+ markdownService.appendNodes(tempLocation, output, classMembers.filter { it.name == "f" })
+ }
+
+ }
}
diff --git a/test/src/model/ClassTest.kt b/test/src/model/ClassTest.kt
index 61bc68bd..5b9e1b1a 100644
--- a/test/src/model/ClassTest.kt
+++ b/test/src/model/ClassTest.kt
@@ -229,6 +229,22 @@ public class ClassTest {
val modifiers = details(DocumentationNode.Kind.Modifier)
assertEquals(2, modifiers.size())
assertEquals("final", modifiers[1].name)
+
+ val overrideReferences = references(DocumentationReference.Kind.Override)
+ assertEquals(1, overrideReferences.size())
+ }
+ }
+ }
+
+ Test fun indirectOverride() {
+ verifyModel("test/data/classes/indirectOverride.kt") { model ->
+ with(model.members.single().members.first { it.name == "E"}.members.first { it.name == "foo" }) {
+ val modifiers = details(DocumentationNode.Kind.Modifier)
+ assertEquals(2, modifiers.size())
+ assertEquals("final", modifiers[1].name)
+
+ val overrideReferences = references(DocumentationReference.Kind.Override)
+ assertEquals(1, overrideReferences.size())
}
}
}