Adds type and default value to parameter table for Kotlin source

Adds a lazy metadata node that we can look up when generating
the DAC parameter table so we can add type (with link support)
and default value information to the table.

Example table: (tab = space between columns)

Parameters
text: String	The text to display.
modifier: Modifier = Modifier.None	Modifier to be applied to the button.
onClick: () -> Unit = null	Will be called when the user clicks the button. The button will be disabled if it is null.
style: ButtonStyle = ContainedButtonStyle()	Contains the styling parameters for the button.

Bug: b/139411548
Bug: b/139407818
Bug: b/143536172
Test: ./gradlew core:cleanTest core:test
Change-Id: Ie62ab30ee18c082d2a486df644a1cfae8f54703b
diff --git a/core/src/main/kotlin/Formats/DacHtmlFormat.kt b/core/src/main/kotlin/Formats/DacHtmlFormat.kt
index 4e7fe38..3b70b5b 100644
--- a/core/src/main/kotlin/Formats/DacHtmlFormat.kt
+++ b/core/src/main/kotlin/Formats/DacHtmlFormat.kt
@@ -5,8 +5,8 @@
 import kotlinx.html.*
 import org.jetbrains.dokka.*
 import org.jetbrains.dokka.Samples.DevsiteSampleProcessingService
+import org.jetbrains.dokka.Kotlin.ParameterInfoNode
 import org.jetbrains.dokka.Utilities.firstSentence
-import org.w3c.dom.html.HTMLElement
 import java.lang.Math.max
 import java.net.URI
 import java.util.Collections.emptyMap
@@ -119,15 +119,25 @@
                                         +name
                                     }
                                 }
-                                sections.forEach {
+                                sections.forEach { section ->
                                     tr {
                                         td {
-                                            code {
-                                                it.subjectName?.let { +it }
+                                            val parameterInfoNode = section.children.find { it is ParameterInfoNode } as? ParameterInfoNode
+                                            // If there is no info found, just display the parameter
+                                            // name.
+                                            if (parameterInfoNode?.parameterContent == null) {
+                                                code {
+                                                    section.subjectName?.let { +it }
+                                                }
+                                            } else {
+                                                // Add already marked up type information here
+                                                metaMarkup(
+                                                    listOf(parameterInfoNode.parameterContent!!)
+                                                )
                                             }
                                         }
                                         td {
-                                            metaMarkup(it.children)
+                                            metaMarkup(section.children)
                                         }
                                     }
                                 }
diff --git a/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt b/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt
index 38dc7dd..6841503 100644
--- a/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt
+++ b/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt
@@ -20,7 +20,9 @@
 import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor
 import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
 import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.psi.KtBinaryExpressionWithTypeRHS
 import org.jetbrains.kotlin.psi.KtDeclaration
+import org.jetbrains.kotlin.psi.KtNamedFunction
 import org.jetbrains.kotlin.resolve.DescriptorUtils
 import org.jetbrains.kotlin.resolve.annotations.argumentValue
 import org.jetbrains.kotlin.resolve.constants.StringValue
@@ -96,6 +98,18 @@
                     }
                     KDocKnownTag.SEE ->
                         content.addTagToSeeAlso(contextDescriptor, it)
+                    KDocKnownTag.PARAM -> {
+                        val section = content.addSection(javadocSectionDisplayName(it.name), it.getSubjectName())
+                        section.append(ParameterInfoNode {
+                            val signature = signatureProvider.signature(descriptor)
+                            refGraph.lookupOrWarn(signature, logger)?.details?.find { node ->
+                                node.kind == NodeKind.Parameter && node.name == it.getSubjectName()
+                            }
+                        })
+                        val sectionContent = it.getContent()
+                        val markdownNode = parseMarkdown(sectionContent)
+                        buildInlineContentTo(markdownNode, section, LinkResolver(linkMap, { href -> linkResolver.resolveContentLink(contextDescriptor, href) }))
+                    }
                     else -> {
                         val section = content.addSection(javadocSectionDisplayName(it.name), it.getSubjectName())
                         val sectionContent = it.getContent()
@@ -283,3 +297,37 @@
     }
 
 }
+
+/**
+ * Lazily executed wrapper node holding a [NodeKind.Parameter] node that will be used to add type
+ * and default value information to
+ * [org.jetbrains.dokka.Formats.DevsiteLayoutHtmlFormatOutputBuilder].
+ *
+ * We make this a [ContentBlock] instead of a [ContentNode] so we won't fallback to calling
+ * [toString] on this and trying to add it to documentation somewhere - returning an empty list
+ * should make this a no-op.
+ *
+ * @property wrappedNode lazily executable lambda that will return the matching documentation node
+ * for this parameter (if it exists)
+ */
+class ParameterInfoNode(private val wrappedNode: () -> DocumentationNode?) : ContentBlock() {
+    private var computed = false
+
+    val parameterContent: NodeRenderContent?
+        get() = lazyNode
+
+    private var lazyNode: NodeRenderContent? = null
+        get() {
+            if (!computed) {
+                computed = true
+
+                val node = wrappedNode()
+                if (node != null) {
+                    field = NodeRenderContent(node, LanguageService.RenderMode.SUMMARY)
+                }
+            }
+        return field
+    }
+
+    override val children = arrayListOf<ContentNode>()
+}