diff options
-rw-r--r-- | src/Formats/StructuredFormatService.kt | 34 | ||||
-rw-r--r-- | src/Kotlin/DocumentationBuilder.kt | 23 | ||||
-rw-r--r-- | src/Model/DocumentationNode.kt | 2 | ||||
-rw-r--r-- | test/data/classes/indirectOverride.kt | 9 | ||||
-rw-r--r-- | test/data/format/overridingFunction.kt | 7 | ||||
-rw-r--r-- | test/data/format/overridingFunction.md | 13 | ||||
-rw-r--r-- | test/src/format/MarkdownFormatTest.kt | 8 | ||||
-rw-r--r-- | test/src/model/ClassTest.kt | 16 |
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()) } } } |