From 93a9052d8434879f8fdf192d9d498285a6a31127 Mon Sep 17 00:00:00 2001 From: Zubakov Aleksey Date: Tue, 17 Jul 2018 17:13:01 +0300 Subject: NodeReferenceGraph style fixes --- core/src/main/kotlin/Model/DocumentationReference.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'core/src/main/kotlin/Model') diff --git a/core/src/main/kotlin/Model/DocumentationReference.kt b/core/src/main/kotlin/Model/DocumentationReference.kt index 89ec1b3e..5db1f05a 100644 --- a/core/src/main/kotlin/Model/DocumentationReference.kt +++ b/core/src/main/kotlin/Model/DocumentationReference.kt @@ -37,24 +37,24 @@ class PendingDocumentationReference(val lazyNodeFrom: () -> DocumentationNode?, } } -class NodeReferenceGraph() { +class NodeReferenceGraph { private val nodeMap = hashMapOf() val references = arrayListOf() fun register(signature: String, node: DocumentationNode) { - nodeMap.put(signature, node) + nodeMap[signature] = node } fun link(fromNode: DocumentationNode, toSignature: String, kind: RefKind) { - references.add(PendingDocumentationReference({ -> fromNode}, { -> nodeMap[toSignature]}, kind)) + references.add(PendingDocumentationReference({ fromNode }, { nodeMap[toSignature] }, kind)) } fun link(fromSignature: String, toNode: DocumentationNode, kind: RefKind) { - references.add(PendingDocumentationReference({ -> nodeMap[fromSignature]}, { -> toNode}, kind)) + references.add(PendingDocumentationReference({ nodeMap[fromSignature] }, { toNode }, kind)) } fun link(fromSignature: String, toSignature: String, kind: RefKind) { - references.add(PendingDocumentationReference({ -> nodeMap[fromSignature]}, { -> nodeMap[toSignature]}, kind)) + references.add(PendingDocumentationReference({ nodeMap[fromSignature] }, { nodeMap[toSignature] }, kind)) } fun lookup(signature: String) = nodeMap[signature] -- 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/Model') 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 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/Model') 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 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/Model') 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 0df19264ccae3d294946caf634ee15eea0c4fe4a Mon Sep 17 00:00:00 2001 From: Zubakov Date: Thu, 6 Sep 2018 19:44:50 +0300 Subject: Minor refactoring, kotlin-website format change: add platforms to summary signatures, platform evaluating logic change --- .../Formats/KotlinWebsiteHtmlFormatService.kt | 7 ++ .../main/kotlin/Formats/StructuredFormatService.kt | 123 +++++++++++++++------ core/src/main/kotlin/Model/DocumentationNode.kt | 6 +- 3 files changed, 103 insertions(+), 33 deletions(-) (limited to 'core/src/main/kotlin/Model') diff --git a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt index 6ced75b5..16bec5a6 100644 --- a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt +++ b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt @@ -169,6 +169,13 @@ open class KotlinWebsiteHtmlOutputBuilder( appendContent(section) } } + + override fun appendAsBlockWithPlatforms(platforms: Set, block: () -> Unit) { + if (platforms.isNotEmpty()) + wrap("", "", block) + else + block() + } } class KotlinWebsiteHtmlFormatService @Inject constructor( diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index b57f21be..53172563 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -83,6 +83,10 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } } + open fun appendAsBlockWithPlatforms(platforms: Set, block: () -> Unit) { + block() + } + open fun appendSymbol(text: String) { appendText(text) } @@ -465,6 +469,18 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, platformsToShow + protected fun mergeVersions(otherKotlinVersion: String, kotlinVersions: List): String { + val allKotlinVersions = (kotlinVersions + otherKotlinVersion).distinct() + + val minVersion = allKotlinVersions.min()!! + val resultVersion: String = when { + allKotlinVersions.size == 1 -> allKotlinVersions.single() + minVersion.endsWith("+") -> minVersion + else -> "$minVersion+" + } + + return resultVersion + } protected fun platformsOfItems(items: List): Set { val platforms = items.asSequence().map { @@ -486,19 +502,38 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, // When no Kotlin version specified, it means that version is 1.0 if (otherKotlinVersion != null && kotlinVersions.isNotEmpty()) { - val allKotlinVersions = (kotlinVersions + otherKotlinVersion).distinct() + result.intersect(platformsOfItem) + mergeVersions(otherKotlinVersion, kotlinVersions) + } else { + result.intersect(platformsOfItem) + } + } + } - val minVersion = allKotlinVersions.min()!! - val resultVersion = when { - allKotlinVersions.size == 1 -> allKotlinVersions.single() - minVersion.endsWith("+") -> minVersion - else -> "$minVersion+" - } + protected fun unionPlatformsOfItems(items: List): Set { + val platforms = items.asSequence().map { + when (it.kind) { + NodeKind.GroupNode -> unionPlatformsOfItems(it.origins) + else -> it.platformsToShow.toSet() + } + } + + fun String.isKotlinVersion() = this.startsWith("Kotlin") + + if (platforms.count() == 0) return emptySet() + + // Calculating common platforms for items + return platforms.reduce { result, platformsOfItem -> + val otherKotlinVersion = result.find { it.isKotlinVersion() } + val (kotlinVersions, otherPlatforms) = platformsOfItem.partition { it.isKotlinVersion() } - result.intersect(otherPlatforms) + resultVersion + // When no Kotlin version specified, it means that version is 1.0 + if (otherKotlinVersion != null && kotlinVersions.isNotEmpty()) { + result.union(otherPlatforms) + mergeVersions(otherKotlinVersion, kotlinVersions) } else { - result.intersect(platformsOfItem) + result.union(otherPlatforms) } + }.let { + if (it.containsAll(impliedPlatforms)) it - impliedPlatforms else it } } @@ -566,6 +601,17 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } } + private fun unionPlatformsOfItems(items: List): Set { + val platforms = items.flatMapTo(mutableSetOf()) { + when (it.kind) { + NodeKind.GroupNode -> unionPlatformsOfItems(it.origins) + else -> it.platforms + } + } + + return platforms.let { if (it.containsAll(impliedPlatforms)) it - impliedPlatforms else it } + } + inner class SectionsBuilder(val node: DocumentationNode): PageBuilder(listOf(node)) { override fun build() { @@ -666,12 +712,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } } appendTableCell { - val nodesToAppend = if (members.all { it.kind == NodeKind.GroupNode }) { - members.flatMap { it.origins } - } else { - members - } - appendSummarySignatures(nodesToAppend, platformsBasedOnMembers, omitSamePlatforms) + appendSummarySignatures(members, platformsBasedOnMembers, omitSamePlatforms) } } } @@ -680,6 +721,10 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } private fun platformsOfItems(items: List, omitSamePlatforms: Boolean = true): Set { + if (items.all { it.kind != NodeKind.Package && it.kind != NodeKind.Module && it.kind != NodeKind.ExternalClass }) { + return unionPlatformsOfItems(items) + } + val platforms = platformsOfItems(items) if (platforms.isNotEmpty() && (platforms != node.platformsToShow.toSet() || !omitSamePlatforms)) { return platforms @@ -688,35 +733,49 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } private fun appendSummarySignatures(items: List, platformsBasedOnMembers: Boolean, omitSamePlatforms: Boolean) { - val summarySignature = languageService.summarizeSignatures(items) - if (summarySignature != null) { - appendSummarySignature(summarySignature, items, platformsBasedOnMembers, omitSamePlatforms) - return - } + val groupBySummary = items.groupBy { it.summary } + for ((summary, node) in groupBySummary) { + val nodesToAppend = if (node.all { it.kind == NodeKind.GroupNode }) { + node.flatMap { it.origins } + } else { + node + } - val groupBySignature = items.groupBy { - languageService.render(it, RenderMode.SUMMARY) - } - for ((sign, node) in groupBySignature) { - appendSummarySignature(sign, node, platformsBasedOnMembers, omitSamePlatforms) + val summarySignature = languageService.summarizeSignatures(nodesToAppend) + if (summarySignature != null) { + appendSignatures(summarySignature, items, platformsBasedOnMembers, omitSamePlatforms) + } else { + val groupBySignature = nodesToAppend.groupBy { + languageService.render(it, RenderMode.SUMMARY) + } + for ((sign, members) in groupBySignature) { + appendSignatures(sign, members, platformsBasedOnMembers, omitSamePlatforms) + } + } + + val platforms = platformsOfItems(node) + appendAsBlockWithPlatforms(platforms) { + appendContent(summary) + appendSoftLineBreak() + } } } - private fun appendSummarySignature(signature: ContentNode, items: List, platformsBasedOnMembers: Boolean, omitSamePlatforms: Boolean) { + private fun appendSignatures(signature: ContentNode, items: List, platformsBasedOnMembers: Boolean, omitSamePlatforms: Boolean) { val elementPlatforms = platformsOfItems(items, omitSamePlatforms) val platforms = if (platformsBasedOnMembers) items.flatMapTo(mutableSetOf()) { platformsOfItems(it.members) } + elementPlatforms else elementPlatforms - appendPlatforms(platforms) - appendAsSignature(signature) { - signature.appendSignature() + appendAsBlockWithPlatforms(platforms) { + appendPlatforms(platforms) + appendAsSignature(signature) { + signature.appendSignature() + } + appendSoftLineBreak() } - - appendContent(items.first().summary) - appendSoftLineBreak() } } diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index 146c1e99..f2b3a937 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -76,7 +76,11 @@ open class DocumentationNode(val name: String, var content: Content = content private set - val summary: ContentNode get() = content.summary + val summary: ContentNode get() = when (kind) { + NodeKind.GroupNode -> this.origins.first().summary + else -> content.summary + } + val owner: DocumentationNode? get() = references(RefKind.Owner).singleOrNull()?.to -- cgit From 0b18da608eddfb48a40675d83ae3a92fc9a85fb6 Mon Sep 17 00:00:00 2001 From: Eugene Petrenko Date: Thu, 13 Sep 2018 13:35:43 +0300 Subject: add nice toString() --- core/src/main/kotlin/Model/Content.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'core/src/main/kotlin/Model') diff --git a/core/src/main/kotlin/Model/Content.kt b/core/src/main/kotlin/Model/Content.kt index 7c776bdb..77451d41 100644 --- a/core/src/main/kotlin/Model/Content.kt +++ b/core/src/main/kotlin/Model/Content.kt @@ -222,7 +222,11 @@ open class Content(): ContentBlock() { sections.firstOrNull { tag.equals(it.tag, ignoreCase = true) } companion object { - val Empty = Content() + val Empty = object: Content() { + override fun toString(): String { + return "EMPTY_CONTENT" + } + } fun of(vararg child: ContentNode): Content { val result = MutableContent() -- cgit From f2bfbc788a995daed52d3c0d587223d7b21cb3cc Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 26 Sep 2018 00:32:08 +0300 Subject: Refactor platforms & SinceKotlin logic --- .../Formats/KotlinWebsiteHtmlFormatService.kt | 7 +- .../main/kotlin/Formats/StructuredFormatService.kt | 292 ++++++++++++--------- .../src/main/kotlin/Kotlin/DocumentationBuilder.kt | 2 +- core/src/main/kotlin/Model/DocumentationNode.kt | 7 + .../main/kotlin/Model/DocumentationReference.kt | 3 +- 5 files changed, 180 insertions(+), 131 deletions(-) (limited to 'core/src/main/kotlin/Model') diff --git a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt index 16bec5a6..e5dd57a7 100644 --- a/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt +++ b/core/src/main/kotlin/Formats/KotlinWebsiteHtmlFormatService.kt @@ -125,14 +125,16 @@ open class KotlinWebsiteHtmlOutputBuilder( fun calculateDataAttributes(platforms: Set): String { fun String.isKotlinVersion() = this.startsWith("Kotlin") fun String.isJREVersion() = this.startsWith("JRE") + fun String.isNoBubbles() = this.startsWith("NoBubbles") val kotlinVersion = platforms.singleOrNull(String::isKotlinVersion) val jreVersion = platforms.singleOrNull(String::isJREVersion) - val targetPlatforms = platforms.filterNot { it.isKotlinVersion() || it.isJREVersion() } + val targetPlatforms = platforms.filterNot { it.isKotlinVersion() || it.isJREVersion() || it.isNoBubbles() } val kotlinVersionAttr = kotlinVersion?.let { " data-kotlin-version=\"$it\"" } ?: "" val jreVersionAttr = jreVersion?.let { " data-jre-version=\"$it\"" } ?: "" val platformsAttr = targetPlatforms.ifNotEmpty { " data-platform=\"${targetPlatforms.joinToString()}\"" } ?: "" - return "$platformsAttr$kotlinVersionAttr$jreVersionAttr" + val classes = if (NoBubbles in platforms) " class=\"no-bubbles\"" else "" + return "$classes$platformsAttr$kotlinVersionAttr$jreVersionAttr" } override fun appendIndexRow(platforms: Set, block: () -> Unit) { @@ -191,3 +193,4 @@ class KotlinWebsiteHtmlFormatService @Inject constructor( KotlinWebsiteHtmlOutputBuilder(to, location, generator, languageService, extension, impliedPlatforms, templateService) } +val NoBubbles = "NoBubbles" \ No newline at end of file diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index 927e0827..c5b6c8eb 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -10,7 +10,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, val generator: NodeLocationAwareGenerator, val languageService: LanguageService, val extension: String, - val impliedPlatforms: List) : FormattedOutputBuilder { + impliedPlatforms: List) : FormattedOutputBuilder { protected fun DocumentationNode.location() = generator.location(this) @@ -312,7 +312,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } else { for ((_, items) in breakdownBySummary) { - appendAsOverloadGroup(to, platformsOfItems(items)) { + appendAsOverloadGroup(to, effectivePlatformsForMembers(items)) { formatOverloadGroup(items) } @@ -463,82 +463,64 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } val DocumentationNode.actualPlatforms: Collection - get() = if (isModuleOrPackage()) - platformsToShow.toSet() + platformsOfItems(members) - else - platformsToShow - - - protected fun mergeVersions(otherKotlinVersion: String, kotlinVersions: List): String { - val allKotlinVersions = (kotlinVersions + otherKotlinVersion).distinct() - - val minVersion = allKotlinVersions.min()!! - val resultVersion: String = when { - allKotlinVersions.size == 1 -> allKotlinVersions.single() - minVersion.endsWith("+") -> minVersion - else -> "$minVersion+" - } - - return resultVersion - } - - protected fun platformsOfItems(items: List): Set { - val platforms = items.asSequence().map { - when (it.kind) { - NodeKind.ExternalClass, NodeKind.Package, NodeKind.Module -> platformsOfItems(it.members) - NodeKind.GroupNode -> platformsOfItems(it.origins) - else -> it.platformsToShow.toSet() - } - } - - fun String.isKotlinVersion() = this.startsWith("Kotlin") - - if (platforms.count() == 0) return emptySet() - - // Calculating common platforms for items - return platforms.reduce { result, platformsOfItem -> - val otherKotlinVersion = result.find { it.isKotlinVersion() } - val (kotlinVersions, otherPlatforms) = platformsOfItem.partition { it.isKotlinVersion() } - - // When no Kotlin version specified, it means that version is 1.0 - if (otherKotlinVersion != null && kotlinVersions.isNotEmpty()) { - result.intersect(platformsOfItem) + mergeVersions(otherKotlinVersion, kotlinVersions) - } else { - result.intersect(platformsOfItem) - } - } - } - - protected fun unionPlatformsOfItems(items: List): Set { - val platforms = items.asSequence().map { - when (it.kind) { - NodeKind.GroupNode -> unionPlatformsOfItems(it.origins) - else -> it.platformsToShow.toSet() - } - } - - fun String.isKotlinVersion() = this.startsWith("Kotlin") - - if (platforms.count() == 0) return emptySet() - - // Calculating common platforms for items - return platforms.reduce { result, platformsOfItem -> - val otherKotlinVersion = result.find { it.isKotlinVersion() } - val (kotlinVersions, otherPlatforms) = platformsOfItem.partition { it.isKotlinVersion() } - - // When no Kotlin version specified, it means that version is 1.0 - if (otherKotlinVersion != null && kotlinVersions.isNotEmpty()) { - result.union(otherPlatforms) + mergeVersions(otherKotlinVersion, kotlinVersions) - } else { - result.union(otherPlatforms) - } - }.let { - if (it.containsAll(impliedPlatforms)) it - impliedPlatforms else it - } - } - - val DocumentationNode.platformsToShow: List - get() = platforms.let { if (it.containsAll(impliedPlatforms)) it - impliedPlatforms else it } + get() = effectivePlatformsForNode(this) + + +// protected fun platformsOfItems(items: List): Set { +// val platforms = items.asSequence().map { +// when (it.kind) { +// NodeKind.ExternalClass, NodeKind.Package, NodeKind.Module -> platformsOfItems(it.members) +// NodeKind.GroupNode -> platformsOfItems(it.origins) +// else -> it.platformsToShow.toSet() +// } +// } +// +// fun String.isKotlinVersion() = this.startsWith("Kotlin") +// +// if (platforms.count() == 0) return emptySet() +// +// // Calculating common platforms for items +// return platforms.reduce { result, platformsOfItem -> +// val otherKotlinVersion = result.find { it.isKotlinVersion() } +// val (kotlinVersions, otherPlatforms) = platformsOfItem.partition { it.isKotlinVersion() } +// +// // When no Kotlin version specified, it means that version is 1.0 +// if (otherKotlinVersion != null && kotlinVersions.isNotEmpty()) { +// result.intersect(platformsOfItem) + mergeVersions(otherKotlinVersion, kotlinVersions) +// } else { +// result.intersect(platformsOfItem) +// } +// } +// } +// +// protected fun unionPlatformsOfItems(items: List): Set { +// val platforms = items.asSequence().map { +// when (it.kind) { +// NodeKind.GroupNode -> unionPlatformsOfItems(it.origins) +// else -> it.platformsToShow.toSet() +// } +// } +// +// fun String.isKotlinVersion() = this.startsWith("Kotlin") +// +// if (platforms.count() == 0) return emptySet() +// +// // Calculating common platforms for items +// return platforms.reduce { result, platformsOfItem -> +// val otherKotlinVersion = result.find { it.isKotlinVersion() } +// val (kotlinVersions, otherPlatforms) = platformsOfItem.partition { it.isKotlinVersion() } +// +// // When no Kotlin version specified, it means that version is 1.0 +// if (otherKotlinVersion != null && kotlinVersions.isNotEmpty()) { +// result.union(otherPlatforms) + mergeVersions(otherKotlinVersion, kotlinVersions) +// } else { +// result.union(otherPlatforms) +// } +// } +// } + +// val DocumentationNode.platformsToShow: List +// get() = platforms private fun DocumentationNode.appendDescription() { if (content.description != ContentEmpty) { @@ -600,17 +582,17 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, SectionsBuilder(node).build() } } - - private fun unionPlatformsOfItems(items: List): Set { - val platforms = items.flatMapTo(mutableSetOf()) { - when (it.kind) { - NodeKind.GroupNode -> unionPlatformsOfItems(it.origins) - else -> it.platforms - } - } - - return platforms.let { if (it.containsAll(impliedPlatforms)) it - impliedPlatforms else it } - } +// +// private fun unionPlatformsOfItems(items: List): Set { +// val platforms = items.flatMapTo(mutableSetOf()) { +// when (it.kind) { +// NodeKind.GroupNode -> unionPlatformsOfItems(it.origins) +// else -> it.platforms +// } +// } +// +// return platforms +// } inner class SectionsBuilder(val node: DocumentationNode): PageBuilder(listOf(node)) { @@ -697,11 +679,11 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, appendTable("Name", "Summary") { appendTableBody { for ((memberLocation, members) in membersMap) { - val elementPlatforms = platformsOfItems(members, omitSamePlatforms) - val platforms = if (platformsBasedOnMembers) - members.flatMapTo(mutableSetOf()) { platformsOfItems(it.members) } + elementPlatforms - else - elementPlatforms + val platforms = effectivePlatformsForMembers(members) + sinceKotlinAsPlatform(effectiveSinceKotlinForNodes(members)) +// val platforms = if (platformsBasedOnMembers) +// members.flatMapTo(mutableSetOf()) { platformsOfItems(it.members) } + elementPlatforms +// else +// elementPlatforms appendIndexRow(platforms) { appendTableCell { appendParagraph { @@ -720,17 +702,18 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } } - private fun platformsOfItems(items: List, omitSamePlatforms: Boolean = true): Set { - if (items.all { it.kind != NodeKind.Package && it.kind != NodeKind.Module && it.kind != NodeKind.ExternalClass }) { - return unionPlatformsOfItems(items) - } - - val platforms = platformsOfItems(items) - if (platforms.isNotEmpty() && (platforms != node.platformsToShow.toSet() || !omitSamePlatforms)) { - return platforms - } - return emptySet() - } +// +// private fun platformsOfItems(items: List, omitSamePlatforms: Boolean = true): Set { +// if (items.all { it.kind != NodeKind.Package && it.kind != NodeKind.Module && it.kind != NodeKind.ExternalClass }) { +// return unionPlatformsOfItems(items) +// } +// +// val platforms = platformsOfItems(items) +// if (platforms.isNotEmpty() && (platforms != node.platformsToShow.toSet() || !omitSamePlatforms)) { +// return platforms +// } +// return emptySet() +// } private fun appendSummarySignatures( items: List, @@ -740,16 +723,16 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, ) { val groupBySummary = items.groupBy { it.summary } - for ((summary, node) in groupBySummary) { - val nodesToAppend = if (node.all { it.kind == NodeKind.GroupNode }) { - node.flatMap { it.origins } + for ((summary, nodes) in groupBySummary) { + val nodesToAppend = if (nodes.all { it.kind == NodeKind.GroupNode }) { + nodes.flatMap { it.origins } } else { - node + nodes } val summarySignature = languageService.summarizeSignatures(nodesToAppend) if (summarySignature != null) { - appendSignatures(summarySignature, items, platformsBasedOnMembers, omitSamePlatforms, parentPlatforms) + appendSignatures(summarySignature, nodes, platformsBasedOnMembers, omitSamePlatforms, parentPlatforms) } else { val groupBySignature = nodesToAppend.groupBy { languageService.render(it, RenderMode.SUMMARY) @@ -759,12 +742,8 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } } - val platforms = platformsOfItems(node) - val platformsToAppend = if (platforms == parentPlatforms) { - emptySet() - } else { - platforms - } + val platforms = effectivePlatformsForMembers(nodes) + val platformsToAppend = platforms + sinceKotlinAsPlatform(effectiveSinceKotlinForNodes(nodes)) + NoBubbles appendAsBlockWithPlatforms(platformsToAppend) { appendContent(summary) appendSoftLineBreak() @@ -779,18 +758,14 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, omitSamePlatforms: Boolean, parentPlatforms: Set ) { - val elementPlatforms = platformsOfItems(items, omitSamePlatforms) - val platforms = if (platformsBasedOnMembers) - items.flatMapTo(mutableSetOf()) { platformsOfItems(it.members) } + elementPlatforms - else - elementPlatforms + val platforms = effectivePlatformsForMembers(items) +// val platforms = if (platformsBasedOnMembers) +// items.flatMapTo(mutableSetOf()) { platformsOfItems(it.members) } + elementPlatforms +// else +// elementPlatforms - - val platformsToAppend = if (platforms == parentPlatforms) { - emptySet() - } else { - platforms - } + print("signature>") + val platformsToAppend = platforms + sinceKotlinAsPlatform(effectiveSinceKotlinForNodes(items)) appendAsBlockWithPlatforms(platformsToAppend) { appendPlatforms(platforms) @@ -866,3 +841,66 @@ abstract class StructuredFormatService(val generator: NodeLocationAwareGenerator override final val linkExtension: String = extension) : FormatService { } + + +fun memberPlatforms(node: DocumentationNode): Sequence> { + val members = when { + node.kind == NodeKind.GroupNode -> node.origins + else -> node.members + } + + return members.asSequence() + .map { effectivePlatformsForNode(it) } +} + +fun effectivePlatformsForNode(node: DocumentationNode): Set { + val platforms = + sequenceOf(node.platforms.toSet()) + memberPlatforms(node) + + + // Calculating common platforms for items + return platforms.reduce { result, platformsOfItem -> + result.union(platformsOfItem) + } +} + +fun effectivePlatformsForMembers(nodes: List): Set { + return nodes.map { effectivePlatformsForNode(it) }.reduce { acc, set -> + acc.union(set) + } +} + +fun mergeVersions(kotlinVersions: List): String { + val allKotlinVersions = kotlinVersions.distinct() + + val minVersion = allKotlinVersions.min()!! + val resultVersion: String = when { + allKotlinVersions.size == 1 -> allKotlinVersions.single() + minVersion.endsWith("+") -> minVersion + else -> "$minVersion+" + } + + return resultVersion +} + +fun effectiveSinceKotlinForNode(node: DocumentationNode, baseVersion: String = "1.0"): String { + val members = when { + node.kind == NodeKind.GroupNode -> node.origins + node.kind in NodeKind.classLike -> emptyList() + node.kind in NodeKind.memberLike -> emptyList() + else -> node.members + } + + val nodeVersion = node.sinceKotlin ?: baseVersion + val memberVersion = if (members.isNotEmpty()) effectiveSinceKotlinForNodes(members, nodeVersion) else nodeVersion + + println("${node.path} > $nodeVersion, $memberVersion") + + return mergeVersions(listOf(memberVersion, nodeVersion)) +} + +fun effectiveSinceKotlinForNodes(nodes: List, baseVersion: String = "1.0"): String { + return mergeVersions(nodes.map { effectiveSinceKotlinForNode(it, baseVersion) }) +} + +fun sinceKotlinAsPlatform(version: String): String = "Kotlin $version" diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index e5bc32ab..38d2df4a 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -275,7 +275,7 @@ class DocumentationBuilder .detail(NodeKind.Value) .name.removeSurrounding("\"") - append(platformNodeRegistry["Kotlin " + kotlinVersion], RefKind.Platform) + sinceKotlin = kotlinVersion } fun DocumentationNode.appendModifiers(descriptor: DeclarationDescriptor) { diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index f2b3a937..5607c6d3 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -116,6 +116,13 @@ open class DocumentationNode(val name: String, val externalType: DocumentationNode? get() = references(RefKind.ExternalType).map { it.to }.firstOrNull() + var sinceKotlin: String? + get() = references(RefKind.SinceKotlin).singleOrNull()?.to?.name + set(value) { + if(value == null) return dropReferences { it.kind == RefKind.SinceKotlin } + append(DocumentationNode(value, Content.Empty, NodeKind.Value), RefKind.SinceKotlin) + } + val supertypes: List get() = details(NodeKind.Supertype) diff --git a/core/src/main/kotlin/Model/DocumentationReference.kt b/core/src/main/kotlin/Model/DocumentationReference.kt index e10796d2..1f2fc0c9 100644 --- a/core/src/main/kotlin/Model/DocumentationReference.kt +++ b/core/src/main/kotlin/Model/DocumentationReference.kt @@ -20,7 +20,8 @@ enum class RefKind { TopLevelPage, Platform, ExternalType, - Origin + Origin, + SinceKotlin } data class DocumentationReference(val from: DocumentationNode, val to: DocumentationNode, val kind: RefKind) { -- cgit From 7d4e133fa46b9ab358472398ae03cbefbf49d9e3 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 3 Oct 2018 07:59:04 +0300 Subject: Correctly lookup summary for group nodes --- core/src/main/kotlin/Model/DocumentationNode.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'core/src/main/kotlin/Model') diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index 5607c6d3..84f9a453 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -77,7 +77,10 @@ open class DocumentationNode(val name: String, private set val summary: ContentNode get() = when (kind) { - NodeKind.GroupNode -> this.origins.first().summary + NodeKind.GroupNode -> this.origins + .map { it.content } + .firstOrNull { !it.isEmpty() } + ?.summary ?: ContentEmpty else -> content.summary } -- cgit From 15b408bb59546a65a9a4f3f47067b4fa174702be Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Mon, 15 Oct 2018 19:03:39 +0300 Subject: Fix sinceKotlin updating & default setting --- core/src/main/kotlin/Kotlin/DocumentationBuilder.kt | 4 +++- core/src/main/kotlin/Model/DocumentationNode.kt | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'core/src/main/kotlin/Model') diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index 3fb22589..205b44bd 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -290,7 +290,9 @@ class DocumentationBuilder } fun DocumentationNode.appendDefaultSinceKotlin() { - sinceKotlin = passConfiguration.sinceKotlin + if (sinceKotlin == null) { + sinceKotlin = passConfiguration.sinceKotlin + } } fun DocumentationNode.appendModifiers(descriptor: DeclarationDescriptor) { diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index 84f9a453..617816b3 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -122,8 +122,10 @@ open class DocumentationNode(val name: String, var sinceKotlin: String? get() = references(RefKind.SinceKotlin).singleOrNull()?.to?.name set(value) { - if(value == null) return dropReferences { it.kind == RefKind.SinceKotlin } - append(DocumentationNode(value, Content.Empty, NodeKind.Value), RefKind.SinceKotlin) + dropReferences { it.kind == RefKind.SinceKotlin } + if (value != null) { + append(DocumentationNode(value, Content.Empty, NodeKind.Value), RefKind.SinceKotlin) + } } val supertypes: List -- cgit