From 7acc52ba723eab08fe796fcfd68755e7f0eb6a66 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Sat, 2 Dec 2017 00:50:08 +0300 Subject: WIP: Refactoring, remove LocationService, rework FormatDescriptor --- .../src/main/kotlin/Generation/ConsoleGenerator.kt | 42 ---------------------- core/src/main/kotlin/Generation/FileGenerator.kt | 17 +++++---- core/src/main/kotlin/Generation/Generator.kt | 5 +++ 3 files changed, 16 insertions(+), 48 deletions(-) delete mode 100644 core/src/main/kotlin/Generation/ConsoleGenerator.kt (limited to 'core/src/main/kotlin/Generation') diff --git a/core/src/main/kotlin/Generation/ConsoleGenerator.kt b/core/src/main/kotlin/Generation/ConsoleGenerator.kt deleted file mode 100644 index 301f86b9..00000000 --- a/core/src/main/kotlin/Generation/ConsoleGenerator.kt +++ /dev/null @@ -1,42 +0,0 @@ -package org.jetbrains.dokka - -class ConsoleGenerator(val signatureGenerator: LanguageService, val locationService: LocationService) { - val IndentStep = " " - - fun generate(node: DocumentationNode, indent: String = "") { - println("@${locationService.location(node).path}") - generateHeader(node, indent) - //generateDetails(node, indent) - generateMembers(node, indent) - generateLinks(node, indent) - } - - fun generateHeader(node: DocumentationNode, indent: String = "") { - println(indent + signatureGenerator.render(node)) - val docString = node.content.toString() - if (!docString.isEmpty()) - println("$indent\"${docString.replace("\n", "\n$indent")}\"") - println() - } - - fun generateMembers(node: DocumentationNode, indent: String = "") { - val items = node.members.sortedBy { it.name } - for (child in items) - generate(child, indent + IndentStep) - } - - fun generateDetails(node: DocumentationNode, indent: String = "") { - val items = node.details - for (child in items) - generate(child, indent + " ") - } - - fun generateLinks(node: DocumentationNode, indent: String = "") { - val items = node.links - if (items.isEmpty()) - return - println("$indent Links") - for (child in items) - generate(child, indent + " ") - } -} \ No newline at end of file diff --git a/core/src/main/kotlin/Generation/FileGenerator.kt b/core/src/main/kotlin/Generation/FileGenerator.kt index e055c537..3193a5bc 100644 --- a/core/src/main/kotlin/Generation/FileGenerator.kt +++ b/core/src/main/kotlin/Generation/FileGenerator.kt @@ -1,22 +1,27 @@ package org.jetbrains.dokka import com.google.inject.Inject +import com.google.inject.name.Named import java.io.File import java.io.FileOutputStream import java.io.IOException import java.io.OutputStreamWriter -class FileGenerator @Inject constructor(val locationService: FileLocationService) : Generator { +class FileGenerator @Inject constructor(@Named("outputDir") val rootFile: File) : NodeLocationAwareGenerator { @set:Inject(optional = true) var outlineService: OutlineFormatService? = null @set:Inject(optional = true) lateinit var formatService: FormatService @set:Inject(optional = true) lateinit var options: DocumentationOptions @set:Inject(optional = true) var packageListService: PackageListService? = null + override fun location(node: DocumentationNode): FileLocation { + return FileLocation(File(rootFile, relativePathToNode(node.path.map { it.name }, node.members.any())).appendExtension(formatService.extension)) + } + override fun buildPages(nodes: Iterable) { - val specificLocationService = locationService.withExtension(formatService.extension) + //val specificLocationService = locationService.withExtension(formatService.extension) - for ((location, items) in nodes.groupBy { specificLocationService.location(it) }) { + for ((location, items) in nodes.groupBy { location(it) }) { val file = location.file file.parentFile?.mkdirsOrFail() try { @@ -34,7 +39,7 @@ class FileGenerator @Inject constructor(val locationService: FileLocationService override fun buildOutlines(nodes: Iterable) { val outlineService = this.outlineService ?: return - for ((location, items) in nodes.groupBy { locationService.location(it) }) { + for ((location, items) in nodes.groupBy { location(it) }) { val file = outlineService.getOutlineFileName(location) file.parentFile?.mkdirsOrFail() FileOutputStream(file).use { @@ -47,7 +52,7 @@ class FileGenerator @Inject constructor(val locationService: FileLocationService override fun buildSupportFiles() { formatService.enumerateSupportFiles { resource, targetPath -> - FileOutputStream(locationService.location(listOf(targetPath), false).file).use { + FileOutputStream(relativePathToNode(listOf(targetPath), false)).use { javaClass.getResourceAsStream(resource).copyTo(it) } } @@ -58,7 +63,7 @@ class FileGenerator @Inject constructor(val locationService: FileLocationService for (module in nodes) { - val moduleRoot = locationService.location(module).file.parentFile + val moduleRoot = location(module).file.parentFile val packageListFile = File(moduleRoot, "package-list") packageListFile.writeText("\$dokka.format:${options.outputFormat}\n" + diff --git a/core/src/main/kotlin/Generation/Generator.kt b/core/src/main/kotlin/Generation/Generator.kt index 76a5f350..003386ef 100644 --- a/core/src/main/kotlin/Generation/Generator.kt +++ b/core/src/main/kotlin/Generation/Generator.kt @@ -19,3 +19,8 @@ fun Generator.buildPage(node: DocumentationNode): Unit = buildPages(listOf(node) fun Generator.buildOutline(node: DocumentationNode): Unit = buildOutlines(listOf(node)) fun Generator.buildAll(node: DocumentationNode): Unit = buildAll(listOf(node)) + + +interface NodeLocationAwareGenerator: Generator { + fun location(node: DocumentationNode): Location +} \ No newline at end of file -- cgit From c7523225200a3e24d24fb3b0492d5c377246fc69 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Sat, 2 Dec 2017 04:57:45 +0300 Subject: Make possible to calculate path to root --- core/src/main/kotlin/Formats/HtmlFormatService.kt | 9 ++------- core/src/main/kotlin/Formats/HtmlTemplateService.kt | 6 +++--- core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt | 4 ++-- core/src/main/kotlin/Generation/FileGenerator.kt | 2 ++ core/src/main/kotlin/Generation/Generator.kt | 3 +++ core/src/main/kotlin/Locations/LocationService.kt | 6 ++++++ 6 files changed, 18 insertions(+), 12 deletions(-) (limited to 'core/src/main/kotlin/Generation') diff --git a/core/src/main/kotlin/Formats/HtmlFormatService.kt b/core/src/main/kotlin/Formats/HtmlFormatService.kt index 560d8597..0073553c 100644 --- a/core/src/main/kotlin/Formats/HtmlFormatService.kt +++ b/core/src/main/kotlin/Formats/HtmlFormatService.kt @@ -80,7 +80,7 @@ open class HtmlOutputBuilder(to: StringBuilder, } override fun appendNodes(nodes: Iterable) { - templateService.appendHeader(to, getPageTitle(nodes), locationService.calcPathToRoot(location)) + templateService.appendHeader(to, getPageTitle(nodes), generator.relativeToRoot(location)) super.appendNodes(nodes) templateService.appendFooter(to) } @@ -108,7 +108,7 @@ open class HtmlFormatService @Inject constructor(generator: NodeLocationAwareGen HtmlOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms, templateService) override fun appendOutline(location: Location, to: StringBuilder, nodes: Iterable) { - templateService.appendHeader(to, "Module Contents", locationService.calcPathToRoot(location)) + templateService.appendHeader(to, "Module Contents", generator.relativeToRoot(location)) super.appendOutline(location, to, nodes) templateService.appendFooter(to) } @@ -132,11 +132,6 @@ open class HtmlFormatService @Inject constructor(generator: NodeLocationAwareGen } } -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): 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 22832e34..84e01910 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("") to.appendln("") } - override fun appendHeader(to: StringBuilder, title: String?, relativePathToRoot: String) { + override fun appendHeader(to: StringBuilder, title: String?, basePath: File) { to.appendln("") to.appendln("") to.appendln("") diff --git a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt index 208756c8..6ced75b5 100644 --- a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt +++ b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt @@ -4,13 +4,13 @@ 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 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) {} } diff --git a/core/src/main/kotlin/Generation/FileGenerator.kt b/core/src/main/kotlin/Generation/FileGenerator.kt index 3193a5bc..9c7c65e6 100644 --- a/core/src/main/kotlin/Generation/FileGenerator.kt +++ b/core/src/main/kotlin/Generation/FileGenerator.kt @@ -14,6 +14,8 @@ class FileGenerator @Inject constructor(@Named("outputDir") val rootFile: File) @set:Inject(optional = true) lateinit var options: DocumentationOptions @set:Inject(optional = true) var packageListService: PackageListService? = null + override val root: File = rootFile + override fun location(node: DocumentationNode): FileLocation { return FileLocation(File(rootFile, relativePathToNode(node.path.map { it.name }, node.members.any())).appendExtension(formatService.extension)) } diff --git a/core/src/main/kotlin/Generation/Generator.kt b/core/src/main/kotlin/Generation/Generator.kt index 003386ef..23286e29 100644 --- a/core/src/main/kotlin/Generation/Generator.kt +++ b/core/src/main/kotlin/Generation/Generator.kt @@ -1,5 +1,7 @@ package org.jetbrains.dokka +import java.io.File + interface Generator { fun buildPages(nodes: Iterable) fun buildOutlines(nodes: Iterable) @@ -23,4 +25,5 @@ fun Generator.buildAll(node: DocumentationNode): Unit = buildAll(listOf(node)) interface NodeLocationAwareGenerator: Generator { fun location(node: DocumentationNode): Location + val root: File } \ No newline at end of file diff --git a/core/src/main/kotlin/Locations/LocationService.kt b/core/src/main/kotlin/Locations/LocationService.kt index 6b7e0511..8ea45dae 100644 --- a/core/src/main/kotlin/Locations/LocationService.kt +++ b/core/src/main/kotlin/Locations/LocationService.kt @@ -94,4 +94,10 @@ fun identifierToFilename(path: String): String { fun NodeLocationAwareGenerator.relativePathToLocation(owner: DocumentationNode, node: DocumentationNode): String { return location(owner).relativePathTo(location(node), null) +} + + +fun NodeLocationAwareGenerator.relativeToRoot(from: Location): File { + val file = File(from.path) + return file.relativeTo(root) } \ No newline at end of file -- cgit From ff8948350406b085ca7feeb5d8aabd74b9eadf83 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Sat, 2 Dec 2017 05:21:10 +0300 Subject: Fix outline file names, fix incorrect placement of support files --- core/src/main/kotlin/Generation/FileGenerator.kt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'core/src/main/kotlin/Generation') diff --git a/core/src/main/kotlin/Generation/FileGenerator.kt b/core/src/main/kotlin/Generation/FileGenerator.kt index 9c7c65e6..ea34a269 100644 --- a/core/src/main/kotlin/Generation/FileGenerator.kt +++ b/core/src/main/kotlin/Generation/FileGenerator.kt @@ -17,11 +17,14 @@ class FileGenerator @Inject constructor(@Named("outputDir") val rootFile: File) override val root: File = rootFile override fun location(node: DocumentationNode): FileLocation { - return FileLocation(File(rootFile, relativePathToNode(node.path.map { it.name }, node.members.any())).appendExtension(formatService.extension)) + return locationWithoutExtension(node).let { it.copy(file = it.file.appendExtension(formatService.linkExtension)) } + } + + fun locationWithoutExtension(node: DocumentationNode): FileLocation { + return FileLocation(File(rootFile, relativePathToNode(node.path.map { it.name }, node.members.any()))) } override fun buildPages(nodes: Iterable) { - //val specificLocationService = locationService.withExtension(formatService.extension) for ((location, items) in nodes.groupBy { location(it) }) { val file = location.file @@ -41,7 +44,7 @@ class FileGenerator @Inject constructor(@Named("outputDir") val rootFile: File) override fun buildOutlines(nodes: Iterable) { val outlineService = this.outlineService ?: return - for ((location, items) in nodes.groupBy { location(it) }) { + for ((location, items) in nodes.groupBy { locationWithoutExtension(it) }) { val file = outlineService.getOutlineFileName(location) file.parentFile?.mkdirsOrFail() FileOutputStream(file).use { @@ -54,7 +57,7 @@ class FileGenerator @Inject constructor(@Named("outputDir") val rootFile: File) override fun buildSupportFiles() { formatService.enumerateSupportFiles { resource, targetPath -> - FileOutputStream(relativePathToNode(listOf(targetPath), false)).use { + FileOutputStream(File(root, relativePathToNode(listOf(targetPath), false))).use { javaClass.getResourceAsStream(resource).copyTo(it) } } -- cgit From d6d5df5bc04be5274446e9f37a3e52672083da36 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Sat, 2 Dec 2017 05:58:30 +0300 Subject: Add actual relativePathToNode function --- core/src/main/kotlin/Generation/FileGenerator.kt | 2 +- core/src/main/kotlin/Locations/LocationService.kt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'core/src/main/kotlin/Generation') diff --git a/core/src/main/kotlin/Generation/FileGenerator.kt b/core/src/main/kotlin/Generation/FileGenerator.kt index ea34a269..3d25e932 100644 --- a/core/src/main/kotlin/Generation/FileGenerator.kt +++ b/core/src/main/kotlin/Generation/FileGenerator.kt @@ -21,7 +21,7 @@ class FileGenerator @Inject constructor(@Named("outputDir") val rootFile: File) } fun locationWithoutExtension(node: DocumentationNode): FileLocation { - return FileLocation(File(rootFile, relativePathToNode(node.path.map { it.name }, node.members.any()))) + return FileLocation(File(rootFile, relativePathToNode(node))) } override fun buildPages(nodes: Iterable) { diff --git a/core/src/main/kotlin/Locations/LocationService.kt b/core/src/main/kotlin/Locations/LocationService.kt index 8ea45dae..e453baca 100644 --- a/core/src/main/kotlin/Locations/LocationService.kt +++ b/core/src/main/kotlin/Locations/LocationService.kt @@ -44,6 +44,7 @@ fun relativePathToNode(qualifiedName: List, hasMembers: Boolean): String } } +fun relativePathToNode(node: DocumentationNode) = relativePathToNode(node.path.map { it.name }, node.members.any()) // -- cgit From 799e3713f8b6a80b53a1b9f28a86844ed30b71ae Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Mon, 11 Dec 2017 18:28:08 +0300 Subject: Fix file extensions when FormatService.extension != linkExtension --- core/src/main/kotlin/Generation/FileGenerator.kt | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'core/src/main/kotlin/Generation') diff --git a/core/src/main/kotlin/Generation/FileGenerator.kt b/core/src/main/kotlin/Generation/FileGenerator.kt index 3d25e932..bc08e180 100644 --- a/core/src/main/kotlin/Generation/FileGenerator.kt +++ b/core/src/main/kotlin/Generation/FileGenerator.kt @@ -2,6 +2,7 @@ package org.jetbrains.dokka import com.google.inject.Inject import com.google.inject.name.Named +import org.jetbrains.kotlin.utils.fileUtils.withReplacedExtensionOrNull import java.io.File import java.io.FileOutputStream import java.io.IOException @@ -17,22 +18,26 @@ class FileGenerator @Inject constructor(@Named("outputDir") val rootFile: File) override val root: File = rootFile override fun location(node: DocumentationNode): FileLocation { - return locationWithoutExtension(node).let { it.copy(file = it.file.appendExtension(formatService.linkExtension)) } + return FileLocation(fileForNode(node, formatService.linkExtension)) + } + + private fun fileForNode(node: DocumentationNode, extension: String = ""): File { + return File(root, relativePathToNode(node)).appendExtension(extension) } fun locationWithoutExtension(node: DocumentationNode): FileLocation { - return FileLocation(File(rootFile, relativePathToNode(node))) + return FileLocation(fileForNode(node)) } override fun buildPages(nodes: Iterable) { - for ((location, items) in nodes.groupBy { location(it) }) { - val file = location.file + for ((file, items) in nodes.groupBy { fileForNode(it, formatService.extension) }) { + file.parentFile?.mkdirsOrFail() try { FileOutputStream(file).use { OutputStreamWriter(it, Charsets.UTF_8).use { - it.write(formatService.format(location, items)) + it.write(formatService.format(location(items.first()), items)) } } } catch (e: Throwable) { -- cgit From 9865da2e6e6c038ab6c719a6a03bb09184542d20 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Thu, 17 May 2018 19:48:44 +0300 Subject: Fix incorrect link to stylesheet in html format --- core/src/main/kotlin/Formats/HtmlFormatService.kt | 5 ++--- core/src/main/kotlin/Generation/FileGenerator.kt | 4 +--- core/src/main/kotlin/Locations/Location.kt | 6 +++--- core/src/test/kotlin/format/FileGeneratorTestCase.kt | 2 +- 4 files changed, 7 insertions(+), 10 deletions(-) (limited to 'core/src/main/kotlin/Generation') diff --git a/core/src/main/kotlin/Formats/HtmlFormatService.kt b/core/src/main/kotlin/Formats/HtmlFormatService.kt index 0073553c..0ad946be 100644 --- a/core/src/main/kotlin/Formats/HtmlFormatService.kt +++ b/core/src/main/kotlin/Formats/HtmlFormatService.kt @@ -4,7 +4,6 @@ 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 open class HtmlOutputBuilder(to: StringBuilder, location: Location, @@ -80,7 +79,7 @@ open class HtmlOutputBuilder(to: StringBuilder, } override fun appendNodes(nodes: Iterable) { - templateService.appendHeader(to, getPageTitle(nodes), generator.relativeToRoot(location)) + templateService.appendHeader(to, getPageTitle(nodes), generator.relativePathToRoot(location)) super.appendNodes(nodes) templateService.appendFooter(to) } @@ -108,7 +107,7 @@ open class HtmlFormatService @Inject constructor(generator: NodeLocationAwareGen HtmlOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms, templateService) override fun appendOutline(location: Location, to: StringBuilder, nodes: Iterable) { - templateService.appendHeader(to, "Module Contents", generator.relativeToRoot(location)) + templateService.appendHeader(to, "Module Contents", generator.relativePathToRoot(location)) super.appendOutline(location, to, nodes) templateService.appendFooter(to) } diff --git a/core/src/main/kotlin/Generation/FileGenerator.kt b/core/src/main/kotlin/Generation/FileGenerator.kt index bc08e180..b7c6cf63 100644 --- a/core/src/main/kotlin/Generation/FileGenerator.kt +++ b/core/src/main/kotlin/Generation/FileGenerator.kt @@ -8,15 +8,13 @@ import java.io.FileOutputStream import java.io.IOException import java.io.OutputStreamWriter -class FileGenerator @Inject constructor(@Named("outputDir") val rootFile: File) : NodeLocationAwareGenerator { +class FileGenerator @Inject constructor(@Named("outputDir") override val root: File) : NodeLocationAwareGenerator { @set:Inject(optional = true) var outlineService: OutlineFormatService? = null @set:Inject(optional = true) lateinit var formatService: FormatService @set:Inject(optional = true) lateinit var options: DocumentationOptions @set:Inject(optional = true) var packageListService: PackageListService? = null - override val root: File = rootFile - override fun location(node: DocumentationNode): FileLocation { return FileLocation(fileForNode(node, formatService.linkExtension)) } diff --git a/core/src/main/kotlin/Locations/Location.kt b/core/src/main/kotlin/Locations/Location.kt index 0e6572d9..4cb0ac39 100644 --- a/core/src/main/kotlin/Locations/Location.kt +++ b/core/src/main/kotlin/Locations/Location.kt @@ -53,9 +53,9 @@ fun NodeLocationAwareGenerator.relativePathToLocation(owner: DocumentationNode, return location(owner).relativePathTo(location(node), null) } -fun NodeLocationAwareGenerator.relativeToRoot(from: Location): File { - val file = File(from.path) - return file.relativeTo(root) +fun NodeLocationAwareGenerator.relativePathToRoot(from: Location): File { + val file = File(from.path).parentFile + return root.relativeTo(file) } fun File.toUnixString() = toString().replace(File.separatorChar, '/') diff --git a/core/src/test/kotlin/format/FileGeneratorTestCase.kt b/core/src/test/kotlin/format/FileGeneratorTestCase.kt index 948426ea..ef9e815d 100644 --- a/core/src/test/kotlin/format/FileGeneratorTestCase.kt +++ b/core/src/test/kotlin/format/FileGeneratorTestCase.kt @@ -27,7 +27,7 @@ abstract class FileGeneratorTestCase { if (sb.isNotBlank() && !sb.endsWith('\n')) { sb.appendln() } - sb.appendln("") + sb.appendln("") } sb.append(loc.file.readText()) } -- cgit From 9ea429920e07c77e1241c4beb172bb36735af783 Mon Sep 17 00:00:00 2001 From: aleksZubakov Date: Tue, 10 Jul 2018 19:27:16 +0300 Subject: Add js platform support --- .../main/kotlin/Analysis/AnalysisEnvironment.kt | 110 +++++++++++++++++---- core/src/main/kotlin/Generation/DokkaGenerator.kt | 24 +++-- .../main/kotlin/Generation/configurationImpl.kt | 13 ++- .../kotlin/org/jetbrains/dokka/configuration.kt | 22 +++++ runners/ant/src/main/kotlin/ant/dokka.kt | 5 +- runners/gradle-plugin/src/main/kotlin/main.kt | 2 + runners/maven-plugin/src/main/kotlin/DokkaMojo.kt | 4 + 7 files changed, 148 insertions(+), 32 deletions(-) (limited to 'core/src/main/kotlin/Generation') diff --git a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt index b2e4b490..453c0311 100644 --- a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt +++ b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt @@ -18,6 +18,8 @@ import com.intellij.psi.PsiElement import com.intellij.psi.search.GlobalSearchScope import com.intellij.util.io.URLUtil import org.jetbrains.kotlin.analyzer.* +import org.jetbrains.kotlin.builtins.jvm.JvmBuiltIns +import org.jetbrains.kotlin.caches.project.LibraryModuleInfo import org.jetbrains.kotlin.caches.resolve.KotlinCacheService import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.messages.MessageCollector @@ -32,14 +34,17 @@ import org.jetbrains.kotlin.container.getService import org.jetbrains.kotlin.context.ProjectContext import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.idea.caches.resolve.JsAnalyzerFacade import org.jetbrains.kotlin.idea.resolve.ResolutionFacade +import org.jetbrains.kotlin.js.config.JSConfigurationKeys +import org.jetbrains.kotlin.js.resolve.JsPlatform import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.platform.JvmBuiltIns import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingTrace import org.jetbrains.kotlin.resolve.CompilerEnvironment +import org.jetbrains.kotlin.resolve.TargetPlatform import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics import org.jetbrains.kotlin.resolve.jvm.JvmAnalyzerFacade import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters @@ -59,7 +64,7 @@ import java.io.File * $messageCollector: required by compiler infrastructure and will receive all compiler messages * $body: optional and can be used to configure environment without creating local variable */ -class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable { +class AnalysisEnvironment(val messageCollector: MessageCollector, val analysisPlatform: Platform) : Disposable { val configuration = CompilerConfiguration() init { @@ -68,7 +73,12 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable { fun createCoreEnvironment(): KotlinCoreEnvironment { System.setProperty("idea.io.use.fallback", "true") - val environment = KotlinCoreEnvironment.createForProduction(this, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES) + + val configFiles = when (analysisPlatform) { + Platform.jvm -> EnvironmentConfigFiles.JVM_CONFIG_FILES + Platform.js -> EnvironmentConfigFiles.JS_CONFIG_FILES + } + val environment = KotlinCoreEnvironment.createForProduction(this, configuration, configFiles) val projectComponentManager = environment.project as MockComponentManager val projectFileIndex = CoreProjectFileIndex(environment.project, @@ -92,14 +102,71 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable { return environment } - fun createSourceModuleSearchScope(project: Project, sourceFiles: List): GlobalSearchScope { - // TODO: Fix when going to implement dokka for JS - return TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, sourceFiles) + fun createSourceModuleSearchScope(project: Project, sourceFiles: List): GlobalSearchScope = when (analysisPlatform) { + Platform.js -> GlobalSearchScope.filesScope(project, sourceFiles.map { it.virtualFile }.toSet()) + Platform.jvm -> TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, sourceFiles) } fun createResolutionFacade(environment: KotlinCoreEnvironment): DokkaResolutionFacade { + return when(analysisPlatform) { + Platform.jvm -> createJVMResolutionFacade(environment) + Platform.js -> createJSResolutionFacade(environment) + } + } + private fun createJSResolutionFacade(environment: KotlinCoreEnvironment): DokkaResolutionFacade { + val projectContext = ProjectContext(environment.project) + val sourceFiles = environment.getSourceFiles() + + val library = object : LibraryModuleInfo { + override val platform: TargetPlatform + get() = JsPlatform + + override fun getLibraryRoots(): Collection { + return classpath.map { it.absolutePath } + } + + override val name: Name = Name.special("") + override fun dependencies(): List = listOf(this) + } + val module = object : ModuleInfo { + override val name: Name = Name.special("") + override fun dependencies(): List = listOf(this, library) + } + + val sourcesScope = createSourceModuleSearchScope(environment.project, sourceFiles) + + val resolverForProject = ResolverForProjectImpl( + debugName = "Dokka", + projectContext = projectContext, + modules = listOf(library, module), + modulesContent = { + when (it) { + library -> ModuleContent(it, emptyList(), GlobalSearchScope.notScope(sourcesScope)) + module -> ModuleContent(it, emptyList(), sourcesScope) + else -> throw IllegalArgumentException("Unexpected module info") + } + }, + modulePlatforms = { JsPlatform.multiTargetPlatform }, + moduleLanguageSettingsProvider = LanguageSettingsProvider.Default /* TODO: Fix this */, + resolverForModuleFactoryByPlatform = { JsAnalyzerFacade }, + platformParameters = object : PlatformAnalysisParameters {}, + targetEnvironment = CompilerEnvironment, + builtIns = JsPlatform.builtIns + ) + + resolverForProject.resolverForModule(library) // Required before module to initialize library properly + val resolverForModule = resolverForProject.resolverForModule(module) + val moduleDescriptor = resolverForProject.descriptorForModule(module) + val created = DokkaResolutionFacade(environment.project, moduleDescriptor, resolverForModule) + val projectComponentManager = environment.project as MockComponentManager + projectComponentManager.registerService(KotlinCacheService::class.java, CoreKotlinCacheService(created)) + return created + + } + + private fun createJVMResolutionFacade(environment: KotlinCoreEnvironment): DokkaResolutionFacade { val projectContext = ProjectContext(environment.project) val sourceFiles = environment.getSourceFiles() @@ -131,30 +198,27 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable { } val resolverForProject = ResolverForProjectImpl( - "Dokka", - projectContext, - listOf(library, module), - { + debugName = "Dokka", + projectContext = projectContext, + modules = listOf(library, module), + modulesContent = { when (it) { library -> ModuleContent(it, emptyList(), GlobalSearchScope.notScope(sourcesScope)) module -> ModuleContent(it, emptyList(), sourcesScope) else -> throw IllegalArgumentException("Unexpected module info") } }, - { - JvmPlatform.multiTargetPlatform - }, - LanguageSettingsProvider.Default /* TODO: Fix this */, - { JvmAnalyzerFacade }, - - JvmPlatformParameters { + modulePlatforms = { JvmPlatform.multiTargetPlatform }, + moduleLanguageSettingsProvider = LanguageSettingsProvider.Default /* TODO: Fix this */, + resolverForModuleFactoryByPlatform = { JvmAnalyzerFacade }, + platformParameters = JvmPlatformParameters { val file = (it as JavaClassImpl).psi.containingFile.virtualFile if (file in sourcesScope) module else library }, - CompilerEnvironment, + targetEnvironment = CompilerEnvironment, packagePartProviderFactory = { content -> JvmPackagePartProvider(configuration.languageVersionSettings, content.moduleContentScope).apply { addRoots(javaRoots) @@ -191,7 +255,10 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable { * $paths: collection of files to add */ fun addClasspath(paths: List) { - configuration.addJvmClasspathRoots(paths) + when (analysisPlatform) { + Platform.js -> configuration.addAll(JSConfigurationKeys.LIBRARIES, paths.map{it.absolutePath}) + Platform.jvm -> configuration.addJvmClasspathRoots(paths) + } } /** @@ -199,7 +266,10 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable { * $path: path to add */ fun addClasspath(path: File) { - configuration.addJvmClasspathRoot(path) + when (analysisPlatform) { + Platform.js -> configuration.add(JSConfigurationKeys.LIBRARIES, path.absolutePath) + Platform.jvm -> configuration.addJvmClasspathRoot(path) + } } /** diff --git a/core/src/main/kotlin/Generation/DokkaGenerator.kt b/core/src/main/kotlin/Generation/DokkaGenerator.kt index 09e5cedf..a0a6eef7 100644 --- a/core/src/main/kotlin/Generation/DokkaGenerator.kt +++ b/core/src/main/kotlin/Generation/DokkaGenerator.kt @@ -35,9 +35,10 @@ class DokkaGenerator(val logger: DokkaLogger, private val documentationModule = DocumentationModule(moduleName) fun generate() { - val sourcesGroupedByPlatform = sources.groupBy { it.platforms.firstOrNull() } - for ((platform, roots) in sourcesGroupedByPlatform) { - appendSourceModule(platform, roots) + val sourcesGroupedByPlatform = sources.groupBy { it.platforms.firstOrNull() to it.analysisPlatform } + for ((platformsInfo, roots) in sourcesGroupedByPlatform) { + val (platform, analysisPlatform) = platformsInfo + appendSourceModule(platform, analysisPlatform, roots) } documentationModule.prepareForGeneration(options) @@ -49,9 +50,14 @@ class DokkaGenerator(val logger: DokkaLogger, logger.info("done in ${timeBuild / 1000} secs") } - private fun appendSourceModule(defaultPlatform: String?, sourceRoots: List) { + private fun appendSourceModule(defaultPlatform: String?, + analysisPlatform: Platform, + sourceRoots: List + + ) { + val sourcePaths = sourceRoots.map { it.path } - val environment = createAnalysisEnvironment(sourcePaths) + val environment = createAnalysisEnvironment(sourcePaths, analysisPlatform) logger.info("Module: $moduleName") logger.info("Output: ${File(options.outputDir)}") @@ -82,11 +88,13 @@ class DokkaGenerator(val logger: DokkaLogger, Disposer.dispose(environment) } - fun createAnalysisEnvironment(sourcePaths: List): AnalysisEnvironment { - val environment = AnalysisEnvironment(DokkaMessageCollector(logger)) + fun createAnalysisEnvironment(sourcePaths: List, analysisPlatform: Platform): AnalysisEnvironment { + val environment = AnalysisEnvironment(DokkaMessageCollector(logger), analysisPlatform) environment.apply { - addClasspath(PathUtil.getJdkClassesRootsFromCurrentJre()) + if (analysisPlatform == Platform.jvm) { + addClasspath(PathUtil.getJdkClassesRootsFromCurrentJre()) + } // addClasspath(PathUtil.getKotlinPathsForCompiler().getRuntimePath()) for (element in this@DokkaGenerator.classpath) { addClasspath(File(element)) diff --git a/core/src/main/kotlin/Generation/configurationImpl.kt b/core/src/main/kotlin/Generation/configurationImpl.kt index 34d4154e..0d916345 100644 --- a/core/src/main/kotlin/Generation/configurationImpl.kt +++ b/core/src/main/kotlin/Generation/configurationImpl.kt @@ -18,13 +18,22 @@ data class SourceLinkDefinitionImpl(override val path: String, } } -class SourceRootImpl(path: String, override val platforms: List = emptyList()) : SourceRoot { +class SourceRootImpl(path: String, override val platforms: List = emptyList(), + override val analysisPlatform: Platform = Platform.DEFAULT) : SourceRoot { override val path: String = File(path).absolutePath companion object { fun parseSourceRoot(sourceRoot: String): SourceRoot { val components = sourceRoot.split("::", limit = 2) - return SourceRootImpl(components.last(), if (components.size == 1) listOf() else components[0].split(',')) + + // TODO: create syntax for cli + val platform = if (components.size == 1) { + Platform.DEFAULT + } else { + Platform.fromString(components[0]) + } + + return SourceRootImpl(components.last(), emptyList(), platform) } } } diff --git a/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt b/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt index 90e5b5fc..b18e5daf 100644 --- a/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt +++ b/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt @@ -17,6 +17,27 @@ class UrlSerializer : ValueSerializer { override fun toJsonValue(value: URL?): Any? = value?.toExternalForm() } +enum class Platform(val key: String) { + jvm("jvm"), + js("js"); +// common("common"); + + + companion object { + val DEFAULT = jvm + + fun fromString(key: String): Platform { + return when (key.toLowerCase()) { + jvm.key -> jvm + js.key -> js +// common.key -> common + else -> TODO("write normal exception") + } + } + } + +} + interface DokkaConfiguration { val moduleName: String val classpath: List @@ -45,6 +66,7 @@ interface DokkaConfiguration { interface SourceRoot { val path: String val platforms: List + val analysisPlatform: Platform } interface SourceLinkDefinition { diff --git a/runners/ant/src/main/kotlin/ant/dokka.kt b/runners/ant/src/main/kotlin/ant/dokka.kt index d1b6bef5..58e2fa28 100644 --- a/runners/ant/src/main/kotlin/ant/dokka.kt +++ b/runners/ant/src/main/kotlin/ant/dokka.kt @@ -17,10 +17,11 @@ class AntLogger(val task: Task): DokkaLogger { class AntSourceLinkDefinition(var path: String? = null, var url: String? = null, var lineSuffix: String? = null) -class AntSourceRoot(var path: String? = null, var platforms: String? = null) { +class AntSourceRoot(var path: String? = null, var platforms: String? = null, + var platform: Platform = Platform.DEFAULT) { fun toSourceRoot(): SourceRootImpl? = path?.let { path -> - SourceRootImpl(path, platforms?.split(',').orEmpty()) + SourceRootImpl(path, platforms?.split(',').orEmpty(), platform) } } diff --git a/runners/gradle-plugin/src/main/kotlin/main.kt b/runners/gradle-plugin/src/main/kotlin/main.kt index 5f02cd0e..324ea8e0 100644 --- a/runners/gradle-plugin/src/main/kotlin/main.kt +++ b/runners/gradle-plugin/src/main/kotlin/main.kt @@ -396,6 +396,8 @@ class SourceRoot : DokkaConfiguration.SourceRoot, Serializable { override var platforms: List = arrayListOf() + override val analysisPlatform: Platform = Platform.DEFAULT + override fun toString(): String { return "${platforms.joinToString()}::$path" } diff --git a/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt b/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt index 09da90c6..6b86948d 100644 --- a/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt +++ b/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt @@ -39,6 +39,10 @@ abstract class AbstractDokkaMojo : AbstractMojo() { @Parameter override var platforms: List = emptyList() + + @Parameter + override var analysisPlatform: Platform = Platform.DEFAULT + } class PackageOptions : DokkaConfiguration.PackageOptions { -- cgit From 1391dcca35a871881420c53755fed08bf47e4087 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 17 Jan 2018 20:01:20 +0300 Subject: [backport] Support propagating inherited extensions from libraries Original: bf2945d --- core/src/main/kotlin/DokkaBootstrapImpl.kt | 3 +- core/src/main/kotlin/Generation/DokkaGenerator.kt | 2 + .../main/kotlin/Generation/configurationImpl.kt | 47 ++--- .../src/main/kotlin/Kotlin/DocumentationBuilder.kt | 200 ++++++++++++++++----- .../Kotlin/ExternalDocumentationLinkResolver.kt | 2 +- core/src/main/kotlin/Model/DocumentationNode.kt | 2 + core/src/test/kotlin/TestAPI.kt | 32 ++-- .../kotlin/org/jetbrains/dokka/configuration.kt | 48 ++--- runners/cli/src/main/kotlin/cli/main.kt | 28 +-- runners/gradle-plugin/src/main/kotlin/main.kt | 51 +++--- 10 files changed, 273 insertions(+), 142 deletions(-) (limited to 'core/src/main/kotlin/Generation') diff --git a/core/src/main/kotlin/DokkaBootstrapImpl.kt b/core/src/main/kotlin/DokkaBootstrapImpl.kt index aeaca8be..b7787be8 100644 --- a/core/src/main/kotlin/DokkaBootstrapImpl.kt +++ b/core/src/main/kotlin/DokkaBootstrapImpl.kt @@ -69,7 +69,8 @@ class DokkaBootstrapImpl : DokkaBootstrap { languageVersion, apiVersion, cacheRoot, - suppressedFiles.map { File(it) }.toSet() + suppressedFiles.map { File(it) }.toSet(), + collectInheritedExtensionsFromLibraries ) ) } diff --git a/core/src/main/kotlin/Generation/DokkaGenerator.kt b/core/src/main/kotlin/Generation/DokkaGenerator.kt index 09e5cedf..33170f35 100644 --- a/core/src/main/kotlin/Generation/DokkaGenerator.kt +++ b/core/src/main/kotlin/Generation/DokkaGenerator.kt @@ -160,6 +160,8 @@ fun buildDocumentationModule(injector: Injector, with(injector.getInstance(DocumentationBuilder::class.java)) { documentationModule.appendFragments(fragments, packageDocs.packageContent, injector.getInstance(PackageDocumentationBuilder::class.java)) + + propagateExtensionFunctionsToSubclasses(fragments, resolutionFacade) } val javaFiles = coreEnvironment.getJavaSourceFiles().filter(filesToDocumentFilter) diff --git a/core/src/main/kotlin/Generation/configurationImpl.kt b/core/src/main/kotlin/Generation/configurationImpl.kt index 34d4154e..52e8446f 100644 --- a/core/src/main/kotlin/Generation/configurationImpl.kt +++ b/core/src/main/kotlin/Generation/configurationImpl.kt @@ -36,27 +36,28 @@ data class PackageOptionsImpl(override val prefix: String, override val suppress: Boolean = false) : DokkaConfiguration.PackageOptions data class DokkaConfigurationImpl( - override val moduleName: String, - override val classpath: List, - override val sourceRoots: List, - override val samples: List, - override val includes: List, - override val outputDir: String, - override val format: String, - override val includeNonPublic: Boolean, - override val includeRootPackage: Boolean, - override val reportUndocumented: Boolean, - override val skipEmptyPackages: Boolean, - override val skipDeprecated: Boolean, - override val jdkVersion: Int, - override val generateIndexPages: Boolean, - override val sourceLinks: List, - override val impliedPlatforms: List, - override val perPackageOptions: List, - override val externalDocumentationLinks: List, - override val noStdlibLink: Boolean, - override val cacheRoot: String?, - override val suppressedFiles: List, - override val languageVersion: String?, - override val apiVersion: String? + override val moduleName: String, + override val classpath: List, + override val sourceRoots: List, + override val samples: List, + override val includes: List, + override val outputDir: String, + override val format: String, + override val includeNonPublic: Boolean, + override val includeRootPackage: Boolean, + override val reportUndocumented: Boolean, + override val skipEmptyPackages: Boolean, + override val skipDeprecated: Boolean, + override val jdkVersion: Int, + override val generateIndexPages: Boolean, + override val sourceLinks: List, + override val impliedPlatforms: List, + override val perPackageOptions: List, + override val externalDocumentationLinks: List, + override val noStdlibLink: Boolean, + override val cacheRoot: String?, + override val suppressedFiles: List, + override val languageVersion: String?, + override val apiVersion: String?, + override val collectInheritedExtensionsFromLibraries: Boolean ) : DokkaConfiguration \ No newline at end of file diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index 11a36a4f..125f9fd4 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -11,6 +11,9 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotated import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.impl.EnumEntrySyntheticClassDescriptor import org.jetbrains.kotlin.idea.kdoc.findKDoc +import org.jetbrains.kotlin.idea.util.fuzzyExtensionReceiverType +import org.jetbrains.kotlin.idea.util.makeNotNullable +import org.jetbrains.kotlin.idea.util.toFuzzyType import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi import org.jetbrains.kotlin.kdoc.psi.impl.KDocSection import org.jetbrains.kotlin.lexer.KtTokens @@ -25,10 +28,11 @@ import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.descriptorUtil.* import org.jetbrains.kotlin.resolve.findTopMostOverriddenDescriptors import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver +import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter +import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered import org.jetbrains.kotlin.resolve.source.PsiSourceElement import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.types.* -import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf import org.jetbrains.kotlin.types.typeUtil.supertypes import java.io.File import java.nio.file.Path @@ -53,7 +57,8 @@ class DocumentationOptions(val outputDir: String, val languageVersion: String?, val apiVersion: String?, cacheRoot: String? = null, - val suppressedFiles: Set = emptySet()) { + val suppressedFiles: Set = emptySet(), + val collectInheritedExtensionsFromLibraries: Boolean = false) { init { if (perPackageOptions.any { it.prefix == "" }) throw IllegalArgumentException("Please do not register packageOptions with all match pattern, use global settings instead") @@ -138,8 +143,20 @@ class DocumentationBuilder refGraph.register(descriptor.signature(), node) } - fun nodeForDescriptor(descriptor: T, kind: NodeKind): DocumentationNode where T : DeclarationDescriptor, T : Named { - val (doc, callback) = descriptorDocumentationParser.parseDocumentationAndDetails(descriptor, kind == NodeKind.Parameter) + fun nodeForDescriptor( + descriptor: T, + kind: NodeKind, + external: Boolean = false + ): DocumentationNode where T : DeclarationDescriptor, T : Named { + val (doc, callback) = + if (external) { + Content.Empty to { node -> } + } else { + descriptorDocumentationParser.parseDocumentationAndDetails( + descriptor, + kind == NodeKind.Parameter + ) + } val node = DocumentationNode(descriptor.name.asString(), doc, kind).withModifiers(descriptor) node.appendSignature(descriptor) callback(node) @@ -226,14 +243,20 @@ class DocumentationBuilder node.appendTextNode("?", NodeKind.NullabilityModifier) } if (classifierDescriptor != null) { - val externalLink = linkResolver.externalDocumentationLinkResolver.buildExternalDocumentationLink(classifierDescriptor) + val externalLink = + linkResolver.externalDocumentationLinkResolver.buildExternalDocumentationLink(classifierDescriptor) if (externalLink != null) { - val targetNode = refGraph.lookup(classifierDescriptor.signature()) ?: classifierDescriptor.build(true) - node.append(DocumentationNode(externalLink, Content.Empty, NodeKind.ExternalLink), RefKind.Link) - node.append(targetNode, RefKind.ExternalType) + if (classifierDescriptor !is TypeParameterDescriptor) { + val targetNode = + refGraph.lookup(classifierDescriptor.signature()) ?: classifierDescriptor.build(true) + node.append(targetNode, RefKind.ExternalType) + node.append(DocumentationNode(externalLink, Content.Empty, NodeKind.ExternalLink), RefKind.Link) + } } else { - link(node, classifierDescriptor, - if (classifierDescriptor.isBoringBuiltinClass()) RefKind.HiddenLink else RefKind.Link) + link( + node, classifierDescriptor, + if (classifierDescriptor.isBoringBuiltinClass()) RefKind.HiddenLink else RefKind.Link + ) } if (classifierDescriptor !is TypeParameterDescriptor) { node.append( @@ -280,6 +303,17 @@ class DocumentationBuilder } } + fun DocumentationNode.appendExternalLink(externalLink: String) { + append(DocumentationNode(externalLink, Content.Empty, NodeKind.ExternalLink), RefKind.Link) + } + + fun DocumentationNode.appendExternalLink(descriptor: DeclarationDescriptor) { + val target = linkResolver.externalDocumentationLinkResolver.buildExternalDocumentationLink(descriptor) + if (target != null) { + appendExternalLink(target) + } + } + fun DocumentationNode.appendSinceKotlin(annotation: DocumentationNode) { val kotlinVersion = annotation .detail(NodeKind.Parameter) @@ -426,15 +460,44 @@ class DocumentationBuilder declarations, allFqNames) } - propagateExtensionFunctionsToSubclasses(fragments) } - private fun propagateExtensionFunctionsToSubclasses(fragments: Collection) { - val allDescriptors = fragments.flatMap { it.getMemberScope().getContributedDescriptors() } - val allClasses = allDescriptors.filterIsInstance() - val classHierarchy = buildClassHierarchy(allClasses) + fun propagateExtensionFunctionsToSubclasses( + fragments: Collection, + resolutionFacade: DokkaResolutionFacade + ) { + + val moduleDescriptor = resolutionFacade.moduleDescriptor + + // Wide-collect all view descriptors + val allPackageViewDescriptors = generateSequence(listOf(moduleDescriptor.getPackage(FqName.ROOT))) { packages -> + packages + .flatMap { pkg -> + moduleDescriptor.getSubPackagesOf(pkg.fqName) { true } + }.map { fqName -> + moduleDescriptor.getPackage(fqName) + }.takeUnless { it.isEmpty() } + }.flatten() + + val allDescriptors = + if (options.collectInheritedExtensionsFromLibraries) { + allPackageViewDescriptors.map { it.memberScope } + } else { + fragments.asSequence().map { it.getMemberScope() } + }.flatMap { + it.getDescriptorsFiltered( + DescriptorKindFilter.CALLABLES + ).asSequence() + } + - val allExtensionFunctions = allDescriptors + val documentingDescriptors = fragments.flatMap { it.getMemberScope().getContributedDescriptors() } + val documentingClasses = documentingDescriptors.filterIsInstance() + + val classHierarchy = buildClassHierarchy(documentingClasses) + + val allExtensionFunctions = + allDescriptors .filterIsInstance() .filter { it.extensionReceiverParameter != null } val extensionFunctionsByName = allExtensionFunctions.groupBy { it.name } @@ -442,15 +505,31 @@ class DocumentationBuilder for (extensionFunction in allExtensionFunctions) { if (extensionFunction.dispatchReceiverParameter != null) continue val possiblyShadowingFunctions = extensionFunctionsByName[extensionFunction.name] - ?.filter { fn -> fn.canShadow(extensionFunction) } + ?.filter { fn -> fn.canShadow(extensionFunction) } ?: emptyList() if (extensionFunction.extensionReceiverParameter?.type?.isDynamic() == true) continue - val classDescriptor = extensionFunction.getExtensionClassDescriptor() ?: continue - val subclasses = classHierarchy[classDescriptor] ?: continue - subclasses.forEach { subclass -> + val subclasses = + classHierarchy.filter { (key) -> key.isExtensionApplicable(extensionFunction) } + if (subclasses.isEmpty()) continue + subclasses.values.flatten().forEach { subclass -> if (subclass.isExtensionApplicable(extensionFunction) && - possiblyShadowingFunctions.none { subclass.isExtensionApplicable(it) }) { + possiblyShadowingFunctions.none { subclass.isExtensionApplicable(it) }) { + + val hasExternalLink = + linkResolver.externalDocumentationLinkResolver.buildExternalDocumentationLink( + extensionFunction + ) != null + if (hasExternalLink) { + val containerDesc = + extensionFunction.containingDeclaration as? PackageFragmentDescriptor + if (containerDesc != null) { + val container = refGraph.lookup(containerDesc.signature()) + ?: containerDesc.buildExternal() + container.append(extensionFunction.buildExternal(), RefKind.Member) + } + } + refGraph.link(subclass.signature(), extensionFunction.signature(), RefKind.Extension) } } @@ -458,12 +537,9 @@ class DocumentationBuilder } private fun ClassDescriptor.isExtensionApplicable(extensionFunction: CallableMemberDescriptor): Boolean { - val receiverType = extensionFunction.extensionReceiverParameter!!.type - if (receiverType.arguments.any { it.type.constructor.declarationDescriptor is TypeParameterDescriptor }) { - val receiverClass = receiverType.constructor.declarationDescriptor - return receiverClass is ClassDescriptor && DescriptorUtils.isSubclass(this, receiverClass) - } - return defaultType.isSubtypeOf(receiverType) + val receiverType = extensionFunction.fuzzyExtensionReceiverType()?.makeNotNullable() + val classType = defaultType.toFuzzyType(declaredTypeParameters) + return receiverType != null && classType.checkIsSubtypeOf(receiverType) != null } private fun buildClassHierarchy(classes: List): Map> { @@ -511,6 +587,24 @@ class DocumentationBuilder else -> throw IllegalStateException("Descriptor $this is not known") } + fun PackageFragmentDescriptor.buildExternal(): DocumentationNode { + val node = DocumentationNode(fqName.asString(), Content.Empty, NodeKind.Package) + + val externalLink = linkResolver.externalDocumentationLinkResolver.buildExternalDocumentationLink(this) + if (externalLink != null) { + node.append(DocumentationNode(externalLink, Content.Empty, NodeKind.ExternalLink), RefKind.Link) + } + register(this, node) + return node + } + + fun CallableDescriptor.buildExternal(): DocumentationNode = when(this) { + is FunctionDescriptor -> build(true) + is PropertyDescriptor -> build(true) + else -> throw IllegalStateException("Descriptor $this is not known") + } + + fun ClassifierDescriptor.build(external: Boolean = false): DocumentationNode = when (this) { is ClassDescriptor -> build(external) is TypeAliasDescriptor -> build(external) @@ -547,7 +641,7 @@ class DocumentationBuilder isSubclassOfThrowable() -> NodeKind.Exception else -> NodeKind.Class } - val node = nodeForDescriptor(this, kind) + val node = nodeForDescriptor(this, kind, external) register(this, node) typeConstructor.supertypes.forEach { node.appendSupertype(this, it) @@ -632,12 +726,12 @@ class DocumentationBuilder return (receiver?.type?.constructor?.declarationDescriptor as? ClassDescriptor)?.isCompanionObject ?: false } - fun FunctionDescriptor.build(): DocumentationNode { + fun FunctionDescriptor.build(external: Boolean = false): DocumentationNode { if (ErrorUtils.containsErrorType(this)) { logger.warn("Found an unresolved type in ${signatureWithSourceLocation()}") } - val node = nodeForDescriptor(this, if (inCompanionObject()) NodeKind.CompanionObjectFunction else NodeKind.Function) + val node = nodeForDescriptor(this, if (inCompanionObject()) NodeKind.CompanionObjectFunction else NodeKind.Function, external) node.appendInPageChildren(typeParameters, RefKind.Detail) extensionReceiverParameter?.let { node.appendChild(it, RefKind.Detail) } @@ -645,8 +739,12 @@ class DocumentationBuilder node.appendType(returnType) node.appendAnnotations(this) node.appendModifiers(this) - node.appendSourceLink(source) - node.appendDefaultPlatforms(this) + if (!external) { + node.appendSourceLink(source) + node.appendDefaultPlatforms(this) + } else { + node.appendExternalLink(this) + } overriddenDescriptors.forEach { addOverrideLink(it, this) @@ -667,32 +765,42 @@ class DocumentationBuilder } } - fun PropertyDescriptor.build(): DocumentationNode { - val node = nodeForDescriptor(this, if (inCompanionObject()) NodeKind.CompanionObjectProperty else NodeKind.Property) + fun PropertyDescriptor.build(external: Boolean = false): DocumentationNode { + val node = nodeForDescriptor( + this, + if (inCompanionObject()) NodeKind.CompanionObjectProperty else NodeKind.Property, + external + ) node.appendInPageChildren(typeParameters, RefKind.Detail) extensionReceiverParameter?.let { node.appendChild(it, RefKind.Detail) } node.appendType(returnType) node.appendAnnotations(this) node.appendModifiers(this) - node.appendSourceLink(source) - if (isVar) { - node.appendTextNode("var", NodeKind.Modifier) - } - getter?.let { - if (!it.isDefault) { - node.addAccessorDocumentation(descriptorDocumentationParser.parseDocumentation(it), "Getter") + if (!external) { + node.appendSourceLink(source) + if (isVar) { + node.appendTextNode("var", NodeKind.Modifier) } - } - setter?.let { - if (!it.isDefault) { - node.addAccessorDocumentation(descriptorDocumentationParser.parseDocumentation(it), "Setter") + + getter?.let { + if (!it.isDefault) { + node.addAccessorDocumentation(descriptorDocumentationParser.parseDocumentation(it), "Getter") + } } + setter?.let { + if (!it.isDefault) { + node.addAccessorDocumentation(descriptorDocumentationParser.parseDocumentation(it), "Setter") + } + } + node.appendDefaultPlatforms(this) + } + if (external) { + node.appendExternalLink(this) } overriddenDescriptors.forEach { addOverrideLink(it, this) } - node.appendDefaultPlatforms(this) register(this, node) return node diff --git a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt index e19ecf76..400326d2 100644 --- a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt +++ b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt @@ -155,8 +155,8 @@ class ExternalDocumentationLinkResolver @Inject constructor( fun buildExternalDocumentationLink(symbol: DeclarationDescriptor): String? { val packageFqName: FqName = when (symbol) { - is DeclarationDescriptorNonRoot -> symbol.parents.firstOrNull { it is PackageFragmentDescriptor }?.fqNameSafe ?: return null is PackageFragmentDescriptor -> symbol.fqName + is DeclarationDescriptorNonRoot -> symbol.parents.firstOrNull { it is PackageFragmentDescriptor }?.fqNameSafe ?: return null else -> return null } diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index a792460f..85ecdf87 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -209,6 +209,8 @@ fun DocumentationNode.appendTextNode(text: String, fun DocumentationNode.qualifiedName(): String { if (kind == NodeKind.Type) { return qualifiedNameFromType() + } else if (kind == NodeKind.Package) { + return name } return path.drop(1).map { it.name }.filter { it.length > 0 }.joinToString(".") } diff --git a/core/src/test/kotlin/TestAPI.kt b/core/src/test/kotlin/TestAPI.kt index 559b715e..aeff9284 100644 --- a/core/src/test/kotlin/TestAPI.kt +++ b/core/src/test/kotlin/TestAPI.kt @@ -25,22 +25,24 @@ fun verifyModel(vararg roots: ContentRoot, includeNonPublic: Boolean = true, perPackageOptions: List = emptyList(), noStdlibLink: Boolean = true, + collectInheritedExtensionsFromLibraries: Boolean = false, verifier: (DocumentationModule) -> Unit) { val documentation = DocumentationModule("test") val options = DocumentationOptions( - "", - format, - includeNonPublic = includeNonPublic, - skipEmptyPackages = false, - includeRootPackage = true, - sourceLinks = listOf(), - perPackageOptions = perPackageOptions, - generateIndexPages = false, - noStdlibLink = noStdlibLink, - cacheRoot = "default", - languageVersion = null, - apiVersion = null + "", + format, + includeNonPublic = includeNonPublic, + skipEmptyPackages = false, + includeRootPackage = true, + sourceLinks = listOf(), + perPackageOptions = perPackageOptions, + generateIndexPages = false, + noStdlibLink = noStdlibLink, + cacheRoot = "default", + languageVersion = null, + apiVersion = null, + collectInheritedExtensionsFromLibraries = collectInheritedExtensionsFromLibraries ) appendDocumentation(documentation, *roots, @@ -162,6 +164,7 @@ fun verifyOutput(roots: Array, format: String = "html", includeNonPublic: Boolean = true, noStdlibLink: Boolean = true, + collectInheritedExtensionsFromLibraries: Boolean = false, outputGenerator: (DocumentationModule, StringBuilder) -> Unit) { verifyModel( *roots, @@ -169,7 +172,8 @@ fun verifyOutput(roots: Array, withKotlinRuntime = withKotlinRuntime, format = format, includeNonPublic = includeNonPublic, - noStdlibLink = noStdlibLink + noStdlibLink = noStdlibLink, + collectInheritedExtensionsFromLibraries = collectInheritedExtensionsFromLibraries ) { verifyModelOutput(it, outputExtension, roots.first().path, outputGenerator) } @@ -194,6 +198,7 @@ fun verifyOutput( format: String = "html", includeNonPublic: Boolean = true, noStdlibLink: Boolean = true, + collectInheritedExtensionsFromLibraries: Boolean = false, outputGenerator: (DocumentationModule, StringBuilder) -> Unit ) { verifyOutput( @@ -204,6 +209,7 @@ fun verifyOutput( format, includeNonPublic, noStdlibLink, + collectInheritedExtensionsFromLibraries, outputGenerator ) } diff --git a/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt b/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt index 90e5b5fc..46a57278 100644 --- a/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt +++ b/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt @@ -41,6 +41,7 @@ interface DokkaConfiguration { val noStdlibLink: Boolean val cacheRoot: String? val suppressedFiles: List + val collectInheritedExtensionsFromLibraries: Boolean interface SourceRoot { val path: String @@ -82,29 +83,30 @@ interface DokkaConfiguration { } data class SerializeOnlyDokkaConfiguration( - override val moduleName: String, - override val classpath: List, - override val sourceRoots: List, - override val samples: List, - override val includes: List, - override val outputDir: String, - override val format: String, - override val includeNonPublic: Boolean, - override val includeRootPackage: Boolean, - override val reportUndocumented: Boolean, - override val skipEmptyPackages: Boolean, - override val skipDeprecated: Boolean, - override val jdkVersion: Int, - override val generateIndexPages: Boolean, - override val sourceLinks: List, - override val impliedPlatforms: List, - override val perPackageOptions: List, - override val externalDocumentationLinks: List, - override val noStdlibLink: Boolean, - override val cacheRoot: String?, - override val suppressedFiles: List, - override val languageVersion: String?, - override val apiVersion: String? + override val moduleName: String, + override val classpath: List, + override val sourceRoots: List, + override val samples: List, + override val includes: List, + override val outputDir: String, + override val format: String, + override val includeNonPublic: Boolean, + override val includeRootPackage: Boolean, + override val reportUndocumented: Boolean, + override val skipEmptyPackages: Boolean, + override val skipDeprecated: Boolean, + override val jdkVersion: Int, + override val generateIndexPages: Boolean, + override val sourceLinks: List, + override val impliedPlatforms: List, + override val perPackageOptions: List, + override val externalDocumentationLinks: List, + override val noStdlibLink: Boolean, + override val cacheRoot: String?, + override val suppressedFiles: List, + override val languageVersion: String?, + override val apiVersion: String?, + override val collectInheritedExtensionsFromLibraries: Boolean ) : DokkaConfiguration diff --git a/runners/cli/src/main/kotlin/cli/main.kt b/runners/cli/src/main/kotlin/cli/main.kt index fe945ed3..111e1420 100644 --- a/runners/cli/src/main/kotlin/cli/main.kt +++ b/runners/cli/src/main/kotlin/cli/main.kt @@ -62,6 +62,9 @@ class DokkaArguments { @set:Argument(value = "apiVersion", description = "Kotlin Api Version to pass to Kotlin Analysis") var apiVersion: String? = null + @set:Argument(value = "collectInheritedExtensionsFromLibraries", description = "Search for applicable extensions in libraries") + var collectInheritedExtensionsFromLibraries: Boolean = false + } @@ -106,18 +109,19 @@ object MainKt { val classPath = arguments.classpath.split(File.pathSeparatorChar).toList() val documentationOptions = DocumentationOptions( - arguments.outputDir.let { if (it.endsWith('/')) it else it + '/' }, - arguments.outputFormat, - skipDeprecated = arguments.nodeprecated, - sourceLinks = sourceLinks, - impliedPlatforms = arguments.impliedPlatforms.split(','), - perPackageOptions = parsePerPackageOptions(arguments.packageOptions), - jdkVersion = arguments.jdkVersion, - externalDocumentationLinks = parseLinks(arguments.links), - noStdlibLink = arguments.noStdlibLink, - cacheRoot = arguments.cacheRoot, - languageVersion = arguments.languageVersion, - apiVersion = arguments.apiVersion + arguments.outputDir.let { if (it.endsWith('/')) it else it + '/' }, + arguments.outputFormat, + skipDeprecated = arguments.nodeprecated, + sourceLinks = sourceLinks, + impliedPlatforms = arguments.impliedPlatforms.split(','), + perPackageOptions = parsePerPackageOptions(arguments.packageOptions), + jdkVersion = arguments.jdkVersion, + externalDocumentationLinks = parseLinks(arguments.links), + noStdlibLink = arguments.noStdlibLink, + cacheRoot = arguments.cacheRoot, + languageVersion = arguments.languageVersion, + apiVersion = arguments.apiVersion, + collectInheritedExtensionsFromLibraries = arguments.collectInheritedExtensionsFromLibraries ) val generator = DokkaGenerator( diff --git a/runners/gradle-plugin/src/main/kotlin/main.kt b/runners/gradle-plugin/src/main/kotlin/main.kt index 5f02cd0e..4812e217 100644 --- a/runners/gradle-plugin/src/main/kotlin/main.kt +++ b/runners/gradle-plugin/src/main/kotlin/main.kt @@ -134,6 +134,9 @@ open class DokkaTask : DefaultTask() { @Optional @Input var apiVersion: String? = null + @Input + var collectInheritedExtensionsFromLibraries: Boolean = false + @get:Internal internal val kotlinCompileBasedClasspathAndSourceRoots: ClasspathAndSourceRoots by lazy { extractClasspathAndSourceRootsFromKotlinTasks() } @@ -287,29 +290,31 @@ open class DokkaTask : DefaultTask() { val bootstrapProxy: DokkaBootstrap = automagicTypedProxy(javaClass.classLoader, bootstrapInstance) val configuration = SerializeOnlyDokkaConfiguration( - moduleName, - fullClasspath.map { it.absolutePath }, - sourceRoots, - samples.filterNotNull().map { project.file(it).absolutePath }, - includes.filterNotNull().map { project.file(it).absolutePath }, - outputDirectory, - outputFormat, - includeNonPublic, - false, - reportUndocumented, - skipEmptyPackages, - skipDeprecated, - jdkVersion, - true, - linkMappings, - impliedPlatforms, - perPackageOptions, - externalDocumentationLinks, - noStdlibLink, - cacheRoot, - collectSuppressedFiles(sourceRoots), - languageVersion, - apiVersion) + moduleName, + fullClasspath.map { it.absolutePath }, + sourceRoots, + samples.filterNotNull().map { project.file(it).absolutePath }, + includes.filterNotNull().map { project.file(it).absolutePath }, + outputDirectory, + outputFormat, + includeNonPublic, + false, + reportUndocumented, + skipEmptyPackages, + skipDeprecated, + jdkVersion, + true, + linkMappings, + impliedPlatforms, + perPackageOptions, + externalDocumentationLinks, + noStdlibLink, + cacheRoot, + collectSuppressedFiles(sourceRoots), + languageVersion, + apiVersion, + collectInheritedExtensionsFromLibraries + ) bootstrapProxy.configure( -- cgit From f301316151dc15b67d926423021abc5e3313aa2a Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Mon, 7 May 2018 20:08:43 +0300 Subject: KT-24300: Support inclusion overview.html into package summary --- core/src/main/kotlin/Generation/DokkaGenerator.kt | 15 ++++- core/src/main/kotlin/Model/PackageDocs.kt | 69 ++++++++++++++++++++++- 2 files changed, 82 insertions(+), 2 deletions(-) (limited to 'core/src/main/kotlin/Generation') diff --git a/core/src/main/kotlin/Generation/DokkaGenerator.kt b/core/src/main/kotlin/Generation/DokkaGenerator.kt index 33170f35..91471849 100644 --- a/core/src/main/kotlin/Generation/DokkaGenerator.kt +++ b/core/src/main/kotlin/Generation/DokkaGenerator.kt @@ -20,7 +20,6 @@ import org.jetbrains.kotlin.config.JVMConfigurationKeys import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.resolve.LazyTopDownAnalyzer import org.jetbrains.kotlin.resolve.TopDownAnalysisMode -import org.jetbrains.kotlin.utils.PathUtil import java.io.File import kotlin.system.measureTimeMillis @@ -157,6 +156,8 @@ fun buildDocumentationModule(injector: Injector, } } + parseJavaPackageDocs(packageDocs, coreEnvironment) + with(injector.getInstance(DocumentationBuilder::class.java)) { documentationModule.appendFragments(fragments, packageDocs.packageContent, injector.getInstance(PackageDocumentationBuilder::class.java)) @@ -170,6 +171,18 @@ fun buildDocumentationModule(injector: Injector, } } +fun parseJavaPackageDocs(packageDocs: PackageDocs, coreEnvironment: KotlinCoreEnvironment) { + val contentRoots = coreEnvironment.configuration.get(JVMConfigurationKeys.CONTENT_ROOTS) + ?.filterIsInstance() + ?.map { it.file } + ?: listOf() + contentRoots.forEach { root -> + root.walkTopDown().filter { it.name == "overview.html" }.forEach { + packageDocs.parseJava(it.path, it.relativeTo(root).parent.replace("/", ".")) + } + } +} + fun KotlinCoreEnvironment.getJavaSourceFiles(): List { val sourceRoots = configuration.get(JVMConfigurationKeys.CONTENT_ROOTS) diff --git a/core/src/main/kotlin/Model/PackageDocs.kt b/core/src/main/kotlin/Model/PackageDocs.kt index 1f6bdcb9..5b628914 100644 --- a/core/src/main/kotlin/Model/PackageDocs.kt +++ b/core/src/main/kotlin/Model/PackageDocs.kt @@ -2,16 +2,25 @@ package org.jetbrains.dokka import com.google.inject.Inject import com.google.inject.Singleton +import com.intellij.ide.highlighter.JavaFileType +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiFileFactory +import com.intellij.psi.util.PsiTreeUtil +import com.intellij.util.LocalTimeCounter import org.intellij.markdown.MarkdownElementTypes import org.intellij.markdown.MarkdownTokenTypes import org.intellij.markdown.parser.LinkMap +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor import java.io.File @Singleton class PackageDocs @Inject constructor(val linkResolver: DeclarationLinkResolver?, - val logger: DokkaLogger) + val logger: DokkaLogger, + val environment: KotlinCoreEnvironment, + val refGraph: NodeReferenceGraph, + val elementSignatureProvider: ElementSignatureProvider) { val moduleContent: MutableContent = MutableContent() private val _packageContent: MutableMap = hashMapOf() @@ -40,6 +49,64 @@ class PackageDocs } } + private fun parseHtmlAsJavadoc(text: String, packageName: String, file: File) { + val javadocText = text + .replace("*/", "*/") + .removeSurrounding("", "", true).trim() + .removeSurrounding("", "", true) + .lineSequence() + .map { "* $it" } + .joinToString (separator = "\n", prefix = "/**\n", postfix = "\n*/") + parseJavadoc(javadocText, packageName, file) + } + + private fun CharSequence.removeSurrounding(prefix: CharSequence, suffix: CharSequence, ignoringCase: Boolean = false): CharSequence { + if ((length >= prefix.length + suffix.length) && startsWith(prefix, ignoringCase) && endsWith(suffix, ignoringCase)) { + return subSequence(prefix.length, length - suffix.length) + } + return subSequence(0, length) + } + + + private fun parseJavadoc(text: String, packageName: String, file: File) { + + val psiFileFactory = PsiFileFactory.getInstance(environment.project) + val psiFile = psiFileFactory.createFileFromText( + file.nameWithoutExtension + ".java", + JavaFileType.INSTANCE, + "package $packageName; $text\npublic class C {}", + LocalTimeCounter.currentTime(), + false, + true + ) + + val psiClass = PsiTreeUtil.getChildOfType(psiFile, PsiClass::class.java)!! + val parser = JavadocParser(refGraph, logger, elementSignatureProvider, linkResolver?.externalDocumentationLinkResolver!!) + findOrCreatePackageContent(packageName).apply { + val content = parser.parseDocumentation(psiClass).content + children.addAll(content.children) + content.sections.forEach { + addSection(it.tag, it.subjectName).children.addAll(it.children) + } + } + } + + + fun parseJava(fileName: String, packageName: String) { + val file = File(fileName) + if (file.exists()) { + val text = file.readText() + + val trimmedText = text.trim() + + if (trimmedText.startsWith("/**")) { + parseJavadoc(text, packageName, file) + } else if (trimmedText.toLowerCase().startsWith("")) { + parseHtmlAsJavadoc(trimmedText, packageName, file) + } + } + } + private fun findTargetContent(heading: String): MutableContent { if (heading.startsWith("Module") || heading.startsWith("module")) { return moduleContent -- cgit From 23861925232505dbd70344a1d690f2475bb022e8 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Mon, 4 Jun 2018 16:23:34 +0300 Subject: [backport] Introduce option to enable/disable jdk linking Original: 8e9e768 --- core/src/main/kotlin/DokkaBootstrapImpl.kt | 39 +++++++++++----------- .../main/kotlin/Generation/configurationImpl.kt | 1 + .../src/main/kotlin/Kotlin/DocumentationBuilder.kt | 6 +++- core/src/test/kotlin/TestAPI.kt | 9 +++++ .../test/kotlin/format/KotlinWebSiteFormatTest.kt | 1 + .../kotlin/format/KotlinWebSiteHtmlFormatTest.kt | 1 + core/src/test/kotlin/format/MarkdownFormatTest.kt | 2 ++ core/src/test/kotlin/model/JavaTest.kt | 4 +-- .../kotlin/org/jetbrains/dokka/configuration.kt | 2 ++ runners/ant/src/main/kotlin/ant/dokka.kt | 2 ++ runners/gradle-plugin/src/main/kotlin/main.kt | 14 +++++--- 11 files changed, 54 insertions(+), 27 deletions(-) (limited to 'core/src/main/kotlin/Generation') diff --git a/core/src/main/kotlin/DokkaBootstrapImpl.kt b/core/src/main/kotlin/DokkaBootstrapImpl.kt index b7787be8..e18ab6cf 100644 --- a/core/src/main/kotlin/DokkaBootstrapImpl.kt +++ b/core/src/main/kotlin/DokkaBootstrapImpl.kt @@ -52,25 +52,26 @@ class DokkaBootstrapImpl : DokkaBootstrap { includes, moduleName, DocumentationOptions( - outputDir, - format, - includeNonPublic, - includeRootPackage, - reportUndocumented, - skipEmptyPackages, - skipDeprecated, - jdkVersion, - generateIndexPages, - sourceLinks, - impliedPlatforms, - perPackageOptions, - externalDocumentationLinks, - noStdlibLink, - languageVersion, - apiVersion, - cacheRoot, - suppressedFiles.map { File(it) }.toSet(), - collectInheritedExtensionsFromLibraries + outputDir = outputDir, + outputFormat = format, + includeNonPublic = includeNonPublic, + includeRootPackage = includeRootPackage, + reportUndocumented = reportUndocumented, + skipEmptyPackages = skipEmptyPackages, + skipDeprecated = skipDeprecated, + jdkVersion = jdkVersion, + generateIndexPages = generateIndexPages, + sourceLinks = sourceLinks, + impliedPlatforms = impliedPlatforms, + perPackageOptions = perPackageOptions, + externalDocumentationLinks = externalDocumentationLinks, + noStdlibLink = noStdlibLink, + noJdkLink = noJdkLink, + languageVersion = languageVersion, + apiVersion = apiVersion, + cacheRoot = cacheRoot, + suppressedFiles = suppressedFiles.map { File(it) }.toSet(), + collectInheritedExtensionsFromLibraries = collectInheritedExtensionsFromLibraries ) ) } diff --git a/core/src/main/kotlin/Generation/configurationImpl.kt b/core/src/main/kotlin/Generation/configurationImpl.kt index 52e8446f..90e27b4b 100644 --- a/core/src/main/kotlin/Generation/configurationImpl.kt +++ b/core/src/main/kotlin/Generation/configurationImpl.kt @@ -55,6 +55,7 @@ data class DokkaConfigurationImpl( override val perPackageOptions: List, override val externalDocumentationLinks: List, override val noStdlibLink: Boolean, + override val noJdkLink: Boolean, override val cacheRoot: String?, override val suppressedFiles: List, override val languageVersion: String?, diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index e6a75277..58f5e246 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -55,6 +55,7 @@ class DocumentationOptions(val outputDir: String, perPackageOptions: List = emptyList(), externalDocumentationLinks: List = emptyList(), noStdlibLink: Boolean, + noJdkLink: Boolean, val languageVersion: String?, val apiVersion: String?, cacheRoot: String? = null, @@ -72,7 +73,10 @@ class DocumentationOptions(val outputDir: String, fun effectivePackageOptions(pack: FqName): PackageOptions = effectivePackageOptions(pack.asString()) val defaultLinks = run { - val links = mutableListOf(ExternalDocumentationLink.Builder("http://docs.oracle.com/javase/$jdkVersion/docs/api/").build()) + val links = mutableListOf() + if (!noJdkLink) + links += ExternalDocumentationLink.Builder("http://docs.oracle.com/javase/$jdkVersion/docs/api/").build() + if (!noStdlibLink) links += ExternalDocumentationLink.Builder("https://kotlinlang.org/api/latest/jvm/stdlib/").build() links diff --git a/core/src/test/kotlin/TestAPI.kt b/core/src/test/kotlin/TestAPI.kt index aeff9284..953e3bab 100644 --- a/core/src/test/kotlin/TestAPI.kt +++ b/core/src/test/kotlin/TestAPI.kt @@ -39,6 +39,7 @@ fun verifyModel(vararg roots: ContentRoot, perPackageOptions = perPackageOptions, generateIndexPages = false, noStdlibLink = noStdlibLink, + noJdkLink = false, cacheRoot = "default", languageVersion = null, apiVersion = null, @@ -269,6 +270,14 @@ fun StringBuilder.appendNode(node: ContentNode): StringBuilder { is ContentBlock -> { appendChildren(node) } + is NodeRenderContent -> { + append("render(") + append(node.node) + append(",") + append(node.mode) + append(")") + } + is ContentSymbol -> { append(node.text) } is ContentEmpty -> { /* nothing */ } else -> throw IllegalStateException("Don't know how to format node $node") } diff --git a/core/src/test/kotlin/format/KotlinWebSiteFormatTest.kt b/core/src/test/kotlin/format/KotlinWebSiteFormatTest.kt index b971b54d..062cf0b5 100644 --- a/core/src/test/kotlin/format/KotlinWebSiteFormatTest.kt +++ b/core/src/test/kotlin/format/KotlinWebSiteFormatTest.kt @@ -54,6 +54,7 @@ class KotlinWebSiteFormatTest: FileGeneratorTestCase() { outputFormat = "html", generateIndexPages = false, noStdlibLink = true, + noJdkLink = true, languageVersion = null, apiVersion = null ) diff --git a/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt b/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt index 49fa6d2f..8076fb92 100644 --- a/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt +++ b/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt @@ -65,6 +65,7 @@ class KotlinWebSiteHtmlFormatTest: FileGeneratorTestCase() { outputFormat = "kotlin-website-html", generateIndexPages = false, noStdlibLink = true, + noJdkLink = true, languageVersion = null, apiVersion = null ) diff --git a/core/src/test/kotlin/format/MarkdownFormatTest.kt b/core/src/test/kotlin/format/MarkdownFormatTest.kt index 9e4c831d..3723e5ae 100644 --- a/core/src/test/kotlin/format/MarkdownFormatTest.kt +++ b/core/src/test/kotlin/format/MarkdownFormatTest.kt @@ -313,6 +313,7 @@ class MarkdownFormatTest: FileGeneratorTestCase() { outputFormat = "html", generateIndexPages = false, noStdlibLink = true, + noJdkLink = true, languageVersion = null, apiVersion = null ) @@ -447,6 +448,7 @@ class MarkdownFormatTest: FileGeneratorTestCase() { outputFormat = "html", generateIndexPages = false, noStdlibLink = true, + noJdkLink = true, languageVersion = null, apiVersion = null ) diff --git a/core/src/test/kotlin/model/JavaTest.kt b/core/src/test/kotlin/model/JavaTest.kt index c2ede8f0..66eb84f1 100644 --- a/core/src/test/kotlin/model/JavaTest.kt +++ b/core/src/test/kotlin/model/JavaTest.kt @@ -18,12 +18,12 @@ public class JavaTest { with(content.sections[0]) { assertEquals("Parameters", tag) assertEquals("name", subjectName) - assertEquals("is String parameter", toTestString()) + assertEquals("render(Type:String,SUMMARY): is String parameter", toTestString()) } with(content.sections[1]) { assertEquals("Parameters", tag) assertEquals("value", subjectName) - assertEquals("is int parameter", toTestString()) + assertEquals("render(Type:String,SUMMARY): is int parameter", toTestString()) } with(content.sections[2]) { assertEquals("Author", tag) diff --git a/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt b/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt index 46a57278..69d19944 100644 --- a/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt +++ b/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt @@ -39,6 +39,7 @@ interface DokkaConfiguration { val languageVersion: String? val apiVersion: String? val noStdlibLink: Boolean + val noJdkLink: Boolean val cacheRoot: String? val suppressedFiles: List val collectInheritedExtensionsFromLibraries: Boolean @@ -102,6 +103,7 @@ data class SerializeOnlyDokkaConfiguration( override val perPackageOptions: List, override val externalDocumentationLinks: List, override val noStdlibLink: Boolean, + override val noJdkLink: Boolean, override val cacheRoot: String?, override val suppressedFiles: List, override val languageVersion: String?, diff --git a/runners/ant/src/main/kotlin/ant/dokka.kt b/runners/ant/src/main/kotlin/ant/dokka.kt index d1b6bef5..79583a1f 100644 --- a/runners/ant/src/main/kotlin/ant/dokka.kt +++ b/runners/ant/src/main/kotlin/ant/dokka.kt @@ -40,6 +40,7 @@ class DokkaAntTask: Task() { var jdkVersion: Int = 6 var noStdlibLink: Boolean = false + var noJdkLink: Boolean = false var skipDeprecated: Boolean = false @@ -131,6 +132,7 @@ class DokkaAntTask: Task() { perPackageOptions = antPackageOptions, externalDocumentationLinks = antExternalDocumentationLinks.map { it.build() }, noStdlibLink = noStdlibLink, + noJdkLink = noJdkLink, cacheRoot = cacheRoot, languageVersion = languageVersion, apiVersion = apiVersion diff --git a/runners/gradle-plugin/src/main/kotlin/main.kt b/runners/gradle-plugin/src/main/kotlin/main.kt index 4812e217..d3a341e0 100644 --- a/runners/gradle-plugin/src/main/kotlin/main.kt +++ b/runners/gradle-plugin/src/main/kotlin/main.kt @@ -124,6 +124,9 @@ open class DokkaTask : DefaultTask() { @Input var noStdlibLink: Boolean = false + @Input + var noJdkLink: Boolean = false + @Optional @Input var cacheRoot: String? = null @@ -309,11 +312,12 @@ open class DokkaTask : DefaultTask() { perPackageOptions, externalDocumentationLinks, noStdlibLink, - cacheRoot, - collectSuppressedFiles(sourceRoots), - languageVersion, - apiVersion, - collectInheritedExtensionsFromLibraries + noJdkLink, + cacheRoot, + collectSuppressedFiles(sourceRoots), + languageVersion, + apiVersion, + collectInheritedExtensionsFromLibraries ) -- cgit From f30807f4e78939fb59f8e46c39b3e538070aacfd Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Sun, 15 Jul 2018 00:48:46 +0300 Subject: Fix missing functions after rebase --- core/src/main/kotlin/Analysis/JavaResolveExtension.kt | 2 +- core/src/main/kotlin/Formats/JavaLayoutHtmlFormat.kt | 3 +-- core/src/main/kotlin/Generation/DokkaGenerator.kt | 1 + core/src/main/kotlin/Kotlin/KotlinLanguageService.kt | 1 - core/src/main/kotlin/Model/DocumentationNode.kt | 7 +++++-- 5 files changed, 8 insertions(+), 6 deletions(-) (limited to 'core/src/main/kotlin/Generation') diff --git a/core/src/main/kotlin/Analysis/JavaResolveExtension.kt b/core/src/main/kotlin/Analysis/JavaResolveExtension.kt index f8992d45..4dc6b366 100644 --- a/core/src/main/kotlin/Analysis/JavaResolveExtension.kt +++ b/core/src/main/kotlin/Analysis/JavaResolveExtension.kt @@ -128,4 +128,4 @@ private fun Collection.findByJavaElemen } fun PsiElement.javaResolutionFacade() = - KotlinCacheService.getInstance(project).getResolutionFacadeByFile(this.originalElement.containingFile, JvmPlatform) + KotlinCacheService.getInstance(project).getResolutionFacadeByFile(this.originalElement.containingFile, JvmPlatform)!! diff --git a/core/src/main/kotlin/Formats/JavaLayoutHtmlFormat.kt b/core/src/main/kotlin/Formats/JavaLayoutHtmlFormat.kt index f73cd23e..885cdf6c 100644 --- a/core/src/main/kotlin/Formats/JavaLayoutHtmlFormat.kt +++ b/core/src/main/kotlin/Formats/JavaLayoutHtmlFormat.kt @@ -6,7 +6,6 @@ import kotlinx.html.li import kotlinx.html.stream.appendHTML import kotlinx.html.ul import org.jetbrains.dokka.* -import org.jetbrains.dokka.Kotlin.KotlinDescriptorSignatureProvider import org.jetbrains.dokka.Samples.DefaultSampleProcessingService import org.jetbrains.dokka.Utilities.bind import org.jetbrains.dokka.Utilities.toType @@ -17,7 +16,7 @@ class JavaLayoutHtmlFormatDescriptor : FormatDescriptor, DefaultAnalysisComponen override val packageDocumentationBuilderClass = KotlinPackageDocumentationBuilder::class override val javaDocumentationBuilderClass = KotlinJavaDocumentationBuilder::class override val sampleProcessingService = DefaultSampleProcessingService::class - override val descriptorSignatureProvider = KotlinDescriptorSignatureProvider::class + override val elementSignatureProvider = KotlinElementSignatureProvider::class override fun configureOutput(binder: Binder): Unit = with(binder) { bind() toType generatorServiceClass diff --git a/core/src/main/kotlin/Generation/DokkaGenerator.kt b/core/src/main/kotlin/Generation/DokkaGenerator.kt index 91471849..46fdaf0a 100644 --- a/core/src/main/kotlin/Generation/DokkaGenerator.kt +++ b/core/src/main/kotlin/Generation/DokkaGenerator.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.config.JVMConfigurationKeys import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.resolve.LazyTopDownAnalyzer import org.jetbrains.kotlin.resolve.TopDownAnalysisMode +import org.jetbrains.kotlin.utils.PathUtil import java.io.File import kotlin.system.measureTimeMillis diff --git a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt index 237fa9b9..6088d3a5 100644 --- a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt +++ b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt @@ -1,6 +1,5 @@ package org.jetbrains.dokka -import org.jetbrains.dokka.Formats.classNodeNameWithOuterClass import org.jetbrains.dokka.LanguageService.RenderMode /** diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index a89f5080..a3388031 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -1,7 +1,5 @@ package org.jetbrains.dokka -import org.jetbrains.dokka.Formats.constantValue -import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult import java.util.* enum class NodeKind { @@ -242,4 +240,9 @@ private fun DocumentationNode.isSuperclassFor(node: DocumentationNode): Boolean NodeKind.Exception -> kind == NodeKind.Class || kind == NodeKind.Exception else -> false } +} + +fun DocumentationNode.classNodeNameWithOuterClass(): String { + assert(kind in NodeKind.classLike) + return path.dropWhile { it.kind == NodeKind.Package || it.kind == NodeKind.Module }.joinToString(separator = ".") { it.name } } \ No newline at end of file -- cgit From 899c11d36f565cd192945573860568ff62c16ef2 Mon Sep 17 00:00:00 2001 From: aleksZubakov Date: Wed, 25 Jul 2018 17:24:00 +0300 Subject: Add logic of merging different platforms graphs --- .../main/kotlin/Formats/StructuredFormatService.kt | 12 +- core/src/main/kotlin/Generation/DokkaGenerator.kt | 232 ++++++++++++++++++++- .../src/main/kotlin/Kotlin/DocumentationBuilder.kt | 6 +- core/src/main/kotlin/Model/DocumentationNode.kt | 10 +- .../main/kotlin/Model/DocumentationReference.kt | 53 ++++- 5 files changed, 288 insertions(+), 25 deletions(-) (limited to 'core/src/main/kotlin/Generation') diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index ebc9cde6..41c8f29a 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -514,15 +514,15 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, 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( diff --git a/core/src/main/kotlin/Generation/DokkaGenerator.kt b/core/src/main/kotlin/Generation/DokkaGenerator.kt index 9de4396b..0c4b3b7e 100644 --- a/core/src/main/kotlin/Generation/DokkaGenerator.kt +++ b/core/src/main/kotlin/Generation/DokkaGenerator.kt @@ -2,6 +2,7 @@ package org.jetbrains.dokka import com.google.inject.Guice import com.google.inject.Injector +import com.intellij.openapi.application.PathManager import com.intellij.openapi.util.Disposer import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.psi.PsiFile @@ -17,6 +18,7 @@ import org.jetbrains.kotlin.cli.common.messages.MessageRenderer import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot import org.jetbrains.kotlin.config.JVMConfigurationKeys +import org.jetbrains.kotlin.config.KotlinSourceRoot import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.resolve.LazyTopDownAnalyzer import org.jetbrains.kotlin.resolve.TopDownAnalysisMode @@ -32,28 +34,34 @@ class DokkaGenerator(val logger: DokkaLogger, val moduleName: String, val options: DocumentationOptions) { - private val documentationModule = DocumentationModule(moduleName) + private val documentationModules: MutableList = mutableListOf() fun generate() { val sourcesGroupedByPlatform = sources.groupBy { it.platforms.firstOrNull() to it.analysisPlatform } for ((platformsInfo, roots) in sourcesGroupedByPlatform) { val (platform, analysisPlatform) = platformsInfo - appendSourceModule(platform, analysisPlatform, roots) + + val documentationModule = DocumentationModule(moduleName) + appendSourceModule(platform, analysisPlatform, roots, documentationModule) + documentationModules.add(documentationModule) } - documentationModule.prepareForGeneration(options) + + val totalDocumentationModule = DocumentationMerger(documentationModules).merge() + totalDocumentationModule.prepareForGeneration(options) val timeBuild = measureTimeMillis { logger.info("Generating pages... ") val outputInjector = Guice.createInjector(DokkaOutputModule(options, logger)) - outputInjector.getInstance(Generator::class.java).buildAll(documentationModule) + outputInjector.getInstance(Generator::class.java).buildAll(totalDocumentationModule) } logger.info("done in ${timeBuild / 1000} secs") } - private fun appendSourceModule(defaultPlatform: String?, - analysisPlatform: Platform, - sourceRoots: List - + private fun appendSourceModule( + defaultPlatform: String?, + analysisPlatform: Platform, + sourceRoots: List, + documentationModule: DocumentationModule ) { val sourcePaths = sourceRoots.map { it.path } @@ -81,6 +89,12 @@ class DokkaGenerator(val logger: DokkaLogger, DokkaAnalysisModule(environment, options, defaultPlatformsProvider, documentationModule.nodeRefGraph, logger)) buildDocumentationModule(injector, documentationModule, { isNotSample(it) }, includes) + documentationModule.nodeRefGraph.nodeMapView.forEach { (_, node) -> + node.addReferenceTo( + DocumentationNode(analysisPlatform.key, Content.Empty, NodeKind.Platform), + RefKind.Platform + ) + } val timeAnalyse = System.currentTimeMillis() - startAnalyse logger.info("done in ${timeAnalyse / 1000} secs") @@ -214,3 +228,205 @@ fun KotlinCoreEnvironment.getJavaSourceFiles(): List { } return result } + +class DocumentationMerger( + private val documentationModules: List +) { + private val producedNodeRefGraph: NodeReferenceGraph + private val signatureMap: Map + + init { + signatureMap = documentationModules + .flatMap { it.nodeRefGraph.nodeMapView.entries } + .map { (k, v) -> v to k } + .toMap() + + producedNodeRefGraph = NodeReferenceGraph() + documentationModules.map { it.nodeRefGraph } + .flatMap { it.references } + .distinct() + .forEach { producedNodeRefGraph.addReference(it) } + } + + private fun splitReferencesByKind( + source: List, + kind: RefKind + ): Pair, List> = + Pair(source.filter { it.kind == kind }, source.filterNot { it.kind == kind }) + + + private fun mergePackageReferences( + from: DocumentationNode, + packages: List + ): List { + val packagesByName = packages + .map { it.to } + .groupBy { it.name } + + val mutableList: MutableList = mutableListOf() + for ((name, listOfPackages) in packagesByName) { + val producedPackage = mergePackagesWithEqualNames(from, listOfPackages) + updatePendingReferences(name, producedPackage) + + mutableList.add( + DocumentationReference(from, producedPackage, RefKind.Member) + ) + } + + return mutableList + } + + private fun mergePackagesWithEqualNames( + from: DocumentationNode, + packages: List + ): DocumentationNode { + val references = packages.flatMap { it.allReferences() } + + val mergedPackage = + DocumentationNode( + packages.first().name, + Content.Empty, + NodeKind.Package + ) + + val mergedReferences = mergeReferences(mergedPackage, references) + + for (packageNode in packages) { + mergedPackage.updateContent { + for (otherChild in packageNode.content.children) { + children.add(otherChild) + } + } + } + + mergedPackage.dropReferences { true } // clear() + for (ref in mergedReferences.distinct()) { + mergedPackage.addReference(ref) + } + + from.append(mergedPackage, RefKind.Member) + + return mergedPackage + } + + + private fun mergeMembers( + from: DocumentationNode, + refs: List + ): List { + val membersBySignature: Map> = refs.map { it.to } + .filter { signatureMap.containsKey(it) } + .groupBy { signatureMap[it]!! } + + val mergedMembers: MutableList = mutableListOf() + for ((signature, members) in membersBySignature) { + val newNode = mergeMembersWithEqualSignature(signature, from, members) + + producedNodeRefGraph.register(signature, newNode) + updatePendingReferences(signature, newNode) + from.append(newNode, RefKind.Member) + + mergedMembers.add(DocumentationReference(from, newNode, RefKind.Member)) + } + + return mergedMembers + } + + private fun mergeMembersWithEqualSignature( + signature: String, + from: DocumentationNode, + refs: List + ): DocumentationNode { + if (refs.size == 1) { + val singleNode = refs.single() + singleNode.owner?.let { owner -> + singleNode.dropReferences { it.to == owner && it.kind == RefKind.Owner } + } + return singleNode + } + val groupNode = DocumentationNode(refs.first().name, Content.Empty, NodeKind.GroupNode) + groupNode.appendTextNode(signature, NodeKind.Signature, RefKind.Detail) + + for (node in refs) { + if (node != groupNode) { + node.owner?.let { owner -> + node.dropReferences { it.to == owner && it.kind == RefKind.Owner } + from.dropReferences { it.to == node && it.kind == RefKind.Member } + } + groupNode.append(node, RefKind.Member) + } + } + return groupNode + } + + + private fun mergeReferences( + from: DocumentationNode, + refs: List + ): List { + val allRefsToPackages = refs.map { it.to } + .all { it.kind == NodeKind.Package } + + if (allRefsToPackages) { + return mergePackageReferences(from, refs) + } + + val (memberRefs, notMemberRefs) = splitReferencesByKind(refs, RefKind.Member) + val mergedMembers = mergeMembers(from, memberRefs) + + return (mergedMembers + notMemberRefs).distinctBy { + it.kind to it.to.name + } + } + + + private fun updatePendingReferences( + signature: String, + nodeToUpdate: DocumentationNode + ) { + producedNodeRefGraph.references.forEach { + it.lazyNodeFrom.update(signature, nodeToUpdate) + it.lazyNodeTo.update(signature, nodeToUpdate) + } + } + + private fun NodeResolver.update(signature: String, nodeToUpdate: DocumentationNode) { + when (this) { + is NodeResolver.BySignature -> update(signature, nodeToUpdate) + is NodeResolver.Exact -> update(signature, nodeToUpdate) + } + } + + private fun NodeResolver.BySignature.update(signature: String, nodeToUpdate: DocumentationNode) { + if (signature == nodeToUpdate.name) { + nodeMap = producedNodeRefGraph.nodeMapView + } + } + + private fun NodeResolver.Exact.update(signature: String, nodeToUpdate: DocumentationNode) { + exactNode?.let { it -> + val equalSignature = + it.anyReference { ref -> ref.to.kind == NodeKind.Signature && ref.to.name == signature } + + if (equalSignature) { + exactNode = nodeToUpdate + } + } + } + + fun merge(): DocumentationModule { + val refs = documentationModules.flatMap { + it.allReferences() + } + val mergedDocumentationModule = DocumentationModule( + name = documentationModules.first().name, + nodeRefGraph = producedNodeRefGraph + ) + + mergeReferences(mergedDocumentationModule, refs) + + return mergedDocumentationModule + } + + +} \ No newline at end of file diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index f1b8e3d3..e3675f9d 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -1079,7 +1079,7 @@ fun DeclarationDescriptor.signature(): String { is TypeAliasDescriptor -> DescriptorUtils.getFqName(this).asString() is PropertyDescriptor -> containingDeclaration.signature() + "$" + name + receiverSignature() - is FunctionDescriptor -> containingDeclaration.signature() + "$" + name + parameterSignature() + is FunctionDescriptor -> containingDeclaration.signature() + "$" + name + parameterSignature() + ":" + returnType?.signature() is ValueParameterDescriptor -> containingDeclaration.signature() + "/" + name is TypeParameterDescriptor -> containingDeclaration.signature() + "*" + name is ReceiverParameterDescriptor -> containingDeclaration.signature() + "/" + name @@ -1149,7 +1149,9 @@ fun DocumentationModule.prepareForGeneration(options: DocumentationOptions) { fun DocumentationNode.generateAllTypesNode() { val allTypes = members(NodeKind.Package) - .flatMap { it.members.filter { it.kind in NodeKind.classLike || it.kind == NodeKind.ExternalClass } } + .flatMap { it.members.filter { + it.kind in NodeKind.classLike || it.kind == NodeKind.ExternalClass + || (it.kind == NodeKind.GroupNode && it.anyReference { it.to.kind in NodeKind.classLike }) } } .sortedBy { if (it.kind == NodeKind.ExternalClass) it.name.substringAfterLast('.').toLowerCase() else it.name.toLowerCase() } val allTypesNode = DocumentationNode("alltypes", Content.Empty, NodeKind.AllTypes) diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index a3388031..bdb7cf20 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -134,6 +134,10 @@ open class DocumentationNode(val name: String, references.add(DocumentationReference(this, to, kind)) } + fun addReference(reference: DocumentationReference) { + references.add(reference) + } + fun dropReferences(predicate: (DocumentationReference) -> Boolean) { references.removeAll(predicate) } @@ -159,6 +163,8 @@ open class DocumentationNode(val name: String, fun member(kind: NodeKind): DocumentationNode = members.filter { it.kind == kind }.single() fun link(kind: NodeKind): DocumentationNode = links.filter { it.kind == kind }.single() + fun anyReference(predicate: (DocumentationReference) -> Boolean): Boolean = references.any(predicate) + fun references(kind: RefKind): List = references.filter { it.kind == kind } fun allReferences(): Set = references @@ -167,9 +173,9 @@ open class DocumentationNode(val name: String, } } -class DocumentationModule(name: String, content: Content = Content.Empty) +class DocumentationModule(name: String, content: Content = Content.Empty, val nodeRefGraph: NodeReferenceGraph = NodeReferenceGraph()) : DocumentationNode(name, content, NodeKind.Module) { - val nodeRefGraph = NodeReferenceGraph() + } val DocumentationNode.path: List diff --git a/core/src/main/kotlin/Model/DocumentationReference.kt b/core/src/main/kotlin/Model/DocumentationReference.kt index 5db1f05a..9223c17a 100644 --- a/core/src/main/kotlin/Model/DocumentationReference.kt +++ b/core/src/main/kotlin/Model/DocumentationReference.kt @@ -25,12 +25,27 @@ enum class RefKind { data class DocumentationReference(val from: DocumentationNode, val to: DocumentationNode, val kind: RefKind) { } -class PendingDocumentationReference(val lazyNodeFrom: () -> DocumentationNode?, - val lazyNodeTo: () -> DocumentationNode?, +sealed class NodeResolver { + abstract fun resolve(): DocumentationNode? + class BySignature(var signature: String, var nodeMap: Map) : NodeResolver() { + override fun resolve(): DocumentationNode? { + return nodeMap[signature] + } + } + + class Exact(var exactNode: DocumentationNode?) : NodeResolver() { + override fun resolve(): DocumentationNode? { + return exactNode + } + } +} + +class PendingDocumentationReference(val lazyNodeFrom: NodeResolver, + val lazyNodeTo: NodeResolver, val kind: RefKind) { fun resolve() { - val fromNode = lazyNodeFrom() - val toNode = lazyNodeTo() + val fromNode = lazyNodeFrom.resolve() + val toNode = lazyNodeTo.resolve() if (fromNode != null && toNode != null) { fromNode.addReferenceTo(toNode, kind) } @@ -39,6 +54,9 @@ class PendingDocumentationReference(val lazyNodeFrom: () -> DocumentationNode?, class NodeReferenceGraph { private val nodeMap = hashMapOf() + val nodeMapView: Map + get() = HashMap(nodeMap) + val references = arrayListOf() fun register(signature: String, node: DocumentationNode) { @@ -46,15 +64,36 @@ class NodeReferenceGraph { } fun link(fromNode: DocumentationNode, toSignature: String, kind: RefKind) { - references.add(PendingDocumentationReference({ fromNode }, { nodeMap[toSignature] }, kind)) + references.add( + PendingDocumentationReference( + NodeResolver.Exact(fromNode), + NodeResolver.BySignature(toSignature, nodeMap), + kind + )) } fun link(fromSignature: String, toNode: DocumentationNode, kind: RefKind) { - references.add(PendingDocumentationReference({ nodeMap[fromSignature] }, { toNode }, kind)) + references.add( + PendingDocumentationReference( + NodeResolver.BySignature(fromSignature, nodeMap), + NodeResolver.Exact(toNode), + kind + ) + ) } fun link(fromSignature: String, toSignature: String, kind: RefKind) { - references.add(PendingDocumentationReference({ nodeMap[fromSignature] }, { nodeMap[toSignature] }, kind)) + references.add( + PendingDocumentationReference( + NodeResolver.BySignature(fromSignature, nodeMap), + NodeResolver.BySignature(toSignature, nodeMap), + kind + ) + ) + } + + fun addReference(reference: PendingDocumentationReference) { + references.add(reference) } fun lookup(signature: String) = nodeMap[signature] -- cgit From 052a218dcf8bc565d5e78dc900a9647f0da5350a Mon Sep 17 00:00:00 2001 From: aleksZubakov Date: Wed, 1 Aug 2018 19:48:45 +0300 Subject: Refactoring, replace DocumentationOption with PassConfiguration --- core/src/main/kotlin/DokkaBootstrapImpl.kt | 32 +----- core/src/main/kotlin/Generation/DokkaGenerator.kt | 58 +++++------ core/src/main/kotlin/Generation/FileGenerator.kt | 5 +- .../main/kotlin/Generation/configurationImpl.kt | 70 ++++++++----- .../kotlin/Java/JavaPsiDocumentationBuilder.kt | 25 +++-- .../main/kotlin/Kotlin/DeclarationLinkResolver.kt | 4 +- .../kotlin/Kotlin/DescriptorDocumentationParser.kt | 2 +- .../src/main/kotlin/Kotlin/DocumentationBuilder.kt | 108 ++++++--------------- .../Kotlin/ExternalDocumentationLinkResolver.kt | 13 ++- .../Kotlin/KotlinAsJavaDocumentationBuilder.kt | 2 +- .../Samples/DefaultSampleProcessingService.kt | 2 +- .../KotlinWebsiteSampleProcessingService.kt | 4 +- core/src/main/kotlin/Utilities/DokkaModules.kt | 18 ++-- core/src/main/kotlin/javadoc/dokka-adapters.kt | 9 +- core/src/test/kotlin/TestAPI.kt | 44 +++++---- .../test/kotlin/format/KotlinWebSiteFormatTest.kt | 19 ++-- .../kotlin/format/KotlinWebSiteHtmlFormatTest.kt | 22 +++-- core/src/test/kotlin/format/MarkdownFormatTest.kt | 36 ++++--- .../kotlin/org/jetbrains/dokka/configuration.kt | 71 ++++++-------- runners/ant/src/main/kotlin/ant/dokka.kt | 49 +++++----- runners/cli/src/main/kotlin/cli/main.kt | 36 ++++--- runners/maven-plugin/src/main/kotlin/DokkaMojo.kt | 47 ++++----- 22 files changed, 323 insertions(+), 353 deletions(-) (limited to 'core/src/main/kotlin/Generation') diff --git a/core/src/main/kotlin/DokkaBootstrapImpl.kt b/core/src/main/kotlin/DokkaBootstrapImpl.kt index e18ab6cf..ccafcd12 100644 --- a/core/src/main/kotlin/DokkaBootstrapImpl.kt +++ b/core/src/main/kotlin/DokkaBootstrapImpl.kt @@ -2,7 +2,6 @@ package org.jetbrains.dokka import org.jetbrains.dokka.DokkaConfiguration.PackageOptions import ru.yole.jkid.deserialization.deserialize -import java.io.File import java.util.function.BiConsumer @@ -44,36 +43,7 @@ class DokkaBootstrapImpl : DokkaBootstrap { = configure(DokkaProxyLogger(logger), deserialize(serializedConfigurationJSON)) fun configure(logger: DokkaLogger, configuration: DokkaConfiguration) = with(configuration) { - generator = DokkaGenerator( - logger, - classpath, - sourceRoots, - samples, - includes, - moduleName, - DocumentationOptions( - outputDir = outputDir, - outputFormat = format, - includeNonPublic = includeNonPublic, - includeRootPackage = includeRootPackage, - reportUndocumented = reportUndocumented, - skipEmptyPackages = skipEmptyPackages, - skipDeprecated = skipDeprecated, - jdkVersion = jdkVersion, - generateIndexPages = generateIndexPages, - sourceLinks = sourceLinks, - impliedPlatforms = impliedPlatforms, - perPackageOptions = perPackageOptions, - externalDocumentationLinks = externalDocumentationLinks, - noStdlibLink = noStdlibLink, - noJdkLink = noJdkLink, - languageVersion = languageVersion, - apiVersion = apiVersion, - cacheRoot = cacheRoot, - suppressedFiles = suppressedFiles.map { File(it) }.toSet(), - collectInheritedExtensionsFromLibraries = collectInheritedExtensionsFromLibraries - ) - ) + generator = DokkaGenerator(configuration, logger) } override fun generate() = generator.generate() diff --git a/core/src/main/kotlin/Generation/DokkaGenerator.kt b/core/src/main/kotlin/Generation/DokkaGenerator.kt index 0c4b3b7e..2e46d908 100644 --- a/core/src/main/kotlin/Generation/DokkaGenerator.kt +++ b/core/src/main/kotlin/Generation/DokkaGenerator.kt @@ -2,13 +2,11 @@ package org.jetbrains.dokka import com.google.inject.Guice import com.google.inject.Injector -import com.intellij.openapi.application.PathManager import com.intellij.openapi.util.Disposer import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.psi.PsiFile import com.intellij.psi.PsiJavaFile import com.intellij.psi.PsiManager -import org.jetbrains.dokka.DokkaConfiguration.SourceRoot import org.jetbrains.dokka.Utilities.DokkaAnalysisModule import org.jetbrains.dokka.Utilities.DokkaOutputModule import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation @@ -18,7 +16,6 @@ import org.jetbrains.kotlin.cli.common.messages.MessageRenderer import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot import org.jetbrains.kotlin.config.JVMConfigurationKeys -import org.jetbrains.kotlin.config.KotlinSourceRoot import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.resolve.LazyTopDownAnalyzer import org.jetbrains.kotlin.resolve.TopDownAnalysisMode @@ -26,56 +23,49 @@ import org.jetbrains.kotlin.utils.PathUtil import java.io.File import kotlin.system.measureTimeMillis -class DokkaGenerator(val logger: DokkaLogger, - val classpath: List, - val sources: List, - val samples: List, - val includes: List, - val moduleName: String, - val options: DocumentationOptions) { +class DokkaGenerator(val dokkaConfiguration: DokkaConfiguration, + val logger: DokkaLogger) { private val documentationModules: MutableList = mutableListOf() - fun generate() { - val sourcesGroupedByPlatform = sources.groupBy { it.platforms.firstOrNull() to it.analysisPlatform } - for ((platformsInfo, roots) in sourcesGroupedByPlatform) { - val (platform, analysisPlatform) = platformsInfo - val documentationModule = DocumentationModule(moduleName) - appendSourceModule(platform, analysisPlatform, roots, documentationModule) + fun generate() = with(dokkaConfiguration) { + + + for (pass in passesConfigurations) { + val documentationModule = DocumentationModule(pass.moduleName) + appendSourceModule(pass, documentationModule) documentationModules.add(documentationModule) } val totalDocumentationModule = DocumentationMerger(documentationModules).merge() - totalDocumentationModule.prepareForGeneration(options) + totalDocumentationModule.prepareForGeneration(dokkaConfiguration) val timeBuild = measureTimeMillis { logger.info("Generating pages... ") - val outputInjector = Guice.createInjector(DokkaOutputModule(options, logger)) + val outputInjector = Guice.createInjector(DokkaOutputModule(dokkaConfiguration, logger)) outputInjector.getInstance(Generator::class.java).buildAll(totalDocumentationModule) } logger.info("done in ${timeBuild / 1000} secs") } private fun appendSourceModule( - defaultPlatform: String?, - analysisPlatform: Platform, - sourceRoots: List, + passConfiguration: DokkaConfiguration.PassConfiguration, documentationModule: DocumentationModule - ) { + ) = with(passConfiguration) { - val sourcePaths = sourceRoots.map { it.path } - val environment = createAnalysisEnvironment(sourcePaths, analysisPlatform) + val sourcePaths = passConfiguration.sourceRoots.map { it.path } + val environment = createAnalysisEnvironment(sourcePaths, passConfiguration) logger.info("Module: $moduleName") - logger.info("Output: ${File(options.outputDir)}") + logger.info("Output: ${File(dokkaConfiguration.outputDir)}") logger.info("Sources: ${sourcePaths.joinToString()}") logger.info("Classpath: ${environment.classpath.joinToString()}") logger.info("Analysing sources and libraries... ") val startAnalyse = System.currentTimeMillis() - val defaultPlatformAsList = defaultPlatform?.let { listOf(it) }.orEmpty() + val defaultPlatformAsList = listOf(passConfiguration.analysisPlatform.key) val defaultPlatformsProvider = object : DefaultPlatformsProvider { override fun getDefaultPlatforms(descriptor: DeclarationDescriptor): List { val containingFilePath = descriptor.sourcePsi()?.containingFile?.virtualFile?.canonicalPath @@ -86,9 +76,9 @@ class DokkaGenerator(val logger: DokkaLogger, } val injector = Guice.createInjector( - DokkaAnalysisModule(environment, options, defaultPlatformsProvider, documentationModule.nodeRefGraph, logger)) + DokkaAnalysisModule(environment, dokkaConfiguration, defaultPlatformsProvider, documentationModule.nodeRefGraph, passConfiguration, logger)) - buildDocumentationModule(injector, documentationModule, { isNotSample(it) }, includes) + buildDocumentationModule(injector, documentationModule, { isNotSample(it, passConfiguration.samples) }, includes) documentationModule.nodeRefGraph.nodeMapView.forEach { (_, node) -> node.addReferenceTo( DocumentationNode(analysisPlatform.key, Content.Empty, NodeKind.Platform), @@ -102,28 +92,28 @@ class DokkaGenerator(val logger: DokkaLogger, Disposer.dispose(environment) } - fun createAnalysisEnvironment(sourcePaths: List, analysisPlatform: Platform): AnalysisEnvironment { - val environment = AnalysisEnvironment(DokkaMessageCollector(logger), analysisPlatform) + fun createAnalysisEnvironment(sourcePaths: List, passConfiguration: DokkaConfiguration.PassConfiguration): AnalysisEnvironment { + val environment = AnalysisEnvironment(DokkaMessageCollector(logger), passConfiguration.analysisPlatform) environment.apply { if (analysisPlatform == Platform.jvm) { addClasspath(PathUtil.getJdkClassesRootsFromCurrentJre()) } // addClasspath(PathUtil.getKotlinPathsForCompiler().getRuntimePath()) - for (element in this@DokkaGenerator.classpath) { + for (element in passConfiguration.classpath) { addClasspath(File(element)) } addSources(sourcePaths) - addSources(this@DokkaGenerator.samples) + addSources(passConfiguration.samples) - loadLanguageVersionSettings(options.languageVersion, options.apiVersion) + loadLanguageVersionSettings(passConfiguration.languageVersion, passConfiguration.apiVersion) } return environment } - fun isNotSample(file: PsiFile): Boolean { + fun isNotSample(file: PsiFile, samples: List): Boolean { val sourceFile = File(file.virtualFile!!.path) return samples.none { sample -> val canonicalSample = File(sample).canonicalPath diff --git a/core/src/main/kotlin/Generation/FileGenerator.kt b/core/src/main/kotlin/Generation/FileGenerator.kt index b7c6cf63..eb6800b3 100644 --- a/core/src/main/kotlin/Generation/FileGenerator.kt +++ b/core/src/main/kotlin/Generation/FileGenerator.kt @@ -2,7 +2,6 @@ package org.jetbrains.dokka import com.google.inject.Inject import com.google.inject.name.Named -import org.jetbrains.kotlin.utils.fileUtils.withReplacedExtensionOrNull import java.io.File import java.io.FileOutputStream import java.io.IOException @@ -12,7 +11,7 @@ class FileGenerator @Inject constructor(@Named("outputDir") override val root: F @set:Inject(optional = true) var outlineService: OutlineFormatService? = null @set:Inject(optional = true) lateinit var formatService: FormatService - @set:Inject(optional = true) lateinit var options: DocumentationOptions + @set:Inject(optional = true) lateinit var dokkaConfiguration: DokkaConfiguration @set:Inject(optional = true) var packageListService: PackageListService? = null override fun location(node: DocumentationNode): FileLocation { @@ -74,7 +73,7 @@ class FileGenerator @Inject constructor(@Named("outputDir") override val root: F val moduleRoot = location(module).file.parentFile val packageListFile = File(moduleRoot, "package-list") - packageListFile.writeText("\$dokka.format:${options.outputFormat}\n" + + packageListFile.writeText("\$dokka.format:${dokkaConfiguration.format}\n" + packageListService!!.formatPackageList(module as DocumentationModule)) } diff --git a/core/src/main/kotlin/Generation/configurationImpl.kt b/core/src/main/kotlin/Generation/configurationImpl.kt index 8829682a..3e39b4ed 100644 --- a/core/src/main/kotlin/Generation/configurationImpl.kt +++ b/core/src/main/kotlin/Generation/configurationImpl.kt @@ -45,29 +45,47 @@ data class PackageOptionsImpl(override val prefix: String, override val suppress: Boolean = false) : DokkaConfiguration.PackageOptions data class DokkaConfigurationImpl( - override val moduleName: String, - override val classpath: List, - override val sourceRoots: List, - override val samples: List, - override val includes: List, - override val outputDir: String, - override val format: String, - override val includeNonPublic: Boolean, - override val includeRootPackage: Boolean, - override val reportUndocumented: Boolean, - override val skipEmptyPackages: Boolean, - override val skipDeprecated: Boolean, - override val jdkVersion: Int, - override val generateIndexPages: Boolean, - override val sourceLinks: List, - override val impliedPlatforms: List, - override val perPackageOptions: List, - override val externalDocumentationLinks: List, - override val noStdlibLink: Boolean, - override val noJdkLink: Boolean, - override val cacheRoot: String?, - override val suppressedFiles: List, - override val languageVersion: String?, - override val apiVersion: String?, - override val collectInheritedExtensionsFromLibraries: Boolean -) : DokkaConfiguration \ No newline at end of file + override val outputDir: String = "", + override val format: String = "html", + override val generateIndexPages: Boolean = false, + override val cacheRoot: String? = null, + override val impliedPlatforms: List = listOf(), + override val passesConfigurations: List = listOf() +) : DokkaConfiguration + +class PassConfigurationImpl ( + override val classpath: List = listOf(), + override val moduleName: String = "", + override val sourceRoots: List = listOf(), + override val samples: List = listOf(), + override val includes: List = listOf(), + override val includeNonPublic: Boolean = false, + override val includeRootPackage: Boolean = false, + override val reportUndocumented: Boolean = false, + override val skipEmptyPackages: Boolean = false, + override val skipDeprecated: Boolean = false, + override val jdkVersion: Int = 6, + override val sourceLinks: List = listOf(), + override val perPackageOptions: List = listOf(), + externalDocumentationLinks: List = listOf(), + override val languageVersion: String? = null, + override val apiVersion: String? = null, + override val noStdlibLink: Boolean = false, + override val noJdkLink: Boolean = false, + override val suppressedFiles: List = listOf(), + override val collectInheritedExtensionsFromLibraries: Boolean = false, + override val analysisPlatform: Platform = Platform.DEFAULT, + override val targets: List = listOf() +): DokkaConfiguration.PassConfiguration { + private val defaultLinks = run { + val links = mutableListOf() + if (!noJdkLink) + links += DokkaConfiguration.ExternalDocumentationLink.Builder("http://docs.oracle.com/javase/$jdkVersion/docs/api/").build() + + if (!noStdlibLink) + links += DokkaConfiguration.ExternalDocumentationLink.Builder("https://kotlinlang.org/api/latest/jvm/stdlib/").build() + links + } + override val externalDocumentationLinks = defaultLinks + externalDocumentationLinks +} + diff --git a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt index 332afffb..1fe4d180 100644 --- a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt +++ b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt @@ -13,7 +13,6 @@ import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtModifierListOwner -import java.io.File fun getSignature(element: PsiElement?) = when(element) { is PsiPackage -> element.qualifiedName @@ -44,24 +43,24 @@ interface JavaDocumentationBuilder { } class JavaPsiDocumentationBuilder : JavaDocumentationBuilder { - private val options: DocumentationOptions + private val passConfiguration: DokkaConfiguration.PassConfiguration private val refGraph: NodeReferenceGraph private val docParser: JavaDocumentationParser @Inject constructor( - options: DocumentationOptions, - refGraph: NodeReferenceGraph, - logger: DokkaLogger, - signatureProvider: ElementSignatureProvider, - externalDocumentationLinkResolver: ExternalDocumentationLinkResolver + passConfiguration: DokkaConfiguration.PassConfiguration, + refGraph: NodeReferenceGraph, + logger: DokkaLogger, + signatureProvider: ElementSignatureProvider, + externalDocumentationLinkResolver: ExternalDocumentationLinkResolver ) { - this.options = options + this.passConfiguration = passConfiguration this.refGraph = refGraph this.docParser = JavadocParser(refGraph, logger, signatureProvider, externalDocumentationLinkResolver) } - constructor(options: DocumentationOptions, refGraph: NodeReferenceGraph, docParser: JavaDocumentationParser) { - this.options = options + constructor(passConfiguration: DokkaConfiguration.PassConfiguration, refGraph: NodeReferenceGraph, docParser: JavaDocumentationParser) { + this.passConfiguration = passConfiguration this.refGraph = refGraph this.docParser = docParser } @@ -141,7 +140,7 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder { } } - private fun skipFile(javaFile: PsiJavaFile): Boolean = options.effectivePackageOptions(javaFile.packageName).suppress + private fun skipFile(javaFile: PsiJavaFile): Boolean = passConfiguration.effectivePackageOptions(javaFile.packageName).suppress private fun skipElement(element: Any) = skipElementByVisibility(element) || @@ -151,13 +150,13 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder { private fun skipElementByVisibility(element: Any): Boolean = element is PsiModifierListOwner && element !is PsiParameter && - !(options.effectivePackageOptions((element.containingFile as? PsiJavaFile)?.packageName ?: "").includeNonPublic) && + !(passConfiguration.effectivePackageOptions((element.containingFile as? PsiJavaFile)?.packageName ?: "").includeNonPublic) && (element.hasModifierProperty(PsiModifier.PRIVATE) || element.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) || element.isInternal()) private fun skipElementBySuppressedFiles(element: Any): Boolean = - element is PsiElement && File(element.containingFile.virtualFile.path).absoluteFile in options.suppressedFiles + element is PsiElement && element.containingFile.virtualFile.path in passConfiguration.suppressedFiles private fun PsiElement.isInternal(): Boolean { val ktElement = (this as? KtLightElement<*, *>)?.kotlinOrigin ?: return false diff --git a/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt b/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt index d73bef4a..c3a84e57 100644 --- a/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt +++ b/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt @@ -10,7 +10,7 @@ class DeclarationLinkResolver @Inject constructor(val resolutionFacade: DokkaResolutionFacade, val refGraph: NodeReferenceGraph, val logger: DokkaLogger, - val options: DocumentationOptions, + val passConfiguration: DokkaConfiguration.PassConfiguration, val externalDocumentationLinkResolver: ExternalDocumentationLinkResolver, val elementSignatureProvider: ElementSignatureProvider) { @@ -63,7 +63,7 @@ class DeclarationLinkResolver if (symbol is CallableMemberDescriptor && symbol.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { return symbol.overriddenDescriptors.firstOrNull() } - if (symbol is TypeAliasDescriptor && !symbol.isDocumented(options)) { + if (symbol is TypeAliasDescriptor && !symbol.isDocumented(passConfiguration)) { return symbol.classDescriptor } return symbol diff --git a/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt b/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt index 7817da18..d0650d45 100644 --- a/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt +++ b/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt @@ -28,7 +28,7 @@ import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered import org.jetbrains.kotlin.resolve.source.PsiSourceElement class DescriptorDocumentationParser - @Inject constructor(val options: DocumentationOptions, + @Inject constructor(val options: DokkaConfiguration.PassConfiguration, val logger: DokkaLogger, val linkResolver: DeclarationLinkResolver, val resolutionFacade: DokkaResolutionFacade, diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index e3675f9d..fb0b898a 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -4,7 +4,7 @@ import com.google.inject.Inject import com.intellij.openapi.util.text.StringUtil import com.intellij.psi.PsiField import com.intellij.psi.PsiJavaFile -import org.jetbrains.dokka.DokkaConfiguration.* +import org.jetbrains.dokka.DokkaConfiguration.PassConfiguration import org.jetbrains.dokka.Kotlin.DescriptorDocumentationParser import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.* @@ -35,62 +35,8 @@ import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.typeUtil.supertypes import org.jetbrains.kotlin.util.supertypesWithAny -import java.io.File -import java.nio.file.Path -import java.nio.file.Paths import com.google.inject.name.Named as GuiceNamed -class DocumentationOptions(val outputDir: String, - val outputFormat: String, - includeNonPublic: Boolean = false, - val includeRootPackage: Boolean = false, - reportUndocumented: Boolean = true, - val skipEmptyPackages: Boolean = true, - skipDeprecated: Boolean = false, - jdkVersion: Int = 6, - val generateIndexPages: Boolean = true, - val sourceLinks: List = emptyList(), - val impliedPlatforms: List = emptyList(), - // Sorted by pattern length - perPackageOptions: List = emptyList(), - externalDocumentationLinks: List = emptyList(), - noStdlibLink: Boolean, - noJdkLink: Boolean = false, - val languageVersion: String?, - val apiVersion: String?, - cacheRoot: String? = null, - val suppressedFiles: Set = emptySet(), - val collectInheritedExtensionsFromLibraries: Boolean = false) { - init { - if (perPackageOptions.any { it.prefix == "" }) - throw IllegalArgumentException("Please do not register packageOptions with all match pattern, use global settings instead") - } - - val perPackageOptions = perPackageOptions.sortedByDescending { it.prefix.length } - val rootPackageOptions = PackageOptionsImpl("", includeNonPublic, reportUndocumented, skipDeprecated) - - fun effectivePackageOptions(pack: String): PackageOptions = perPackageOptions.firstOrNull { pack == it.prefix || pack.startsWith(it.prefix + ".") } ?: rootPackageOptions - fun effectivePackageOptions(pack: FqName): PackageOptions = effectivePackageOptions(pack.asString()) - - val defaultLinks = run { - val links = mutableListOf() - if (!noJdkLink) - links += ExternalDocumentationLink.Builder("http://docs.oracle.com/javase/$jdkVersion/docs/api/").build() - - if (!noStdlibLink) - links += ExternalDocumentationLink.Builder("https://kotlinlang.org/api/latest/jvm/stdlib/").build() - links - } - - val externalDocumentationLinks = defaultLinks + externalDocumentationLinks - - val cacheRoot: Path? = when { - cacheRoot == "default" -> Paths.get(System.getProperty("user.home"), ".cache", "dokka") - cacheRoot != null -> Paths.get(cacheRoot) - else -> null - } -} - private fun isExtensionForExternalClass(extensionFunctionDescriptor: DeclarationDescriptor, extensionReceiverDescriptor: DeclarationDescriptor, allFqNames: Collection): Boolean { @@ -120,7 +66,7 @@ val ignoredSupertypes = setOf( class DocumentationBuilder @Inject constructor(val resolutionFacade: DokkaResolutionFacade, val descriptorDocumentationParser: DescriptorDocumentationParser, - val options: DocumentationOptions, + val passConfiguration: DokkaConfiguration.PassConfiguration, val refGraph: NodeReferenceGraph, val platformNodeRegistry: PlatformNodeRegistry, val logger: DokkaLogger, @@ -352,7 +298,7 @@ class DocumentationBuilder fun DocumentationNode.isSinceKotlin() = name == "SinceKotlin" && kind == NodeKind.Annotation fun DocumentationNode.appendSourceLink(sourceElement: SourceElement) { - appendSourceLink(sourceElement.getPsi(), options.sourceLinks) + appendSourceLink(sourceElement.getPsi(), passConfiguration.sourceLinks) } fun DocumentationNode.appendSignature(descriptor: DeclarationDescriptor) { @@ -360,7 +306,7 @@ class DocumentationBuilder } fun DocumentationNode.appendChild(descriptor: DeclarationDescriptor, kind: RefKind): DocumentationNode? { - if (!descriptor.isGenerated() && descriptor.isDocumented(options)) { + if (!descriptor.isGenerated() && descriptor.isDocumented(passConfiguration)) { val node = descriptor.build() append(node, kind) return node @@ -387,7 +333,7 @@ class DocumentationBuilder fun DocumentationNode.appendOrUpdateMember(descriptor: DeclarationDescriptor) { - if (descriptor.isGenerated() || !descriptor.isDocumented(options)) return + if (descriptor.isGenerated() || !descriptor.isDocumented(passConfiguration)) return val existingNode = refGraph.lookup(descriptor.signature()) if (existingNode != null) { @@ -459,10 +405,10 @@ class DocumentationBuilder val allFqNames = fragments.map { it.fqName }.distinct() for (packageName in allFqNames) { - if (packageName.isRoot && !options.includeRootPackage) continue + if (packageName.isRoot && !passConfiguration.includeRootPackage) continue val declarations = fragments.filter { it.fqName == packageName }.flatMap { it.getMemberScope().getContributedDescriptors() } - if (options.skipEmptyPackages && declarations.none { it.isDocumented(options) }) continue + if (passConfiguration.skipEmptyPackages && declarations.none { it.isDocumented(passConfiguration) }) continue logger.info(" package $packageName: ${declarations.count()} declarations") val packageNode = findOrCreatePackageNode(this, packageName.asString(), packageContent, this@DocumentationBuilder.refGraph) packageDocumentationBuilder.buildPackageDocumentation(this@DocumentationBuilder, packageName, packageNode, @@ -489,7 +435,7 @@ class DocumentationBuilder }.flatten() val allDescriptors = - if (options.collectInheritedExtensionsFromLibraries) { + if (passConfiguration.collectInheritedExtensionsFromLibraries) { allPackageViewDescriptors.map { it.memberScope } } else { fragments.asSequence().map { it.getMemberScope() } @@ -694,7 +640,7 @@ class DocumentationBuilder .mapTo(result) { ClassMember(it, extraModifier = "static") } val companionObjectDescriptor = companionObjectDescriptor - if (companionObjectDescriptor != null && companionObjectDescriptor.isDocumented(options)) { + if (companionObjectDescriptor != null && companionObjectDescriptor.isDocumented(passConfiguration)) { val descriptors = companionObjectDescriptor.defaultType.memberScope.getContributedDescriptors() val descriptorsToDocument = descriptors.filter { it !is CallableDescriptor || !it.isInheritedFromAny() } descriptorsToDocument.mapTo(result) { @@ -967,12 +913,12 @@ class DocumentationBuilder } -fun DeclarationDescriptor.isDocumented(options: DocumentationOptions): Boolean { - return (options.effectivePackageOptions(fqNameSafe).includeNonPublic +fun DeclarationDescriptor.isDocumented(passConfiguration: DokkaConfiguration.PassConfiguration): Boolean { + return (passConfiguration.effectivePackageOptions(fqNameSafe).includeNonPublic || this !is MemberDescriptor || this.visibility.isPublicAPI) - && !isDocumentationSuppressed(options) - && (!options.effectivePackageOptions(fqNameSafe).skipDeprecated || !isDeprecated()) + && !isDocumentationSuppressed(passConfiguration) + && (!passConfiguration.effectivePackageOptions(fqNameSafe).skipDeprecated || !isDeprecated()) } private fun DeclarationDescriptor.isGenerated() = this is CallableMemberDescriptor && kind != CallableMemberDescriptor.Kind.DECLARATION @@ -986,7 +932,7 @@ class KotlinPackageDocumentationBuilder : PackageDocumentationBuilder { val externalClassNodes = hashMapOf() declarations.forEach { descriptor -> with(documentationBuilder) { - if (descriptor.isDocumented(options)) { + if (descriptor.isDocumented(passConfiguration)) { val parent = packageNode.getParentForPackageMember(descriptor, externalClassNodes, allFqNames) parent.appendOrUpdateMember(descriptor) } @@ -998,14 +944,14 @@ class KotlinPackageDocumentationBuilder : PackageDocumentationBuilder { class KotlinJavaDocumentationBuilder @Inject constructor(val resolutionFacade: DokkaResolutionFacade, val documentationBuilder: DocumentationBuilder, - val options: DocumentationOptions, + val passConfiguration: DokkaConfiguration.PassConfiguration, val logger: DokkaLogger) : JavaDocumentationBuilder { override fun appendFile(file: PsiJavaFile, module: DocumentationModule, packageContent: Map) { val classDescriptors = file.classes.map { it.getJavaClassDescriptor(resolutionFacade) } - if (classDescriptors.any { it != null && it.isDocumented(options) }) { + if (classDescriptors.any { it != null && it.isDocumented(passConfiguration) }) { val packageNode = findOrCreatePackageNode(module, file.packageName, packageContent, documentationBuilder.refGraph) for (descriptor in classDescriptors.filterNotNull()) { @@ -1035,13 +981,13 @@ fun AnnotationDescriptor.mustBeDocumented(): Boolean { return annotationClass.isDocumentedAnnotation() } -fun DeclarationDescriptor.isDocumentationSuppressed(options: DocumentationOptions): Boolean { +fun DeclarationDescriptor.isDocumentationSuppressed(passConfiguration: DokkaConfiguration.PassConfiguration): Boolean { - if (options.effectivePackageOptions(fqNameSafe).suppress) return true + if (passConfiguration.effectivePackageOptions(fqNameSafe).suppress) return true val path = this.findPsi()?.containingFile?.virtualFile?.path if (path != null) { - if (File(path).absoluteFile in options.suppressedFiles) return true + if (path in passConfiguration.suppressedFiles) return true } val doc = findKDoc() @@ -1079,7 +1025,7 @@ fun DeclarationDescriptor.signature(): String { is TypeAliasDescriptor -> DescriptorUtils.getFqName(this).asString() is PropertyDescriptor -> containingDeclaration.signature() + "$" + name + receiverSignature() - is FunctionDescriptor -> containingDeclaration.signature() + "$" + name + parameterSignature() + ":" + returnType?.signature() + is FunctionDescriptor -> containingDeclaration.signature() + "$" + name + parameterSignature() + ":" + returnType?.signature() is ValueParameterDescriptor -> containingDeclaration.signature() + "/" + name is TypeParameterDescriptor -> containingDeclaration.signature() + "*" + name is ReceiverParameterDescriptor -> containingDeclaration.signature() + "/" + name @@ -1140,8 +1086,8 @@ fun DeclarationDescriptor.sourceLocation(): String? { return null } -fun DocumentationModule.prepareForGeneration(options: DocumentationOptions) { - if (options.generateIndexPages) { +fun DocumentationModule.prepareForGeneration(configuration: DokkaConfiguration) { + if (configuration.generateIndexPages) { generateAllTypesNode() } nodeRefGraph.resolveReferences() @@ -1167,4 +1113,12 @@ fun ClassDescriptor.supertypesWithAnyPrecise(): Collection { return emptyList() } return typeConstructor.supertypesWithAny() -} \ No newline at end of file +} + +fun PassConfiguration.effectivePackageOptions(pack: String): DokkaConfiguration.PackageOptions { + val rootPackageOptions = PackageOptionsImpl("", includeNonPublic, reportUndocumented, skipDeprecated) + return perPackageOptions.firstOrNull { pack == it.prefix || pack.startsWith(it.prefix + ".") } ?: rootPackageOptions +} + +fun PassConfiguration.effectivePackageOptions(pack: FqName): DokkaConfiguration.PackageOptions = effectivePackageOptions(pack.asString()) + diff --git a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt index a8129793..2fc207b9 100644 --- a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt +++ b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt @@ -22,6 +22,7 @@ import java.net.HttpURLConnection import java.net.URL import java.net.URLConnection import java.nio.file.Path +import java.nio.file.Paths import java.security.MessageDigest import javax.inject.Named import kotlin.reflect.full.findAnnotation @@ -30,7 +31,8 @@ fun ByteArray.toHexString() = this.joinToString(separator = "") { "%02x".format( @Singleton class ExternalDocumentationLinkResolver @Inject constructor( - val options: DocumentationOptions, + val configuration: DokkaConfiguration, + val passConfiguration: DokkaConfiguration.PassConfiguration, @Named("libraryResolutionFacade") val libraryResolutionFacade: DokkaResolutionFacade, val logger: DokkaLogger ) { @@ -42,7 +44,12 @@ class ExternalDocumentationLinkResolver @Inject constructor( override fun toString(): String = rootUrl.toString() } - val cacheDir: Path? = options.cacheRoot?.resolve("packageListCache")?.apply { createDirectories() } + + val cacheDir: Path? = when { + configuration.cacheRoot == "default" -> Paths.get(System.getProperty("user.home"), ".cache", "dokka") + configuration.cacheRoot != null -> Paths.get(configuration.cacheRoot) + else -> null + }?.resolve("packageListCache")?.apply { createDirectories() } val cachedProtocols = setOf("http", "https", "ftp") @@ -157,7 +164,7 @@ class ExternalDocumentationLinkResolver @Inject constructor( } init { - options.externalDocumentationLinks.forEach { + passConfiguration.externalDocumentationLinks.forEach { try { loadPackageList(it) } catch (e: Exception) { diff --git a/core/src/main/kotlin/Kotlin/KotlinAsJavaDocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/KotlinAsJavaDocumentationBuilder.kt index c7ed8292..be6dd2e1 100644 --- a/core/src/main/kotlin/Kotlin/KotlinAsJavaDocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/KotlinAsJavaDocumentationBuilder.kt @@ -28,7 +28,7 @@ class KotlinAsJavaDocumentationBuilder return } - val javaDocumentationBuilder = JavaPsiDocumentationBuilder(documentationBuilder.options, + val javaDocumentationBuilder = JavaPsiDocumentationBuilder(documentationBuilder.passConfiguration, documentationBuilder.refGraph, kotlinAsJavaDocumentationParser) diff --git a/core/src/main/kotlin/Samples/DefaultSampleProcessingService.kt b/core/src/main/kotlin/Samples/DefaultSampleProcessingService.kt index 116a5c02..f3f45c3f 100644 --- a/core/src/main/kotlin/Samples/DefaultSampleProcessingService.kt +++ b/core/src/main/kotlin/Samples/DefaultSampleProcessingService.kt @@ -20,7 +20,7 @@ import org.jetbrains.kotlin.resolve.scopes.ResolutionScope open class DefaultSampleProcessingService -@Inject constructor(val options: DocumentationOptions, +@Inject constructor(val configuration: DokkaConfiguration, val logger: DokkaLogger, val resolutionFacade: DokkaResolutionFacade) : SampleProcessingService { diff --git a/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt b/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt index b0988c35..b5801457 100644 --- a/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt +++ b/core/src/main/kotlin/Samples/KotlinWebsiteSampleProcessingService.kt @@ -12,10 +12,10 @@ import org.jetbrains.kotlin.psi.psiUtil.prevLeaf import org.jetbrains.kotlin.resolve.ImportPath open class KotlinWebsiteSampleProcessingService -@Inject constructor(options: DocumentationOptions, +@Inject constructor(dokkaConfiguration: DokkaConfiguration, logger: DokkaLogger, resolutionFacade: DokkaResolutionFacade) - : DefaultSampleProcessingService(options, logger, resolutionFacade) { + : DefaultSampleProcessingService(dokkaConfiguration, logger, resolutionFacade) { private class SampleBuilder : KtTreeVisitorVoid() { val builder = StringBuilder() diff --git a/core/src/main/kotlin/Utilities/DokkaModules.kt b/core/src/main/kotlin/Utilities/DokkaModules.kt index 732cbc48..251d5c23 100644 --- a/core/src/main/kotlin/Utilities/DokkaModules.kt +++ b/core/src/main/kotlin/Utilities/DokkaModules.kt @@ -14,9 +14,10 @@ import kotlin.reflect.KClass const val impliedPlatformsName = "impliedPlatforms" class DokkaAnalysisModule(val environment: AnalysisEnvironment, - val options: DocumentationOptions, + val configuration: DokkaConfiguration, val defaultPlatformsProvider: DefaultPlatformsProvider, val nodeReferenceGraph: NodeReferenceGraph, + val passConfiguration: DokkaConfiguration.PassConfiguration, val logger: DokkaLogger) : Module { override fun configure(binder: Binder) { binder.bind().toInstance(logger) @@ -28,29 +29,30 @@ class DokkaAnalysisModule(val environment: AnalysisEnvironment, binder.bind().toInstance(dokkaResolutionFacade) binder.bind().annotatedWith(Names.named("libraryResolutionFacade")).toInstance(libraryResolutionFacade) - binder.bind().toInstance(options) + binder.bind().toInstance(configuration) + binder.bind().toInstance(passConfiguration) binder.bind().toInstance(defaultPlatformsProvider) binder.bind().toInstance(nodeReferenceGraph) - val descriptor = ServiceLocator.lookup("format", options.outputFormat) + val descriptor = ServiceLocator.lookup("format", configuration.format) descriptor.configureAnalysis(binder) } } object StringListType : TypeLiteral<@JvmSuppressWildcards List>() -class DokkaOutputModule(val options: DocumentationOptions, +class DokkaOutputModule(val configuration: DokkaConfiguration, val logger: DokkaLogger) : Module { override fun configure(binder: Binder) { - binder.bind(File::class.java).annotatedWith(Names.named("outputDir")).toInstance(File(options.outputDir)) + binder.bind(File::class.java).annotatedWith(Names.named("outputDir")).toInstance(File(configuration.outputDir)) - binder.bind().toInstance(options) + binder.bind().toInstance(configuration) binder.bind().toInstance(logger) - binder.bind(StringListType).annotatedWith(Names.named(impliedPlatformsName)).toInstance(options.impliedPlatforms) + binder.bind(StringListType).annotatedWith(Names.named(impliedPlatformsName)).toInstance(configuration.impliedPlatforms) - val descriptor = ServiceLocator.lookup("format", options.outputFormat) + val descriptor = ServiceLocator.lookup("format", configuration.format) descriptor.configureOutput(binder) } diff --git a/core/src/main/kotlin/javadoc/dokka-adapters.kt b/core/src/main/kotlin/javadoc/dokka-adapters.kt index 483fb3cd..1329876a 100644 --- a/core/src/main/kotlin/javadoc/dokka-adapters.kt +++ b/core/src/main/kotlin/javadoc/dokka-adapters.kt @@ -4,16 +4,19 @@ import com.google.inject.Binder import com.google.inject.Inject import com.sun.tools.doclets.formats.html.HtmlDoclet import org.jetbrains.dokka.* -import org.jetbrains.dokka.Formats.* +import org.jetbrains.dokka.Formats.DefaultAnalysisComponent +import org.jetbrains.dokka.Formats.DefaultAnalysisComponentServices +import org.jetbrains.dokka.Formats.FormatDescriptor +import org.jetbrains.dokka.Formats.KotlinAsJava import org.jetbrains.dokka.Utilities.bind import org.jetbrains.dokka.Utilities.toType -class JavadocGenerator @Inject constructor(val options: DocumentationOptions, val logger: DokkaLogger) : Generator { +class JavadocGenerator @Inject constructor(val configuration: DokkaConfiguration, val logger: DokkaLogger) : Generator { override fun buildPages(nodes: Iterable) { val module = nodes.single() as DocumentationModule - HtmlDoclet.start(ModuleNodeAdapter(module, StandardReporter(logger), options.outputDir)) + HtmlDoclet.start(ModuleNodeAdapter(module, StandardReporter(logger), configuration.outputDir)) } override fun buildOutlines(nodes: Iterable) { diff --git a/core/src/test/kotlin/TestAPI.kt b/core/src/test/kotlin/TestAPI.kt index 4a755130..b65efbe9 100644 --- a/core/src/test/kotlin/TestAPI.kt +++ b/core/src/test/kotlin/TestAPI.kt @@ -35,31 +35,35 @@ fun verifyModel(modelConfig: ModelConfig, verifier: (DocumentationModule) -> Unit) { val documentation = DocumentationModule("test") - val options = DocumentationOptions( - "", - modelConfig.format, - includeNonPublic = modelConfig.includeNonPublic, - skipEmptyPackages = false, - includeRootPackage = true, - sourceLinks = listOf(), - perPackageOptions = modelConfig.perPackageOptions, - generateIndexPages = false, - noStdlibLink = modelConfig.noStdlibLink, - noJdkLink = false, - cacheRoot = "default", - languageVersion = null, - apiVersion = null, - collectInheritedExtensionsFromLibraries = modelConfig.collectInheritedExtensionsFromLibraries + val passConfiguration = PassConfigurationImpl ( + includeNonPublic = modelConfig.includeNonPublic, + skipEmptyPackages = false, + includeRootPackage = true, + sourceLinks = listOf(), + perPackageOptions = modelConfig.perPackageOptions, + noStdlibLink = modelConfig.noStdlibLink, + noJdkLink = false, + languageVersion = null, + apiVersion = null, + collectInheritedExtensionsFromLibraries = modelConfig.collectInheritedExtensionsFromLibraries + ) + val configuration = DokkaConfigurationImpl( + outputDir = "", + format = modelConfig.format, + generateIndexPages = false, + cacheRoot = "default", + passesConfigurations = listOf(passConfiguration) ) - appendDocumentation(documentation, options, modelConfig) - documentation.prepareForGeneration(options) + appendDocumentation(documentation, configuration, passConfiguration, modelConfig) + documentation.prepareForGeneration(configuration) verifier(documentation) } fun appendDocumentation(documentation: DocumentationModule, - options: DocumentationOptions, + dokkaConfiguration: DokkaConfiguration, + passConfiguration: DokkaConfiguration.PassConfiguration, modelConfig: ModelConfig ) { val messageCollector = object : MessageCollector { @@ -108,13 +112,13 @@ fun appendDocumentation(documentation: DocumentationModule, } addRoots(modelConfig.roots.toList()) - loadLanguageVersionSettings(options.languageVersion, options.apiVersion) + loadLanguageVersionSettings(passConfiguration.languageVersion, passConfiguration.apiVersion) } val defaultPlatformsProvider = object : DefaultPlatformsProvider { override fun getDefaultPlatforms(descriptor: DeclarationDescriptor) = modelConfig.defaultPlatforms } val injector = Guice.createInjector( - DokkaAnalysisModule(environment, options, defaultPlatformsProvider, documentation.nodeRefGraph, DokkaConsoleLogger)) + DokkaAnalysisModule(environment, dokkaConfiguration, defaultPlatformsProvider, documentation.nodeRefGraph, passConfiguration, DokkaConsoleLogger)) buildDocumentationModule(injector, documentation) Disposer.dispose(environment) } diff --git a/core/src/test/kotlin/format/KotlinWebSiteFormatTest.kt b/core/src/test/kotlin/format/KotlinWebSiteFormatTest.kt index 643b5b2d..4f292e37 100644 --- a/core/src/test/kotlin/format/KotlinWebSiteFormatTest.kt +++ b/core/src/test/kotlin/format/KotlinWebSiteFormatTest.kt @@ -48,17 +48,20 @@ class KotlinWebSiteFormatTest: FileGeneratorTestCase() { private fun buildMultiplePlatforms(path: String): DocumentationModule { val module = DocumentationModule("test") - val options = DocumentationOptions( - outputDir = "", - outputFormat = "html", - generateIndexPages = false, - noStdlibLink = true, + val passConfiguration = PassConfigurationImpl(noStdlibLink = true, noJdkLink = true, languageVersion = null, apiVersion = null ) + val configuration = DokkaConfigurationImpl( + outputDir = "", + format = "html", + generateIndexPages = false, + passesConfigurations = listOf(passConfiguration) + ) + appendDocumentation( - module, options, ModelConfig( + module, configuration, passConfiguration, ModelConfig( roots = arrayOf(contentRootFromPath("testdata/format/website/$path/jvm.kt")), defaultPlatforms = listOf("JVM") ) @@ -67,13 +70,13 @@ class KotlinWebSiteFormatTest: FileGeneratorTestCase() { appendDocumentation( - module, options, ModelConfig( + module, configuration, passConfiguration, ModelConfig( roots = arrayOf(contentRootFromPath("testdata/format/website/$path/jre7.kt")), defaultPlatforms = listOf("JVM", "JRE7") ) ) appendDocumentation( - module, options, ModelConfig( + module, configuration, passConfiguration, ModelConfig( roots = arrayOf(contentRootFromPath("testdata/format/website/$path/js.kt")), defaultPlatforms = listOf("JS") ) diff --git a/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt b/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt index 3ae0930e..1901154f 100644 --- a/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt +++ b/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt @@ -64,29 +64,37 @@ abstract class BaseKotlinWebSiteHtmlFormatTest(val analysisPlatform: Platform): private fun buildMultiplePlatforms(path: String): DocumentationModule { val module = DocumentationModule("test") - val options = DocumentationOptions( - outputDir = "", - outputFormat = "kotlin-website-html", - generateIndexPages = false, + val passConfiguration = PassConfigurationImpl( noStdlibLink = true, noJdkLink = true, languageVersion = null, apiVersion = null ) + + val dokkaConfiguration = DokkaConfigurationImpl( + outputDir = "", + format = "kotlin-website-html", + generateIndexPages = false, + passesConfigurations = listOf( + passConfiguration + ) + + ) + appendDocumentation( - module, options, ModelConfig( + module, dokkaConfiguration, passConfiguration, ModelConfig( roots = arrayOf(contentRootFromPath("testdata/format/website-html/$path/jvm.kt")), defaultPlatforms = listOf("JVM") ) ) appendDocumentation( - module, options, ModelConfig( + module, dokkaConfiguration, passConfiguration, ModelConfig( roots = arrayOf(contentRootFromPath("testdata/format/website-html/$path/jre7.kt")), defaultPlatforms = listOf("JVM", "JRE7") ) ) appendDocumentation( - module, options, ModelConfig( + module, dokkaConfiguration, passConfiguration, ModelConfig( roots = arrayOf(contentRootFromPath("testdata/format/website-html/$path/js.kt")), defaultPlatforms = listOf("JS") ) diff --git a/core/src/test/kotlin/format/MarkdownFormatTest.kt b/core/src/test/kotlin/format/MarkdownFormatTest.kt index 4de70751..29d2d20f 100644 --- a/core/src/test/kotlin/format/MarkdownFormatTest.kt +++ b/core/src/test/kotlin/format/MarkdownFormatTest.kt @@ -1,7 +1,6 @@ package org.jetbrains.dokka.tests import org.jetbrains.dokka.* -import org.junit.Before import org.junit.Test abstract class BaseMarkdownFormatTest(val analysisPlatform: Platform): FileGeneratorTestCase() { @@ -249,16 +248,23 @@ abstract class BaseMarkdownFormatTest(val analysisPlatform: Platform): FileGener @Test fun packagePlatformsWithExtExtensions() { val path = "multiplatform/packagePlatformsWithExtExtensions" val module = DocumentationModule("test") - val options = DocumentationOptions( - outputDir = "", - outputFormat = "html", - generateIndexPages = false, + val passConfiguration = PassConfigurationImpl( noStdlibLink = true, noJdkLink = true, languageVersion = null, apiVersion = null ) - appendDocumentation(module, options, ModelConfig( + + val dokkaConfiguration = DokkaConfigurationImpl( + outputDir = "", + format = "html", + generateIndexPages = false, + passesConfigurations = listOf( + passConfiguration + ) + ) + + appendDocumentation(module, dokkaConfiguration, passConfiguration, ModelConfig( roots = arrayOf(contentRootFromPath("testdata/format/$path/jvm.kt")), defaultPlatforms = listOf("JVM"), withKotlinRuntime = true, @@ -373,24 +379,30 @@ abstract class BaseMarkdownFormatTest(val analysisPlatform: Platform): FileGener private fun buildMultiplePlatforms(path: String): DocumentationModule { val module = DocumentationModule("test") - val options = DocumentationOptions( - outputDir = "", - outputFormat = "html", - generateIndexPages = false, + val passConfiguration = PassConfigurationImpl( noStdlibLink = true, noJdkLink = true, languageVersion = null, apiVersion = null ) + val dokkaConfiguration = DokkaConfigurationImpl( + outputDir = "", + format = "html", + generateIndexPages = false, + passesConfigurations = listOf( + passConfiguration + ) + + ) appendDocumentation( - module, options, ModelConfig( + module, dokkaConfiguration, passConfiguration, ModelConfig( roots = arrayOf(contentRootFromPath("testdata/format/$path/jvm.kt")), defaultPlatforms = listOf("JVM"), analysisPlatform = Platform.jvm ) ) appendDocumentation( - module, options, ModelConfig( + module, dokkaConfiguration, passConfiguration, ModelConfig( roots = arrayOf(contentRootFromPath("testdata/format/$path/js.kt")), defaultPlatforms = listOf("JS"), analysisPlatform = Platform.js diff --git a/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt b/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt index 287b628a..e0fa27d1 100644 --- a/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt +++ b/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt @@ -39,31 +39,37 @@ enum class Platform(val key: String) { } interface DokkaConfiguration { - val moduleName: String - val classpath: List - val sourceRoots: List - val samples: List - val includes: List val outputDir: String val format: String - val includeNonPublic: Boolean - val includeRootPackage: Boolean - val reportUndocumented: Boolean - val skipEmptyPackages: Boolean - val skipDeprecated: Boolean - val jdkVersion: Int val generateIndexPages: Boolean - val sourceLinks: List - val impliedPlatforms: List - val perPackageOptions: List - val externalDocumentationLinks: List - val languageVersion: String? - val apiVersion: String? - val noStdlibLink: Boolean - val noJdkLink: Boolean val cacheRoot: String? - val suppressedFiles: List - val collectInheritedExtensionsFromLibraries: Boolean + val passesConfigurations: List + val impliedPlatforms: List + + interface PassConfiguration { + val moduleName: String + val classpath: List + val sourceRoots: List + val samples: List + val includes: List + val includeNonPublic: Boolean + val includeRootPackage: Boolean + val reportUndocumented: Boolean + val skipEmptyPackages: Boolean + val skipDeprecated: Boolean + val jdkVersion: Int + val sourceLinks: List + val perPackageOptions: List + val externalDocumentationLinks: List + val languageVersion: String? + val apiVersion: String? + val noStdlibLink: Boolean + val noJdkLink: Boolean + val suppressedFiles: List + val collectInheritedExtensionsFromLibraries: Boolean + val analysisPlatform: Platform + val targets: List + } interface SourceRoot { val path: String @@ -106,31 +112,12 @@ interface DokkaConfiguration { } data class SerializeOnlyDokkaConfiguration( - override val moduleName: String, - override val classpath: List, - override val sourceRoots: List, - override val samples: List, - override val includes: List, override val outputDir: String, override val format: String, - override val includeNonPublic: Boolean, - override val includeRootPackage: Boolean, - override val reportUndocumented: Boolean, - override val skipEmptyPackages: Boolean, - override val skipDeprecated: Boolean, - override val jdkVersion: Int, override val generateIndexPages: Boolean, - override val sourceLinks: List, - override val impliedPlatforms: List, - override val perPackageOptions: List, - override val externalDocumentationLinks: List, - override val noStdlibLink: Boolean, - override val noJdkLink: Boolean, override val cacheRoot: String?, - override val suppressedFiles: List, - override val languageVersion: String?, - override val apiVersion: String?, - override val collectInheritedExtensionsFromLibraries: Boolean + override val impliedPlatforms: List, + override val passesConfigurations: List ) : DokkaConfiguration diff --git a/runners/ant/src/main/kotlin/ant/dokka.kt b/runners/ant/src/main/kotlin/ant/dokka.kt index 0b1ccc13..4f629198 100644 --- a/runners/ant/src/main/kotlin/ant/dokka.kt +++ b/runners/ant/src/main/kotlin/ant/dokka.kt @@ -116,29 +116,34 @@ class DokkaAntTask: Task() { SourceLinkDefinitionImpl(File(path).canonicalFile.absolutePath, url, it.lineSuffix) } - val generator = DokkaGenerator( - AntLogger(this), - compileClasspath.list().toList(), - sourcePath.list().map { SourceRootImpl(it) } + antSourceRoots.mapNotNull { it.toSourceRoot() }, - samplesPath.list().toList(), - includesPath.list().toList(), - moduleName!!, - DocumentationOptions( - outputDir!!, - outputFormat, - skipDeprecated = skipDeprecated, - sourceLinks = sourceLinks, - jdkVersion = jdkVersion, - impliedPlatforms = impliedPlatforms.split(','), - perPackageOptions = antPackageOptions, - externalDocumentationLinks = antExternalDocumentationLinks.map { it.build() }, - noStdlibLink = noStdlibLink, - noJdkLink = noJdkLink, - cacheRoot = cacheRoot, - languageVersion = languageVersion, - apiVersion = apiVersion - ) + val passConfiguration = PassConfigurationImpl( + classpath = compileClasspath.list().toList(), + sourceRoots = sourcePath.list().map { SourceRootImpl(it) } + antSourceRoots.mapNotNull { it.toSourceRoot() }, + samples = samplesPath.list().toList(), + includes = includesPath.list().toList(), + moduleName = moduleName!!, + skipDeprecated = skipDeprecated, + sourceLinks = sourceLinks, + jdkVersion = jdkVersion, + perPackageOptions = antPackageOptions, + externalDocumentationLinks = antExternalDocumentationLinks.map { it.build() }, + noStdlibLink = noStdlibLink, + noJdkLink = noJdkLink, + languageVersion = languageVersion, + apiVersion = apiVersion ) + + val configuration = DokkaConfigurationImpl( + outputDir = outputDir!!, + format = outputFormat, + impliedPlatforms = impliedPlatforms.split(','), + cacheRoot = cacheRoot, + passesConfigurations = listOf( + passConfiguration + ) + ) + + val generator = DokkaGenerator(configuration, AntLogger(this)) generator.generate() } } \ No newline at end of file diff --git a/runners/cli/src/main/kotlin/cli/main.kt b/runners/cli/src/main/kotlin/cli/main.kt index f871f406..330de5e1 100644 --- a/runners/cli/src/main/kotlin/cli/main.kt +++ b/runners/cli/src/main/kotlin/cli/main.kt @@ -44,7 +44,7 @@ class DokkaArguments { @set:Argument(value = "impliedPlatforms", description = "List of implied platforms (comma-separated)") var impliedPlatforms: String = "" - @set:Argument(value = "packageOptions", description = "List of package options in format \"prefix,-deprecated,-privateApi,+warnUndocumented,+suppress;...\" ") + @set:Argument(value = "packageOptions", description = "List of package passConfiguration in format \"prefix,-deprecated,-privateApi,+warnUndocumented,+suppress;...\" ") var packageOptions: String = "" @set:Argument(value = "links", description = "External documentation links in format url^packageListUrl^^url2...") @@ -111,31 +111,37 @@ object MainKt { val classPath = arguments.classpath.split(File.pathSeparatorChar).toList() - val documentationOptions = DocumentationOptions( - arguments.outputDir.let { if (it.endsWith('/')) it else it + '/' }, - arguments.outputFormat, + val passConfig = PassConfigurationImpl( skipDeprecated = arguments.nodeprecated, sourceLinks = sourceLinks, - impliedPlatforms = arguments.impliedPlatforms.split(','), perPackageOptions = parsePerPackageOptions(arguments.packageOptions), jdkVersion = arguments.jdkVersion, externalDocumentationLinks = parseLinks(arguments.links), noStdlibLink = arguments.noStdlibLink, - cacheRoot = arguments.cacheRoot, languageVersion = arguments.languageVersion, apiVersion = arguments.apiVersion, collectInheritedExtensionsFromLibraries = arguments.collectInheritedExtensionsFromLibraries, - noJdkLink = arguments.noJdkLink + noJdkLink = arguments.noJdkLink, + sourceRoots = sources.map(SourceRootImpl.Companion::parseSourceRoot), + analysisPlatform = sources.map (SourceRootImpl.Companion::parseSourceRoot).single().analysisPlatform, + samples = samples, + includes = includes, + moduleName = arguments.moduleName, + classpath = classPath + ) + + val config = DokkaConfigurationImpl( + outputDir = arguments.outputDir.let { if (it.endsWith('/')) it else it + '/' }, + format = arguments.outputFormat, + impliedPlatforms = arguments.impliedPlatforms.split(','), + cacheRoot = arguments.cacheRoot, + + passesConfigurations = listOf( + passConfig + ) ) - val generator = DokkaGenerator( - DokkaConsoleLogger, - classPath, - sources.map(SourceRootImpl.Companion::parseSourceRoot), - samples, - includes, - arguments.moduleName, - documentationOptions) + val generator = DokkaGenerator(config, DokkaConsoleLogger) generator.generate() DokkaConsoleLogger.report() diff --git a/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt b/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt index ea55c8fe..78fd2d86 100644 --- a/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt +++ b/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt @@ -129,30 +129,33 @@ abstract class AbstractDokkaMojo : AbstractMojo() { return } - val gen = DokkaGenerator( - MavenDokkaLogger(log), - classpath, - sourceDirectories.map { SourceRootImpl(it) } + sourceRoots, - samplesDirs, - includeDirs + includes, - moduleName, - DocumentationOptions(getOutDir(), getOutFormat(), - sourceLinks = sourceLinks.map { SourceLinkDefinitionImpl(it.dir, it.url, it.urlSuffix) }, - jdkVersion = jdkVersion, - skipDeprecated = skipDeprecated, - skipEmptyPackages = skipEmptyPackages, - reportUndocumented = reportNotDocumented, - impliedPlatforms = impliedPlatforms, - perPackageOptions = perPackageOptions, - externalDocumentationLinks = externalDocumentationLinks.map { it.build() }, - noStdlibLink = noStdlibLink, - noJdkLink = noJdkLink, - cacheRoot = cacheRoot, - languageVersion = languageVersion, - apiVersion = apiVersion - ) + val passConfiguration = PassConfigurationImpl( + sourceLinks = sourceLinks.map { SourceLinkDefinitionImpl(it.dir, it.url, it.urlSuffix) }, + jdkVersion = jdkVersion, + skipDeprecated = skipDeprecated, + skipEmptyPackages = skipEmptyPackages, + reportUndocumented = reportNotDocumented, + perPackageOptions = perPackageOptions, + externalDocumentationLinks = externalDocumentationLinks.map { it.build() }, + noStdlibLink = noStdlibLink, + noJdkLink = noJdkLink, + languageVersion = languageVersion, + apiVersion = apiVersion + + ) + + val configuration = DokkaConfigurationImpl( + outputDir = getOutDir(), + format = getOutFormat(), + impliedPlatforms = impliedPlatforms, + cacheRoot = cacheRoot, + passesConfigurations = listOf( + passConfiguration + ) ) + val gen = DokkaGenerator(configuration, MavenDokkaLogger(log)) + gen.generate() } } -- cgit From ba09711a1ecbdaede86cab9e76d13ff1047f89b2 Mon Sep 17 00:00:00 2001 From: aleksZubakov Date: Thu, 2 Aug 2018 18:59:20 +0300 Subject: ExternalDocumentationLinkResolver refactoring, extract common dependencies from guice modules --- core/src/main/kotlin/Generation/DokkaGenerator.kt | 11 +- .../Kotlin/ExternalDocumentationLinkResolver.kt | 114 ++++++++++++++------- core/src/main/kotlin/Utilities/DokkaModules.kt | 19 ++-- core/src/test/kotlin/TestAPI.kt | 19 +++- 4 files changed, 112 insertions(+), 51 deletions(-) (limited to 'core/src/main/kotlin/Generation') diff --git a/core/src/main/kotlin/Generation/DokkaGenerator.kt b/core/src/main/kotlin/Generation/DokkaGenerator.kt index 2e46d908..22d1519f 100644 --- a/core/src/main/kotlin/Generation/DokkaGenerator.kt +++ b/core/src/main/kotlin/Generation/DokkaGenerator.kt @@ -9,6 +9,7 @@ import com.intellij.psi.PsiJavaFile import com.intellij.psi.PsiManager import org.jetbrains.dokka.Utilities.DokkaAnalysisModule import org.jetbrains.dokka.Utilities.DokkaOutputModule +import org.jetbrains.dokka.Utilities.DokkaRunModule import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.MessageCollector @@ -27,6 +28,7 @@ class DokkaGenerator(val dokkaConfiguration: DokkaConfiguration, val logger: DokkaLogger) { private val documentationModules: MutableList = mutableListOf() + private val globalInjector = Guice.createInjector(DokkaRunModule(dokkaConfiguration)) fun generate() = with(dokkaConfiguration) { @@ -43,8 +45,9 @@ class DokkaGenerator(val dokkaConfiguration: DokkaConfiguration, val timeBuild = measureTimeMillis { logger.info("Generating pages... ") - val outputInjector = Guice.createInjector(DokkaOutputModule(dokkaConfiguration, logger)) - outputInjector.getInstance(Generator::class.java).buildAll(totalDocumentationModule) + val outputInjector = globalInjector.createChildInjector(DokkaOutputModule(dokkaConfiguration, logger)) + val instance = outputInjector.getInstance(Generator::class.java) + instance.buildAll(totalDocumentationModule) } logger.info("done in ${timeBuild / 1000} secs") } @@ -75,11 +78,11 @@ class DokkaGenerator(val dokkaConfiguration: DokkaConfiguration, } } - val injector = Guice.createInjector( + val injector = globalInjector.createChildInjector( DokkaAnalysisModule(environment, dokkaConfiguration, defaultPlatformsProvider, documentationModule.nodeRefGraph, passConfiguration, logger)) buildDocumentationModule(injector, documentationModule, { isNotSample(it, passConfiguration.samples) }, includes) - documentationModule.nodeRefGraph.nodeMapView.forEach { (_, node) -> + documentationModule.nodeRefGraph.nodeMapView.forEach { (_, node) -> // FIXME: change to full graph visiting node.addReferenceTo( DocumentationNode(analysisPlatform.key, Content.Empty, NodeKind.Platform), RefKind.Platform diff --git a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt index 2fc207b9..9d986aee 100644 --- a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt +++ b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt @@ -29,21 +29,14 @@ import kotlin.reflect.full.findAnnotation fun ByteArray.toHexString() = this.joinToString(separator = "") { "%02x".format(it) } +typealias PackageFqNameToLocation = MutableMap + @Singleton -class ExternalDocumentationLinkResolver @Inject constructor( - val configuration: DokkaConfiguration, - val passConfiguration: DokkaConfiguration.PassConfiguration, - @Named("libraryResolutionFacade") val libraryResolutionFacade: DokkaResolutionFacade, - val logger: DokkaLogger +class PackageListProvider @Inject constructor( + val configuration: DokkaConfiguration, + val logger: DokkaLogger ) { - - val packageFqNameToLocation = mutableMapOf() - val formats = mutableMapOf() - - class ExternalDocumentationRoot(val rootUrl: URL, val resolver: InboundExternalLinkResolutionService, val locations: Map) { - override fun toString(): String = rootUrl.toString() - } - + val storage = mutableMapOf() val cacheDir: Path? = when { configuration.cacheRoot == "default" -> Paths.get(System.getProperty("user.home"), ".cache", "dokka") @@ -53,6 +46,25 @@ class ExternalDocumentationLinkResolver @Inject constructor( val cachedProtocols = setOf("http", "https", "ftp") + init { + for (conf in configuration.passesConfigurations) { + for (link in conf.externalDocumentationLinks) { + if (link in storage) { + continue + } + + try { + loadPackageList(link) + } catch (e: Exception) { + throw RuntimeException("Exception while loading package-list from $link", e) + } + } + + } + } + + + fun URL.doOpenConnectionToReadContent(timeout: Int = 10000, redirectsAllowed: Int = 16): URLConnection { val connection = this.openConnection() connection.connectTimeout = timeout @@ -127,23 +139,23 @@ class ExternalDocumentationLinkResolver @Inject constructor( val (params, packages) = packageListStream - .bufferedReader() - .useLines { lines -> lines.partition { it.startsWith(DOKKA_PARAM_PREFIX) } } + .bufferedReader() + .useLines { lines -> lines.partition { it.startsWith(ExternalDocumentationLinkResolver.DOKKA_PARAM_PREFIX) } } val paramsMap = params.asSequence() - .map { it.removePrefix(DOKKA_PARAM_PREFIX).split(":", limit = 2) } - .groupBy({ (key, _) -> key }, { (_, value) -> value }) + .map { it.removePrefix(ExternalDocumentationLinkResolver.DOKKA_PARAM_PREFIX).split(":", limit = 2) } + .groupBy({ (key, _) -> key }, { (_, value) -> value }) val format = paramsMap["format"]?.singleOrNull() ?: "javadoc" val locations = paramsMap["location"].orEmpty() - .map { it.split("\u001f", limit = 2) } - .map { (key, value) -> key to value } - .toMap() + .map { it.split("\u001f", limit = 2) } + .map { (key, value) -> key to value } + .toMap() - val defaultResolverDesc = services["dokka-default"]!! - val resolverDesc = services[format] + val defaultResolverDesc = ExternalDocumentationLinkResolver.services["dokka-default"]!! + val resolverDesc = ExternalDocumentationLinkResolver.services[format] ?: defaultResolverDesc.takeIf { format in formatsWithDefaultResolver } ?: defaultResolverDesc.also { logger.warn("Couldn't find InboundExternalLinkResolutionService(format = `$format`) for $link, using Dokka default") @@ -160,16 +172,52 @@ class ExternalDocumentationLinkResolver @Inject constructor( val rootInfo = ExternalDocumentationRoot(link.url, resolver, locations) - packages.map { FqName(it) }.forEach { packageFqNameToLocation[it] = rootInfo } + val packageFqNameToLocation = mutableMapOf() + storage[link] = packageFqNameToLocation + + val fqNames = packages.map { FqName(it) } + for(name in fqNames) { + packageFqNameToLocation[name] = rootInfo + } + } + + + + class ExternalDocumentationRoot(val rootUrl: URL, val resolver: InboundExternalLinkResolutionService, val locations: Map) { + override fun toString(): String = rootUrl.toString() } + companion object { + private val formatsWithDefaultResolver = + ServiceLocator + .allServices("format") + .filter { + val desc = ServiceLocator.lookup(it) as? FileGeneratorBasedFormatDescriptor + desc?.generatorServiceClass == FileGenerator::class + }.map { it.name } + .toSet() + + } + +} + +class ExternalDocumentationLinkResolver @Inject constructor( + val configuration: DokkaConfiguration, + val passConfiguration: DokkaConfiguration.PassConfiguration, + @Named("libraryResolutionFacade") val libraryResolutionFacade: DokkaResolutionFacade, + val logger: DokkaLogger, + val packageListProvider: PackageListProvider +) { + + val formats = mutableMapOf() + val packageFqNameToLocation = mutableMapOf() + init { - passConfiguration.externalDocumentationLinks.forEach { - try { - loadPackageList(it) - } catch (e: Exception) { - throw RuntimeException("Exception while loading package-list from $it", e) - } + val fqNameToLocationMaps = passConfiguration.externalDocumentationLinks + .mapNotNull { packageListProvider.storage[it] } + + for(map in fqNameToLocationMaps) { + packageFqNameToLocation.putAll(map) } } @@ -198,14 +246,6 @@ class ExternalDocumentationLinkResolver @Inject constructor( companion object { const val DOKKA_PARAM_PREFIX = "\$dokka." val services = ServiceLocator.allServices("inbound-link-resolver").associateBy { it.name } - private val formatsWithDefaultResolver = - ServiceLocator - .allServices("format") - .filter { - val desc = ServiceLocator.lookup(it) as? FileGeneratorBasedFormatDescriptor - desc?.generatorServiceClass == FileGenerator::class - }.map { it.name } - .toSet() } } diff --git a/core/src/main/kotlin/Utilities/DokkaModules.kt b/core/src/main/kotlin/Utilities/DokkaModules.kt index 251d5c23..c2e652b6 100644 --- a/core/src/main/kotlin/Utilities/DokkaModules.kt +++ b/core/src/main/kotlin/Utilities/DokkaModules.kt @@ -1,8 +1,6 @@ package org.jetbrains.dokka.Utilities -import com.google.inject.Binder -import com.google.inject.Module -import com.google.inject.TypeLiteral +import com.google.inject.* import com.google.inject.binder.AnnotatedBindingBuilder import com.google.inject.name.Names import org.jetbrains.dokka.* @@ -13,6 +11,16 @@ import kotlin.reflect.KClass const val impliedPlatformsName = "impliedPlatforms" +class DokkaRunModule(val configuration: DokkaConfiguration) : Module { + override fun configure(binder: Binder) { + binder.bind().toInstance(configuration) + binder.bind(StringListType).annotatedWith(Names.named(impliedPlatformsName)).toInstance(configuration.impliedPlatforms) + + binder.bind(File::class.java).annotatedWith(Names.named("outputDir")).toInstance(File(configuration.outputDir)) + } + +} + class DokkaAnalysisModule(val environment: AnalysisEnvironment, val configuration: DokkaConfiguration, val defaultPlatformsProvider: DefaultPlatformsProvider, @@ -29,7 +37,6 @@ class DokkaAnalysisModule(val environment: AnalysisEnvironment, binder.bind().toInstance(dokkaResolutionFacade) binder.bind().annotatedWith(Names.named("libraryResolutionFacade")).toInstance(libraryResolutionFacade) - binder.bind().toInstance(configuration) binder.bind().toInstance(passConfiguration) binder.bind().toInstance(defaultPlatformsProvider) @@ -46,11 +53,7 @@ object StringListType : TypeLiteral<@JvmSuppressWildcards List>() class DokkaOutputModule(val configuration: DokkaConfiguration, val logger: DokkaLogger) : Module { override fun configure(binder: Binder) { - binder.bind(File::class.java).annotatedWith(Names.named("outputDir")).toInstance(File(configuration.outputDir)) - - binder.bind().toInstance(configuration) binder.bind().toInstance(logger) - binder.bind(StringListType).annotatedWith(Names.named(impliedPlatformsName)).toInstance(configuration.impliedPlatforms) val descriptor = ServiceLocator.lookup("format", configuration.format) diff --git a/core/src/test/kotlin/TestAPI.kt b/core/src/test/kotlin/TestAPI.kt index b65efbe9..8974bd0b 100644 --- a/core/src/test/kotlin/TestAPI.kt +++ b/core/src/test/kotlin/TestAPI.kt @@ -7,6 +7,7 @@ import com.intellij.openapi.util.io.FileUtil import com.intellij.rt.execution.junit.FileComparisonFailure import org.jetbrains.dokka.* import org.jetbrains.dokka.Utilities.DokkaAnalysisModule +import org.jetbrains.dokka.Utilities.DokkaRunModule import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.MessageCollector @@ -117,8 +118,22 @@ fun appendDocumentation(documentation: DocumentationModule, val defaultPlatformsProvider = object : DefaultPlatformsProvider { override fun getDefaultPlatforms(descriptor: DeclarationDescriptor) = modelConfig.defaultPlatforms } - val injector = Guice.createInjector( - DokkaAnalysisModule(environment, dokkaConfiguration, defaultPlatformsProvider, documentation.nodeRefGraph, passConfiguration, DokkaConsoleLogger)) + + val globalInjector = Guice.createInjector( + DokkaRunModule(dokkaConfiguration) + ) + + val injector = globalInjector.createChildInjector( + DokkaAnalysisModule( + environment, + dokkaConfiguration, + defaultPlatformsProvider, + documentation.nodeRefGraph, + passConfiguration, + DokkaConsoleLogger + ) + ) + buildDocumentationModule(injector, documentation) Disposer.dispose(environment) } -- cgit From 77ce80517f79a774ef985be47ae00db828e34273 Mon Sep 17 00:00:00 2001 From: aleksZubakov Date: Mon, 6 Aug 2018 13:42:44 +0300 Subject: DocumentationMerger refactoring --- .../main/kotlin/Generation/DocumentationMerger.kt | 179 ++++++++++++++++ core/src/main/kotlin/Generation/DokkaGenerator.kt | 227 ++------------------- core/src/main/kotlin/Generation/FileGenerator.kt | 2 +- .../main/kotlin/Generation/configurationImpl.kt | 1 - .../src/main/kotlin/Kotlin/DocumentationBuilder.kt | 2 +- core/src/main/kotlin/Model/DocumentationNode.kt | 1 - .../main/kotlin/Model/DocumentationReference.kt | 26 +-- 7 files changed, 212 insertions(+), 226 deletions(-) create mode 100644 core/src/main/kotlin/Generation/DocumentationMerger.kt (limited to 'core/src/main/kotlin/Generation') diff --git a/core/src/main/kotlin/Generation/DocumentationMerger.kt b/core/src/main/kotlin/Generation/DocumentationMerger.kt new file mode 100644 index 00000000..c2089821 --- /dev/null +++ b/core/src/main/kotlin/Generation/DocumentationMerger.kt @@ -0,0 +1,179 @@ +package org.jetbrains.dokka.Generation + +import org.jetbrains.dokka.* + +class DocumentationMerger( + private val documentationModules: List +) { + private val producedNodeRefGraph: NodeReferenceGraph + private val signatureMap: Map + private val oldToNewNodeMap: MutableMap = mutableMapOf() + + init { + if (documentationModules.groupBy { it.name }.size > 1) { + throw IllegalArgumentException("Modules should have similar names") + } + + signatureMap = documentationModules + .flatMap { it.nodeRefGraph.nodeMapView.entries } + .associate { (k, v) -> v to k } + + + producedNodeRefGraph = NodeReferenceGraph() + documentationModules.map { it.nodeRefGraph } + .flatMap { it.references } + .distinct() + .forEach { producedNodeRefGraph.addReference(it) } + } + + private fun mergePackageReferences( + from: DocumentationNode, + packages: List + ): List { + + val packagesByName = packages + .map { it.to } + .groupBy { it.name } + + val mutableList = mutableListOf() + for ((name, listOfPackages) in packagesByName) { + val producedPackage = mergePackagesWithEqualNames(name, from, listOfPackages) + updatePendingReferences() + + mutableList.add( + DocumentationReference(from, producedPackage, RefKind.Member) + ) + } + + return mutableList + } + + private fun mergePackagesWithEqualNames( + name: String, + from: DocumentationNode, + packages: List + ): DocumentationNode { + val mergedPackage = DocumentationNode(name, Content.Empty, NodeKind.Package) + for (packageNode in packages) { + // TODO: Discuss + mergedPackage.updateContent { + for (otherChild in packageNode.content.children) { + children.add(otherChild) + } + } + oldToNewNodeMap[packageNode] = mergedPackage + } + mergedPackage.clear() + + val references = packages.flatMap { it.allReferences() } + val mergedReferences = mergeReferences(mergedPackage, references) + for (ref in mergedReferences.distinct()) { + mergedPackage.addReference(ref) + } + + from.append(mergedPackage, RefKind.Member) + + return mergedPackage + } + + private fun DocumentationNode.clear() = dropReferences { true } + + private fun mergeMembers( + from: DocumentationNode, + refs: List + ): List { + val membersBySignature: Map> = refs.map { it.to } + .groupBy { signatureMap[it]!! } + + val mergedMembers: MutableList = mutableListOf() + for ((signature, members) in membersBySignature) { + val newNode = mergeMembersWithEqualSignature(signature, from, members) + + producedNodeRefGraph.register(signature, newNode) + updatePendingReferences() + from.append(newNode, RefKind.Member) + + mergedMembers.add(DocumentationReference(from, newNode, RefKind.Member)) + } + + return mergedMembers + } + + private fun mergeMembersWithEqualSignature( + signature: String, + from: DocumentationNode, + refs: List + ): DocumentationNode { + val singleNode = refs.singleOrNull() + if (singleNode != null) { + singleNode.owner?.let { owner -> + singleNode.dropReferences { it.to == owner && it.kind == RefKind.Owner } + } + return singleNode + } + val groupNode = DocumentationNode(refs.first().name, Content.Empty, NodeKind.GroupNode) + groupNode.appendTextNode(signature, NodeKind.Signature, RefKind.Detail) + + for (node in refs) { + if (node != groupNode) { + node.owner?.let { owner -> + node.dropReferences { it.to == owner && it.kind == RefKind.Owner } + from.dropReferences { it.to == node && it.kind == RefKind.Member } + } + groupNode.append(node, RefKind.Member) + + oldToNewNodeMap[node] = groupNode + } + } + return groupNode + } + + + private fun mergeReferences( + from: DocumentationNode, + refs: List + ): List { + val (refsToPackages, usualRefs) = refs.partition { it.to.kind == NodeKind.Package } + val mergedPackages = mergePackageReferences(from, refsToPackages) + + val (refsToMembers, refsNotToMembers) = usualRefs.partition { it.kind == RefKind.Member } + val mergedMembers = mergeMembers(from, refsToMembers) + + // TODO: think about + return mergedPackages + (mergedMembers + refsNotToMembers).distinctBy { + it.to.kind to it.to.name + } + } + + + private fun updatePendingReferences() { + producedNodeRefGraph.references.forEach { + it.lazyNodeFrom.update() + it.lazyNodeTo.update() + } + } + + private fun NodeResolver.update() { + if (this is NodeResolver.Exact) { + if (exactNode != null && oldToNewNodeMap.containsKey(exactNode!!)) { + exactNode = oldToNewNodeMap[exactNode!!] + } + } + } + + fun merge(): DocumentationModule { + val mergedDocumentationModule = DocumentationModule( + name = documentationModules.first().name, + nodeRefGraph = producedNodeRefGraph + ) + + val refs = documentationModules.flatMap { + it.allReferences() + } + mergeReferences(mergedDocumentationModule, refs) + + return mergedDocumentationModule + } + + +} \ No newline at end of file diff --git a/core/src/main/kotlin/Generation/DokkaGenerator.kt b/core/src/main/kotlin/Generation/DokkaGenerator.kt index 22d1519f..37f62ed6 100644 --- a/core/src/main/kotlin/Generation/DokkaGenerator.kt +++ b/core/src/main/kotlin/Generation/DokkaGenerator.kt @@ -7,6 +7,7 @@ import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.psi.PsiFile import com.intellij.psi.PsiJavaFile import com.intellij.psi.PsiManager +import org.jetbrains.dokka.Generation.DocumentationMerger import org.jetbrains.dokka.Utilities.DokkaAnalysisModule import org.jetbrains.dokka.Utilities.DokkaOutputModule import org.jetbrains.dokka.Utilities.DokkaRunModule @@ -82,8 +83,8 @@ class DokkaGenerator(val dokkaConfiguration: DokkaConfiguration, DokkaAnalysisModule(environment, dokkaConfiguration, defaultPlatformsProvider, documentationModule.nodeRefGraph, passConfiguration, logger)) buildDocumentationModule(injector, documentationModule, { isNotSample(it, passConfiguration.samples) }, includes) - documentationModule.nodeRefGraph.nodeMapView.forEach { (_, node) -> // FIXME: change to full graph visiting - node.addReferenceTo( + documentationModule.visit { it -> + it.addReferenceTo( DocumentationNode(analysisPlatform.key, Content.Empty, NodeKind.Platform), RefKind.Platform ) @@ -95,7 +96,19 @@ class DokkaGenerator(val dokkaConfiguration: DokkaConfiguration, Disposer.dispose(environment) } - fun createAnalysisEnvironment(sourcePaths: List, passConfiguration: DokkaConfiguration.PassConfiguration): AnalysisEnvironment { + private fun DocumentationNode.visit(action: (DocumentationNode) -> Unit) { + action(this) + + for (member in members) { + member.visit(action) + } + } + + + fun createAnalysisEnvironment( + sourcePaths: List, + passConfiguration: DokkaConfiguration.PassConfiguration + ): AnalysisEnvironment { val environment = AnalysisEnvironment(DokkaMessageCollector(logger), passConfiguration.analysisPlatform) environment.apply { @@ -116,7 +129,7 @@ class DokkaGenerator(val dokkaConfiguration: DokkaConfiguration, return environment } - fun isNotSample(file: PsiFile, samples: List): Boolean { + private fun isNotSample(file: PsiFile, samples: List): Boolean { val sourceFile = File(file.virtualFile!!.path) return samples.none { sample -> val canonicalSample = File(sample).canonicalPath @@ -155,9 +168,7 @@ fun buildDocumentationModule(injector: Injector, val analyzer = resolutionFacade.getFrontendService(LazyTopDownAnalyzer::class.java) analyzer.analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, fragmentFiles) - val fragments = fragmentFiles - .map { resolutionFacade.resolveSession.getPackageFragment(it.packageFqName) } - .filterNotNull() + val fragments = fragmentFiles.mapNotNull { resolutionFacade.resolveSession.getPackageFragment(it.packageFqName) } .distinct() val packageDocs = injector.getInstance(PackageDocs::class.java) @@ -220,206 +231,4 @@ fun KotlinCoreEnvironment.getJavaSourceFiles(): List { } } return result -} - -class DocumentationMerger( - private val documentationModules: List -) { - private val producedNodeRefGraph: NodeReferenceGraph - private val signatureMap: Map - - init { - signatureMap = documentationModules - .flatMap { it.nodeRefGraph.nodeMapView.entries } - .map { (k, v) -> v to k } - .toMap() - - producedNodeRefGraph = NodeReferenceGraph() - documentationModules.map { it.nodeRefGraph } - .flatMap { it.references } - .distinct() - .forEach { producedNodeRefGraph.addReference(it) } - } - - private fun splitReferencesByKind( - source: List, - kind: RefKind - ): Pair, List> = - Pair(source.filter { it.kind == kind }, source.filterNot { it.kind == kind }) - - - private fun mergePackageReferences( - from: DocumentationNode, - packages: List - ): List { - val packagesByName = packages - .map { it.to } - .groupBy { it.name } - - val mutableList: MutableList = mutableListOf() - for ((name, listOfPackages) in packagesByName) { - val producedPackage = mergePackagesWithEqualNames(from, listOfPackages) - updatePendingReferences(name, producedPackage) - - mutableList.add( - DocumentationReference(from, producedPackage, RefKind.Member) - ) - } - - return mutableList - } - - private fun mergePackagesWithEqualNames( - from: DocumentationNode, - packages: List - ): DocumentationNode { - val references = packages.flatMap { it.allReferences() } - - val mergedPackage = - DocumentationNode( - packages.first().name, - Content.Empty, - NodeKind.Package - ) - - val mergedReferences = mergeReferences(mergedPackage, references) - - for (packageNode in packages) { - mergedPackage.updateContent { - for (otherChild in packageNode.content.children) { - children.add(otherChild) - } - } - } - - mergedPackage.dropReferences { true } // clear() - for (ref in mergedReferences.distinct()) { - mergedPackage.addReference(ref) - } - - from.append(mergedPackage, RefKind.Member) - - return mergedPackage - } - - - private fun mergeMembers( - from: DocumentationNode, - refs: List - ): List { - val membersBySignature: Map> = refs.map { it.to } - .filter { signatureMap.containsKey(it) } - .groupBy { signatureMap[it]!! } - - val mergedMembers: MutableList = mutableListOf() - for ((signature, members) in membersBySignature) { - val newNode = mergeMembersWithEqualSignature(signature, from, members) - - producedNodeRefGraph.register(signature, newNode) - updatePendingReferences(signature, newNode) - from.append(newNode, RefKind.Member) - - mergedMembers.add(DocumentationReference(from, newNode, RefKind.Member)) - } - - return mergedMembers - } - - private fun mergeMembersWithEqualSignature( - signature: String, - from: DocumentationNode, - refs: List - ): DocumentationNode { - if (refs.size == 1) { - val singleNode = refs.single() - singleNode.owner?.let { owner -> - singleNode.dropReferences { it.to == owner && it.kind == RefKind.Owner } - } - return singleNode - } - val groupNode = DocumentationNode(refs.first().name, Content.Empty, NodeKind.GroupNode) - groupNode.appendTextNode(signature, NodeKind.Signature, RefKind.Detail) - - for (node in refs) { - if (node != groupNode) { - node.owner?.let { owner -> - node.dropReferences { it.to == owner && it.kind == RefKind.Owner } - from.dropReferences { it.to == node && it.kind == RefKind.Member } - } - groupNode.append(node, RefKind.Member) - } - } - return groupNode - } - - - private fun mergeReferences( - from: DocumentationNode, - refs: List - ): List { - val allRefsToPackages = refs.map { it.to } - .all { it.kind == NodeKind.Package } - - if (allRefsToPackages) { - return mergePackageReferences(from, refs) - } - - val (memberRefs, notMemberRefs) = splitReferencesByKind(refs, RefKind.Member) - val mergedMembers = mergeMembers(from, memberRefs) - - return (mergedMembers + notMemberRefs).distinctBy { - it.kind to it.to.name - } - } - - - private fun updatePendingReferences( - signature: String, - nodeToUpdate: DocumentationNode - ) { - producedNodeRefGraph.references.forEach { - it.lazyNodeFrom.update(signature, nodeToUpdate) - it.lazyNodeTo.update(signature, nodeToUpdate) - } - } - - private fun NodeResolver.update(signature: String, nodeToUpdate: DocumentationNode) { - when (this) { - is NodeResolver.BySignature -> update(signature, nodeToUpdate) - is NodeResolver.Exact -> update(signature, nodeToUpdate) - } - } - - private fun NodeResolver.BySignature.update(signature: String, nodeToUpdate: DocumentationNode) { - if (signature == nodeToUpdate.name) { - nodeMap = producedNodeRefGraph.nodeMapView - } - } - - private fun NodeResolver.Exact.update(signature: String, nodeToUpdate: DocumentationNode) { - exactNode?.let { it -> - val equalSignature = - it.anyReference { ref -> ref.to.kind == NodeKind.Signature && ref.to.name == signature } - - if (equalSignature) { - exactNode = nodeToUpdate - } - } - } - - fun merge(): DocumentationModule { - val refs = documentationModules.flatMap { - it.allReferences() - } - val mergedDocumentationModule = DocumentationModule( - name = documentationModules.first().name, - nodeRefGraph = producedNodeRefGraph - ) - - mergeReferences(mergedDocumentationModule, refs) - - return mergedDocumentationModule - } - - } \ No newline at end of file diff --git a/core/src/main/kotlin/Generation/FileGenerator.kt b/core/src/main/kotlin/Generation/FileGenerator.kt index eb6800b3..d7b35581 100644 --- a/core/src/main/kotlin/Generation/FileGenerator.kt +++ b/core/src/main/kotlin/Generation/FileGenerator.kt @@ -10,7 +10,7 @@ import java.io.OutputStreamWriter class FileGenerator @Inject constructor(@Named("outputDir") override val root: File) : NodeLocationAwareGenerator { @set:Inject(optional = true) var outlineService: OutlineFormatService? = null - @set:Inject(optional = true) lateinit var formatService: FormatService + @set:Inject lateinit var formatService: FormatService @set:Inject(optional = true) lateinit var dokkaConfiguration: DokkaConfiguration @set:Inject(optional = true) var packageListService: PackageListService? = null diff --git a/core/src/main/kotlin/Generation/configurationImpl.kt b/core/src/main/kotlin/Generation/configurationImpl.kt index 3e39b4ed..f2a91002 100644 --- a/core/src/main/kotlin/Generation/configurationImpl.kt +++ b/core/src/main/kotlin/Generation/configurationImpl.kt @@ -26,7 +26,6 @@ class SourceRootImpl(path: String, override val platforms: List = emptyL fun parseSourceRoot(sourceRoot: String): SourceRoot { val components = sourceRoot.split("::", limit = 2) - // TODO: create syntax for cli val platform = if (components.size == 1) { Platform.DEFAULT } else { diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index fb0b898a..be3eef71 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -1097,7 +1097,7 @@ fun DocumentationNode.generateAllTypesNode() { val allTypes = members(NodeKind.Package) .flatMap { it.members.filter { it.kind in NodeKind.classLike || it.kind == NodeKind.ExternalClass - || (it.kind == NodeKind.GroupNode && it.anyReference { it.to.kind in NodeKind.classLike }) } } + || (it.kind == NodeKind.GroupNode && it.members.all { it.kind in NodeKind.classLike }) } } .sortedBy { if (it.kind == NodeKind.ExternalClass) it.name.substringAfterLast('.').toLowerCase() else it.name.toLowerCase() } val allTypesNode = DocumentationNode("alltypes", Content.Empty, NodeKind.AllTypes) diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index bdb7cf20..23137364 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -163,7 +163,6 @@ open class DocumentationNode(val name: String, fun member(kind: NodeKind): DocumentationNode = members.filter { it.kind == kind }.single() fun link(kind: NodeKind): DocumentationNode = links.filter { it.kind == kind }.single() - fun anyReference(predicate: (DocumentationReference) -> Boolean): Boolean = references.any(predicate) fun references(kind: RefKind): List = references.filter { it.kind == kind } fun allReferences(): Set = references diff --git a/core/src/main/kotlin/Model/DocumentationReference.kt b/core/src/main/kotlin/Model/DocumentationReference.kt index 9223c17a..282d87d8 100644 --- a/core/src/main/kotlin/Model/DocumentationReference.kt +++ b/core/src/main/kotlin/Model/DocumentationReference.kt @@ -26,15 +26,15 @@ data class DocumentationReference(val from: DocumentationNode, val to: Documenta } sealed class NodeResolver { - abstract fun resolve(): DocumentationNode? - class BySignature(var signature: String, var nodeMap: Map) : NodeResolver() { - override fun resolve(): DocumentationNode? { - return nodeMap[signature] + abstract fun resolve(nodeRephGraph: NodeReferenceGraph): DocumentationNode? + class BySignature(var signature: String) : NodeResolver() { + override fun resolve(nodeRephGraph: NodeReferenceGraph): DocumentationNode? { + return nodeRephGraph.lookup(signature) } } class Exact(var exactNode: DocumentationNode?) : NodeResolver() { - override fun resolve(): DocumentationNode? { + override fun resolve(nodeRephGraph: NodeReferenceGraph): DocumentationNode? { return exactNode } } @@ -43,9 +43,9 @@ sealed class NodeResolver { class PendingDocumentationReference(val lazyNodeFrom: NodeResolver, val lazyNodeTo: NodeResolver, val kind: RefKind) { - fun resolve() { - val fromNode = lazyNodeFrom.resolve() - val toNode = lazyNodeTo.resolve() + fun resolve(nodeRephGraph: NodeReferenceGraph) { + val fromNode = lazyNodeFrom.resolve(nodeRephGraph) + val toNode = lazyNodeTo.resolve(nodeRephGraph) if (fromNode != null && toNode != null) { fromNode.addReferenceTo(toNode, kind) } @@ -67,7 +67,7 @@ class NodeReferenceGraph { references.add( PendingDocumentationReference( NodeResolver.Exact(fromNode), - NodeResolver.BySignature(toSignature, nodeMap), + NodeResolver.BySignature(toSignature), kind )) } @@ -75,7 +75,7 @@ class NodeReferenceGraph { fun link(fromSignature: String, toNode: DocumentationNode, kind: RefKind) { references.add( PendingDocumentationReference( - NodeResolver.BySignature(fromSignature, nodeMap), + NodeResolver.BySignature(fromSignature), NodeResolver.Exact(toNode), kind ) @@ -85,8 +85,8 @@ class NodeReferenceGraph { fun link(fromSignature: String, toSignature: String, kind: RefKind) { references.add( PendingDocumentationReference( - NodeResolver.BySignature(fromSignature, nodeMap), - NodeResolver.BySignature(toSignature, nodeMap), + NodeResolver.BySignature(fromSignature), + NodeResolver.BySignature(toSignature), kind ) ) @@ -107,7 +107,7 @@ class NodeReferenceGraph { } fun resolveReferences() { - references.forEach { it.resolve() } + references.forEach { it.resolve(this) } } } -- cgit From 4456ead8b702e4881321488969cb4ce1711e5663 Mon Sep 17 00:00:00 2001 From: aleksZubakov Date: Mon, 6 Aug 2018 17:14:28 +0300 Subject: Optional dependency bug workaround: google/guice#847 --- core/src/main/kotlin/Formats/FormatDescriptor.kt | 1 + core/src/main/kotlin/Generation/FileGenerator.kt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'core/src/main/kotlin/Generation') diff --git a/core/src/main/kotlin/Formats/FormatDescriptor.kt b/core/src/main/kotlin/Formats/FormatDescriptor.kt index b497fb0f..4bac8aa0 100644 --- a/core/src/main/kotlin/Formats/FormatDescriptor.kt +++ b/core/src/main/kotlin/Formats/FormatDescriptor.kt @@ -25,6 +25,7 @@ abstract class FileGeneratorBasedFormatDescriptor : FormatDescriptor { override fun configureOutput(binder: Binder): Unit = with(binder) { bind() toType NodeLocationAwareGenerator::class bind() toType generatorServiceClass + bind(generatorServiceClass.java) // https://github.com/google/guice/issues/847 bind() toType languageServiceClass diff --git a/core/src/main/kotlin/Generation/FileGenerator.kt b/core/src/main/kotlin/Generation/FileGenerator.kt index d7b35581..eb6800b3 100644 --- a/core/src/main/kotlin/Generation/FileGenerator.kt +++ b/core/src/main/kotlin/Generation/FileGenerator.kt @@ -10,7 +10,7 @@ import java.io.OutputStreamWriter class FileGenerator @Inject constructor(@Named("outputDir") override val root: File) : NodeLocationAwareGenerator { @set:Inject(optional = true) var outlineService: OutlineFormatService? = null - @set:Inject lateinit var formatService: FormatService + @set:Inject(optional = true) lateinit var formatService: FormatService @set:Inject(optional = true) lateinit var dokkaConfiguration: DokkaConfiguration @set:Inject(optional = true) var packageListService: PackageListService? = null -- cgit From 1f45cac76a79abb6eaad99b541234cbf34fbce9c Mon Sep 17 00:00:00 2001 From: Zubakov Aleksey Date: Fri, 17 Aug 2018 13:00:06 +0300 Subject: Merger platforms bug fix, refactoring --- .../main/kotlin/Formats/StructuredFormatService.kt | 2 + .../main/kotlin/Generation/DocumentationMerger.kt | 58 ++++++++-------------- core/src/main/kotlin/Generation/DokkaGenerator.kt | 19 +------ .../src/main/kotlin/Kotlin/DocumentationBuilder.kt | 23 ++++++--- 4 files changed, 42 insertions(+), 60 deletions(-) (limited to 'core/src/main/kotlin/Generation') diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index 41c8f29a..b810dfca 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -404,6 +404,8 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, 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() } diff --git a/core/src/main/kotlin/Generation/DocumentationMerger.kt b/core/src/main/kotlin/Generation/DocumentationMerger.kt index c2089821..c4a40df6 100644 --- a/core/src/main/kotlin/Generation/DocumentationMerger.kt +++ b/core/src/main/kotlin/Generation/DocumentationMerger.kt @@ -22,7 +22,6 @@ class DocumentationMerger( producedNodeRefGraph = NodeReferenceGraph() documentationModules.map { it.nodeRefGraph } .flatMap { it.references } - .distinct() .forEach { producedNodeRefGraph.addReference(it) } } @@ -30,7 +29,6 @@ class DocumentationMerger( from: DocumentationNode, packages: List ): List { - val packagesByName = packages .map { it.to } .groupBy { it.name } @@ -63,11 +61,13 @@ class DocumentationMerger( } oldToNewNodeMap[packageNode] = mergedPackage } - mergedPackage.clear() val references = packages.flatMap { it.allReferences() } val mergedReferences = mergeReferences(mergedPackage, references) - for (ref in mergedReferences.distinct()) { + for (ref in mergedReferences) { + if (ref.kind == RefKind.Owner) { + continue + } mergedPackage.addReference(ref) } @@ -76,8 +76,6 @@ class DocumentationMerger( return mergedPackage } - private fun DocumentationNode.clear() = dropReferences { true } - private fun mergeMembers( from: DocumentationNode, refs: List @@ -106,24 +104,17 @@ class DocumentationMerger( ): DocumentationNode { val singleNode = refs.singleOrNull() if (singleNode != null) { - singleNode.owner?.let { owner -> - singleNode.dropReferences { it.to == owner && it.kind == RefKind.Owner } - } + singleNode.dropReferences { it.kind == RefKind.Owner } return singleNode } val groupNode = DocumentationNode(refs.first().name, Content.Empty, NodeKind.GroupNode) groupNode.appendTextNode(signature, NodeKind.Signature, RefKind.Detail) for (node in refs) { - if (node != groupNode) { - node.owner?.let { owner -> - node.dropReferences { it.to == owner && it.kind == RefKind.Owner } - from.dropReferences { it.to == node && it.kind == RefKind.Member } - } - groupNode.append(node, RefKind.Member) + node.dropReferences { it.kind == RefKind.Owner } + groupNode.append(node, RefKind.Member) - oldToNewNodeMap[node] = groupNode - } + oldToNewNodeMap[node] = groupNode } return groupNode } @@ -140,25 +131,7 @@ class DocumentationMerger( val mergedMembers = mergeMembers(from, refsToMembers) // TODO: think about - return mergedPackages + (mergedMembers + refsNotToMembers).distinctBy { - it.to.kind to it.to.name - } - } - - - private fun updatePendingReferences() { - producedNodeRefGraph.references.forEach { - it.lazyNodeFrom.update() - it.lazyNodeTo.update() - } - } - - private fun NodeResolver.update() { - if (this is NodeResolver.Exact) { - if (exactNode != null && oldToNewNodeMap.containsKey(exactNode!!)) { - exactNode = oldToNewNodeMap[exactNode!!] - } - } + return mergedPackages + mergedMembers + refsNotToMembers } fun merge(): DocumentationModule { @@ -175,5 +148,18 @@ class DocumentationMerger( return mergedDocumentationModule } + private fun updatePendingReferences() { + for (ref in producedNodeRefGraph.references) { + ref.lazyNodeFrom.update() + ref.lazyNodeTo.update() + } + } + private fun NodeResolver.update() { + if (this is NodeResolver.Exact) { + if (exactNode != null && exactNode!! in oldToNewNodeMap) { + exactNode = oldToNewNodeMap[exactNode!!] + } + } + } } \ No newline at end of file diff --git a/core/src/main/kotlin/Generation/DokkaGenerator.kt b/core/src/main/kotlin/Generation/DokkaGenerator.kt index 37f62ed6..1193657e 100644 --- a/core/src/main/kotlin/Generation/DokkaGenerator.kt +++ b/core/src/main/kotlin/Generation/DokkaGenerator.kt @@ -69,13 +69,13 @@ class DokkaGenerator(val dokkaConfiguration: DokkaConfiguration, logger.info("Analysing sources and libraries... ") val startAnalyse = System.currentTimeMillis() - val defaultPlatformAsList = listOf(passConfiguration.analysisPlatform.key) + val defaultPlatformAsList = passConfiguration.targets val defaultPlatformsProvider = object : DefaultPlatformsProvider { override fun getDefaultPlatforms(descriptor: DeclarationDescriptor): List { val containingFilePath = descriptor.sourcePsi()?.containingFile?.virtualFile?.canonicalPath ?.let { File(it).absolutePath } val sourceRoot = containingFilePath?.let { path -> sourceRoots.find { path.startsWith(it.path) } } - return sourceRoot?.platforms ?: defaultPlatformAsList + return /*sourceRoot?.platforms ?: */defaultPlatformAsList } } @@ -83,12 +83,6 @@ class DokkaGenerator(val dokkaConfiguration: DokkaConfiguration, DokkaAnalysisModule(environment, dokkaConfiguration, defaultPlatformsProvider, documentationModule.nodeRefGraph, passConfiguration, logger)) buildDocumentationModule(injector, documentationModule, { isNotSample(it, passConfiguration.samples) }, includes) - documentationModule.visit { it -> - it.addReferenceTo( - DocumentationNode(analysisPlatform.key, Content.Empty, NodeKind.Platform), - RefKind.Platform - ) - } val timeAnalyse = System.currentTimeMillis() - startAnalyse logger.info("done in ${timeAnalyse / 1000} secs") @@ -96,15 +90,6 @@ class DokkaGenerator(val dokkaConfiguration: DokkaConfiguration, Disposer.dispose(environment) } - private fun DocumentationNode.visit(action: (DocumentationNode) -> Unit) { - action(this) - - for (member in members) { - member.visit(action) - } - } - - fun createAnalysisEnvironment( sourcePaths: List, passConfiguration: DokkaConfiguration.PassConfiguration diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index be3eef71..c25a7069 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -889,23 +889,27 @@ class DocumentationBuilder } - fun DocumentationNode.getParentForPackageMember(descriptor: DeclarationDescriptor, - externalClassNodes: MutableMap, - allFqNames: Collection): DocumentationNode { + fun DocumentationNode.getParentForPackageMember( + descriptor: DeclarationDescriptor, + externalClassNodes: MutableMap, + allFqNames: Collection, + packageName: FqName + ): DocumentationNode { if (descriptor is CallableMemberDescriptor) { val extensionClassDescriptor = descriptor.getExtensionClassDescriptor() if (extensionClassDescriptor != null && isExtensionForExternalClass(descriptor, extensionClassDescriptor, allFqNames) && !ErrorUtils.isError(extensionClassDescriptor)) { val fqName = DescriptorUtils.getFqNameSafe(extensionClassDescriptor) - return externalClassNodes.getOrPut(fqName, { + return externalClassNodes.getOrPut(fqName) { val newNode = DocumentationNode(fqName.asString(), Content.Empty, NodeKind.ExternalClass) val externalLink = linkResolver.externalDocumentationLinkResolver.buildExternalDocumentationLink(extensionClassDescriptor) if (externalLink != null) { newNode.append(DocumentationNode(externalLink, Content.Empty, NodeKind.ExternalLink), RefKind.Link) } append(newNode, RefKind.Member) + refGraph.register("${packageName.asString()}:${extensionClassDescriptor.signature()}", newNode) newNode - }) + } } } return this @@ -933,7 +937,12 @@ class KotlinPackageDocumentationBuilder : PackageDocumentationBuilder { declarations.forEach { descriptor -> with(documentationBuilder) { if (descriptor.isDocumented(passConfiguration)) { - val parent = packageNode.getParentForPackageMember(descriptor, externalClassNodes, allFqNames) + val parent = packageNode.getParentForPackageMember( + descriptor, + externalClassNodes, + allFqNames, + packageName + ) parent.appendOrUpdateMember(descriptor) } } @@ -1025,7 +1034,7 @@ fun DeclarationDescriptor.signature(): String { is TypeAliasDescriptor -> DescriptorUtils.getFqName(this).asString() is PropertyDescriptor -> containingDeclaration.signature() + "$" + name + receiverSignature() - is FunctionDescriptor -> containingDeclaration.signature() + "$" + name + parameterSignature() + ":" + returnType?.signature() + is FunctionDescriptor -> containingDeclaration.signature() + "$" + name + parameterSignature() + ":" + returnType?.signature() is ValueParameterDescriptor -> containingDeclaration.signature() + "/" + name is TypeParameterDescriptor -> containingDeclaration.signature() + "*" + name is ReceiverParameterDescriptor -> containingDeclaration.signature() + "/" + name -- cgit From 0b43db4ff81746e44d06780d8d14bb49dc1d87aa Mon Sep 17 00:00:00 2001 From: Zubakov Date: Mon, 27 Aug 2018 16:27:41 +0300 Subject: Introduce origin reference kind, change documentation graph merge logic, minor refactoring --- .../main/kotlin/Formats/StructuredFormatService.kt | 28 +++++----- .../main/kotlin/Generation/DocumentationMerger.kt | 65 +++++++++++++--------- .../src/main/kotlin/Kotlin/DocumentationBuilder.kt | 2 +- core/src/main/kotlin/Model/DocumentationNode.kt | 4 ++ .../main/kotlin/Model/DocumentationReference.kt | 5 +- 5 files changed, 61 insertions(+), 43 deletions(-) (limited to 'core/src/main/kotlin/Generation') diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index b810dfca..1ca636ec 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -192,22 +192,20 @@ 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 = + FormatLink(name(to), from.location().relativePathTo(to.location())) - 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) - - if (from.owner?.kind == NodeKind.GroupNode) - return link(from.owner!!, to, extension, name) - - return FormatLink(name(to), from.location().relativePathTo(to.location())) - } fun locationHref(from: Location, to: DocumentationNode): String { val topLevelPage = to.references(RefKind.TopLevelPage).singleOrNull()?.to diff --git a/core/src/main/kotlin/Generation/DocumentationMerger.kt b/core/src/main/kotlin/Generation/DocumentationMerger.kt index c4a40df6..0394dce2 100644 --- a/core/src/main/kotlin/Generation/DocumentationMerger.kt +++ b/core/src/main/kotlin/Generation/DocumentationMerger.kt @@ -5,7 +5,7 @@ import org.jetbrains.dokka.* class DocumentationMerger( private val documentationModules: List ) { - private val producedNodeRefGraph: NodeReferenceGraph + private val producedNodeRefGraph: NodeReferenceGraph = NodeReferenceGraph() private val signatureMap: Map private val oldToNewNodeMap: MutableMap = mutableMapOf() @@ -19,7 +19,6 @@ class DocumentationMerger( .associate { (k, v) -> v to k } - producedNodeRefGraph = NodeReferenceGraph() documentationModules.map { it.nodeRefGraph } .flatMap { it.references } .forEach { producedNodeRefGraph.addReference(it) } @@ -33,17 +32,17 @@ class DocumentationMerger( .map { it.to } .groupBy { it.name } - val mutableList = mutableListOf() + val resultReferences = mutableListOf() for ((name, listOfPackages) in packagesByName) { val producedPackage = mergePackagesWithEqualNames(name, from, listOfPackages) updatePendingReferences() - mutableList.add( + resultReferences.add( DocumentationReference(from, producedPackage, RefKind.Member) ) } - return mutableList + return resultReferences } private fun mergePackagesWithEqualNames( @@ -52,14 +51,17 @@ class DocumentationMerger( packages: List ): DocumentationNode { val mergedPackage = DocumentationNode(name, Content.Empty, NodeKind.Package) - for (packageNode in packages) { - // TODO: Discuss + + for (contentToAppend in packages.map { it.content }.distinct()) { mergedPackage.updateContent { - for (otherChild in packageNode.content.children) { + for (otherChild in contentToAppend.children) { children.add(otherChild) } } - oldToNewNodeMap[packageNode] = mergedPackage + } + + for (node in packages) { + oldToNewNodeMap[node] = mergedPackage } val references = packages.flatMap { it.allReferences() } @@ -76,7 +78,7 @@ class DocumentationMerger( return mergedPackage } - private fun mergeMembers( + private fun mergeMemberReferences( from: DocumentationNode, refs: List ): List { @@ -85,7 +87,7 @@ class DocumentationMerger( val mergedMembers: MutableList = mutableListOf() for ((signature, members) in membersBySignature) { - val newNode = mergeMembersWithEqualSignature(signature, from, members) + val newNode = mergeMembersWithEqualSignature(signature, members) producedNodeRefGraph.register(signature, newNode) updatePendingReferences() @@ -99,23 +101,39 @@ class DocumentationMerger( private fun mergeMembersWithEqualSignature( signature: String, - from: DocumentationNode, - refs: List + nodes: List ): DocumentationNode { - val singleNode = refs.singleOrNull() + val singleNode = nodes.singleOrNull() if (singleNode != null) { singleNode.dropReferences { it.kind == RefKind.Owner } return singleNode } - val groupNode = DocumentationNode(refs.first().name, Content.Empty, NodeKind.GroupNode) + + val groupNode = DocumentationNode(nodes.first().name, Content.Empty, NodeKind.GroupNode) groupNode.appendTextNode(signature, NodeKind.Signature, RefKind.Detail) - for (node in refs) { + for (node in nodes) { node.dropReferences { it.kind == RefKind.Owner } - groupNode.append(node, RefKind.Member) + groupNode.append(node, RefKind.Origin) oldToNewNodeMap[node] = groupNode } + + // if nodes are classes, nested members should be also merged and + // inserted at the same level with class + if (nodes.all { it.kind == NodeKind.Class }) { + val members = nodes.flatMap { it.allReferences() }.filter { it.kind == RefKind.Member } + val mergedMembers = mergeMemberReferences(groupNode, members) + + for (ref in mergedMembers) { + if (ref.kind == RefKind.Owner) { + continue + } + + groupNode.append(ref.to, RefKind.Member) + } + } + return groupNode } @@ -124,13 +142,12 @@ class DocumentationMerger( from: DocumentationNode, refs: List ): List { - val (refsToPackages, usualRefs) = refs.partition { it.to.kind == NodeKind.Package } + val (refsToPackages, otherRefs) = refs.partition { it.to.kind == NodeKind.Package } val mergedPackages = mergePackageReferences(from, refsToPackages) - val (refsToMembers, refsNotToMembers) = usualRefs.partition { it.kind == RefKind.Member } - val mergedMembers = mergeMembers(from, refsToMembers) + val (refsToMembers, refsNotToMembers) = otherRefs.partition { it.kind == RefKind.Member } + val mergedMembers = mergeMemberReferences(from, refsToMembers) - // TODO: think about return mergedPackages + mergedMembers + refsNotToMembers } @@ -156,10 +173,8 @@ class DocumentationMerger( } private fun NodeResolver.update() { - if (this is NodeResolver.Exact) { - if (exactNode != null && exactNode!! in oldToNewNodeMap) { - exactNode = oldToNewNodeMap[exactNode!!] - } + if (this is NodeResolver.Exact && exactNode in oldToNewNodeMap) { + exactNode = oldToNewNodeMap[exactNode]!! } } } \ No newline at end of file diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index c25a7069..e5bc32ab 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -1106,7 +1106,7 @@ fun DocumentationNode.generateAllTypesNode() { val allTypes = members(NodeKind.Package) .flatMap { it.members.filter { it.kind in NodeKind.classLike || it.kind == NodeKind.ExternalClass - || (it.kind == NodeKind.GroupNode && it.members.all { it.kind in NodeKind.classLike }) } } + || (it.kind == NodeKind.GroupNode && it.origins.all { it.kind in NodeKind.classLike }) } } .sortedBy { if (it.kind == NodeKind.ExternalClass) it.name.substringAfterLast('.').toLowerCase() else it.name.toLowerCase() } val allTypesNode = DocumentationNode("alltypes", Content.Empty, NodeKind.AllTypes) diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index 23137364..146c1e99 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -84,6 +84,9 @@ open class DocumentationNode(val name: String, get() = references(RefKind.Detail).map { it.to } val members: List get() = references(RefKind.Member).map { it.to } + val origins: List + get() = references(RefKind.Origin).map { it.to } + val inheritedMembers: List get() = references(RefKind.InheritedMember).map { it.to } val allInheritedMembers: List @@ -203,6 +206,7 @@ fun DocumentationNode.append(child: DocumentationNode, kind: RefKind) { RefKind.Detail -> child.addReferenceTo(this, RefKind.Owner) RefKind.Member -> child.addReferenceTo(this, RefKind.Owner) RefKind.Owner -> child.addReferenceTo(this, RefKind.Member) + RefKind.Origin -> child.addReferenceTo(this, RefKind.Owner) else -> { /* Do not add any links back for other types */ } } diff --git a/core/src/main/kotlin/Model/DocumentationReference.kt b/core/src/main/kotlin/Model/DocumentationReference.kt index 282d87d8..e10796d2 100644 --- a/core/src/main/kotlin/Model/DocumentationReference.kt +++ b/core/src/main/kotlin/Model/DocumentationReference.kt @@ -19,7 +19,8 @@ enum class RefKind { Deprecation, TopLevelPage, Platform, - ExternalType + ExternalType, + Origin } data class DocumentationReference(val from: DocumentationNode, val to: DocumentationNode, val kind: RefKind) { @@ -33,7 +34,7 @@ sealed class NodeResolver { } } - class Exact(var exactNode: DocumentationNode?) : NodeResolver() { + class Exact(var exactNode: DocumentationNode) : NodeResolver() { override fun resolve(nodeRephGraph: NodeReferenceGraph): DocumentationNode? { return exactNode } -- cgit From a4ae451279b4f89b9994d333c6d6d88a0868c5e4 Mon Sep 17 00:00:00 2001 From: Zubakov Date: Mon, 27 Aug 2018 21:35:29 +0300 Subject: Drop unnecessary properties in SourceRoot --- core/src/main/kotlin/Generation/configurationImpl.kt | 15 ++------------- .../src/main/kotlin/org/jetbrains/dokka/configuration.kt | 2 -- runners/ant/src/main/kotlin/ant/dokka.kt | 8 +++----- runners/gradle-plugin/src/main/kotlin/main.kt | 8 +------- runners/maven-plugin/src/main/kotlin/DokkaMojo.kt | 7 ------- 5 files changed, 6 insertions(+), 34 deletions(-) (limited to 'core/src/main/kotlin/Generation') diff --git a/core/src/main/kotlin/Generation/configurationImpl.kt b/core/src/main/kotlin/Generation/configurationImpl.kt index f2a91002..2aa0e0d7 100644 --- a/core/src/main/kotlin/Generation/configurationImpl.kt +++ b/core/src/main/kotlin/Generation/configurationImpl.kt @@ -18,22 +18,11 @@ data class SourceLinkDefinitionImpl(override val path: String, } } -class SourceRootImpl(path: String, override val platforms: List = emptyList(), - override val analysisPlatform: Platform = Platform.DEFAULT) : SourceRoot { +class SourceRootImpl(path: String) : SourceRoot { override val path: String = File(path).absolutePath companion object { - fun parseSourceRoot(sourceRoot: String): SourceRoot { - val components = sourceRoot.split("::", limit = 2) - - val platform = if (components.size == 1) { - Platform.DEFAULT - } else { - Platform.fromString(components[0]) - } - - return SourceRootImpl(components.last(), emptyList(), platform) - } + fun parseSourceRoot(sourceRoot: String): SourceRoot = SourceRootImpl(sourceRoot) } } diff --git a/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt b/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt index e0fa27d1..5f1f4bb0 100644 --- a/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt +++ b/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt @@ -73,8 +73,6 @@ interface DokkaConfiguration { interface SourceRoot { val path: String - val platforms: List - val analysisPlatform: Platform } interface SourceLinkDefinition { diff --git a/runners/ant/src/main/kotlin/ant/dokka.kt b/runners/ant/src/main/kotlin/ant/dokka.kt index 9428a7ce..8be9246f 100644 --- a/runners/ant/src/main/kotlin/ant/dokka.kt +++ b/runners/ant/src/main/kotlin/ant/dokka.kt @@ -17,11 +17,9 @@ class AntLogger(val task: Task): DokkaLogger { class AntSourceLinkDefinition(var path: String? = null, var url: String? = null, var lineSuffix: String? = null) -class AntSourceRoot(var path: String? = null, var platforms: String? = null, - var platform: Platform = Platform.DEFAULT) { - fun toSourceRoot(): SourceRootImpl? = path?.let { - path -> - SourceRootImpl(path, platforms?.split(',').orEmpty(), platform) +class AntSourceRoot(var path: String? = null) { + fun toSourceRoot(): SourceRootImpl? = path?.let { path -> + SourceRootImpl(path) } } diff --git a/runners/gradle-plugin/src/main/kotlin/main.kt b/runners/gradle-plugin/src/main/kotlin/main.kt index 9c8fd652..91639e11 100644 --- a/runners/gradle-plugin/src/main/kotlin/main.kt +++ b/runners/gradle-plugin/src/main/kotlin/main.kt @@ -403,13 +403,7 @@ class SourceRoot : DokkaConfiguration.SourceRoot, Serializable { field = File(value).absolutePath } - override var platforms: List = arrayListOf() - - override val analysisPlatform: Platform = Platform.DEFAULT - - override fun toString(): String { - return "${platforms.joinToString()}::$path" - } + override fun toString(): String = path } open class LinkMapping : Serializable, DokkaConfiguration.SourceLinkDefinition { diff --git a/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt b/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt index 78fd2d86..a2771306 100644 --- a/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt +++ b/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt @@ -36,13 +36,6 @@ abstract class AbstractDokkaMojo : AbstractMojo() { class SourceRoot : DokkaConfiguration.SourceRoot { @Parameter(required = true) override var path: String = "" - - @Parameter - override var platforms: List = emptyList() - - @Parameter - override var analysisPlatform: Platform = Platform.DEFAULT - } class PackageOptions : DokkaConfiguration.PackageOptions { -- cgit