aboutsummaryrefslogtreecommitdiff
path: root/core/src/main/kotlin/Formats
diff options
context:
space:
mode:
authorEugene Petrenko <eugene.petrenko@gmail.com>2018-09-11 14:03:29 +0300
committerEugene Petrenko <eugene.petrenko@gmail.com>2018-09-11 14:03:29 +0300
commita54070f5db04d05b48c369b211efe044fbc02a8d (patch)
treeaac5889906f49f68c39e1416ea39d4d19bad008e /core/src/main/kotlin/Formats
parente29f1c966056b0f7ee31dd9bd7d55f9e526fa7fe (diff)
parent0df19264ccae3d294946caf634ee15eea0c4fe4a (diff)
downloaddokka-a54070f5db04d05b48c369b211efe044fbc02a8d.tar.gz
dokka-a54070f5db04d05b48c369b211efe044fbc02a8d.tar.bz2
dokka-a54070f5db04d05b48c369b211efe044fbc02a8d.zip
Merge remote-tracking branch 'zub/dev-multiplatf' into kotlin-website-jonnyzzz
Diffstat (limited to 'core/src/main/kotlin/Formats')
-rw-r--r--core/src/main/kotlin/Formats/AnalysisComponents.kt45
-rw-r--r--core/src/main/kotlin/Formats/FormatDescriptor.kt48
-rw-r--r--core/src/main/kotlin/Formats/GFMFormatService.kt46
-rw-r--r--core/src/main/kotlin/Formats/HtmlFormatService.kt23
-rw-r--r--core/src/main/kotlin/Formats/HtmlTemplateService.kt8
-rw-r--r--core/src/main/kotlin/Formats/JavaLayoutHtml/JavaLayoutHtmlPackageListService.kt117
-rw-r--r--core/src/main/kotlin/Formats/JavaLayoutHtmlFormat.kt91
-rw-r--r--core/src/main/kotlin/Formats/JekyllFormatService.kt26
-rw-r--r--core/src/main/kotlin/Formats/KotlinWebsiteFormatService.kt67
-rw-r--r--core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt41
-rw-r--r--core/src/main/kotlin/Formats/MarkdownFormatService.kt14
-rw-r--r--core/src/main/kotlin/Formats/OutlineService.kt2
-rw-r--r--core/src/main/kotlin/Formats/PackageListService.kt10
-rw-r--r--core/src/main/kotlin/Formats/StandardFormats.kt44
-rw-r--r--core/src/main/kotlin/Formats/StructuredFormatService.kt381
-rw-r--r--core/src/main/kotlin/Formats/YamlOutlineService.kt8
16 files changed, 711 insertions, 260 deletions
diff --git a/core/src/main/kotlin/Formats/AnalysisComponents.kt b/core/src/main/kotlin/Formats/AnalysisComponents.kt
new file mode 100644
index 00000000..d78d4a0c
--- /dev/null
+++ b/core/src/main/kotlin/Formats/AnalysisComponents.kt
@@ -0,0 +1,45 @@
+package org.jetbrains.dokka.Formats
+
+import com.google.inject.Binder
+import org.jetbrains.dokka.*
+import org.jetbrains.dokka.KotlinAsJavaElementSignatureProvider
+import org.jetbrains.dokka.KotlinElementSignatureProvider
+import org.jetbrains.dokka.ElementSignatureProvider
+import org.jetbrains.dokka.Samples.DefaultSampleProcessingService
+import org.jetbrains.dokka.Samples.SampleProcessingService
+import org.jetbrains.dokka.Utilities.bind
+import org.jetbrains.dokka.Utilities.toType
+import kotlin.reflect.KClass
+
+
+interface DefaultAnalysisComponentServices {
+ val packageDocumentationBuilderClass: KClass<out PackageDocumentationBuilder>
+ val javaDocumentationBuilderClass: KClass<out JavaDocumentationBuilder>
+ val sampleProcessingService: KClass<out SampleProcessingService>
+ val elementSignatureProvider: KClass<out ElementSignatureProvider>
+}
+
+interface DefaultAnalysisComponent : FormatDescriptorAnalysisComponent, DefaultAnalysisComponentServices {
+ override fun configureAnalysis(binder: Binder): Unit = with(binder) {
+ bind<ElementSignatureProvider>() toType elementSignatureProvider
+ bind<PackageDocumentationBuilder>() toType packageDocumentationBuilderClass
+ bind<JavaDocumentationBuilder>() toType javaDocumentationBuilderClass
+ bind<SampleProcessingService>() toType sampleProcessingService
+ }
+}
+
+
+object KotlinAsJava : DefaultAnalysisComponentServices {
+ override val packageDocumentationBuilderClass = KotlinAsJavaDocumentationBuilder::class
+ override val javaDocumentationBuilderClass = JavaPsiDocumentationBuilder::class
+ override val sampleProcessingService = DefaultSampleProcessingService::class
+ override val elementSignatureProvider = KotlinAsJavaElementSignatureProvider::class
+}
+
+
+object KotlinAsKotlin : DefaultAnalysisComponentServices {
+ override val packageDocumentationBuilderClass = KotlinPackageDocumentationBuilder::class
+ override val javaDocumentationBuilderClass = KotlinJavaDocumentationBuilder::class
+ override val sampleProcessingService = DefaultSampleProcessingService::class
+ override val elementSignatureProvider = KotlinElementSignatureProvider::class
+} \ No newline at end of file
diff --git a/core/src/main/kotlin/Formats/FormatDescriptor.kt b/core/src/main/kotlin/Formats/FormatDescriptor.kt
index da0156a7..4bac8aa0 100644
--- a/core/src/main/kotlin/Formats/FormatDescriptor.kt
+++ b/core/src/main/kotlin/Formats/FormatDescriptor.kt
@@ -1,17 +1,43 @@
package org.jetbrains.dokka.Formats
+import com.google.inject.Binder
import org.jetbrains.dokka.*
-import org.jetbrains.dokka.Model.DescriptorSignatureProvider
-import org.jetbrains.dokka.Samples.SampleProcessingService
+import org.jetbrains.dokka.Utilities.bind
+import org.jetbrains.dokka.Utilities.lazyBind
+import org.jetbrains.dokka.Utilities.toOptional
+import org.jetbrains.dokka.Utilities.toType
import kotlin.reflect.KClass
-interface FormatDescriptor {
- val formatServiceClass: KClass<out FormatService>?
- val outlineServiceClass: KClass<out OutlineFormatService>?
- val generatorServiceClass: KClass<out Generator>
- val packageDocumentationBuilderClass: KClass<out PackageDocumentationBuilder>
- val javaDocumentationBuilderClass: KClass<out JavaDocumentationBuilder>
- val sampleProcessingService: KClass<out SampleProcessingService>
- val packageListServiceClass: KClass<out PackageListService>?
- val descriptorSignatureProvider: KClass<out DescriptorSignatureProvider>
+
+interface FormatDescriptorAnalysisComponent {
+ fun configureAnalysis(binder: Binder)
+}
+
+interface FormatDescriptorOutputComponent {
+ fun configureOutput(binder: Binder)
}
+
+interface FormatDescriptor : FormatDescriptorAnalysisComponent, FormatDescriptorOutputComponent
+
+
+abstract class FileGeneratorBasedFormatDescriptor : FormatDescriptor {
+
+ override fun configureOutput(binder: Binder): Unit = with(binder) {
+ bind<Generator>() toType NodeLocationAwareGenerator::class
+ bind<NodeLocationAwareGenerator>() toType generatorServiceClass
+ bind(generatorServiceClass.java) // https://github.com/google/guice/issues/847
+
+ bind<LanguageService>() toType languageServiceClass
+
+ lazyBind<OutlineFormatService>() toOptional (outlineServiceClass)
+ lazyBind<FormatService>() toOptional formatServiceClass
+ lazyBind<PackageListService>() toOptional packageListServiceClass
+ }
+
+ abstract val formatServiceClass: KClass<out FormatService>?
+ abstract val outlineServiceClass: KClass<out OutlineFormatService>?
+ abstract val generatorServiceClass: KClass<out FileGenerator>
+ abstract val packageListServiceClass: KClass<out PackageListService>?
+
+ open val languageServiceClass: KClass<out LanguageService> = KotlinLanguageService::class
+} \ No newline at end of file
diff --git a/core/src/main/kotlin/Formats/GFMFormatService.kt b/core/src/main/kotlin/Formats/GFMFormatService.kt
index f741561c..036ec856 100644
--- a/core/src/main/kotlin/Formats/GFMFormatService.kt
+++ b/core/src/main/kotlin/Formats/GFMFormatService.kt
@@ -4,14 +4,14 @@ import com.google.inject.Inject
import com.google.inject.name.Named
import org.jetbrains.dokka.Utilities.impliedPlatformsName
-open class GFMOutputBuilder(to: StringBuilder,
- location: Location,
- locationService: LocationService,
- languageService: LanguageService,
- extension: String,
- impliedPlatforms: List<String>)
- : MarkdownOutputBuilder(to, location, locationService, languageService, extension, impliedPlatforms)
-{
+open class GFMOutputBuilder(
+ to: StringBuilder,
+ location: Location,
+ generator: NodeLocationAwareGenerator,
+ languageService: LanguageService,
+ extension: String,
+ impliedPlatforms: List<String>
+) : MarkdownOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms) {
override fun appendTable(vararg columns: String, body: () -> Unit) {
to.appendln(columns.joinToString(" | ", "| ", " |"))
to.appendln("|" + "---|".repeat(columns.size))
@@ -21,8 +21,7 @@ open class GFMOutputBuilder(to: StringBuilder,
override fun appendUnorderedList(body: () -> Unit) {
if (inTableCell) {
wrapInTag("ul", body)
- }
- else {
+ } else {
super.appendUnorderedList(body)
}
}
@@ -30,8 +29,7 @@ open class GFMOutputBuilder(to: StringBuilder,
override fun appendOrderedList(body: () -> Unit) {
if (inTableCell) {
wrapInTag("ol", body)
- }
- else {
+ } else {
super.appendOrderedList(body)
}
}
@@ -39,23 +37,25 @@ open class GFMOutputBuilder(to: StringBuilder,
override fun appendListItem(body: () -> Unit) {
if (inTableCell) {
wrapInTag("li", body)
- }
- else {
+ } else {
super.appendListItem(body)
}
}
}
-open class GFMFormatService(locationService: LocationService,
- signatureGenerator: LanguageService,
- linkExtension: String,
- impliedPlatforms: List<String>)
-: MarkdownFormatService(locationService, signatureGenerator, linkExtension, impliedPlatforms) {
+open class GFMFormatService(
+ generator: NodeLocationAwareGenerator,
+ signatureGenerator: LanguageService,
+ linkExtension: String,
+ impliedPlatforms: List<String>
+) : MarkdownFormatService(generator, signatureGenerator, linkExtension, impliedPlatforms) {
- @Inject constructor(locationService: LocationService,
- signatureGenerator: LanguageService,
- @Named(impliedPlatformsName) impliedPlatforms: List<String>) : this(locationService, signatureGenerator, "md", impliedPlatforms)
+ @Inject constructor(
+ generator: NodeLocationAwareGenerator,
+ signatureGenerator: LanguageService,
+ @Named(impliedPlatformsName) impliedPlatforms: List<String>
+ ) : this(generator, signatureGenerator, "md", impliedPlatforms)
override fun createOutputBuilder(to: StringBuilder, location: Location): FormattedOutputBuilder =
- GFMOutputBuilder(to, location, locationService, languageService, extension, impliedPlatforms)
+ GFMOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms)
}
diff --git a/core/src/main/kotlin/Formats/HtmlFormatService.kt b/core/src/main/kotlin/Formats/HtmlFormatService.kt
index 5e05f51a..0ad946be 100644
--- a/core/src/main/kotlin/Formats/HtmlFormatService.kt
+++ b/core/src/main/kotlin/Formats/HtmlFormatService.kt
@@ -4,17 +4,15 @@ import com.google.inject.Inject
import com.google.inject.name.Named
import org.jetbrains.dokka.Utilities.impliedPlatformsName
import java.io.File
-import java.nio.file.Path
-import java.nio.file.Paths
open class HtmlOutputBuilder(to: StringBuilder,
location: Location,
- locationService: LocationService,
+ generator: NodeLocationAwareGenerator,
languageService: LanguageService,
extension: String,
impliedPlatforms: List<String>,
val templateService: HtmlTemplateService)
- : StructuredOutputBuilder(to, location, locationService, languageService, extension, impliedPlatforms)
+ : StructuredOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms)
{
override fun appendText(text: String) {
to.append(text.htmlEscape())
@@ -81,7 +79,7 @@ open class HtmlOutputBuilder(to: StringBuilder,
}
override fun appendNodes(nodes: Iterable<DocumentationNode>) {
- templateService.appendHeader(to, getPageTitle(nodes), locationService.calcPathToRoot(location))
+ templateService.appendHeader(to, getPageTitle(nodes), generator.relativePathToRoot(location))
super.appendNodes(nodes)
templateService.appendFooter(to)
}
@@ -95,21 +93,21 @@ open class HtmlOutputBuilder(to: StringBuilder,
}
}
-open class HtmlFormatService @Inject constructor(@Named("folders") locationService: LocationService,
+open class HtmlFormatService @Inject constructor(generator: NodeLocationAwareGenerator,
signatureGenerator: LanguageService,
val templateService: HtmlTemplateService,
@Named(impliedPlatformsName) val impliedPlatforms: List<String>)
-: StructuredFormatService(locationService, signatureGenerator, "html"), OutlineFormatService {
+: StructuredFormatService(generator, signatureGenerator, "html"), OutlineFormatService {
override fun enumerateSupportFiles(callback: (String, String) -> Unit) {
callback("/dokka/styles/style.css", "style.css")
}
override fun createOutputBuilder(to: StringBuilder, location: Location) =
- HtmlOutputBuilder(to, location, locationService, languageService, extension, impliedPlatforms, templateService)
+ HtmlOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms, templateService)
override fun appendOutline(location: Location, to: StringBuilder, nodes: Iterable<DocumentationNode>) {
- templateService.appendHeader(to, "Module Contents", locationService.calcPathToRoot(location))
+ templateService.appendHeader(to, "Module Contents", generator.relativePathToRoot(location))
super.appendOutline(location, to, nodes)
templateService.appendFooter(to)
}
@@ -123,7 +121,7 @@ open class HtmlFormatService @Inject constructor(@Named("folders") locationServi
link.append(languageService.render(node, LanguageService.RenderMode.FULL))
val tempBuilder = StringBuilder()
createOutputBuilder(tempBuilder, location).appendContent(link)
- to.appendln("<a href=\"${location.path}\">${tempBuilder.toString()}</a><br/>")
+ to.appendln("<a href=\"${location.path}\">$tempBuilder</a><br/>")
}
override fun appendOutlineLevel(to: StringBuilder, body: () -> Unit) {
@@ -133,11 +131,6 @@ open class HtmlFormatService @Inject constructor(@Named("folders") locationServi
}
}
-private fun LocationService.calcPathToRoot(location: Location): Path {
- val path = Paths.get(location.path)
- return path.parent?.relativize(Paths.get(root.path + '/')) ?: path
-}
-
fun getPageTitle(nodes: Iterable<DocumentationNode>): String? {
val breakdownByLocation = nodes.groupBy { node -> formatPageTitle(node) }
return breakdownByLocation.keys.singleOrNull()
diff --git a/core/src/main/kotlin/Formats/HtmlTemplateService.kt b/core/src/main/kotlin/Formats/HtmlTemplateService.kt
index 010bc702..a65a7b18 100644
--- a/core/src/main/kotlin/Formats/HtmlTemplateService.kt
+++ b/core/src/main/kotlin/Formats/HtmlTemplateService.kt
@@ -1,9 +1,9 @@
package org.jetbrains.dokka
-import java.nio.file.Path
+import java.io.File
interface HtmlTemplateService {
- fun appendHeader(to: StringBuilder, title: String?, basePath: Path)
+ fun appendHeader(to: StringBuilder, title: String?, basePath: File)
fun appendFooter(to: StringBuilder)
companion object {
@@ -16,7 +16,7 @@ interface HtmlTemplateService {
to.appendln("</BODY>")
to.appendln("</HTML>")
}
- override fun appendHeader(to: StringBuilder, title: String?, basePath: Path) {
+ override fun appendHeader(to: StringBuilder, title: String?, basePath: File) {
to.appendln("<HTML>")
to.appendln("<HEAD>")
to.appendln("<meta charset=\"UTF-8\">")
@@ -24,7 +24,7 @@ interface HtmlTemplateService {
to.appendln("<title>$title</title>")
}
if (css != null) {
- val cssPath = basePath.resolve(css)
+ val cssPath = basePath.resolve(css).toUnixString()
to.appendln("<link rel=\"stylesheet\" href=\"$cssPath\">")
}
to.appendln("</HEAD>")
diff --git a/core/src/main/kotlin/Formats/JavaLayoutHtml/JavaLayoutHtmlPackageListService.kt b/core/src/main/kotlin/Formats/JavaLayoutHtml/JavaLayoutHtmlPackageListService.kt
new file mode 100644
index 00000000..09bb2602
--- /dev/null
+++ b/core/src/main/kotlin/Formats/JavaLayoutHtml/JavaLayoutHtmlPackageListService.kt
@@ -0,0 +1,117 @@
+package org.jetbrains.dokka.Formats
+
+import org.jetbrains.dokka.*
+import org.jetbrains.dokka.ExternalDocumentationLinkResolver.Companion.DOKKA_PARAM_PREFIX
+import org.jetbrains.kotlin.descriptors.*
+import org.jetbrains.kotlin.descriptors.impl.EnumEntrySyntheticClassDescriptor
+import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
+import org.jetbrains.kotlin.resolve.descriptorUtil.isCompanionObject
+import org.jetbrains.kotlin.types.KotlinType
+
+class JavaLayoutHtmlPackageListService: PackageListService {
+
+ private fun StringBuilder.appendParam(name: String, value: String) {
+ append(DOKKA_PARAM_PREFIX)
+ append(name)
+ append(":")
+ appendln(value)
+ }
+
+ override fun formatPackageList(module: DocumentationModule): String {
+ val packages = module.members(NodeKind.Package).map { it.name }
+
+ return buildString {
+ appendParam("format", "java-layout-html")
+ appendParam("mode", "kotlin")
+ for (p in packages) {
+ appendln(p)
+ }
+ }
+ }
+
+}
+
+class JavaLayoutHtmlInboundLinkResolutionService(private val paramMap: Map<String, List<String>>) : InboundExternalLinkResolutionService {
+ private fun getContainerPath(symbol: DeclarationDescriptor): String? {
+ return when (symbol) {
+ is PackageFragmentDescriptor -> symbol.fqName.asString().replace('.', '/') + "/"
+ is ClassifierDescriptor -> getContainerPath(symbol.findPackage()) + symbol.nameWithOuter() + ".html"
+ else -> null
+ }
+ }
+
+ private fun DeclarationDescriptor.findPackage(): PackageFragmentDescriptor =
+ generateSequence(this) { it.containingDeclaration }.filterIsInstance<PackageFragmentDescriptor>().first()
+
+ private fun ClassifierDescriptor.nameWithOuter(): String =
+ generateSequence(this) { it.containingDeclaration as? ClassifierDescriptor }
+ .toList().asReversed().joinToString(".") { it.name.asString() }
+
+ private fun getPagePath(symbol: DeclarationDescriptor): String? {
+ return when (symbol) {
+ is PackageFragmentDescriptor -> getContainerPath(symbol) + "package-summary.html"
+ is EnumEntrySyntheticClassDescriptor -> getContainerPath(symbol.containingDeclaration) + "#" + symbol.signatureForAnchorUrlEncoded()
+ is ClassifierDescriptor -> getContainerPath(symbol) + "#"
+ is FunctionDescriptor, is PropertyDescriptor -> getContainerPath(symbol.containingDeclaration!!) + "#" + symbol.signatureForAnchorUrlEncoded()
+ else -> null
+ }
+ }
+
+ private fun DeclarationDescriptor.signatureForAnchor(): String? {
+
+ fun ReceiverParameterDescriptor.extractReceiverName(): String {
+ var receiverClass: DeclarationDescriptor = type.constructor.declarationDescriptor!!
+ if (receiverClass.isCompanionObject()) {
+ receiverClass = receiverClass.containingDeclaration!!
+ } else if (receiverClass is TypeParameterDescriptor) {
+ val upperBoundClass = receiverClass.upperBounds.singleOrNull()?.constructor?.declarationDescriptor
+ if (upperBoundClass != null) {
+ receiverClass = upperBoundClass
+ }
+ }
+
+ return receiverClass.name.asString()
+ }
+
+ fun KotlinType.qualifiedNameForSignature(): String {
+ val desc = constructor.declarationDescriptor
+ return desc?.fqNameUnsafe?.asString() ?: "<ERROR TYPE NAME>"
+ }
+
+ fun StringBuilder.appendReceiverAndCompanion(desc: CallableDescriptor) {
+ if (desc.containingDeclaration.isCompanionObject()) {
+ append("Companion.")
+ }
+ desc.extensionReceiverParameter?.let {
+ append("(")
+ append(it.extractReceiverName())
+ append(").")
+ }
+ }
+
+ return when(this) {
+ is EnumEntrySyntheticClassDescriptor -> buildString {
+ append("ENUM_VALUE:")
+ append(name.asString())
+ }
+ is FunctionDescriptor -> buildString {
+ appendReceiverAndCompanion(this@signatureForAnchor)
+ append(name.asString())
+ valueParameters.joinTo(this, prefix = "(", postfix = ")") {
+ it.type.qualifiedNameForSignature()
+ }
+ }
+ is PropertyDescriptor -> buildString {
+ appendReceiverAndCompanion(this@signatureForAnchor)
+ append(name.asString())
+ append(":")
+ append(returnType?.qualifiedNameForSignature())
+ }
+ else -> null
+ }
+ }
+
+ private fun DeclarationDescriptor.signatureForAnchorUrlEncoded(): String? = signatureForAnchor()?.urlEncoded()
+
+ override fun getPath(symbol: DeclarationDescriptor) = getPagePath(symbol)
+} \ No newline at end of file
diff --git a/core/src/main/kotlin/Formats/JavaLayoutHtmlFormat.kt b/core/src/main/kotlin/Formats/JavaLayoutHtmlFormat.kt
new file mode 100644
index 00000000..885cdf6c
--- /dev/null
+++ b/core/src/main/kotlin/Formats/JavaLayoutHtmlFormat.kt
@@ -0,0 +1,91 @@
+package org.jetbrains.dokka.Formats
+
+import com.google.inject.Binder
+import com.google.inject.Inject
+import kotlinx.html.li
+import kotlinx.html.stream.appendHTML
+import kotlinx.html.ul
+import org.jetbrains.dokka.*
+import org.jetbrains.dokka.Samples.DefaultSampleProcessingService
+import org.jetbrains.dokka.Utilities.bind
+import org.jetbrains.dokka.Utilities.toType
+import java.io.File
+
+
+class JavaLayoutHtmlFormatDescriptor : FormatDescriptor, DefaultAnalysisComponent {
+ override val packageDocumentationBuilderClass = KotlinPackageDocumentationBuilder::class
+ override val javaDocumentationBuilderClass = KotlinJavaDocumentationBuilder::class
+ override val sampleProcessingService = DefaultSampleProcessingService::class
+ override val elementSignatureProvider = KotlinElementSignatureProvider::class
+
+ override fun configureOutput(binder: Binder): Unit = with(binder) {
+ bind<Generator>() toType generatorServiceClass
+ }
+
+ val formatServiceClass = JavaLayoutHtmlFormatService::class
+ val generatorServiceClass = JavaLayoutHtmlFormatGenerator::class
+}
+
+
+class JavaLayoutHtmlFormatService : FormatService {
+ override val extension: String
+ get() = TODO("not implemented")
+
+
+ override fun createOutputBuilder(to: StringBuilder, location: Location): FormattedOutputBuilder {
+ TODO("not implemented")
+ }
+}
+
+class JavaLayoutHtmlFormatOutputBuilder : FormattedOutputBuilder {
+ override fun appendNodes(nodes: Iterable<DocumentationNode>) {
+
+ }
+}
+
+
+class JavaLayoutHtmlFormatNavListBuilder @Inject constructor() : OutlineFormatService {
+ override fun getOutlineFileName(location: Location): File {
+ TODO()
+ }
+
+ override fun appendOutlineHeader(location: Location, node: DocumentationNode, to: StringBuilder) {
+ with(to.appendHTML()) {
+ //a(href = )
+ li {
+ when {
+ node.kind == NodeKind.Package -> appendOutline(location, to, node.members)
+ }
+ }
+ }
+ }
+
+ override fun appendOutlineLevel(to: StringBuilder, body: () -> Unit) {
+ with(to.appendHTML()) {
+ ul { body() }
+ }
+ }
+
+}
+
+class JavaLayoutHtmlFormatGenerator @Inject constructor(
+ private val outlineFormatService: OutlineFormatService
+) : Generator {
+ override fun buildPages(nodes: Iterable<DocumentationNode>) {
+
+ }
+
+ override fun buildOutlines(nodes: Iterable<DocumentationNode>) {
+ for (node in nodes) {
+ if (node.kind == NodeKind.Module) {
+ //outlineFormatService.formatOutline()
+ }
+ }
+ }
+
+ override fun buildSupportFiles() {}
+
+ override fun buildPackageList(nodes: Iterable<DocumentationNode>) {
+
+ }
+} \ No newline at end of file
diff --git a/core/src/main/kotlin/Formats/JekyllFormatService.kt b/core/src/main/kotlin/Formats/JekyllFormatService.kt
index 6b97bbe0..a948dfa9 100644
--- a/core/src/main/kotlin/Formats/JekyllFormatService.kt
+++ b/core/src/main/kotlin/Formats/JekyllFormatService.kt
@@ -6,12 +6,11 @@ import org.jetbrains.dokka.Utilities.impliedPlatformsName
open class JekyllOutputBuilder(to: StringBuilder,
location: Location,
- locationService: LocationService,
+ generator: NodeLocationAwareGenerator,
languageService: LanguageService,
extension: String,
impliedPlatforms: List<String>)
- : MarkdownOutputBuilder(to, location, locationService, languageService, extension, impliedPlatforms)
-{
+ : MarkdownOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms) {
override fun appendNodes(nodes: Iterable<DocumentationNode>) {
to.appendln("---")
appendFrontMatter(nodes, to)
@@ -26,17 +25,20 @@ open class JekyllOutputBuilder(to: StringBuilder,
}
-open class JekyllFormatService(locationService: LocationService,
- signatureGenerator: LanguageService,
- linkExtension: String,
- impliedPlatforms: List<String>)
-: MarkdownFormatService(locationService, signatureGenerator, linkExtension, impliedPlatforms) {
+open class JekyllFormatService(
+ generator: NodeLocationAwareGenerator,
+ signatureGenerator: LanguageService,
+ linkExtension: String,
+ impliedPlatforms: List<String>
+) : MarkdownFormatService(generator, signatureGenerator, linkExtension, impliedPlatforms) {
- @Inject constructor(locationService: LocationService,
- signatureGenerator: LanguageService,
- @Named(impliedPlatformsName) impliedPlatforms: List<String>): this(locationService, signatureGenerator, "html", impliedPlatforms)
+ @Inject constructor(
+ generator: NodeLocationAwareGenerator,
+ signatureGenerator: LanguageService,
+ @Named(impliedPlatformsName) impliedPlatforms: List<String>
+ ) : this(generator, signatureGenerator, "html", impliedPlatforms)
override fun createOutputBuilder(to: StringBuilder, location: Location): FormattedOutputBuilder =
- JekyllOutputBuilder(to, location, locationService, languageService, extension, impliedPlatforms)
+ JekyllOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms)
}
diff --git a/core/src/main/kotlin/Formats/KotlinWebsiteFormatService.kt b/core/src/main/kotlin/Formats/KotlinWebsiteFormatService.kt
index 08349980..a98002d4 100644
--- a/core/src/main/kotlin/Formats/KotlinWebsiteFormatService.kt
+++ b/core/src/main/kotlin/Formats/KotlinWebsiteFormatService.kt
@@ -6,14 +6,14 @@ import org.jetbrains.dokka.Utilities.impliedPlatformsName
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
-open class KotlinWebsiteOutputBuilder(to: StringBuilder,
- location: Location,
- locationService: LocationService,
- languageService: LanguageService,
- extension: String,
- impliedPlatforms: List<String>)
- : JekyllOutputBuilder(to, location, locationService, languageService, extension, impliedPlatforms)
-{
+open class KotlinWebsiteOutputBuilder(
+ to: StringBuilder,
+ location: Location,
+ generator: NodeLocationAwareGenerator,
+ languageService: LanguageService,
+ extension: String,
+ impliedPlatforms: List<String>
+) : JekyllOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms) {
private var needHardLineBreaks = false
private var insideDiv = 0
@@ -70,8 +70,7 @@ open class KotlinWebsiteOutputBuilder(to: StringBuilder,
override fun appendHeader(level: Int, body: () -> Unit) {
if (insideDiv > 0) {
wrapInTag("p", body, newlineAfterClose = true)
- }
- else {
+ } else {
super.appendHeader(level, body)
}
}
@@ -79,8 +78,7 @@ open class KotlinWebsiteOutputBuilder(to: StringBuilder,
override fun appendLine() {
if (insideDiv > 0) {
to.appendln("<br/>")
- }
- else {
+ } else {
super.appendLine()
}
}
@@ -135,13 +133,14 @@ open class KotlinWebsiteOutputBuilder(to: StringBuilder,
to.append("<br/>")
}
+
override fun appendIndentedSoftLineBreak() {
if (needHardLineBreaks) {
to.append("<br/>&nbsp;&nbsp;&nbsp;&nbsp;")
}
}
- private fun identifierClassName(kind: IdentifierKind) = when(kind) {
+ private fun identifierClassName(kind: IdentifierKind) = when (kind) {
IdentifierKind.ParameterName -> "parameterName"
IdentifierKind.SummarizedTypeName -> "summarizedTypeName"
else -> "identifier"
@@ -172,28 +171,29 @@ open class KotlinWebsiteOutputBuilder(to: StringBuilder,
}
}
-class KotlinWebsiteFormatService @Inject constructor(locationService: LocationService,
- signatureGenerator: LanguageService,
- @Named(impliedPlatformsName) impliedPlatforms: List<String>,
- logger: DokkaLogger)
- : JekyllFormatService(locationService, signatureGenerator, "html", impliedPlatforms)
-{
+class KotlinWebsiteFormatService @Inject constructor(
+ generator: NodeLocationAwareGenerator,
+ signatureGenerator: LanguageService,
+ @Named(impliedPlatformsName) impliedPlatforms: List<String>,
+ logger: DokkaLogger
+) : JekyllFormatService(generator, signatureGenerator, "html", impliedPlatforms) {
init {
logger.warn("Format kotlin-website deprecated and will be removed in next release")
}
override fun createOutputBuilder(to: StringBuilder, location: Location) =
- KotlinWebsiteOutputBuilder(to, location, locationService, languageService, extension, impliedPlatforms)
+ KotlinWebsiteOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms)
}
-class KotlinWebsiteRunnableSamplesOutputBuilder(to: StringBuilder,
- location: Location,
- locationService: LocationService,
- languageService: LanguageService,
- extension: String,
- impliedPlatforms: List<String>)
- : KotlinWebsiteOutputBuilder(to, location, locationService, languageService, extension, impliedPlatforms) {
+class KotlinWebsiteRunnableSamplesOutputBuilder(
+ to: StringBuilder,
+ location: Location,
+ generator: NodeLocationAwareGenerator,
+ languageService: LanguageService,
+ extension: String,
+ impliedPlatforms: List<String>
+) : KotlinWebsiteOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms) {
override fun appendSampleBlockCode(language: String, imports: () -> Unit, body: () -> Unit) {
div(to, "sample", markdown = true) {
@@ -207,17 +207,18 @@ class KotlinWebsiteRunnableSamplesOutputBuilder(to: StringBuilder,
}
}
-class KotlinWebsiteRunnableSamplesFormatService @Inject constructor(locationService: LocationService,
- signatureGenerator: LanguageService,
- @Named(impliedPlatformsName) impliedPlatforms: List<String>,
- logger: DokkaLogger)
- : JekyllFormatService(locationService, signatureGenerator, "html", impliedPlatforms) {
+class KotlinWebsiteRunnableSamplesFormatService @Inject constructor(
+ generator: NodeLocationAwareGenerator,
+ signatureGenerator: LanguageService,
+ @Named(impliedPlatformsName) impliedPlatforms: List<String>,
+ logger: DokkaLogger
+) : JekyllFormatService(generator, signatureGenerator, "html", impliedPlatforms) {
init {
logger.warn("Format kotlin-website-samples deprecated and will be removed in next release")
}
override fun createOutputBuilder(to: StringBuilder, location: Location) =
- KotlinWebsiteRunnableSamplesOutputBuilder(to, location, locationService, languageService, extension, impliedPlatforms)
+ KotlinWebsiteRunnableSamplesOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms)
}
diff --git a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt
index 378401f3..16bec5a6 100644
--- a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt
+++ b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt
@@ -4,23 +4,25 @@ import com.google.inject.Inject
import com.google.inject.name.Named
import org.jetbrains.dokka.Utilities.impliedPlatformsName
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
-import java.nio.file.Path
+import java.io.File
-private object EmptyHtmlTemplateService : HtmlTemplateService {
+object EmptyHtmlTemplateService : HtmlTemplateService {
override fun appendFooter(to: StringBuilder) {}
- override fun appendHeader(to: StringBuilder, title: String?, basePath: Path) {}
+ override fun appendHeader(to: StringBuilder, title: String?, basePath: File) {}
}
-open class KotlinWebsiteHtmlOutputBuilder(to: StringBuilder,
- location: Location,
- locationService: LocationService,
- languageService: LanguageService,
- extension: String,
- impliedPlatforms: List<String>)
- : HtmlOutputBuilder(to, location, locationService, languageService, extension, impliedPlatforms, EmptyHtmlTemplateService) {
+open class KotlinWebsiteHtmlOutputBuilder(
+ to: StringBuilder,
+ location: Location,
+ generator: NodeLocationAwareGenerator,
+ languageService: LanguageService,
+ extension: String,
+ impliedPlatforms: List<String>,
+ templateService: HtmlTemplateService
+) : HtmlOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms, templateService) {
private var needHardLineBreaks = false
private var insideDiv = 0
@@ -167,16 +169,25 @@ open class KotlinWebsiteHtmlOutputBuilder(to: StringBuilder,
appendContent(section)
}
}
+
+ override fun appendAsBlockWithPlatforms(platforms: Set<String>, block: () -> Unit) {
+ if (platforms.isNotEmpty())
+ wrap("<div${calculateDataAttributes(platforms)}>", "</div>", block)
+ else
+ block()
+ }
}
-class KotlinWebsiteHtmlFormatService @Inject constructor(locationService: LocationService,
- signatureGenerator: LanguageService,
- @Named(impliedPlatformsName) impliedPlatforms: List<String>)
- : HtmlFormatService(locationService, signatureGenerator, EmptyHtmlTemplateService, impliedPlatforms) {
+class KotlinWebsiteHtmlFormatService @Inject constructor(
+ generator: NodeLocationAwareGenerator,
+ signatureGenerator: LanguageService,
+ @Named(impliedPlatformsName) impliedPlatforms: List<String>,
+ templateService: HtmlTemplateService
+) : HtmlFormatService(generator, signatureGenerator, templateService, impliedPlatforms) {
override fun enumerateSupportFiles(callback: (String, String) -> Unit) {}
override fun createOutputBuilder(to: StringBuilder, location: Location) =
- KotlinWebsiteHtmlOutputBuilder(to, location, locationService, languageService, extension, impliedPlatforms)
+ KotlinWebsiteHtmlOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms, templateService)
}
diff --git a/core/src/main/kotlin/Formats/MarkdownFormatService.kt b/core/src/main/kotlin/Formats/MarkdownFormatService.kt
index a7c18a28..4265394f 100644
--- a/core/src/main/kotlin/Formats/MarkdownFormatService.kt
+++ b/core/src/main/kotlin/Formats/MarkdownFormatService.kt
@@ -21,11 +21,11 @@ private val TWO_LINE_BREAKS = System.lineSeparator() + System.lineSeparator()
open class MarkdownOutputBuilder(to: StringBuilder,
location: Location,
- locationService: LocationService,
+ generator: NodeLocationAwareGenerator,
languageService: LanguageService,
extension: String,
impliedPlatforms: List<String>)
- : StructuredOutputBuilder(to, location, locationService, languageService, extension, impliedPlatforms)
+ : StructuredOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms)
{
private val listStack = ArrayDeque<ListState>()
protected var inTableCell = false
@@ -225,15 +225,15 @@ open class MarkdownOutputBuilder(to: StringBuilder,
}
}
-open class MarkdownFormatService(locationService: LocationService,
+open class MarkdownFormatService(generator: NodeLocationAwareGenerator,
signatureGenerator: LanguageService,
linkExtension: String,
val impliedPlatforms: List<String>)
-: StructuredFormatService(locationService, signatureGenerator, "md", linkExtension) {
- @Inject constructor(locationService: LocationService,
+: StructuredFormatService(generator, signatureGenerator, "md", linkExtension) {
+ @Inject constructor(generator: NodeLocationAwareGenerator,
signatureGenerator: LanguageService,
- @Named(impliedPlatformsName) impliedPlatforms: List<String>): this(locationService, signatureGenerator, "md", impliedPlatforms)
+ @Named(impliedPlatformsName) impliedPlatforms: List<String>): this(generator, signatureGenerator, "md", impliedPlatforms)
override fun createOutputBuilder(to: StringBuilder, location: Location): FormattedOutputBuilder =
- MarkdownOutputBuilder(to, location, locationService, languageService, extension, impliedPlatforms)
+ MarkdownOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms)
}
diff --git a/core/src/main/kotlin/Formats/OutlineService.kt b/core/src/main/kotlin/Formats/OutlineService.kt
index 3c31ba57..958e93af 100644
--- a/core/src/main/kotlin/Formats/OutlineService.kt
+++ b/core/src/main/kotlin/Formats/OutlineService.kt
@@ -16,7 +16,7 @@ interface OutlineFormatService {
for (node in nodes) {
appendOutlineHeader(location, node, to)
if (node.members.any()) {
- val sortedMembers = node.members.sortedBy { it.name }
+ val sortedMembers = node.members.sortedBy { it.name.toLowerCase() }
appendOutlineLevel(to) {
appendOutline(location, to, sortedMembers)
}
diff --git a/core/src/main/kotlin/Formats/PackageListService.kt b/core/src/main/kotlin/Formats/PackageListService.kt
index e7f4e952..7b68098e 100644
--- a/core/src/main/kotlin/Formats/PackageListService.kt
+++ b/core/src/main/kotlin/Formats/PackageListService.kt
@@ -7,10 +7,10 @@ interface PackageListService {
fun formatPackageList(module: DocumentationModule): String
}
-class DefaultPackageListService @Inject constructor(locationService: FileLocationService,
- val formatService: FormatService) : PackageListService {
-
- val locationService: FileLocationService = locationService.withExtension(formatService.linkExtension)
+class DefaultPackageListService @Inject constructor(
+ val generator: NodeLocationAwareGenerator,
+ val formatService: FormatService
+) : PackageListService {
override fun formatPackageList(module: DocumentationModule): String {
val packages = mutableSetOf<String>()
@@ -26,7 +26,7 @@ class DefaultPackageListService @Inject constructor(locationService: FileLocatio
}
NodeKind.Signature -> {
if (relocated)
- nonStandardLocations[node.name] = locationService.relativePathToLocation(module, node.owner!!)
+ nonStandardLocations[node.name] = generator.relativePathToLocation(module, node.owner!!)
}
NodeKind.ExternalClass -> {
node.members.forEach { visit(it, relocated = true) }
diff --git a/core/src/main/kotlin/Formats/StandardFormats.kt b/core/src/main/kotlin/Formats/StandardFormats.kt
index f3d638c6..dd67ac97 100644
--- a/core/src/main/kotlin/Formats/StandardFormats.kt
+++ b/core/src/main/kotlin/Formats/StandardFormats.kt
@@ -1,41 +1,36 @@
package org.jetbrains.dokka.Formats
+import com.google.inject.Binder
import org.jetbrains.dokka.*
-import org.jetbrains.dokka.Kotlin.KotlinAsJavaDescriptorSignatureProvider
-import org.jetbrains.dokka.Kotlin.KotlinDescriptorSignatureProvider
-import org.jetbrains.dokka.Model.DescriptorSignatureProvider
-import org.jetbrains.dokka.Samples.DefaultSampleProcessingService
import org.jetbrains.dokka.Samples.KotlinWebsiteSampleProcessingService
-import org.jetbrains.dokka.Samples.SampleProcessingService
+import org.jetbrains.dokka.Utilities.bind
import kotlin.reflect.KClass
-abstract class KotlinFormatDescriptorBase : FormatDescriptor {
- override val packageDocumentationBuilderClass = KotlinPackageDocumentationBuilder::class
- override val javaDocumentationBuilderClass = KotlinJavaDocumentationBuilder::class
-
+abstract class KotlinFormatDescriptorBase
+ : FileGeneratorBasedFormatDescriptor(),
+ DefaultAnalysisComponent,
+ DefaultAnalysisComponentServices by KotlinAsKotlin {
override val generatorServiceClass = FileGenerator::class
override val outlineServiceClass: KClass<out OutlineFormatService>? = null
- override val sampleProcessingService: KClass<out SampleProcessingService> = DefaultSampleProcessingService::class
override val packageListServiceClass: KClass<out PackageListService>? = DefaultPackageListService::class
- override val descriptorSignatureProvider = KotlinDescriptorSignatureProvider::class
-}
-
-class HtmlFormatDescriptor : KotlinFormatDescriptorBase() {
- override val formatServiceClass = HtmlFormatService::class
- override val outlineServiceClass = HtmlFormatService::class
}
-class HtmlAsJavaFormatDescriptor : FormatDescriptor {
+abstract class HtmlFormatDescriptorBase : FileGeneratorBasedFormatDescriptor(), DefaultAnalysisComponent {
override val formatServiceClass = HtmlFormatService::class
override val outlineServiceClass = HtmlFormatService::class
override val generatorServiceClass = FileGenerator::class
- override val packageDocumentationBuilderClass = KotlinAsJavaDocumentationBuilder::class
- override val javaDocumentationBuilderClass = JavaPsiDocumentationBuilder::class
- override val sampleProcessingService: KClass<out SampleProcessingService> = DefaultSampleProcessingService::class
- override val packageListServiceClass: KClass<out PackageListService>? = DefaultPackageListService::class
- override val descriptorSignatureProvider = KotlinAsJavaDescriptorSignatureProvider::class
+ override val packageListServiceClass = DefaultPackageListService::class
+
+ override fun configureOutput(binder: Binder): Unit = with(binder) {
+ super.configureOutput(binder)
+ bind<HtmlTemplateService>().toProvider { HtmlTemplateService.default("style.css") }
+ }
}
+class HtmlFormatDescriptor : HtmlFormatDescriptorBase(), DefaultAnalysisComponentServices by KotlinAsKotlin
+
+class HtmlAsJavaFormatDescriptor : HtmlFormatDescriptorBase(), DefaultAnalysisComponentServices by KotlinAsJava
+
class KotlinWebsiteFormatDescriptor : KotlinFormatDescriptorBase() {
override val formatServiceClass = KotlinWebsiteFormatService::class
override val outlineServiceClass = YamlOutlineService::class
@@ -51,6 +46,11 @@ class KotlinWebsiteHtmlFormatDescriptor : KotlinFormatDescriptorBase() {
override val formatServiceClass = KotlinWebsiteHtmlFormatService::class
override val sampleProcessingService = KotlinWebsiteSampleProcessingService::class
override val outlineServiceClass = YamlOutlineService::class
+
+ override fun configureOutput(binder: Binder) = with(binder) {
+ super.configureOutput(binder)
+ bind<HtmlTemplateService>().toInstance(EmptyHtmlTemplateService)
+ }
}
class JekyllFormatDescriptor : KotlinFormatDescriptorBase() {
diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt
index 5167a102..53172563 100644
--- a/core/src/main/kotlin/Formats/StructuredFormatService.kt
+++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt
@@ -7,11 +7,13 @@ data class FormatLink(val text: String, val href: String)
abstract class StructuredOutputBuilder(val to: StringBuilder,
val location: Location,
- val locationService: LocationService,
+ val generator: NodeLocationAwareGenerator,
val languageService: LanguageService,
val extension: String,
val impliedPlatforms: List<String>) : FormattedOutputBuilder {
+ protected fun DocumentationNode.location() = generator.location(this)
+
protected fun wrap(prefix: String, suffix: String, body: () -> Unit) {
to.append(prefix)
body()
@@ -81,6 +83,10 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
}
}
+ open fun appendAsBlockWithPlatforms(platforms: Set<String>, block: () -> Unit) {
+ block()
+ }
+
open fun appendSymbol(text: String) {
appendText(text)
}
@@ -190,30 +196,28 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
}
}
- 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,
+ 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 {
- if (to.owner?.kind == NodeKind.GroupNode)
- return link(from, to.owner!!, extension, name)
+ open fun link(
+ from: DocumentationNode,
+ to: DocumentationNode,
+ extension: String,
+ name: (DocumentationNode) -> String = DocumentationNode::name
+ ): FormatLink =
+ FormatLink(name(to), from.location().relativePathTo(to.location()))
- if (from.owner?.kind == NodeKind.GroupNode)
- return link(from.owner!!, to, extension, name)
-
- return FormatLink(name(to), locationService.relativePathToLocation(from, to))
- }
fun locationHref(from: Location, to: DocumentationNode): String {
val topLevelPage = to.references(RefKind.TopLevelPage).singleOrNull()?.to
if (topLevelPage != null) {
val signature = to.detailOrNull(NodeKind.Signature)
- return from.relativePathTo(locationService.location(topLevelPage), signature?.name ?: to.name)
+ return from.relativePathTo(topLevelPage.location(), signature?.name ?: to.name)
}
- return from.relativePathTo(locationService.location(to))
+ return from.relativePathTo(to.location())
}
private fun DocumentationNode.isModuleOrPackage(): Boolean =
@@ -296,7 +300,12 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
}
private fun appendDocumentation(overloads: Iterable<DocumentationNode>, isSingleNode: Boolean) {
- val breakdownBySummary = overloads.groupByTo(LinkedHashMap()) { node -> node.content }
+ val breakdownBySummary = overloads.groupByTo(LinkedHashMap()) { node ->
+ when (node.kind) {
+ NodeKind.GroupNode -> node.origins.first().content
+ else -> node.content
+ }
+ }
if (breakdownBySummary.size == 1) {
formatOverloadGroup(breakdownBySummary.values.single(), isSingleNode)
@@ -314,29 +323,90 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
private fun formatOverloadGroup(items: List<DocumentationNode>, isSingleNode: Boolean = false) {
for ((index, item) in items.withIndex()) {
if (index > 0) appendLine()
- val rendered = languageService.render(item)
- item.detailOrNull(NodeKind.Signature)?.let {
- if (item.kind !in NodeKind.classLike || !isSingleNode)
- appendAnchor(it.name)
- }
- appendAsSignature(rendered) {
- appendCode { appendContent(rendered) }
- item.appendSourceLink()
+
+ if (item.kind == NodeKind.GroupNode) {
+ renderGroupNode(item, isSingleNode)
+ } else {
+ renderSimpleNode(item, isSingleNode)
}
- item.appendOverrides()
- item.appendDeprecation()
- item.appendPlatforms()
+
}
// All items have exactly the same documentation, so we can use any item to render it
val item = items.first()
+ // TODO: remove this block cause there is no one node with OverloadGroupNote detail
item.details(NodeKind.OverloadGroupNote).forEach {
appendContent(it.content)
}
- appendContent(item.content.summary)
+ if (item.kind == NodeKind.GroupNode) {
+ for (origin in item.origins) {
+ if (origin.content.isEmpty()) continue
+ appendParagraph {
+ appendStrong { to.append("Platform and version requirements:") }
+ to.append(" " + origin.actualPlatforms)
+ appendContent(origin.summary)
+ }
+ }
+ } else {
+ if (!item.content.isEmpty()) {
+ appendStrong { to.append("Platform and version requirements:") }
+ to.append(" " + item.actualPlatforms)
+ appendContent(item.content.summary)
+ }
+ }
+
item.appendDescription()
}
+
+ fun renderSimpleNode(item: DocumentationNode, isSingleNode: Boolean) {
+ // TODO: use summarizesignatures
+ val rendered = languageService.render(item)
+ item.detailOrNull(NodeKind.Signature)?.let {
+ if (item.kind !in NodeKind.classLike || !isSingleNode)
+ appendAnchor(it.name)
+ }
+ appendAsSignature(rendered) {
+ appendCode { appendContent(rendered) }
+ item.appendSourceLink()
+ }
+ item.appendOverrides()
+ item.appendDeprecation()
+ item.appendPlatforms()
+ }
+
+ fun renderGroupNode(item: DocumentationNode, isSingleNode: Boolean) {
+ // TODO: use summarizesignatures
+ val groupBySignature = item.origins.groupBy {
+ languageService.render(it)
+ }
+
+ for ((sign, nodes) in groupBySignature) {
+ val first = nodes.first()
+ first.detailOrNull(NodeKind.Signature)?.let {
+ if (item.kind !in NodeKind.classLike || !isSingleNode)
+ appendAnchor(it.name)
+ }
+
+ appendAsSignature(sign) {
+ appendCode { appendContent(sign) }
+ }
+ first.appendOverrides()
+ first.appendDeprecation()
+
+
+ appendParagraph {
+ appendStrong { to.append("Platform and version requirements:") }
+ to.append(" " + nodes
+ .flatMap { it.actualPlatforms }
+ .distinct()
+ .joinToString()
+ )
+ }
+
+ }
+ }
+
private fun DocumentationNode.appendSourceLink() {
val sourceUrl = details(NodeKind.SourceUrl).firstOrNull()
if (sourceUrl != null) {
@@ -349,7 +419,8 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
overrides.forEach {
appendParagraph {
to.append("Overrides ")
- val location = locationService.relativePathToLocation(this, it)
+ val location = location().relativePathTo(it.location())
+
appendLink(FormatLink(it.owner!!.name + "." + it.name, location))
}
}
@@ -360,30 +431,30 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
val deprecationParameter = deprecation!!.details(NodeKind.Parameter).firstOrNull()
val deprecationValue = deprecationParameter?.details(NodeKind.Value)?.firstOrNull()
appendLine()
- if (deprecationValue != null) {
- appendStrong { to.append("Deprecated:") }
- appendText(" " + deprecationValue.name.removeSurrounding("\""))
- appendLine()
- appendLine()
- } else if (deprecation?.content != Content.Empty) {
- appendStrong { to.append("Deprecated:") }
- to.append(" ")
- appendContent(deprecation!!.content)
- } else {
- appendStrong { to.append("Deprecated") }
- appendLine()
- appendLine()
+ when {
+ deprecationValue != null -> {
+ appendStrong { to.append("Deprecated:") }
+ appendText(" " + deprecationValue.name.removeSurrounding("\""))
+ appendLine()
+ appendLine()
+ }
+ deprecation?.content != Content.Empty -> {
+ appendStrong { to.append("Deprecated:") }
+ to.append(" ")
+ appendContent(deprecation!!.content)
+ }
+ else -> {
+ appendStrong { to.append("Deprecated") }
+ appendLine()
+ appendLine()
+ }
}
}
}
private fun DocumentationNode.appendPlatforms() {
- val platforms = if (isModuleOrPackage())
- platformsToShow.toSet() + platformsOfItems(members)
- else
- platformsToShow
-
- if(platforms.isEmpty()) return
+ val platforms = actualPlatforms
+ if (platforms.isEmpty()) return
appendParagraph {
appendStrong { to.append("Platform and version requirements:") }
@@ -391,16 +462,39 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
}
}
+ val DocumentationNode.actualPlatforms: Collection<String>
+ get() = if (isModuleOrPackage())
+ platformsToShow.toSet() + platformsOfItems(members)
+ else
+ platformsToShow
+
+
+ protected fun mergeVersions(otherKotlinVersion: String, kotlinVersions: List<String>): String {
+ val allKotlinVersions = (kotlinVersions + otherKotlinVersion).distinct()
+
+ val minVersion = allKotlinVersions.min()!!
+ val resultVersion: String = when {
+ allKotlinVersions.size == 1 -> allKotlinVersions.single()
+ minVersion.endsWith("+") -> minVersion
+ else -> "$minVersion+"
+ }
+
+ return resultVersion
+ }
+
protected fun platformsOfItems(items: List<DocumentationNode>): Set<String> {
val platforms = items.asSequence().map {
when (it.kind) {
- NodeKind.ExternalClass, NodeKind.Package, NodeKind.Module, NodeKind.GroupNode -> platformsOfItems(it.members)
+ NodeKind.ExternalClass, NodeKind.Package, NodeKind.Module -> platformsOfItems(it.members)
+ NodeKind.GroupNode -> platformsOfItems(it.origins)
else -> it.platformsToShow.toSet()
}
}
fun String.isKotlinVersion() = this.startsWith("Kotlin")
+ if (platforms.count() == 0) return emptySet()
+
// Calculating common platforms for items
return platforms.reduce { result, platformsOfItem ->
val otherKotlinVersion = result.find { it.isKotlinVersion() }
@@ -408,19 +502,38 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
// When no Kotlin version specified, it means that version is 1.0
if (otherKotlinVersion != null && kotlinVersions.isNotEmpty()) {
- val allKotlinVersions = (kotlinVersions + otherKotlinVersion).distinct()
+ result.intersect(platformsOfItem) + mergeVersions(otherKotlinVersion, kotlinVersions)
+ } else {
+ result.intersect(platformsOfItem)
+ }
+ }
+ }
- val minVersion = allKotlinVersions.min()!!
- val resultVersion = when {
- allKotlinVersions.size == 1 -> allKotlinVersions.single()
- minVersion.endsWith("+") -> minVersion
- else -> minVersion + "+"
- }
+ protected fun unionPlatformsOfItems(items: List<DocumentationNode>): Set<String> {
+ val platforms = items.asSequence().map {
+ when (it.kind) {
+ NodeKind.GroupNode -> unionPlatformsOfItems(it.origins)
+ else -> it.platformsToShow.toSet()
+ }
+ }
+
+ fun String.isKotlinVersion() = this.startsWith("Kotlin")
+
+ if (platforms.count() == 0) return emptySet()
+
+ // Calculating common platforms for items
+ return platforms.reduce { result, platformsOfItem ->
+ val otherKotlinVersion = result.find { it.isKotlinVersion() }
+ val (kotlinVersions, otherPlatforms) = platformsOfItem.partition { it.isKotlinVersion() }
- result.intersect(otherPlatforms) + resultVersion
+ // When no Kotlin version specified, it means that version is 1.0
+ if (otherKotlinVersion != null && kotlinVersions.isNotEmpty()) {
+ result.union(otherPlatforms) + mergeVersions(otherKotlinVersion, kotlinVersions)
} else {
- result.intersect(platformsOfItem)
+ result.union(otherPlatforms)
}
+ }.let {
+ if (it.containsAll(impliedPlatforms)) it - impliedPlatforms else it
}
}
@@ -456,6 +569,15 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
}
}
+ inner class SingleNodePageBuilder(val node: DocumentationNode, noHeader: Boolean = false) :
+ PageBuilder(listOf(node), noHeader) {
+
+ override fun build() {
+ super.build()
+ SectionsBuilder(node).build()
+ }
+ }
+
inner class GroupNodePageBuilder(val node: DocumentationNode) : PageBuilder(listOf(node)) {
override fun build() {
@@ -466,39 +588,40 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
appendLine()
appendHeader { appendText(node.name) }
- fun DocumentationNode.priority(): Int = when (kind) {
- NodeKind.TypeAlias -> 1
- NodeKind.Class -> 2
- else -> 3
- }
+ renderGroupNode(node, true)
- for (member in node.members.sortedBy(DocumentationNode::priority)) {
+ for (origin in node.origins) {
+ if (origin.content.isEmpty()) continue
+ appendStrong { to.append("Platform and version requirements:") }
+ to.append(" " + origin.actualPlatforms)
+ appendContent(origin.content.summary)
+ }
- appendAsOverloadGroup(to, platformsOfItems(listOf(member))) {
- formatSubNodeOfGroup(member)
- }
+ SectionsBuilder(node).build()
+ }
+ }
+ private fun unionPlatformsOfItems(items: List<DocumentationNode>): Set<String> {
+ val platforms = items.flatMapTo(mutableSetOf<String>()) {
+ when (it.kind) {
+ NodeKind.GroupNode -> unionPlatformsOfItems(it.origins)
+ else -> it.platforms
}
}
- fun formatSubNodeOfGroup(member: DocumentationNode) {
- SingleNodePageBuilder(member, true).build()
- }
+ return platforms.let { if (it.containsAll(impliedPlatforms)) it - impliedPlatforms else it }
}
- inner class SingleNodePageBuilder(val node: DocumentationNode, noHeader: Boolean = false)
- : PageBuilder(listOf(node), noHeader) {
+ inner class SectionsBuilder(val node: DocumentationNode): PageBuilder(listOf(node)) {
override fun build() {
- super.build()
-
if (node.kind == NodeKind.ExternalClass) {
appendSection("Extensions for ${node.name}", node.members)
return
}
fun DocumentationNode.membersOrGroupMembers(predicate: (DocumentationNode) -> Boolean): List<DocumentationNode> {
- return members.filter(predicate) + members(NodeKind.GroupNode).flatMap { it.members.filter(predicate) }
+ return members.filter(predicate) + members(NodeKind.GroupNode).filter{ it.origins.isNotEmpty() && predicate(it.origins.first()) }
}
fun DocumentationNode.membersOrGroupMembers(kind: NodeKind): List<DocumentationNode> {
@@ -506,20 +629,19 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
}
appendSection("Packages", node.members(NodeKind.Package), platformsBasedOnMembers = true)
- appendSection("Types", node.membersOrGroupMembers { it.kind in NodeKind.classLike && it.kind != NodeKind.TypeAlias && it.kind != NodeKind.AnnotationClass && it.kind != NodeKind.Exception })
+ appendSection("Types", node.membersOrGroupMembers { it.kind in NodeKind.classLike /*&& it.kind != NodeKind.TypeAlias*/ && it.kind != NodeKind.AnnotationClass && it.kind != NodeKind.Exception })
appendSection("Annotations", node.membersOrGroupMembers(NodeKind.AnnotationClass))
appendSection("Exceptions", node.membersOrGroupMembers(NodeKind.Exception))
- appendSection("Type Aliases", node.membersOrGroupMembers(NodeKind.TypeAlias))
appendSection("Extensions for External Classes", node.members(NodeKind.ExternalClass))
- appendSection("Enum Values", node.members(NodeKind.EnumItem), sortMembers = false, omitSamePlatforms = true)
- appendSection("Constructors", node.members(NodeKind.Constructor), omitSamePlatforms = true)
- appendSection("Properties", node.members(NodeKind.Property), omitSamePlatforms = true)
+ appendSection("Enum Values", node.membersOrGroupMembers(NodeKind.EnumItem), sortMembers = false, omitSamePlatforms = true)
+ appendSection("Constructors", node.membersOrGroupMembers(NodeKind.Constructor), omitSamePlatforms = true)
+ appendSection("Properties", node.membersOrGroupMembers(NodeKind.Property), omitSamePlatforms = true)
appendSection("Inherited Properties", node.inheritedMembers(NodeKind.Property))
- appendSection("Functions", node.members(NodeKind.Function), omitSamePlatforms = true)
+ appendSection("Functions", node.membersOrGroupMembers(NodeKind.Function), omitSamePlatforms = true)
appendSection("Inherited Functions", node.inheritedMembers(NodeKind.Function))
- appendSection("Companion Object Properties", node.members(NodeKind.CompanionObjectProperty), omitSamePlatforms = true)
+ appendSection("Companion Object Properties", node.membersOrGroupMembers(NodeKind.CompanionObjectProperty), omitSamePlatforms = true)
appendSection("Inherited Companion Object Properties", node.inheritedCompanionObjectMembers(NodeKind.Property))
- appendSection("Companion Object Functions", node.members(NodeKind.CompanionObjectFunction), omitSamePlatforms = true)
+ appendSection("Companion Object Functions", node.membersOrGroupMembers(NodeKind.CompanionObjectFunction), omitSamePlatforms = true)
appendSection("Inherited Companion Object Functions", node.inheritedCompanionObjectMembers(NodeKind.Function))
appendSection("Other members", node.members.filter {
it.kind !in setOf(
@@ -554,7 +676,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
if (node.kind == NodeKind.Module) {
appendHeader(3) { to.append("Index") }
node.members(NodeKind.AllTypes).singleOrNull()?.let { allTypes ->
- appendLink(link(node, allTypes, { "All Types" }))
+ appendLink(link(node, allTypes) { "All Types" })
}
}
}
@@ -567,7 +689,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
appendHeader(3) { appendText(caption) }
- val children = if (sortMembers) members.sortedBy { it.name } else members
+ val children = if (sortMembers) members.sortedBy { it.name.toLowerCase() } else members
val membersMap = children.groupBy { link(node, it) }
@@ -590,11 +712,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
}
}
appendTableCell {
- val breakdownBySummary = members.groupBy { it.summary }
- for ((summary, items) in breakdownBySummary) {
- appendSummarySignatures(items)
- appendContent(summary)
- }
+ appendSummarySignatures(members, platformsBasedOnMembers, omitSamePlatforms)
}
}
}
@@ -603,6 +721,10 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
}
private fun platformsOfItems(items: List<DocumentationNode>, omitSamePlatforms: Boolean = true): Set<String> {
+ if (items.all { it.kind != NodeKind.Package && it.kind != NodeKind.Module && it.kind != NodeKind.ExternalClass }) {
+ return unionPlatformsOfItems(items)
+ }
+
val platforms = platformsOfItems(items)
if (platforms.isNotEmpty() && (platforms != node.platformsToShow.toSet() || !omitSamePlatforms)) {
return platforms
@@ -610,27 +732,62 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
return emptySet()
}
- private fun appendSummarySignatures(items: List<DocumentationNode>) {
- val summarySignature = languageService.summarizeSignatures(items)
- if (summarySignature != null) {
- appendAsSignature(summarySignature) {
- summarySignature.appendSignature()
+ private fun appendSummarySignatures(items: List<DocumentationNode>, platformsBasedOnMembers: Boolean, omitSamePlatforms: Boolean) {
+ val groupBySummary = items.groupBy { it.summary }
+
+ for ((summary, node) in groupBySummary) {
+ val nodesToAppend = if (node.all { it.kind == NodeKind.GroupNode }) {
+ node.flatMap { it.origins }
+ } else {
+ node
}
- return
- }
- val renderedSignatures = items.map { languageService.render(it, RenderMode.SUMMARY) }
- renderedSignatures.subList(0, renderedSignatures.size - 1).forEach {
- appendAsSignature(it) {
- it.appendSignature()
+
+ val summarySignature = languageService.summarizeSignatures(nodesToAppend)
+ if (summarySignature != null) {
+ appendSignatures(summarySignature, items, platformsBasedOnMembers, omitSamePlatforms)
+ } else {
+ val groupBySignature = nodesToAppend.groupBy {
+ languageService.render(it, RenderMode.SUMMARY)
+ }
+ for ((sign, members) in groupBySignature) {
+ appendSignatures(sign, members, platformsBasedOnMembers, omitSamePlatforms)
+ }
+ }
+
+ val platforms = platformsOfItems(node)
+ appendAsBlockWithPlatforms(platforms) {
+ appendContent(summary)
+ appendSoftLineBreak()
}
- appendLine()
}
- appendAsSignature(renderedSignatures.last()) {
- renderedSignatures.last().appendSignature()
+ }
+
+ private fun appendSignatures(signature: ContentNode, items: List<DocumentationNode>, platformsBasedOnMembers: Boolean, omitSamePlatforms: Boolean) {
+ val elementPlatforms = platformsOfItems(items, omitSamePlatforms)
+ val platforms = if (platformsBasedOnMembers)
+ items.flatMapTo(mutableSetOf()) { platformsOfItems(it.members) } + elementPlatforms
+ else
+ elementPlatforms
+
+ appendAsBlockWithPlatforms(platforms) {
+ appendPlatforms(platforms)
+ appendAsSignature(signature) {
+ signature.appendSignature()
+ }
+ appendSoftLineBreak()
}
}
}
+ private fun DocumentationNode.isClassLikeGroupNode(): Boolean {
+ if (kind != NodeKind.GroupNode) {
+ return false
+ }
+
+ return origins.all { it.kind in NodeKind.classLike }
+ }
+
+
inner class AllTypesNodeBuilder(val node: DocumentationNode)
: PageBuilder(listOf(node)) {
@@ -654,7 +811,13 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
}
}
appendTableCell {
- appendContent(type.summary)
+ val summary = if (type.isClassLikeGroupNode()) {
+ type.origins.first().summary
+ } else {
+ type.summary
+ }
+
+ appendContent(summary)
}
}
}
@@ -674,9 +837,9 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
}
}
-abstract class StructuredFormatService(locationService: LocationService,
+abstract class StructuredFormatService(val generator: NodeLocationAwareGenerator,
val languageService: LanguageService,
override val extension: String,
override final val linkExtension: String = extension) : FormatService {
- val locationService: LocationService = locationService.withExtension(linkExtension)
+
}
diff --git a/core/src/main/kotlin/Formats/YamlOutlineService.kt b/core/src/main/kotlin/Formats/YamlOutlineService.kt
index 7968824c..c36f98eb 100644
--- a/core/src/main/kotlin/Formats/YamlOutlineService.kt
+++ b/core/src/main/kotlin/Formats/YamlOutlineService.kt
@@ -3,15 +3,17 @@ package org.jetbrains.dokka
import com.google.inject.Inject
import java.io.File
-class YamlOutlineService @Inject constructor(val locationService: LocationService,
- val languageService: LanguageService) : OutlineFormatService {
+class YamlOutlineService @Inject constructor(
+ val generator: NodeLocationAwareGenerator,
+ val languageService: LanguageService
+) : OutlineFormatService {
override fun getOutlineFileName(location: Location): File = File("${location.path}.yml")
var outlineLevel = 0
override fun appendOutlineHeader(location: Location, node: DocumentationNode, to: StringBuilder) {
val indent = " ".repeat(outlineLevel)
to.appendln("$indent- title: ${languageService.renderName(node)}")
- to.appendln("$indent url: ${locationService.location(node).path}")
+ to.appendln("$indent url: ${generator.location(node).path}")
}
override fun appendOutlineLevel(to: StringBuilder, body: () -> Unit) {