aboutsummaryrefslogtreecommitdiff
path: root/src/Formats
diff options
context:
space:
mode:
Diffstat (limited to 'src/Formats')
-rw-r--r--src/Formats/FormatService.kt2
-rw-r--r--src/Formats/HtmlFormatService.kt12
-rw-r--r--src/Formats/JekyllFormatService.kt2
-rw-r--r--src/Formats/KotlinWebsiteFormatService.kt35
-rw-r--r--src/Formats/OutlineService.kt4
-rw-r--r--src/Formats/StructuredFormatService.kt200
6 files changed, 160 insertions, 95 deletions
diff --git a/src/Formats/FormatService.kt b/src/Formats/FormatService.kt
index 93470a4c..7e66a6b7 100644
--- a/src/Formats/FormatService.kt
+++ b/src/Formats/FormatService.kt
@@ -17,4 +17,4 @@ public interface FormatService {
}
/** Format content to [String] using specified [location] */
-fun FormatService.format(location: Location, nodes: Iterable<DocumentationNode>): String = StringBuilder { appendNodes(location, this, nodes) }.toString()
+fun FormatService.format(location: Location, nodes: Iterable<DocumentationNode>): String = StringBuilder().apply { appendNodes(location, this, nodes) }.toString()
diff --git a/src/Formats/HtmlFormatService.kt b/src/Formats/HtmlFormatService.kt
index 5dcd432b..e810ef7f 100644
--- a/src/Formats/HtmlFormatService.kt
+++ b/src/Formats/HtmlFormatService.kt
@@ -114,13 +114,13 @@ public open class HtmlFormatService @Inject constructor(@Named("folders") locati
override fun appendNodes(location: Location, to: StringBuilder, nodes: Iterable<DocumentationNode>) {
templateService.appendHeader(to, getPageTitle(nodes))
- super<StructuredFormatService>.appendNodes(location, to, nodes)
+ super.appendNodes(location, to, nodes)
templateService.appendFooter(to)
}
override fun appendOutline(location: Location, to: StringBuilder, nodes: Iterable<DocumentationNode>) {
templateService.appendHeader(to, "Module Contents")
- super<OutlineFormatService>.appendOutline(location, to, nodes)
+ super.appendOutline(location, to, nodes)
templateService.appendFooter(to)
}
@@ -146,16 +146,16 @@ public open class HtmlFormatService @Inject constructor(@Named("folders") locati
fun getPageTitle(nodes: Iterable<DocumentationNode>): String? {
val breakdownByLocation = nodes.groupBy { node -> formatPageTitle(node) }
- return breakdownByLocation.keySet().singleOrNull()
+ return breakdownByLocation.keys.singleOrNull()
}
fun formatPageTitle(node: DocumentationNode): String {
val path = node.path
- if (path.size() == 1) {
+ if (path.size == 1) {
return path.first().name
}
- val qualifiedName = path.drop(1).map { it.name }.filter { it.length() > 0 }.join(".")
- if (qualifiedName.length() == 0 && path.size() == 2) {
+ val qualifiedName = node.qualifiedName()
+ if (qualifiedName.length == 0 && path.size == 2) {
return path.first().name + " / root package"
}
return path.first().name + " / " + qualifiedName
diff --git a/src/Formats/JekyllFormatService.kt b/src/Formats/JekyllFormatService.kt
index 113f229f..75684ac2 100644
--- a/src/Formats/JekyllFormatService.kt
+++ b/src/Formats/JekyllFormatService.kt
@@ -11,7 +11,7 @@ public open class JekyllFormatService @Inject constructor(locationService: Locat
appendFrontMatter(nodes, to)
to.appendln("---")
to.appendln("")
- super<MarkdownFormatService>.appendNodes(location, to, nodes)
+ super.appendNodes(location, to, nodes)
}
protected open fun appendFrontMatter(nodes: Iterable<DocumentationNode>, to: StringBuilder) {
diff --git a/src/Formats/KotlinWebsiteFormatService.kt b/src/Formats/KotlinWebsiteFormatService.kt
index 8fbebaae..25491cb3 100644
--- a/src/Formats/KotlinWebsiteFormatService.kt
+++ b/src/Formats/KotlinWebsiteFormatService.kt
@@ -5,6 +5,7 @@ import com.google.inject.Inject
public class KotlinWebsiteFormatService @Inject constructor(locationService: LocationService,
signatureGenerator: LanguageService)
: JekyllFormatService(locationService, signatureGenerator) {
+ private var needHardLineBreaks = false
override fun appendFrontMatter(nodes: Iterable<DocumentationNode>, to: StringBuilder) {
super.appendFrontMatter(nodes, to)
@@ -23,16 +24,27 @@ public class KotlinWebsiteFormatService @Inject constructor(locationService: Loc
return ""
}
- override public fun formatCode(code: String): String = if (code.length() > 0) "<code>$code</code>" else ""
+ override public fun formatCode(code: String): String = if (code.length > 0) "<code>$code</code>" else ""
override fun formatStrikethrough(text: String): String = "<s>$text</s>"
- override fun appendAsSignature(to: StringBuilder, block: () -> Unit) {
- val oldLength = to.length()
- block()
- if (to.length() > oldLength) {
- to.append("<br/>") // since we've used HTML to format the signature, add an HTML line break following it
+ override fun appendAsSignature(to: StringBuilder, node: ContentNode, block: () -> Unit) {
+ val contentLength = node.textLength
+ if (contentLength == 0) return
+ to.append("<div class=\"signature\">")
+ needHardLineBreaks = contentLength >= 62
+ try {
+ block()
+ } finally {
+ needHardLineBreaks = false
}
+ to.append("</div>")
+ }
+
+ override fun appendAsOverloadGroup(to: StringBuilder, block: () -> Unit) {
+ to.append("<div class=\"overload-group\">\n")
+ block()
+ to.append("</div>\n")
}
override fun formatLink(text: String, href: String): String {
@@ -91,8 +103,19 @@ public class KotlinWebsiteFormatService @Inject constructor(locationService: Loc
return "<span class=\"${identifierClassName(kind)}\">${formatText(text)}</span>"
}
+ override fun formatSoftLineBreak(): String = if (needHardLineBreaks)
+ "<br/>"
+ else
+ ""
+
+ override fun formatIndentedSoftLineBreak(): String = if (needHardLineBreaks)
+ "<br/>&nbsp;&nbsp;&nbsp;&nbsp;"
+ else
+ ""
+
private fun identifierClassName(kind: IdentifierKind) = when(kind) {
IdentifierKind.ParameterName -> "parameterName"
+ IdentifierKind.SummarizedTypeName -> "summarizedTypeName"
else -> "identifier"
}
}
diff --git a/src/Formats/OutlineService.kt b/src/Formats/OutlineService.kt
index 6c7e882e..6626cf51 100644
--- a/src/Formats/OutlineService.kt
+++ b/src/Formats/OutlineService.kt
@@ -16,7 +16,7 @@ public interface OutlineFormatService {
for (node in nodes) {
appendOutlineHeader(location, node, to)
if (node.members.any()) {
- val sortedMembers = node.members.sortBy { it.name }
+ val sortedMembers = node.members.sortedBy { it.name }
appendOutlineLevel(to) {
appendOutline(location, to, sortedMembers)
}
@@ -25,5 +25,5 @@ public interface OutlineFormatService {
}
fun formatOutline(location: Location, nodes: Iterable<DocumentationNode>): String =
- StringBuilder { appendOutline(location, this, nodes) }.toString()
+ StringBuilder().apply { appendOutline(location, this, nodes) }.toString()
}
diff --git a/src/Formats/StructuredFormatService.kt b/src/Formats/StructuredFormatService.kt
index 1c2e5338..41ffc61d 100644
--- a/src/Formats/StructuredFormatService.kt
+++ b/src/Formats/StructuredFormatService.kt
@@ -1,62 +1,66 @@
package org.jetbrains.dokka
-import java.util.LinkedHashMap
import org.jetbrains.dokka.LanguageService.RenderMode
+import java.util.*
-public data class FormatLink(val text: String, val href: String)
+data class FormatLink(val text: String, val href: String)
enum class ListKind {
Ordered,
Unordered
}
-public abstract class StructuredFormatService(locationService: LocationService,
+abstract class StructuredFormatService(locationService: LocationService,
val languageService: LanguageService,
override val extension: String) : FormatService {
val locationService: LocationService = locationService.withExtension(extension)
- abstract public fun appendBlockCode(to: StringBuilder, line: String, language: String)
- abstract public fun appendHeader(to: StringBuilder, text: String, level: Int = 1)
- abstract public fun appendParagraph(to: StringBuilder, text: String)
- abstract public fun appendLine(to: StringBuilder, text: String)
- public abstract fun appendLine(to: StringBuilder)
- public abstract fun appendAnchor(to: StringBuilder, anchor: String)
-
- public abstract fun appendTable(to: StringBuilder, body: () -> Unit)
- public abstract fun appendTableHeader(to: StringBuilder, body: () -> Unit)
- public abstract fun appendTableBody(to: StringBuilder, body: () -> Unit)
- public abstract fun appendTableRow(to: StringBuilder, body: () -> Unit)
- public abstract fun appendTableCell(to: StringBuilder, body: () -> Unit)
-
- public abstract fun formatText(text: String): String
- public abstract fun formatSymbol(text: String): String
- public abstract fun formatKeyword(text: String): String
- public abstract fun formatIdentifier(text: String, kind: IdentifierKind): String
- public fun formatEntity(text: String): String = text
- public abstract fun formatLink(text: String, href: String): String
- public open fun formatLink(link: FormatLink): String = formatLink(formatText(link.text), link.href)
- public abstract fun formatStrong(text: String): String
- public abstract fun formatStrikethrough(text: String): String
- public abstract fun formatEmphasis(text: String): String
- public abstract fun formatCode(code: String): String
- public abstract fun formatUnorderedList(text: String): String
- public abstract fun formatOrderedList(text: String): String
- public abstract fun formatListItem(text: String, kind: ListKind): String
- public abstract fun formatBreadcrumbs(items: Iterable<FormatLink>): String
- public abstract fun formatNonBreakingSpace(): String
+ abstract fun appendBlockCode(to: StringBuilder, line: String, language: String)
+ abstract fun appendHeader(to: StringBuilder, text: String, level: Int = 1)
+ abstract fun appendParagraph(to: StringBuilder, text: String)
+ abstract fun appendLine(to: StringBuilder, text: String)
+ abstract fun appendLine(to: StringBuilder)
+ abstract fun appendAnchor(to: StringBuilder, anchor: String)
+
+ abstract fun appendTable(to: StringBuilder, body: () -> Unit)
+ abstract fun appendTableHeader(to: StringBuilder, body: () -> Unit)
+ abstract fun appendTableBody(to: StringBuilder, body: () -> Unit)
+ abstract fun appendTableRow(to: StringBuilder, body: () -> Unit)
+ abstract fun appendTableCell(to: StringBuilder, body: () -> Unit)
+
+ abstract fun formatText(text: String): String
+ abstract fun formatSymbol(text: String): String
+ abstract fun formatKeyword(text: String): String
+ abstract fun formatIdentifier(text: String, kind: IdentifierKind): String
+ fun formatEntity(text: String): String = text
+ abstract fun formatLink(text: String, href: String): String
+ open fun formatLink(link: FormatLink): String = formatLink(formatText(link.text), link.href)
+ abstract fun formatStrong(text: String): String
+ abstract fun formatStrikethrough(text: String): String
+ abstract fun formatEmphasis(text: String): String
+ abstract fun formatCode(code: String): String
+ abstract fun formatUnorderedList(text: String): String
+ abstract fun formatOrderedList(text: String): String
+ abstract fun formatListItem(text: String, kind: ListKind): String
+ abstract fun formatBreadcrumbs(items: Iterable<FormatLink>): String
+ abstract fun formatNonBreakingSpace(): String
+ open fun formatSoftLineBreak(): String = ""
+ open fun formatIndentedSoftLineBreak(): String = ""
open fun formatText(location: Location, nodes: Iterable<ContentNode>, listKind: ListKind = ListKind.Unordered): String {
- return nodes.map { formatText(location, it, listKind) }.join("")
+ return nodes.map { formatText(location, it, listKind) }.joinToString("")
}
open fun formatText(location: Location, content: ContentNode, listKind: ListKind = ListKind.Unordered): String {
- return StringBuilder {
+ return StringBuilder().apply {
when (content) {
is ContentText -> append(formatText(content.text))
is ContentSymbol -> append(formatSymbol(content.text))
is ContentKeyword -> append(formatKeyword(content.text))
is ContentIdentifier -> append(formatIdentifier(content.text, content.kind))
is ContentNonBreakingSpace -> append(formatNonBreakingSpace())
+ is ContentSoftLineBreak -> append(formatSoftLineBreak())
+ is ContentIndentedSoftLineBreak -> append(formatIndentedSoftLineBreak())
is ContentEntity -> append(formatEntity(content.text))
is ContentStrong -> append(formatStrong(formatText(location, content.children)))
is ContentStrikethrough -> append(formatStrikethrough(formatText(location, content.children)))
@@ -92,9 +96,9 @@ public abstract class StructuredFormatService(locationService: LocationService,
}.toString()
}
- open public fun link(from: DocumentationNode, to: DocumentationNode): FormatLink = link(from, to, extension)
+ open fun link(from: DocumentationNode, to: DocumentationNode): FormatLink = link(from, to, extension)
- open public fun link(from: DocumentationNode, to: DocumentationNode, extension: String): FormatLink {
+ open fun link(from: DocumentationNode, to: DocumentationNode, extension: String): FormatLink {
return FormatLink(to.name, locationService.relativePathToLocation(from, to))
}
@@ -110,41 +114,47 @@ public abstract class StructuredFormatService(locationService: LocationService,
val breakdownBySummary = overloads.groupByTo(LinkedHashMap()) { node -> node.content }
for ((summary, items) in breakdownBySummary) {
- items.forEach {
- appendAsSignature(to) {
- to.append(formatCode(formatText(location, languageService.render(it))))
- it.appendSourceLink(to)
+ appendAsOverloadGroup(to) {
+ 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)
}
- 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(DocumentationNode.Kind.OverloadGroupNote).forEach {
- to.append(formatText(location, it.content))
+ // All items have exactly the same documentation, so we can use any item to render it
+ val item = items.first()
+ item.details(DocumentationNode.Kind.OverloadGroupNote).forEach {
+ to.append(formatText(location, it.content))
+ }
+ to.append(formatText(location, item.content.summary))
+ appendDescription(location, to, item)
+ appendLine(to)
+ appendLine(to)
}
- to.append(formatText(location, item.content.summary))
- appendDescription(location, to, item)
- appendLine(to)
- appendLine(to)
}
}
private fun DocumentationNode.isModuleOrPackage(): Boolean =
kind == DocumentationNode.Kind.Module || kind == DocumentationNode.Kind.Package
- protected open fun appendAsSignature(to: StringBuilder, block: () -> Unit) {
+ protected open fun appendAsSignature(to: StringBuilder, node: ContentNode, block: () -> Unit) {
+ block()
+ }
+
+ protected open fun appendAsOverloadGroup(to: StringBuilder, block: () -> Unit) {
block()
}
fun appendDescription(location: Location, to: StringBuilder, node: DocumentationNode) {
if (node.content.description != ContentEmpty) {
- appendHeader(to, ContentTags.Description, 3)
appendLine(to, formatText(location, node.content.description))
appendLine(to)
}
node.content.getSectionsWithSubjects().forEach {
- appendSectionWithSubject(it.getKey(), location, it.getValue(), to)
+ appendSectionWithSubject(it.key, location, it.value, to)
}
for (section in node.content.sections.filter { it.subjectName == null }) {
@@ -221,11 +231,11 @@ public abstract class StructuredFormatService(locationService: LocationService,
}
}
- private fun StructuredFormatService.appendSection(location: Location, caption: String, nodes: List<DocumentationNode>, node: DocumentationNode, to: StringBuilder) {
+ private fun appendSection(location: Location, caption: String, nodes: List<DocumentationNode>, node: DocumentationNode, to: StringBuilder) {
if (nodes.any()) {
appendHeader(to, caption, 3)
- val children = nodes.sortBy { it.name }
+ val children = nodes.sortedBy { it.name }
val membersMap = children.groupBy { link(node, it) }
appendTable(to) {
@@ -238,24 +248,7 @@ public abstract class StructuredFormatService(locationService: LocationService,
appendTableCell(to) {
val breakdownBySummary = members.groupBy { formatText(location, it.summary) }
for ((summary, items) in breakdownBySummary) {
- val signatureTexts = items map { signature ->
- val signatureText = languageService.render(signature, RenderMode.SUMMARY)
- if (signatureText is ContentBlock && signatureText.isEmpty()) {
- ""
- } else {
- val signatureAsCode = ContentCode()
- signatureAsCode.append(signatureText)
- formatText(location, signatureAsCode)
- }
- }
- signatureTexts.subList(0, signatureTexts.size()-1).forEach {
- appendAsSignature(to) {
- appendLine(to, it)
- }
- }
- appendAsSignature(to) {
- to.append(signatureTexts.last())
- }
+ appendSummarySignatures(items, location, to)
if (!summary.isEmpty()) {
to.append(summary)
}
@@ -268,6 +261,35 @@ public abstract class StructuredFormatService(locationService: LocationService,
}
}
+ 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))
+ }
+ 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))
+ }
+ }
+
+ private fun ContentNode.signatureToText(location: Location): String {
+ return if (this is ContentBlock && this.isEmpty()) {
+ ""
+ } else {
+ val signatureAsCode = ContentCode()
+ signatureAsCode.append(this)
+ formatText(location, signatureAsCode)
+ }
+ }
+
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) })
@@ -295,12 +317,14 @@ public abstract class StructuredFormatService(locationService: LocationService,
DocumentationNode.Kind.AnnotationClass)
}, node, to)
appendSection(location, "Extensions for External Classes", node.members(DocumentationNode.Kind.ExternalClass), node, to)
+ appendSection(location, "Enum Values", node.members(DocumentationNode.Kind.EnumItem), node, to)
appendSection(location, "Constructors", node.members(DocumentationNode.Kind.Constructor), node, to)
appendSection(location, "Properties", node.members(DocumentationNode.Kind.Property), node, to)
+ appendSection(location, "Inherited Properties", node.inheritedMembers(DocumentationNode.Kind.Property), node, to)
appendSection(location, "Functions", node.members(DocumentationNode.Kind.Function), node, to)
+ appendSection(location, "Inherited Functions", node.inheritedMembers(DocumentationNode.Kind.Function), node, to)
appendSection(location, "Companion Object Properties", node.members(DocumentationNode.Kind.CompanionObjectProperty), node, to)
appendSection(location, "Companion Object Functions", node.members(DocumentationNode.Kind.CompanionObjectFunction), node, to)
- appendSection(location, "Enum Values", node.members(DocumentationNode.Kind.EnumItem), node, to)
appendSection(location, "Other members", node.members.filter {
it.kind !in setOf(
DocumentationNode.Kind.Class,
@@ -318,14 +342,32 @@ public abstract class StructuredFormatService(locationService: LocationService,
DocumentationNode.Kind.EnumItem
)
}, node, to)
- appendSection(location, "Extension Properties", node.extensions.filter { it.kind == DocumentationNode.Kind.Property }, node, to)
- appendSection(location, "Extension Functions", node.extensions.filter { it.kind == DocumentationNode.Kind.Function }, node, to)
- appendSection(location, "Companion Object Extension Properties", node.extensions.filter { it.kind == DocumentationNode.Kind.CompanionObjectProperty }, node, to)
- appendSection(location, "Companion Object Extension Functions", node.extensions.filter { it.kind == DocumentationNode.Kind.CompanionObjectFunction }, node, to)
+
+ val allExtensions = collectAllExtensions(node)
+ appendSection(location, "Extension Properties", allExtensions.filter { it.kind == DocumentationNode.Kind.Property }, node, to)
+ appendSection(location, "Extension Functions", allExtensions.filter { it.kind == DocumentationNode.Kind.Function }, node, to)
+ appendSection(location, "Companion Object Extension Properties", allExtensions.filter { it.kind == DocumentationNode.Kind.CompanionObjectProperty }, node, to)
+ appendSection(location, "Companion Object Extension Functions", allExtensions.filter { it.kind == DocumentationNode.Kind.CompanionObjectFunction }, node, to)
appendSection(location, "Inheritors",
node.inheritors.filter { it.kind != DocumentationNode.Kind.EnumItem }, node, to)
appendSection(location, "Links", node.links, node, to)
}
}
+
+ 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(DocumentationReference.Kind.Superclass).forEach { collect(it.to) }
+ }
+
+ collect(node)
+
+ return result
+
+ }
} \ No newline at end of file