diff options
author | Dmitry Jemerov <yole@jetbrains.com> | 2016-01-04 20:50:11 +0100 |
---|---|---|
committer | Dmitry Jemerov <yole@jetbrains.com> | 2016-01-04 20:50:11 +0100 |
commit | e0d00cba3613d092b6fa6af961378584c7c77b75 (patch) | |
tree | 9285e1d95a3869d8e6daa0481e4ab5dc4553b621 | |
parent | 2e77e004919664512f88d3ce8d28697c26f9c521 (diff) | |
download | dokka-e0d00cba3613d092b6fa6af961378584c7c77b75.tar.gz dokka-e0d00cba3613d092b6fa6af961378584c7c77b75.tar.bz2 dokka-e0d00cba3613d092b6fa6af961378584c7c77b75.zip |
StructuredFormatService restructured so that it makes more sense: we're either generating a doc for a group of overloads (which have no members) or for a single node (where a list of members can be displayed)
-rw-r--r-- | core/src/main/kotlin/Formats/StructuredFormatService.kt | 347 | ||||
-rw-r--r-- | core/testdata/format/deprecated.class.html | 11 |
2 files changed, 181 insertions, 177 deletions
diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index 941ee899..e1ca7a62 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -110,44 +110,8 @@ abstract class StructuredFormatService(locationService: LocationService, return from.relativePathTo(locationService.location(to)) } - fun appendDocumentation(location: Location, to: StringBuilder, overloads: Iterable<DocumentationNode>) { - val breakdownBySummary = overloads.groupByTo(LinkedHashMap()) { node -> node.content } - - if (breakdownBySummary.size == 1) { - formatOverloadGroup(breakdownBySummary.values.single(), location, to) - } - else { - for ((summary, items) in breakdownBySummary) { - appendAsOverloadGroup(to) { - formatOverloadGroup(items, location, to) - } - } - } - } - - private fun formatOverloadGroup(items: MutableList<DocumentationNode>, location: Location, to: StringBuilder) { - items.forEach { - val rendered = languageService.render(it) - appendAsSignature(to, rendered) { - to.append(formatCode(formatText(location, rendered))) - it.appendSourceLink(to) - } - it.appendOverrides(to) - it.appendDeprecation(location, to) - } - // All items have exactly the same documentation, so we can use any item to render it - val item = items.first() - item.details(NodeKind.OverloadGroupNote).forEach { - to.append(formatText(location, it.content)) - } - to.append(formatText(location, item.content.summary)) - appendDescription(location, to, item) - appendLine(to) - appendLine(to) - } - private fun DocumentationNode.isModuleOrPackage(): Boolean = - kind == NodeKind.Module || kind == NodeKind.Package + kind == NodeKind.Module || kind == NodeKind.Package protected open fun appendAsSignature(to: StringBuilder, node: ContentNode, block: () -> Unit) { block() @@ -157,37 +121,9 @@ abstract class StructuredFormatService(locationService: LocationService, block() } - fun appendDescription(location: Location, to: StringBuilder, node: DocumentationNode) { - if (node.content.description != ContentEmpty) { - appendLine(to, formatText(location, node.content.description)) - appendLine(to) - } - node.content.getSectionsWithSubjects().forEach { - appendSectionWithSubject(it.key, location, it.value, to) - } - - for (section in node.content.sections.filter { it.subjectName == null }) { - appendLine(to, formatStrong(formatText(section.tag))) - appendLine(to, formatText(location, section)) - } - } - fun Content.getSectionsWithSubjects(): Map<String, List<ContentSection>> = sections.filter { it.subjectName != null }.groupBy { it.tag } - fun appendSectionWithSubject(title: String, location: Location, subjectSections: List<ContentSection>, to: StringBuilder) { - appendHeader(to, title, 3) - subjectSections.forEach { - val subjectName = it.subjectName - if (subjectName != null) { - appendAnchor(to, subjectName) - to.append(formatCode(subjectName)).append(" - ") - to.append(formatText(location, it)) - appendLine(to) - } - } - } - private fun DocumentationNode.appendOverrides(to: StringBuilder) { overrides.forEach { to.append("Overrides ") @@ -224,110 +160,132 @@ abstract class StructuredFormatService(locationService: LocationService, } } - fun appendLocation(location: Location, to: StringBuilder, nodes: Iterable<DocumentationNode>) { - val singleNode = nodes.singleOrNull() - if (singleNode != null && singleNode.isModuleOrPackage()) { - if (singleNode.kind == NodeKind.Package) { - appendHeader(to, "Package " + formatText(singleNode.name), 2) - } - to.append(formatText(location, singleNode.content)) + private fun ContentNode.signatureToText(location: Location): String { + return if (this is ContentBlock && this.isEmpty()) { + "" } else { - val breakdownByName = nodes.groupBy { node -> node.name } - for ((name, items) in breakdownByName) { - appendHeader(to, formatText(name)) - appendDocumentation(location, to, items) - } + val signatureAsCode = ContentCode() + signatureAsCode.append(this) + formatText(location, signatureAsCode) } } - private fun appendSection(location: Location, caption: String, nodes: List<DocumentationNode>, node: DocumentationNode, to: StringBuilder) { - if (nodes.any()) { - appendHeader(to, caption, 3) + open inner class PageBuilder(val location: Location, val to: StringBuilder, val nodes: Iterable<DocumentationNode>) { + open fun build() { + val breakdownByLocation = nodes.groupBy { node -> + formatBreadcrumbs(node.path.filterNot { it.name.isEmpty() }.map { link(node, it) }) + } - val children = nodes.sortedBy { it.name } - val membersMap = children.groupBy { link(node, it) } + for ((breadcrumbs, items) in breakdownByLocation) { + appendLine(to, breadcrumbs) + appendLine(to) + appendLocation(items.filter { it.kind != NodeKind.ExternalClass }) + } + } - appendTable(to) { - appendTableBody(to) { - for ((memberLocation, members) in membersMap) { - appendTableRow(to) { - appendTableCell(to) { - to.append(formatLink(memberLocation)) - } - appendTableCell(to) { - val breakdownBySummary = members.groupBy { formatText(location, it.summary) } - for ((summary, items) in breakdownBySummary) { - appendSummarySignatures(items, location, to) - if (!summary.isEmpty()) { - to.append(summary) - } - } - } - } - } + private fun appendLocation(nodes: Iterable<DocumentationNode>) { + val singleNode = nodes.singleOrNull() + if (singleNode != null && singleNode.isModuleOrPackage()) { + if (singleNode.kind == NodeKind.Package) { + appendHeader(to, "Package " + formatText(singleNode.name), 2) + } + to.append(formatText(location, singleNode.content)) + } else { + val breakdownByName = nodes.groupBy { node -> node.name } + for ((name, items) in breakdownByName) { + appendHeader(to, formatText(name)) + appendDocumentation(items) } } } - } - private fun appendSummarySignatures(items: List<DocumentationNode>, location: Location, to: StringBuilder) { - val summarySignature = languageService.summarizeSignatures(items) - if (summarySignature != null) { - appendAsSignature(to, summarySignature) { - appendLine(to, summarySignature.signatureToText(location)) + private fun appendDocumentation(overloads: Iterable<DocumentationNode>) { + val breakdownBySummary = overloads.groupByTo(LinkedHashMap()) { node -> node.content } + + if (breakdownBySummary.size == 1) { + formatOverloadGroup(breakdownBySummary.values.single()) + } else { + for ((summary, items) in breakdownBySummary) { + appendAsOverloadGroup(to) { + formatOverloadGroup(items) + } + } } - return } - val renderedSignatures = items.map { languageService.render(it, RenderMode.SUMMARY) } - renderedSignatures.subList(0, renderedSignatures.size - 1).forEach { - appendAsSignature(to, it) { - appendLine(to, it.signatureToText(location)) + + private fun formatOverloadGroup(items: MutableList<DocumentationNode>) { + items.forEach { + val rendered = languageService.render(it) + appendAsSignature(to, rendered) { + to.append(formatCode(formatText(location, rendered))) + it.appendSourceLink(to) + } + it.appendOverrides(to) + it.appendDeprecation(location, to) } + // All items have exactly the same documentation, so we can use any item to render it + val item = items.first() + item.details(NodeKind.OverloadGroupNote).forEach { + to.append(formatText(location, it.content)) + } + to.append(formatText(location, item.content.summary)) + appendDescription(item) + appendLine(to) + appendLine(to) } - appendAsSignature(to, renderedSignatures.last()) { - to.append(renderedSignatures.last().signatureToText(location)) + + private fun appendDescription(node: DocumentationNode) { + if (node.content.description != ContentEmpty) { + appendLine(to, formatText(location, node.content.description)) + appendLine(to) + } + node.content.getSectionsWithSubjects().forEach { + appendSectionWithSubject(it.key, it.value) + } + + for (section in node.content.sections.filter { it.subjectName == null }) { + appendLine(to, formatStrong(formatText(section.tag))) + appendLine(to, formatText(location, section)) + } } - } - private fun ContentNode.signatureToText(location: Location): String { - return if (this is ContentBlock && this.isEmpty()) { - "" - } else { - val signatureAsCode = ContentCode() - signatureAsCode.append(this) - formatText(location, signatureAsCode) + fun appendSectionWithSubject(title: String, subjectSections: List<ContentSection>) { + appendHeader(to, title, 3) + subjectSections.forEach { + val subjectName = it.subjectName + if (subjectName != null) { + appendAnchor(to, subjectName) + to.append(formatCode(subjectName)).append(" - ") + to.append(formatText(location, it)) + appendLine(to) + } + } } } - override fun appendNodes(location: Location, to: StringBuilder, nodes: Iterable<DocumentationNode>) { - val breakdownByLocation = nodes.groupBy { node -> - formatBreadcrumbs(node.path.filterNot { it.name.isEmpty() }.map { link(node, it) }) - } + inner class SingleNodePageBuilder(location: Location, to: StringBuilder, val node: DocumentationNode) + : PageBuilder(location, to, listOf(node)) { - for ((breadcrumbs, items) in breakdownByLocation) { - appendLine(to, breadcrumbs) - appendLine(to) - appendLocation(location, to, items.filter { it.kind != NodeKind.ExternalClass }) - } + override fun build() { + super.build() - for (node in nodes) { if (node.kind == NodeKind.ExternalClass) { - appendSection(location, "Extensions for ${node.name}", node.members, node, to) - continue + appendSection("Extensions for ${node.name}", node.members) + return } - appendSection(location, "Packages", node.members(NodeKind.Package), node, to) - appendSection(location, "Types", node.members.filter { it.kind in NodeKind.classLike }, node, to) - appendSection(location, "Extensions for External Classes", node.members(NodeKind.ExternalClass), node, to) - appendSection(location, "Enum Values", node.members(NodeKind.EnumItem), node, to) - appendSection(location, "Constructors", node.members(NodeKind.Constructor), node, to) - appendSection(location, "Properties", node.members(NodeKind.Property), node, to) - appendSection(location, "Inherited Properties", node.inheritedMembers(NodeKind.Property), node, to) - appendSection(location, "Functions", node.members(NodeKind.Function), node, to) - appendSection(location, "Inherited Functions", node.inheritedMembers(NodeKind.Function), node, to) - appendSection(location, "Companion Object Properties", node.members(NodeKind.CompanionObjectProperty), node, to) - appendSection(location, "Companion Object Functions", node.members(NodeKind.CompanionObjectFunction), node, to) - appendSection(location, "Other members", node.members.filter { + appendSection("Packages", node.members(NodeKind.Package)) + appendSection("Types", node.members.filter { it.kind in NodeKind.classLike }) + appendSection("Extensions for External Classes", node.members(NodeKind.ExternalClass)) + appendSection("Enum Values", node.members(NodeKind.EnumItem)) + appendSection("Constructors", node.members(NodeKind.Constructor)) + appendSection("Properties", node.members(NodeKind.Property)) + appendSection("Inherited Properties", node.inheritedMembers(NodeKind.Property)) + appendSection("Functions", node.members(NodeKind.Function)) + appendSection("Inherited Functions", node.inheritedMembers(NodeKind.Function)) + appendSection("Companion Object Properties", node.members(NodeKind.CompanionObjectProperty)) + appendSection("Companion Object Functions", node.members(NodeKind.CompanionObjectFunction)) + appendSection("Other members", node.members.filter { it.kind !in setOf( NodeKind.Class, NodeKind.Interface, @@ -342,34 +300,91 @@ abstract class StructuredFormatService(locationService: LocationService, NodeKind.CompanionObjectFunction, NodeKind.ExternalClass, NodeKind.EnumItem - ) - }, node, to) + ) + }) val allExtensions = collectAllExtensions(node) - appendSection(location, "Extension Properties", allExtensions.filter { it.kind == NodeKind.Property }, node, to) - appendSection(location, "Extension Functions", allExtensions.filter { it.kind == NodeKind.Function }, node, to) - appendSection(location, "Companion Object Extension Properties", allExtensions.filter { it.kind == NodeKind.CompanionObjectProperty }, node, to) - appendSection(location, "Companion Object Extension Functions", allExtensions.filter { it.kind == NodeKind.CompanionObjectFunction }, node, to) - appendSection(location, "Inheritors", - node.inheritors.filter { it.kind != NodeKind.EnumItem }, node, to) - appendSection(location, "Links", node.links, node, to) - + appendSection("Extension Properties", allExtensions.filter { it.kind == NodeKind.Property }) + appendSection("Extension Functions", allExtensions.filter { it.kind == NodeKind.Function }) + appendSection("Companion Object Extension Properties", allExtensions.filter { it.kind == NodeKind.CompanionObjectProperty }) + appendSection("Companion Object Extension Functions", allExtensions.filter { it.kind == NodeKind.CompanionObjectFunction }) + appendSection("Inheritors", + node.inheritors.filter { it.kind != NodeKind.EnumItem }) + appendSection("Links", node.links) } - } - private fun collectAllExtensions(node: DocumentationNode): Collection<DocumentationNode> { - val result = LinkedHashSet<DocumentationNode>() - val visited = hashSetOf<DocumentationNode>() + private fun appendSection(caption: String, members: List<DocumentationNode>) { + if (members.isEmpty()) return + + appendHeader(to, caption, 3) + + val children = members.sortedBy { it.name } + val membersMap = children.groupBy { link(node, it) } + + appendTable(to) { + appendTableBody(to) { + for ((memberLocation, members) in membersMap) { + appendTableRow(to) { + appendTableCell(to) { + to.append(formatLink(memberLocation)) + } + appendTableCell(to) { + val breakdownBySummary = members.groupBy { formatText(location, it.summary) } + for ((summary, items) in breakdownBySummary) { + appendSummarySignatures(items) + if (!summary.isEmpty()) { + to.append(summary) + } + } + } + } + } + } + } + } - fun collect(node: DocumentationNode) { - if (!visited.add(node)) return - result.addAll(node.extensions) - node.references(RefKind.Superclass).forEach { collect(it.to) } + private fun appendSummarySignatures(items: List<DocumentationNode>) { + val summarySignature = languageService.summarizeSignatures(items) + if (summarySignature != null) { + appendAsSignature(to, summarySignature) { + appendLine(to, summarySignature.signatureToText(location)) + } + return + } + val renderedSignatures = items.map { languageService.render(it, RenderMode.SUMMARY) } + renderedSignatures.subList(0, renderedSignatures.size - 1).forEach { + appendAsSignature(to, it) { + appendLine(to, it.signatureToText(location)) + } + } + appendAsSignature(to, renderedSignatures.last()) { + to.append(renderedSignatures.last().signatureToText(location)) + } } + } - collect(node) + override fun appendNodes(location: Location, to: StringBuilder, nodes: Iterable<DocumentationNode>) { + val singleNode = nodes.singleOrNull() + if (singleNode != null) { + SingleNodePageBuilder(location, to, singleNode).build() + } + else { + PageBuilder(location, to, nodes).build() + } + } +} - return result +private fun collectAllExtensions(node: DocumentationNode): Collection<DocumentationNode> { + val result = LinkedHashSet<DocumentationNode>() + val visited = hashSetOf<DocumentationNode>() + fun collect(node: DocumentationNode) { + if (!visited.add(node)) return + result.addAll(node.extensions) + node.references(RefKind.Superclass).forEach { collect(it.to) } } -}
\ No newline at end of file + + collect(node) + + return result +} diff --git a/core/testdata/format/deprecated.class.html b/core/testdata/format/deprecated.class.html index 69da63a1..b9939cd8 100644 --- a/core/testdata/format/deprecated.class.html +++ b/core/testdata/format/deprecated.class.html @@ -26,16 +26,5 @@ <br/> <br/> <br/> -<h3>Constructors</h3> -<table> -<tbody> -<tr> -<td> -<a href="test/-c/-init-"><init></a></td> -<td> -<code><span class="identifier">C</span><span class="symbol">(</span><span class="symbol">)</span></code></td> -</tr> -</tbody> -</table> </BODY> </HTML> |