aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraleksZubakov <aleks.zubakov@gmail.com>2018-08-06 13:42:44 +0300
committeraleksZubakov <aleks.zubakov@gmail.com>2018-08-06 13:42:44 +0300
commit77ce80517f79a774ef985be47ae00db828e34273 (patch)
tree3e2998d3e54a8c7e3c8335c72eeaa037b279acdd
parentba09711a1ecbdaede86cab9e76d13ff1047f89b2 (diff)
downloaddokka-77ce80517f79a774ef985be47ae00db828e34273.tar.gz
dokka-77ce80517f79a774ef985be47ae00db828e34273.tar.bz2
dokka-77ce80517f79a774ef985be47ae00db828e34273.zip
DocumentationMerger refactoring
-rw-r--r--core/src/main/kotlin/Generation/DocumentationMerger.kt179
-rw-r--r--core/src/main/kotlin/Generation/DokkaGenerator.kt227
-rw-r--r--core/src/main/kotlin/Generation/FileGenerator.kt2
-rw-r--r--core/src/main/kotlin/Generation/configurationImpl.kt1
-rw-r--r--core/src/main/kotlin/Kotlin/DocumentationBuilder.kt2
-rw-r--r--core/src/main/kotlin/Model/DocumentationNode.kt1
-rw-r--r--core/src/main/kotlin/Model/DocumentationReference.kt26
7 files changed, 212 insertions, 226 deletions
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<DocumentationModule>
+) {
+ private val producedNodeRefGraph: NodeReferenceGraph
+ private val signatureMap: Map<DocumentationNode, String>
+ private val oldToNewNodeMap: MutableMap<DocumentationNode, DocumentationNode> = 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<DocumentationReference>
+ ): List<DocumentationReference> {
+
+ val packagesByName = packages
+ .map { it.to }
+ .groupBy { it.name }
+
+ val mutableList = mutableListOf<DocumentationReference>()
+ 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>
+ ): 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<DocumentationReference>
+ ): List<DocumentationReference> {
+ val membersBySignature: Map<String, List<DocumentationNode>> = refs.map { it.to }
+ .groupBy { signatureMap[it]!! }
+
+ val mergedMembers: MutableList<DocumentationReference> = 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>
+ ): 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<DocumentationReference>
+ ): List<DocumentationReference> {
+ 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<String>, passConfiguration: DokkaConfiguration.PassConfiguration): AnalysisEnvironment {
+ private fun DocumentationNode.visit(action: (DocumentationNode) -> Unit) {
+ action(this)
+
+ for (member in members) {
+ member.visit(action)
+ }
+ }
+
+
+ fun createAnalysisEnvironment(
+ sourcePaths: List<String>,
+ 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<String>): Boolean {
+ private fun isNotSample(file: PsiFile, samples: List<String>): 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<PsiJavaFile> {
}
}
return result
-}
-
-class DocumentationMerger(
- private val documentationModules: List<DocumentationModule>
-) {
- private val producedNodeRefGraph: NodeReferenceGraph
- private val signatureMap: Map<DocumentationNode, String>
-
- 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<DocumentationReference>,
- kind: RefKind
- ): Pair<List<DocumentationReference>, List<DocumentationReference>> =
- Pair(source.filter { it.kind == kind }, source.filterNot { it.kind == kind })
-
-
- private fun mergePackageReferences(
- from: DocumentationNode,
- packages: List<DocumentationReference>
- ): List<DocumentationReference> {
- val packagesByName = packages
- .map { it.to }
- .groupBy { it.name }
-
- val mutableList: MutableList<DocumentationReference> = 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>
- ): 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<DocumentationReference>
- ): List<DocumentationReference> {
- val membersBySignature: Map<String, List<DocumentationNode>> = refs.map { it.to }
- .filter { signatureMap.containsKey(it) }
- .groupBy { signatureMap[it]!! }
-
- val mergedMembers: MutableList<DocumentationReference> = 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>
- ): 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<DocumentationReference>
- ): List<DocumentationReference> {
- 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<String> = 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<DocumentationReference> = references.filter { it.kind == kind }
fun allReferences(): Set<DocumentationReference> = 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<String, DocumentationNode>) : 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) }
}
}