aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Jemerov <yole@jetbrains.com>2016-01-04 20:50:11 +0100
committerDmitry Jemerov <yole@jetbrains.com>2016-01-04 20:50:11 +0100
commite0d00cba3613d092b6fa6af961378584c7c77b75 (patch)
tree9285e1d95a3869d8e6daa0481e4ab5dc4553b621
parent2e77e004919664512f88d3ce8d28697c26f9c521 (diff)
downloaddokka-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.kt347
-rw-r--r--core/testdata/format/deprecated.class.html11
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-">&lt;init&gt;</a></td>
-<td>
-<code><span class="identifier">C</span><span class="symbol">(</span><span class="symbol">)</span></code></td>
-</tr>
-</tbody>
-</table>
</BODY>
</HTML>