From f3ed9f5fa553c72a254e5ca5d28e108849937769 Mon Sep 17 00:00:00 2001
From: Dmitry Jemerov <yole@jetbrains.com>
Date: Tue, 12 Jan 2016 19:04:53 +0100
Subject: generate all types index

---
 .../main/kotlin/Formats/StructuredFormatService.kt | 65 +++++++++++++++++++---
 .../src/main/kotlin/Kotlin/DocumentationBuilder.kt | 14 +++++
 core/src/main/kotlin/Model/DocumentationNode.kt    |  2 +
 3 files changed, 73 insertions(+), 8 deletions(-)

(limited to 'core')

diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt
index 9221004c..c9218c46 100644
--- a/core/src/main/kotlin/Formats/StructuredFormatService.kt
+++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt
@@ -98,10 +98,15 @@ abstract class StructuredFormatService(locationService: LocationService,
         }
     }
 
-    open fun link(from: DocumentationNode, to: DocumentationNode): FormatLink = link(from, to, extension)
-
-    open fun link(from: DocumentationNode, to: DocumentationNode, extension: String): FormatLink {
-        return FormatLink(to.name, locationService.relativePathToLocation(from, to))
+    open fun link(from: DocumentationNode,
+                  to: DocumentationNode,
+                  name: (DocumentationNode) -> String = DocumentationNode::name): FormatLink = link(from, to, extension, name)
+
+    open fun link(from: DocumentationNode,
+                  to: DocumentationNode,
+                  extension: String,
+                  name: (DocumentationNode) -> String = DocumentationNode::name): FormatLink {
+        return FormatLink(name(to), locationService.relativePathToLocation(from, to))
     }
 
     fun locationHref(from: Location, to: DocumentationNode): String {
@@ -279,7 +284,7 @@ abstract class StructuredFormatService(locationService: LocationService,
     }
 
     inner class SingleNodePageBuilder(location: Location, to: StringBuilder, val node: DocumentationNode)
-    : PageBuilder(location, to, listOf(node)) {
+            : PageBuilder(location, to, listOf(node)) {
 
         override fun build() {
             super.build()
@@ -319,7 +324,8 @@ abstract class StructuredFormatService(locationService: LocationService,
                         NodeKind.CompanionObjectProperty,
                         NodeKind.CompanionObjectFunction,
                         NodeKind.ExternalClass,
-                        NodeKind.EnumItem
+                        NodeKind.EnumItem,
+                        NodeKind.AllTypes
                 )
             })
 
@@ -330,7 +336,13 @@ abstract class StructuredFormatService(locationService: LocationService,
             appendSection("Companion Object Extension Functions", allExtensions.filter { it.kind == NodeKind.CompanionObjectFunction })
             appendSection("Inheritors",
                     node.inheritors.filter { it.kind != NodeKind.EnumItem })
-            appendSection("Links", node.links)
+
+            if (node.kind == NodeKind.Module) {
+                appendHeader(to, "Index", 3)
+                node.members(NodeKind.AllTypes).singleOrNull()?.let { allTypes ->
+                    to.append(formatLink(link(node, allTypes, { "All Types" })))
+                }
+            }
         }
 
         private fun appendSection(caption: String, members: List<DocumentationNode>) {
@@ -383,10 +395,47 @@ abstract class StructuredFormatService(locationService: LocationService,
         }
     }
 
+    inner class AllTypesNodeBuilder(location: Location, to: StringBuilder, val node: DocumentationNode)
+        : PageBuilder(location, to, listOf(node)) {
+
+        override fun build() {
+            to.append(formatText(location, node.owner!!.summary))
+            appendHeader(to, "All Types", 3)
+
+            appendTable(to) {
+                appendTableBody(to) {
+                    for (type in node.members) {
+                        appendTableRow(to) {
+                            appendTableCell(to) {
+                                to.append(formatLink(link(node, type) {
+                                    if (it.kind == NodeKind.ExternalClass) it.name else it.qualifiedName()
+                                }))
+                                if (type.kind == NodeKind.ExternalClass) {
+                                    val packageName = type.owner?.name
+                                    if (packageName != null) {
+                                        to.append(formatText(" (extensions in package $packageName)"))
+                                    }
+                                }
+                            }
+                            appendTableCell(to) {
+                                to.append(formatText(location, type.summary))
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
     override fun appendNodes(location: Location, to: StringBuilder, nodes: Iterable<DocumentationNode>) {
         val singleNode = nodes.singleOrNull()
         if (singleNode != null) {
-            SingleNodePageBuilder(location, to, singleNode).build()
+            if (singleNode.kind == NodeKind.AllTypes) {
+                AllTypesNodeBuilder(location, to, singleNode).build()
+            }
+            else {
+                SingleNodePageBuilder(location, to, singleNode).build()
+            }
         }
         else {
             PageBuilder(location, to, nodes).build()
diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt
index 3c4c0c39..1bc41f54 100644
--- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt
+++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt
@@ -293,6 +293,7 @@ class DocumentationBuilder
         }
 
         propagateExtensionFunctionsToSubclasses(fragments)
+        generateAllTypesNode()
     }
 
     private fun propagateExtensionFunctionsToSubclasses(fragments: Collection<PackageFragmentDescriptor>) {
@@ -356,6 +357,19 @@ class DocumentationBuilder
         return false
     }
 
+    private fun DocumentationNode.generateAllTypesNode() {
+        val allTypes = members(NodeKind.Package)
+                .flatMap { it.members.filter { it.kind in NodeKind.classLike || it.kind == NodeKind.ExternalClass } }
+                .sortedBy { if (it.kind == NodeKind.ExternalClass) it.name.substringAfterLast('.') else it.name }
+
+        val allTypesNode = DocumentationNode("alltypes", Content.Empty, NodeKind.AllTypes)
+        for (typeNode in allTypes) {
+            allTypesNode.addReferenceTo(typeNode, RefKind.Member)
+        }
+
+        append(allTypesNode, RefKind.Member)
+    }
+
     fun DeclarationDescriptor.build(): DocumentationNode = when (this) {
         is ClassDescriptor -> build()
         is ConstructorDescriptor -> build()
diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt
index f7e935b2..afa513d1 100644
--- a/core/src/main/kotlin/Model/DocumentationNode.kt
+++ b/core/src/main/kotlin/Model/DocumentationNode.kt
@@ -46,6 +46,8 @@ enum class NodeKind {
 
     ExternalLink,
 
+    AllTypes,
+
     /**
      * A note which is rendered once on a page documenting a group of overloaded functions.
      * Needs to be generated equally on all overloads.
-- 
cgit