aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.idea/compiler.xml10
-rw-r--r--core/src/main/kotlin/Generation/DocumentationMerger.kt235
-rw-r--r--core/src/main/kotlin/Generation/DokkaGenerator.kt71
-rw-r--r--core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt81
-rw-r--r--core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt75
-rw-r--r--core/src/main/kotlin/Kotlin/DocumentationBuilder.kt914
-rw-r--r--core/src/main/kotlin/Kotlin/KotlinAsJavaDocumentationBuilder.kt3
-rw-r--r--core/src/main/kotlin/Model/DocumentationNode.kt339
-rw-r--r--core/src/main/kotlin/Model/DocumentationReference.kt115
-rw-r--r--core/src/main/kotlin/Utilities/DokkaModules.kt3
-rw-r--r--core/src/main/kotlin/links/DRI.kt2
11 files changed, 307 insertions, 1541 deletions
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index 71547e0e..d3328b68 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -52,6 +52,8 @@
<module name="dokka.runners.maven-plugin.test" target="1.8" />
<module name="fatjar_main" target="1.8" />
<module name="fatjar_test" target="1.8" />
+ <module name="gradle-integration-tests.org.jetbrains.dokka.gradle-integration-tests.main" target="1.8" />
+ <module name="gradle-integration-tests.org.jetbrains.dokka.gradle-integration-tests.test" target="1.8" />
<module name="gradle-integration-tests_main" target="1.8" />
<module name="gradle-integration-tests_test" target="1.8" />
<module name="gradle-plugin_main" target="1.8" />
@@ -70,6 +72,8 @@
<module name="org.jetbrains.dokka.cli.test" target="1.8" />
<module name="org.jetbrains.dokka.core.main" target="1.8" />
<module name="org.jetbrains.dokka.core.test" target="1.8" />
+ <module name="org.jetbrains.dokka.coreDependencies.main" target="1.8" />
+ <module name="org.jetbrains.dokka.coreDependencies.test" target="1.8" />
<module name="org.jetbrains.dokka.fatjar.main" target="1.8" />
<module name="org.jetbrains.dokka.fatjar.test" target="1.8" />
<module name="org.jetbrains.dokka.gradle-integration-tests.main" target="1.8" />
@@ -78,8 +82,14 @@
<module name="org.jetbrains.dokka.gradle-plugin.test" target="1.8" />
<module name="org.jetbrains.dokka.integration.main" target="1.8" />
<module name="org.jetbrains.dokka.integration.test" target="1.8" />
+ <module name="org.jetbrains.dokka.javadoc8.main" target="1.8" />
+ <module name="org.jetbrains.dokka.javadoc8.test" target="1.8" />
<module name="org.jetbrains.dokka.maven-plugin.main" target="1.8" />
<module name="org.jetbrains.dokka.maven-plugin.test" target="1.8" />
+ <module name="org.jetbrains.dokka.plugins.main" target="1.8" />
+ <module name="org.jetbrains.dokka.plugins.test" target="1.8" />
+ <module name="org.jetbrains.dokka.testApi.main" target="1.8" />
+ <module name="org.jetbrains.dokka.testApi.test" target="1.8" />
</bytecodeTargetLevel>
</component>
</project> \ No newline at end of file
diff --git a/core/src/main/kotlin/Generation/DocumentationMerger.kt b/core/src/main/kotlin/Generation/DocumentationMerger.kt
deleted file mode 100644
index 53dc23a9..00000000
--- a/core/src/main/kotlin/Generation/DocumentationMerger.kt
+++ /dev/null
@@ -1,235 +0,0 @@
-package org.jetbrains.dokka.Generation
-
-import org.jetbrains.dokka.*
-
-class DocumentationMerger(
- private val documentationModules: List<DocumentationModule>,
- val logger: DokkaLogger
-) {
- private val producedNodeRefGraph: NodeReferenceGraph = 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: ${documentationModules.joinToString(", ") {it.name}}")
- }
-
- signatureMap = documentationModules
- .flatMap { it.nodeRefGraph.nodeMapView.entries }
- .associate { (k, v) -> v to k }
-
-
- documentationModules.map { it.nodeRefGraph }
- .flatMap { it.references }
- .forEach { producedNodeRefGraph.addReference(it) }
- }
-
- private fun mergePackageReferences(
- from: DocumentationNode,
- packages: List<DocumentationReference>
- ): List<DocumentationReference> {
- val packagesByName = packages
- .map { it.to }
- .groupBy { it.name }
-
- val resultReferences = mutableListOf<DocumentationReference>()
- for ((name, listOfPackages) in packagesByName) {
- try {
- val producedPackage = mergePackagesWithEqualNames(name, from, listOfPackages)
- updatePendingReferences()
-
- resultReferences.add(
- DocumentationReference(from, producedPackage, RefKind.Member)
- )
- } catch (t: Throwable) {
- val entries = listOfPackages.joinToString(",") { "references:${it.allReferences().size}" }
- throw Error("Failed to merge package $name from $from with entries $entries. ${t.message}", t)
- }
- }
-
- return resultReferences
- }
-
- private fun mergePackagesWithEqualNames(
- name: String,
- from: DocumentationNode,
- packages: List<DocumentationNode>
- ): DocumentationNode {
- val mergedPackage = DocumentationNode(name, Content.Empty, NodeKind.Package)
-
- for (contentToAppend in packages.map { it.content }.distinct()) {
- mergedPackage.updateContent {
- for (otherChild in contentToAppend.children) {
- children.add(otherChild)
- }
- }
- }
-
- for (node in packages) {
- oldToNewNodeMap[node] = mergedPackage
- }
-
- val references = packages.flatMap { it.allReferences() }
- val mergedReferences = mergeReferences(mergedPackage, references)
- for (ref in mergedReferences) {
- if (ref.kind == RefKind.Owner) {
- continue
- }
- mergedPackage.addReference(ref)
- }
-
- from.append(mergedPackage, RefKind.Member)
-
- return mergedPackage
- }
-
- private fun mergeMemberGroupBy(it: DocumentationNode): String {
- val signature = signatureMap[it]
-
- if (signature != null) {
- return signature
- }
-
- logger.error("Failed to find signature for $it in \n${it.allReferences().joinToString { "\n ${it.kind} ${it.to}" }}")
- return "<ERROR>"
- }
-
- private fun mergeMemberReferences(
- from: DocumentationNode,
- refs: List<DocumentationReference>
- ): List<DocumentationReference> {
- val membersBySignature: Map<String, List<DocumentationNode>> = refs.map { it.to }
- .groupBy(this::mergeMemberGroupBy)
-
- val mergedMembers: MutableList<DocumentationReference> = mutableListOf()
- for ((signature, members) in membersBySignature) {
- val newNode = mergeMembersWithEqualSignature(signature, 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,
- nodes: List<DocumentationNode>
- ): DocumentationNode {
- require(nodes.isNotEmpty())
-
- val singleNode = nodes.singleOrNull()
- if (singleNode != null) {
- singleNode.dropReferences { it.kind == RefKind.Owner }
- return singleNode
- }
-
- // Specialization processing
- // Given (Common, JVM, JRE6, JS) and (JVM, JRE6) and (JVM, JRE7)
- // Sorted: (JVM, JRE6), (JVM, JRE7), (Common, JVM, JRE6, JS)
- // Should output: (JVM, JRE6), (JVM, JRE7), (Common, JS)
- // Should not remove first platform
- val nodesSortedByPlatformCount = nodes.sortedBy { it.platforms.size }
- val allPlatforms = mutableSetOf<String>()
- nodesSortedByPlatformCount.forEach { node ->
- node.platforms
- .filterNot { allPlatforms.add(it) }
- .filter { it != node.platforms.first() }
- .forEach { platform ->
- node.dropReferences { it.kind == RefKind.Platform && it.to.name == platform }
- }
- }
-
- // TODO: Quick and dirty fox for merging extensions for external classes. Fix this probably in StructuredFormatService
- // TODO: while refactoring documentation model
-
- val groupNode = if(nodes.first().kind == NodeKind.ExternalClass){
- DocumentationNode(nodes.first().name, Content.Empty, NodeKind.ExternalClass)
- } else {
- DocumentationNode(nodes.first().name, Content.Empty, NodeKind.GroupNode)
- }
- groupNode.appendTextNode(signature, NodeKind.Signature, RefKind.Detail)
-
- for (node in nodes) {
- node.dropReferences { it.kind == RefKind.Owner }
- groupNode.append(node, RefKind.Origin)
- node.append(groupNode, RefKind.TopLevelPage)
-
- oldToNewNodeMap[node] = groupNode
- }
-
- if (groupNode.kind == NodeKind.ExternalClass){
- val refs = nodes.flatMap { it.allReferences() }.filter { it.kind != RefKind.Owner && it.kind != RefKind.TopLevelPage }
- refs.forEach {
- if (it.kind != RefKind.Link) {
- it.to.dropReferences { ref -> ref.kind == RefKind.Owner }
- it.to.append(groupNode, RefKind.Owner)
- }
- groupNode.append(it.to, it.kind)
- }
- }
-
- // if nodes are classes, nested members should be also merged and
- // inserted at the same level with class
- if (nodes.all { it.kind in NodeKind.classLike }) {
- 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
- }
-
-
- private fun mergeReferences(
- from: DocumentationNode,
- refs: List<DocumentationReference>
- ): List<DocumentationReference> {
- val (refsToPackages, otherRefs) = refs.partition { it.to.kind == NodeKind.Package }
- val mergedPackages = mergePackageReferences(from, refsToPackages)
-
- val (refsToMembers, refsNotToMembers) = otherRefs.partition { it.kind == RefKind.Member }
- val mergedMembers = mergeMemberReferences(from, refsToMembers)
-
- return mergedPackages + mergedMembers + refsNotToMembers
- }
-
- fun merge(): DocumentationModule {
- val mergedDocumentationModule = DocumentationModule(
- name = documentationModules.first().name,
- content = documentationModules.first().content,
- nodeRefGraph = producedNodeRefGraph
- )
-
- val refs = documentationModules.flatMap {
- it.allReferences()
- }
- mergeReferences(mergedDocumentationModule, refs)
-
- return mergedDocumentationModule
- }
-
- private fun updatePendingReferences() {
- for (ref in producedNodeRefGraph.references) {
- ref.lazyNodeFrom.update()
- ref.lazyNodeTo.update()
- }
- }
-
- private fun NodeResolver.update() {
- if (this is NodeResolver.Exact && exactNode in oldToNewNodeMap) {
- exactNode = oldToNewNodeMap[exactNode]!!
- }
- }
-} \ No newline at end of file
diff --git a/core/src/main/kotlin/Generation/DokkaGenerator.kt b/core/src/main/kotlin/Generation/DokkaGenerator.kt
index 90d7cfcc..51d70fbd 100644
--- a/core/src/main/kotlin/Generation/DokkaGenerator.kt
+++ b/core/src/main/kotlin/Generation/DokkaGenerator.kt
@@ -7,9 +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
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
@@ -24,12 +22,13 @@ import org.jetbrains.kotlin.resolve.LazyTopDownAnalyzer
import org.jetbrains.kotlin.resolve.TopDownAnalysisMode
import org.jetbrains.kotlin.utils.PathUtil
import java.io.File
-import kotlin.system.measureTimeMillis
-class DokkaGenerator(val dokkaConfiguration: DokkaConfiguration,
- val logger: DokkaLogger) {
+class DokkaGenerator(
+ val dokkaConfiguration: DokkaConfiguration,
+ val logger: DokkaLogger
+) {
- private val documentationModules: MutableList<DocumentationModule> = mutableListOf()
+ private val documentationModules: MutableList<DocumentationNodes.Module> = mutableListOf()
private val globalInjector = Guice.createInjector(DokkaRunModule(dokkaConfiguration))
@@ -37,26 +36,15 @@ class DokkaGenerator(val dokkaConfiguration: DokkaConfiguration,
for (pass in passesConfigurations) {
- val documentationModule = DocumentationModule(pass.moduleName)
+ val documentationModule = DocumentationNodes.Module(pass.moduleName)
appendSourceModule(pass, documentationModule)
documentationModules.add(documentationModule)
}
-
- val totalDocumentationModule = DocumentationMerger(documentationModules, logger).merge()
- totalDocumentationModule.prepareForGeneration(dokkaConfiguration)
-
- val timeBuild = measureTimeMillis {
- logger.info("Generating pages... ")
- val outputInjector = globalInjector.createChildInjector(DokkaOutputModule(dokkaConfiguration, logger))
- val instance = outputInjector.getInstance(Generator::class.java)
- instance.buildAll(totalDocumentationModule)
- }
- logger.info("done in ${timeBuild / 1000} secs")
}
private fun appendSourceModule(
passConfiguration: DokkaConfiguration.PassConfiguration,
- documentationModule: DocumentationModule
+ documentationModule: DocumentationNodes.Module
) = with(passConfiguration) {
val sourcePaths = passConfiguration.sourceRoots.map { it.path }
@@ -84,9 +72,15 @@ class DokkaGenerator(val dokkaConfiguration: DokkaConfiguration,
}
val injector = globalInjector.createChildInjector(
- DokkaAnalysisModule(environment, dokkaConfiguration, defaultPlatformsProvider, documentationModule.nodeRefGraph, passConfiguration, logger))
+ DokkaAnalysisModule(environment, dokkaConfiguration, defaultPlatformsProvider, passConfiguration, logger)
+ )
- buildDocumentationModule(injector, documentationModule, { isNotSample(it, passConfiguration.samples) }, includes)
+ buildDocumentationModule(
+ injector,
+ documentationModule,
+ { isNotSample(it, passConfiguration.samples) },
+ includes
+ )
val timeAnalyse = System.currentTimeMillis() - startAnalyse
logger.info("done in ${timeAnalyse / 1000} secs")
@@ -118,7 +112,7 @@ class DokkaGenerator(val dokkaConfiguration: DokkaConfiguration,
return environment
}
- private 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
@@ -145,10 +139,12 @@ class DokkaMessageCollector(val logger: DokkaLogger) : MessageCollector {
override fun hasErrors() = seenErrors
}
-fun buildDocumentationModule(injector: Injector,
- documentationModule: DocumentationModule,
- filesToDocumentFilter: (PsiFile) -> Boolean = { file -> true },
- includes: List<String> = listOf()) {
+fun buildDocumentationModule(
+ injector: Injector,
+ documentationModule: DocumentationNodes.Module,
+ filesToDocumentFilter: (PsiFile) -> Boolean = { file -> true },
+ includes: List<String> = listOf()
+) {
val coreEnvironment = injector.getInstance(KotlinCoreEnvironment::class.java)
val fragmentFiles = coreEnvironment.getSourceFiles().filter(filesToDocumentFilter)
@@ -158,25 +154,20 @@ fun buildDocumentationModule(injector: Injector,
analyzer.analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, fragmentFiles)
val fragments = fragmentFiles.mapNotNull { resolutionFacade.resolveSession.getPackageFragment(it.packageFqName) }
- .distinct()
+ .distinct()
val packageDocs = injector.getInstance(PackageDocs::class.java)
for (include in includes) {
packageDocs.parse(include, fragments)
}
- if (documentationModule.content.isEmpty()) {
- documentationModule.updateContent {
- for (node in packageDocs.moduleContent.children) {
- append(node)
- }
- }
- }
parseJavaPackageDocs(packageDocs, coreEnvironment)
with(injector.getInstance(DocumentationBuilder::class.java)) {
- documentationModule.appendFragments(fragments, packageDocs.packageContent,
- injector.getInstance(PackageDocumentationBuilder::class.java))
+ documentationModule.appendFragments(
+ fragments,
+ injector.getInstance(PackageDocumentationBuilder::class.java)
+ )
propagateExtensionFunctionsToSubclasses(fragments, resolutionFacade)
}
@@ -189,8 +180,8 @@ fun buildDocumentationModule(injector: Injector,
fun parseJavaPackageDocs(packageDocs: PackageDocs, coreEnvironment: KotlinCoreEnvironment) {
val contentRoots = coreEnvironment.configuration.get(CLIConfigurationKeys.CONTENT_ROOTS)
- ?.filterIsInstance<JavaSourceRoot>()
- ?.map { it.file }
+ ?.filterIsInstance<JavaSourceRoot>()
+ ?.map { it.file }
?: listOf()
contentRoots.forEach { root ->
root.walkTopDown().filter { it.name == "overview.html" }.forEach {
@@ -202,8 +193,8 @@ fun parseJavaPackageDocs(packageDocs: PackageDocs, coreEnvironment: KotlinCoreEn
fun KotlinCoreEnvironment.getJavaSourceFiles(): List<PsiJavaFile> {
val sourceRoots = configuration.get(CLIConfigurationKeys.CONTENT_ROOTS)
- ?.filterIsInstance<JavaSourceRoot>()
- ?.map { it.file }
+ ?.filterIsInstance<JavaSourceRoot>()
+ ?.map { it.file }
?: listOf()
val result = arrayListOf<PsiJavaFile>()
diff --git a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt
index 3b368329..d3fc7048 100644
--- a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt
+++ b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.asJava.elements.KtLightElement
import org.jetbrains.kotlin.kdoc.parser.KDocKnownTag
import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag
import org.jetbrains.kotlin.lexer.KtTokens
-import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtModifierListOwner
fun getSignature(element: PsiElement?) = when(element) {
@@ -55,30 +54,33 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder {
private val passConfiguration: DokkaConfiguration.PassConfiguration
private val refGraph: NodeReferenceGraph
private val docParser: JavaDocumentationParser
+ private val documentationBuilder: DocumentationBuilder
@Inject constructor(
- passConfiguration: DokkaConfiguration.PassConfiguration,
+ documentationBuilder: DocumentationBuilder,
refGraph: NodeReferenceGraph,
logger: DokkaLogger,
signatureProvider: ElementSignatureProvider,
externalDocumentationLinkResolver: ExternalDocumentationLinkResolver
) {
- this.passConfiguration = passConfiguration
+ this.passConfiguration = documentationBuilder.passConfiguration
+ this.documentationBuilder = documentationBuilder
this.refGraph = refGraph
this.docParser = JavadocParser(refGraph, logger, signatureProvider, externalDocumentationLinkResolver)
}
- constructor(passConfiguration: DokkaConfiguration.PassConfiguration, refGraph: NodeReferenceGraph, docParser: JavaDocumentationParser) {
- this.passConfiguration = passConfiguration
+ constructor(documentationBuilder: DocumentationBuilder, refGraph: NodeReferenceGraph, docParser: JavaDocumentationParser) {
+ this.passConfiguration = documentationBuilder.passConfiguration
this.refGraph = refGraph
this.docParser = docParser
+ this.documentationBuilder = documentationBuilder
}
override fun appendFile(file: PsiJavaFile, module: DocumentationModule, packageContent: Map<String, Content>) {
if (skipFile(file) || file.classes.all { skipElement(it) }) {
return
}
- val packageNode = findOrCreatePackageNode(module, file.packageName, emptyMap(), refGraph)
+ val packageNode = documentationBuilder.findOrCreatePackageNode(module, file.packageName, emptyMap(), refGraph)
appendClasses(packageNode, file.classes)
}
@@ -108,7 +110,7 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder {
}
fun nodeForElement(element: PsiNamedElement,
- kind: NodeKind,
+ kind: DocumentationNodes,
name: String = element.name ?: "<anonymous>",
register: Boolean = false): DocumentationNode {
val (docComment, deprecatedContent) = docParser.parseDocumentation(element)
@@ -125,14 +127,6 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder {
}
}
}
- if (deprecatedContent != null) {
- val deprecationNode = DocumentationNode("", deprecatedContent, NodeKind.Modifier)
- node.append(deprecationNode, RefKind.Deprecation)
- }
- if (element is PsiDocCommentOwner && element.isDeprecated && node.deprecation == null) {
- val deprecationNode = DocumentationNode("", Content.of(ContentText("Deprecated")), NodeKind.Modifier)
- node.append(deprecationNode, RefKind.Deprecation)
- }
return node
}
@@ -182,15 +176,15 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder {
fun PsiClass.build(): DocumentationNode {
val kind = when {
- isAnnotationType -> NodeKind.AnnotationClass
- isInterface -> NodeKind.Interface
- isEnum -> NodeKind.Enum
- isException() -> NodeKind.Exception
- else -> NodeKind.Class
+ isAnnotationType -> DocumentationNodes.AnnotationClass
+ isInterface -> DocumentationNodes.Interface
+ isEnum -> DocumentationNodes.Enum
+ isException() -> DocumentationNodes.Exception
+ else -> DocumentationNodes.Class
}
val node = nodeForElement(this, kind, register = isAnnotationType)
superTypes.filter { !ignoreSupertype(it) }.forEach {
- node.appendType(it, NodeKind.Supertype)
+ node.appendType(it, DocumentationNodes.Supertype)
val superClass = it.resolve()
if (superClass != null) {
link(superClass, node, RefKind.Inheritor)
@@ -239,13 +233,13 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder {
"\"" + StringUtil.escapeStringCharacters(value) + "\""
else -> value.toString()
}
- append(DocumentationNode(text, Content.Empty, NodeKind.Value), RefKind.Detail)
+ append(DocumentationNode(text, Content.Empty, DocumentationNodes.Value), RefKind.Detail)
}
}
- private fun PsiField.nodeKind(): NodeKind = when {
- this is PsiEnumConstant -> NodeKind.EnumItem
- else -> NodeKind.Field
+ private fun PsiField.nodeKind(): DocumentationNodes = when {
+ this is PsiEnumConstant -> DocumentationNodes.EnumItem
+ else -> DocumentationNodes.Field
}
fun PsiMethod.build(): DocumentationNode {
@@ -261,24 +255,21 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder {
return node
}
- private fun PsiMethod.nodeKind(): NodeKind = when {
- isConstructor -> NodeKind.Constructor
- else -> NodeKind.Function
+ private fun PsiMethod.nodeKind(): DocumentationNodes = when {
+ isConstructor -> DocumentationNodes.Constructor
+ else -> DocumentationNodes.Function
}
fun PsiParameter.build(): DocumentationNode {
- val node = nodeForElement(this, NodeKind.Parameter)
+ val node = nodeForElement(this, DocumentationNodes.Parameter::class)
node.appendType(type)
- if (type is PsiEllipsisType) {
- node.appendTextNode("vararg", NodeKind.Modifier, RefKind.Detail)
- }
return node
}
fun PsiTypeParameter.build(): DocumentationNode {
- val node = nodeForElement(this, NodeKind.TypeParameter)
- extendsListTypes.forEach { node.appendType(it, NodeKind.UpperBound) }
- implementsListTypes.forEach { node.appendType(it, NodeKind.UpperBound) }
+ val node = nodeForElement(this, DocumentationNodes.TypeParameter)
+ extendsListTypes.forEach { node.appendType(it, DocumentationNodes.UpperBound) }
+ implementsListTypes.forEach { node.appendType(it, DocumentationNodes.UpperBound) }
return node
}
@@ -287,27 +278,27 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder {
PsiModifier.MODIFIERS.forEach {
if (modifierList.hasExplicitModifier(it)) {
- appendTextNode(it, NodeKind.Modifier)
+ appendTextNode(it, DocumentationNodes.Modifier)
}
}
}
- fun DocumentationNode.appendType(psiType: PsiType?, kind: NodeKind = NodeKind.Type) {
+ fun DocumentationNode.appendType(psiType: PsiType?, kind: DocumentationNodes = DocumentationNodes.Type) {
if (psiType == null) {
return
}
append(psiType.build(kind), RefKind.Detail)
}
- fun PsiType.build(kind: NodeKind = NodeKind.Type): DocumentationNode {
+ fun PsiType.build(kind: DocumentationNodes = DocumentationNodes.Type): DocumentationNode {
val name = mapTypeName(this)
val node = DocumentationNode(name, Content.Empty, kind)
if (this is PsiClassType) {
- node.appendDetails(parameters) { build(NodeKind.Type) }
+ node.appendDetails(parameters) { build(DocumentationNodes.Type) }
link(node, resolve())
}
if (this is PsiArrayType && this !is PsiEllipsisType) {
- node.append(componentType.build(NodeKind.Type), RefKind.Detail)
+ node.append(componentType.build(DocumentationNodes.Type), RefKind.Detail)
}
return node
}
@@ -316,7 +307,7 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder {
val existing = refGraph.lookup(getSignature(psiClass)!!)
if (existing != null) return existing
val new = psiClass.build()
- val packageNode = findOrCreatePackageNode(null, (psiClass.containingFile as PsiJavaFile).packageName, emptyMap(), refGraph)
+ val packageNode = documentation. findOrCreatePackageNode(null, (psiClass.containingFile as PsiJavaFile).packageName, emptyMap(), refGraph)
packageNode.append(new, RefKind.Member)
return new
}
@@ -327,20 +318,20 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder {
is KtLightAbstractAnnotation -> clsDelegate
else -> this
}
- val node = DocumentationNode(qualifiedName?.substringAfterLast(".") ?: "<?>", Content.Empty, NodeKind.Annotation)
+ val node = DocumentationNodes.Annotation(qualifiedName?.substringAfterLast(".") ?: "<?>")
val psiClass = original.nameReferenceElement?.resolve() as? PsiClass
if (psiClass != null && psiClass.isAnnotationType) {
node.append(lookupOrBuildClass(psiClass), RefKind.Link)
}
parameterList.attributes.forEach {
- val parameter = DocumentationNode(it.name ?: "value", Content.Empty, NodeKind.Parameter)
+ val parameter = DocumentationNodes.Parameter(it.name ?: "value", this.extractDescriptor())
val value = it.value
if (value != null) {
val valueText = (value as? PsiLiteralExpression)?.value as? String ?: value.text
- val valueNode = DocumentationNode(valueText, Content.Empty, NodeKind.Value)
+ val valueNode = DocumentationNode(valueText, Content.Empty, DocumentationNodes.Value)
parameter.append(valueNode, RefKind.Detail)
}
- node.append(parameter, RefKind.Detail)
+ node.append(parameter, RefKind.Detail)m
}
return node
}
diff --git a/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt b/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt
index ce20aeec..7c9f2d15 100644
--- a/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt
+++ b/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt
@@ -30,20 +30,28 @@ import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
class DescriptorDocumentationParser
- @Inject constructor(val options: DokkaConfiguration.PassConfiguration,
- val logger: DokkaLogger,
- val linkResolver: DeclarationLinkResolver,
- val resolutionFacade: DokkaResolutionFacade,
- val refGraph: NodeReferenceGraph,
- val sampleService: SampleProcessingService,
- val signatureProvider: KotlinElementSignatureProvider,
- val externalDocumentationLinkResolver: ExternalDocumentationLinkResolver
-)
-{
- fun parseDocumentation(descriptor: DeclarationDescriptor, inline: Boolean = false, isDefaultNoArgConstructor: Boolean = false): Content =
- parseDocumentationAndDetails(descriptor, inline, isDefaultNoArgConstructor).first
+@Inject constructor(
+ val options: DokkaConfiguration.PassConfiguration,
+ val logger: DokkaLogger,
+ val linkResolver: DeclarationLinkResolver,
+ val resolutionFacade: DokkaResolutionFacade,
+ val refGraph: NodeReferenceGraph,
+ val sampleService: SampleProcessingService,
+ val signatureProvider: KotlinElementSignatureProvider,
+ val externalDocumentationLinkResolver: ExternalDocumentationLinkResolver
+) {
+ fun parseDocumentation(
+ descriptor: DeclarationDescriptor,
+ inline: Boolean = false,
+ isDefaultNoArgConstructor: Boolean = false
+ ): Content =
+ parseDocumentationAndDetails(descriptor, inline, isDefaultNoArgConstructor).first
- fun parseDocumentationAndDetails(descriptor: DeclarationDescriptor, inline: Boolean = false, isDefaultNoArgConstructor: Boolean = false): Pair<Content, (DocumentationNode) -> Unit> {
+ fun parseDocumentationAndDetails(
+ descriptor: DeclarationDescriptor,
+ inline: Boolean = false,
+ isDefaultNoArgConstructor: Boolean = false
+ ): Pair<Content, (DocumentationNode) -> Unit> {
if (descriptor is JavaClassDescriptor || descriptor is JavaCallableMemberDescriptor) {
return parseJavadoc(descriptor)
}
@@ -51,8 +59,8 @@ class DescriptorDocumentationParser
val kdoc = descriptor.findKDoc() ?: findStdlibKDoc(descriptor)
if (kdoc == null) {
if (options.effectivePackageOptions(descriptor.fqNameSafe).reportUndocumented && !descriptor.isDeprecated() &&
- descriptor !is ValueParameterDescriptor && descriptor !is TypeParameterDescriptor &&
- descriptor !is PropertyAccessorDescriptor && !descriptor.isSuppressWarning()) {
+ descriptor !is ValueParameterDescriptor && descriptor !is TypeParameterDescriptor &&
+ descriptor !is PropertyAccessorDescriptor && !descriptor.isSuppressWarning()) {
logger.warn("No documentation for ${descriptor.signatureWithSourceLocation()}")
}
return Content.Empty to { node -> }
@@ -62,7 +70,7 @@ class DescriptorDocumentationParser
(PsiTreeUtil.getParentOfType(kdoc, KDoc::class.java)?.context as? KtDeclaration)
?.takeIf { it != descriptor.original.sourcePsi() }
?.resolveToDescriptorIfAny()
- ?: descriptor
+ ?: descriptor
var kdocText = if (isDefaultNoArgConstructor) {
getConstructorTagContent(descriptor) ?: kdoc.getContent()
@@ -74,7 +82,11 @@ class DescriptorDocumentationParser
}
val tree = parseMarkdown(kdocText)
val linkMap = LinkMap.buildLinkMap(tree.node, kdocText)
- val content = buildContent(tree, LinkResolver(linkMap) { href -> linkResolver.resolveContentLink(contextDescriptor, href) }, inline)
+ val content = buildContent(
+ tree,
+ LinkResolver(linkMap) { href -> linkResolver.resolveContentLink(contextDescriptor, href) },
+ inline
+ )
if (kdoc is KDocSection) {
val tags = kdoc.getTags()
tags.forEach {
@@ -87,7 +99,10 @@ class DescriptorDocumentationParser
val section = content.addSection(javadocSectionDisplayName(it.name), it.getSubjectName())
val sectionContent = it.getContent()
val markdownNode = parseMarkdown(sectionContent)
- buildInlineContentTo(markdownNode, section, LinkResolver(linkMap) { href -> linkResolver.resolveContentLink(contextDescriptor, href) })
+ buildInlineContentTo(
+ markdownNode,
+ section,
+ LinkResolver(linkMap) { href -> linkResolver.resolveContentLink(contextDescriptor, href) })
}
}
}
@@ -102,7 +117,7 @@ class DescriptorDocumentationParser
}
- private fun DeclarationDescriptor.isSuppressWarning() : Boolean {
+ private fun DeclarationDescriptor.isSuppressWarning(): Boolean {
val suppressAnnotation = annotations.findAnnotation(FqName(Suppress::class.qualifiedName!!))
return if (suppressAnnotation != null) {
@Suppress("UNCHECKED_CAST")
@@ -126,11 +141,12 @@ class DescriptorDocumentationParser
}
if (DescriptorUtils.getFqName(deepestDescriptor.containingDeclaration).asString() == "kotlin.Any") {
val anyClassDescriptors = resolutionFacade.resolveSession.getTopLevelClassifierDescriptors(
- FqName.fromSegments(listOf("kotlin", "Any")), NoLookupLocation.FROM_IDE)
+ FqName.fromSegments(listOf("kotlin", "Any")), NoLookupLocation.FROM_IDE
+ )
anyClassDescriptors.forEach {
val anyMethod = (it as ClassDescriptor).getMemberScope(listOf())
- .getDescriptorsFiltered(DescriptorKindFilter.FUNCTIONS) { it == descriptor.name }
- .single()
+ .getDescriptorsFiltered(DescriptorKindFilter.FUNCTIONS) { it == descriptor.name }
+ .single()
val kdoc = anyMethod.findKDoc()
if (kdoc != null) {
return kdoc
@@ -145,17 +161,12 @@ class DescriptorDocumentationParser
val psi = ((descriptor as? DeclarationDescriptorWithSource)?.source as? PsiSourceElement)?.psi
if (psi is PsiDocCommentOwner) {
val parseResult = JavadocParser(
- refGraph,
- logger,
- signatureProvider,
- externalDocumentationLinkResolver
+ refGraph,
+ logger,
+ signatureProvider,
+ externalDocumentationLinkResolver
).parseDocumentation(psi as PsiNamedElement)
- return parseResult.content to { node ->
- parseResult.deprecatedContent?.let {
- val deprecationNode = DocumentationNode("", it, NodeKind.Modifier)
- node.append(deprecationNode, RefKind.Deprecation)
- }
- }
+ return parseResult.content to { node -> }
}
return Content.Empty to { node -> }
}
diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt
index 3168e033..6d258564 100644
--- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt
+++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt
@@ -1,61 +1,51 @@
package org.jetbrains.dokka
import com.google.inject.Inject
-import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.PsiJavaFile
import org.jetbrains.dokka.DokkaConfiguration.PassConfiguration
-import org.jetbrains.dokka.Kotlin.DescriptorDocumentationParser
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
-import org.jetbrains.kotlin.coroutines.hasFunctionOrSuspendFunctionType
import org.jetbrains.kotlin.descriptors.*
-import org.jetbrains.kotlin.descriptors.annotations.Annotated
-import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
-import org.jetbrains.kotlin.descriptors.impl.EnumEntrySyntheticClassDescriptor
import org.jetbrains.kotlin.idea.kdoc.findKDoc
-import org.jetbrains.kotlin.idea.util.fuzzyExtensionReceiverType
-import org.jetbrains.kotlin.idea.util.makeNotNullable
-import org.jetbrains.kotlin.idea.util.toFuzzyType
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
import org.jetbrains.kotlin.kdoc.psi.impl.KDocSection
-import org.jetbrains.kotlin.lexer.KtTokens
-import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
-import org.jetbrains.kotlin.name.Name
-import org.jetbrains.kotlin.psi.KtModifierListOwner
-import org.jetbrains.kotlin.psi.KtParameter
-import org.jetbrains.kotlin.psi.addRemoveModifier.MODIFIERS_ORDER
import org.jetbrains.kotlin.resolve.DescriptorUtils
-import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.resolve.descriptorUtil.*
import org.jetbrains.kotlin.resolve.findTopMostOverriddenDescriptors
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
-import org.jetbrains.kotlin.resolve.source.getPsi
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes
import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
import org.jetbrains.kotlin.types.typeUtil.supertypes
import org.jetbrains.kotlin.util.supertypesWithAny
+import kotlin.reflect.KClass
import com.google.inject.name.Named as GuiceNamed
-private fun isExtensionForExternalClass(extensionFunctionDescriptor: DeclarationDescriptor,
- extensionReceiverDescriptor: DeclarationDescriptor,
- allFqNames: Collection<FqName>): Boolean {
- val extensionFunctionPackage = DescriptorUtils.getParentOfType(extensionFunctionDescriptor, PackageFragmentDescriptor::class.java)
- val extensionReceiverPackage = DescriptorUtils.getParentOfType(extensionReceiverDescriptor, PackageFragmentDescriptor::class.java)
+private fun isExtensionForExternalClass(
+ extensionFunctionDescriptor: DeclarationDescriptor,
+ extensionReceiverDescriptor: DeclarationDescriptor,
+ allFqNames: Collection<FqName>
+): Boolean {
+ val extensionFunctionPackage =
+ DescriptorUtils.getParentOfType(extensionFunctionDescriptor, PackageFragmentDescriptor::class.java)
+ val extensionReceiverPackage =
+ DescriptorUtils.getParentOfType(extensionReceiverDescriptor, PackageFragmentDescriptor::class.java)
return extensionFunctionPackage != null && extensionReceiverPackage != null &&
extensionFunctionPackage.fqName != extensionReceiverPackage.fqName &&
extensionReceiverPackage.fqName !in allFqNames
}
interface PackageDocumentationBuilder {
- fun buildPackageDocumentation(documentationBuilder: DocumentationBuilder,
- packageName: FqName,
- packageNode: DocumentationNode,
- declarations: List<DeclarationDescriptor>,
- allFqNames: Collection<FqName>)
+ fun buildPackageDocumentation(
+ documentationBuilder: DocumentationBuilder,
+ packageName: FqName,
+ packageNode: DocumentationNodes.Package,
+ declarations: List<DeclarationDescriptor>,
+ allFqNames: Collection<FqName>
+ )
}
interface DefaultPlatformsProvider {
@@ -67,121 +57,33 @@ val ignoredSupertypes = setOf(
)
class DocumentationBuilder
-@Inject constructor(val resolutionFacade: DokkaResolutionFacade,
- val descriptorDocumentationParser: DescriptorDocumentationParser,
- val passConfiguration: DokkaConfiguration.PassConfiguration,
- val refGraph: NodeReferenceGraph,
- val platformNodeRegistry: PlatformNodeRegistry,
- val logger: DokkaLogger,
- val linkResolver: DeclarationLinkResolver,
- val defaultPlatformsProvider: DefaultPlatformsProvider) {
- val boringBuiltinClasses = setOf(
- "kotlin.Unit", "kotlin.Byte", "kotlin.Short", "kotlin.Int", "kotlin.Long", "kotlin.Char", "kotlin.Boolean",
- "kotlin.Float", "kotlin.Double", "kotlin.String", "kotlin.Array", "kotlin.Any")
- val knownModifiers = setOf(
- KtTokens.PUBLIC_KEYWORD, KtTokens.PROTECTED_KEYWORD, KtTokens.INTERNAL_KEYWORD, KtTokens.PRIVATE_KEYWORD,
- KtTokens.OPEN_KEYWORD, KtTokens.FINAL_KEYWORD, KtTokens.ABSTRACT_KEYWORD, KtTokens.SEALED_KEYWORD,
- KtTokens.OVERRIDE_KEYWORD, KtTokens.INLINE_KEYWORD)
-
- fun link(node: DocumentationNode, descriptor: DeclarationDescriptor, kind: RefKind) {
- refGraph.link(node, descriptor.signature(), kind)
- }
-
- fun link(fromDescriptor: DeclarationDescriptor?, toDescriptor: DeclarationDescriptor?, kind: RefKind) {
- if (fromDescriptor != null && toDescriptor != null) {
- refGraph.link(fromDescriptor.signature(), toDescriptor.signature(), kind)
- }
- }
-
- fun register(descriptor: DeclarationDescriptor, node: DocumentationNode) {
- refGraph.register(descriptor.signature(), node)
- }
-
- fun <T> nodeForDescriptor(
- descriptor: T,
- kind: NodeKind,
- external: Boolean = false
- ): DocumentationNode where T : DeclarationDescriptor, T : Named {
- val (doc, callback) =
- if (external) {
- Content.Empty to { node -> }
- } else {
- descriptorDocumentationParser.parseDocumentationAndDetails(
- descriptor,
- kind == NodeKind.Parameter
- )
- }
- val node = DocumentationNode(descriptor.name.asString(), doc, kind).withModifiers(descriptor)
- node.appendSignature(descriptor)
- callback(node)
- return node
- }
-
- private fun DocumentationNode.withModifiers(descriptor: DeclarationDescriptor): DocumentationNode {
- if (descriptor is MemberDescriptor) {
- appendVisibility(descriptor)
- if (descriptor !is ConstructorDescriptor) {
- appendModality(descriptor)
- }
- }
- return this
- }
+@Inject constructor(
+ val resolutionFacade: DokkaResolutionFacade,
+ val passConfiguration: DokkaConfiguration.PassConfiguration,
+ val logger: DokkaLogger
+) {
- fun DocumentationNode.appendModality(descriptor: MemberDescriptor) {
- var modality = descriptor.modality
- if (modality == Modality.OPEN) {
- val containingClass = descriptor.containingDeclaration as? ClassDescriptor
- if (containingClass?.modality == Modality.FINAL) {
- modality = Modality.FINAL
- }
- }
- val modifier = modality.name.toLowerCase()
- appendTextNode(modifier, NodeKind.Modifier)
- }
-
- fun DocumentationNode.appendInline(descriptor: DeclarationDescriptor, psi: KtModifierListOwner) {
- if (!psi.hasModifier(KtTokens.INLINE_KEYWORD)) return
- if (descriptor is FunctionDescriptor
- && descriptor.valueParameters.none { it.hasFunctionOrSuspendFunctionType }) return
- appendTextNode(KtTokens.INLINE_KEYWORD.value, NodeKind.Modifier)
- }
-
- fun DocumentationNode.appendVisibility(descriptor: DeclarationDescriptorWithVisibility) {
- val modifier = descriptor.visibility.normalize().displayName
- appendTextNode(modifier, NodeKind.Modifier)
- }
-
- fun DocumentationNode.appendSupertype(descriptor: ClassDescriptor, superType: KotlinType, backref: Boolean) {
+ private fun DocumentationNodes.Class.appendSupertype(descriptor: ClassDescriptor, superType: KotlinType, backref: Boolean) {
val unwrappedType = superType.unwrap()
if (unwrappedType is AbbreviatedType) {
appendSupertype(descriptor, unwrappedType.abbreviation, backref)
} else {
- appendType(unwrappedType, NodeKind.Supertype)
- val superclass = unwrappedType.constructor.declarationDescriptor
- if (backref) {
- link(superclass, descriptor, RefKind.Inheritor)
- }
- link(descriptor, superclass, RefKind.Superclass)
+ appendType(unwrappedType, descriptor)
}
}
- fun DocumentationNode.appendProjection(projection: TypeProjection, kind: NodeKind = NodeKind.Type) {
- if (projection.isStarProjection) {
- appendTextNode("*", NodeKind.Type)
- } else {
- appendType(projection.type, kind, projection.projectionKind.label)
- }
- }
-
- fun DocumentationNode.appendType(kotlinType: KotlinType?, kind: NodeKind = NodeKind.Type, prefix: String = "") {
+ private fun DocumentationNodes.Class.appendType(
+ kotlinType: KotlinType?,
+ descriptor: ClassDescriptor?
+ ) {
if (kotlinType == null)
return
(kotlinType.unwrap() as? AbbreviatedType)?.let {
- return appendType(it.abbreviation)
+ return appendType(it.abbreviation, descriptor)
}
if (kotlinType.isDynamic()) {
- append(DocumentationNode("dynamic", Content.Empty, kind), RefKind.Detail)
+ append(kind.createNode("dynamic", descriptor), RefKind.Detail)
return
}
@@ -198,244 +100,80 @@ class DocumentationBuilder
is Named -> classifierDescriptor.name.asString()
else -> "<anonymous>"
}
- val node = DocumentationNode(name, Content.Empty, kind)
- if (prefix != "") {
- node.appendTextNode(prefix, NodeKind.Modifier)
- }
- if (kotlinType.isNullabilityFlexible()) {
- node.appendTextNode("!", NodeKind.NullabilityModifier)
- } else if (kotlinType.isMarkedNullable) {
- node.appendTextNode("?", NodeKind.NullabilityModifier)
- }
- if (classifierDescriptor != null) {
- val externalLink =
- linkResolver.externalDocumentationLinkResolver.buildExternalDocumentationLink(classifierDescriptor)
- if (externalLink != null) {
- if (classifierDescriptor !is TypeParameterDescriptor) {
- val targetNode =
- refGraph.lookup(classifierDescriptor.signature()) ?: classifierDescriptor.build(true)
- node.append(targetNode, RefKind.ExternalType)
- node.append(DocumentationNode(externalLink, Content.Empty, NodeKind.ExternalLink), RefKind.Link)
- }
- } else {
- link(
- node, classifierDescriptor,
- if (classifierDescriptor.isBoringBuiltinClass()) RefKind.HiddenLink else RefKind.Link
- )
- }
- if (classifierDescriptor !is TypeParameterDescriptor) {
- node.append(
- DocumentationNode(
- classifierDescriptor.fqNameUnsafe.asString(),
- Content.Empty,
- NodeKind.QualifiedName
- ), RefKind.Detail
- )
- }
- }
-
+ val node = kind.createNode(name, descriptor)
append(node, RefKind.Detail)
- node.appendAnnotations(kotlinType)
for (typeArgument in kotlinType.arguments) {
- node.appendProjection(typeArgument)
- }
- }
-
- fun ClassifierDescriptor.isBoringBuiltinClass(): Boolean =
- DescriptorUtils.getFqName(this).asString() in boringBuiltinClasses
-
- fun DocumentationNode.appendAnnotations(annotated: Annotated) {
- annotated.annotations.forEach {
- it.build()?.let { annotationNode ->
- if (annotationNode.isSinceKotlin()) {
- appendSinceKotlin(annotationNode)
- }
- else {
- val refKind = when {
- it.isDocumented() ->
- when {
- annotationNode.isDeprecation() -> RefKind.Deprecation
- else -> RefKind.Annotation
- }
- it.isHiddenInDocumentation() -> RefKind.HiddenAnnotation
- else -> return@forEach
- }
- append(annotationNode, refKind)
- }
-
- }
- }
- }
-
- fun DocumentationNode.appendExternalLink(externalLink: String) {
- append(DocumentationNode(externalLink, Content.Empty, NodeKind.ExternalLink), RefKind.Link)
- }
-
- fun DocumentationNode.appendExternalLink(descriptor: DeclarationDescriptor) {
- val target = linkResolver.externalDocumentationLinkResolver.buildExternalDocumentationLink(descriptor)
- if (target != null) {
- appendExternalLink(target)
- }
- }
-
- fun DocumentationNode.appendSinceKotlin(annotation: DocumentationNode) {
- val kotlinVersion = annotation
- .detail(NodeKind.Parameter)
- .detail(NodeKind.Value)
- .name.removeSurrounding("\"")
-
- sinceKotlin = kotlinVersion
- }
-
- fun DocumentationNode.appendDefaultSinceKotlin() {
- if (sinceKotlin == null) {
- sinceKotlin = passConfiguration.sinceKotlin
- }
- }
-
- fun DocumentationNode.appendModifiers(descriptor: DeclarationDescriptor) {
- val psi = (descriptor as DeclarationDescriptorWithSource).source.getPsi() as? KtModifierListOwner ?: return
- KtTokens.MODIFIER_KEYWORDS_ARRAY.filter {
- it !in knownModifiers
- }.sortedBy {
- MODIFIERS_ORDER.indexOf(it)
- }.forEach {
- if (psi.hasModifier(it)) {
- appendTextNode(it.value, NodeKind.Modifier)
- }
+ node.appendProjection(typeArgument, null)
}
- appendInline(descriptor, psi)
}
- fun DocumentationNode.appendDefaultPlatforms(descriptor: DeclarationDescriptor) {
- for (platform in defaultPlatformsProvider.getDefaultPlatforms(descriptor)) {
- append(platformNodeRegistry[platform], RefKind.Platform)
- }
- }
-
- fun DocumentationNode.isDeprecation() = name == "Deprecated" || name == "deprecated"
-
- fun DocumentationNode.isSinceKotlin() = name == "SinceKotlin" && kind == NodeKind.Annotation
-
- fun DocumentationNode.appendSourceLink(sourceElement: SourceElement) {
- appendSourceLink(sourceElement.getPsi(), passConfiguration.sourceLinks)
- }
-
- fun DocumentationNode.appendSignature(descriptor: DeclarationDescriptor) {
- appendTextNode(descriptor.signature(), NodeKind.Signature, RefKind.Detail)
- }
-
- fun DocumentationNode.appendChild(descriptor: DeclarationDescriptor, kind: RefKind): DocumentationNode? {
+ fun DocumentationNode<*>.appendChild(descriptor: DeclarationDescriptor) {
if (!descriptor.isGenerated() && descriptor.isDocumented(passConfiguration)) {
val node = descriptor.build()
append(node, kind)
- return node
}
- return null
}
- fun createGroupNode(signature: String, nodes: List<DocumentationNode>) = (nodes.find { it.kind == NodeKind.GroupNode } ?:
- DocumentationNode(nodes.first().name, Content.Empty, NodeKind.GroupNode).apply {
- appendTextNode(signature, NodeKind.Signature, RefKind.Detail)
- })
- .also { groupNode ->
- nodes.forEach { node ->
- if (node != groupNode) {
- node.owner?.let { owner ->
- node.dropReferences { it.to == owner && it.kind == RefKind.Owner }
- owner.dropReferences { it.to == node && it.kind == RefKind.Member }
- owner.append(groupNode, RefKind.Member)
- }
- groupNode.append(node, RefKind.Member)
- }
- }
- }
-
-
- fun DocumentationNode.appendOrUpdateMember(descriptor: DeclarationDescriptor) {
- if (descriptor.isGenerated() || !descriptor.isDocumented(passConfiguration)) return
-
- val existingNode = refGraph.lookup(descriptor.signature())
- if (existingNode != null) {
- if (existingNode.kind == NodeKind.TypeAlias && descriptor is ClassDescriptor
- || existingNode.kind == NodeKind.Class && descriptor is TypeAliasDescriptor) {
- val node = createGroupNode(descriptor.signature(), listOf(existingNode, descriptor.build()))
- register(descriptor, node)
- return
- }
-
- existingNode.updatePlatforms(descriptor)
-
- if (descriptor is ClassDescriptor) {
- val membersToDocument = descriptor.collectMembersToDocument()
- for ((memberDescriptor, inheritedLinkKind, extraModifier) in membersToDocument) {
- if (memberDescriptor is ClassDescriptor) {
- existingNode.appendOrUpdateMember(memberDescriptor) // recurse into nested classes
- }
- else {
- val existingMemberNode = refGraph.lookup(memberDescriptor.signature())
- if (existingMemberNode != null) {
- existingMemberNode.updatePlatforms(memberDescriptor)
- }
- else {
- existingNode.appendClassMember(memberDescriptor, inheritedLinkKind, extraModifier)
+ fun DocumentationNode.appendMember(descriptor: DeclarationDescriptor) {
+ if (!descriptor.isGenerated() && descriptor.isDocumented(passConfiguration)) {
+ val existingNode = members.firstOrNull { it.descriptor?.fqNameSafe == descriptor.fqNameSafe }
+ if (existingNode != null) {
+ if (descriptor is ClassDescriptor) {
+ val membersToDocument = descriptor.collectMembersToDocument()
+ for ((memberDescriptor, _, _) in membersToDocument) {
+ if (memberDescriptor is ClassDescriptor) {
+ existingNode.appendMember(memberDescriptor) // recurse into nested classes
+ } else {
+ if (members.any { it.descriptor?.fqNameSafe == memberDescriptor.fqNameSafe }) {
+ existingNode.appendClassMember(memberDescriptor)
+ }
}
}
}
+ } else {
+ appendChild(descriptor, RefKind.Member)
}
}
- else {
- appendChild(descriptor, RefKind.Member)
- }
- }
-
- private fun DocumentationNode.updatePlatforms(descriptor: DeclarationDescriptor) {
- for (platform in defaultPlatformsProvider.getDefaultPlatforms(descriptor) - platforms) {
- append(platformNodeRegistry[platform], RefKind.Platform)
- }
}
- fun DocumentationNode.appendClassMember(descriptor: DeclarationDescriptor,
- inheritedLinkKind: RefKind = RefKind.InheritedMember,
- extraModifier: String?) {
- if (descriptor is CallableMemberDescriptor && descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
- val baseDescriptor = descriptor.overriddenDescriptors.firstOrNull()
- if (baseDescriptor != null) {
- link(this, baseDescriptor, inheritedLinkKind)
- }
- } else {
+ private fun DocumentationNode.appendClassMember(descriptor: DeclarationDescriptor) {
+ if (descriptor !is CallableMemberDescriptor || descriptor.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
val descriptorToUse = if (descriptor is ConstructorDescriptor) descriptor else descriptor.original
- val child = appendChild(descriptorToUse, RefKind.Member)
- if (extraModifier != null) {
- child?.appendTextNode("static", NodeKind.Modifier)
- }
+ appendChild(descriptorToUse, RefKind.Member)
}
}
- fun DocumentationNode.appendInPageChildren(descriptors: Iterable<DeclarationDescriptor>, kind: RefKind) {
- descriptors.forEach { descriptor ->
- val node = appendChild(descriptor, kind)
- node?.addReferenceTo(this, RefKind.TopLevelPage)
- }
- }
-
- fun DocumentationModule.appendFragments(fragments: Collection<PackageFragmentDescriptor>,
- packageContent: Map<String, Content>,
- packageDocumentationBuilder: PackageDocumentationBuilder) {
- val allFqNames = fragments.filter{ it.isDocumented(passConfiguration) }.map { it.fqName }.distinct()
+ fun DocumentationNodes.Module.appendFragments(
+ fragments: Collection<PackageFragmentDescriptor>,
+ packageDocumentationBuilder: PackageDocumentationBuilder
+ ) {
+ val allFqNames = fragments.filter { it.isDocumented(passConfiguration) }.map { it.fqName }.distinct()
for (packageName in allFqNames) {
if (packageName.isRoot && !passConfiguration.includeRootPackage) continue
- val declarations = fragments.filter { it.fqName == packageName }.flatMap { it.getMemberScope().getContributedDescriptors() }
+ val declarations = fragments.filter { it.fqName == packageName }
+ .flatMap { it.getMemberScope().getContributedDescriptors() }
if (passConfiguration.skipEmptyPackages && declarations.none { it.isDocumented(passConfiguration) }) continue
logger.info(" package $packageName: ${declarations.count()} declarations")
- val packageNode = findOrCreatePackageNode(this, packageName.asString(), packageContent, this@DocumentationBuilder.refGraph)
- packageDocumentationBuilder.buildPackageDocumentation(this@DocumentationBuilder, packageName, packageNode,
- declarations, allFqNames)
+ val packageNode = findOrCreatePackageNode(this, packageName.asString())
+ packageDocumentationBuilder.buildPackageDocumentation(
+ this@DocumentationBuilder, packageName, packageNode,
+ declarations, allFqNames
+ )
}
+ }
+ fun findOrCreatePackageNode(
+ module: DocumentationNodes.Module,
+ packageName: String
+ ): DocumentationNode<*> {
+ val node = module?.member(DocumentationNodes.Package::class) ?: DocumentationNodes.Package(packageName)
+ if (module != null && node !in module.members) {
+ module.append(node, RefKind.Member)
+ }
+ return node
}
fun propagateExtensionFunctionsToSubclasses(
@@ -466,12 +204,6 @@ class DocumentationBuilder
).asSequence()
}
-
- val documentingDescriptors = fragments.flatMap { it.getMemberScope().getContributedDescriptors() }
- val documentingClasses = documentingDescriptors.filterIsInstance<ClassDescriptor>()
-
- val classHierarchy = buildClassHierarchy(documentingClasses)
-
val allExtensionFunctions =
allDescriptors
.filterIsInstance<CallableMemberDescriptor>()
@@ -479,9 +211,9 @@ class DocumentationBuilder
val extensionFunctionsByName = allExtensionFunctions.groupBy { it.name }
fun isIgnoredReceiverType(type: KotlinType) =
- type.isDynamic() ||
- type.isAnyOrNullableAny() ||
- (type.isTypeParameter() && type.immediateSupertypes().all { it.isAnyOrNullableAny() })
+ type.isDynamic() ||
+ type.isAnyOrNullableAny() ||
+ (type.isTypeParameter() && type.immediateSupertypes().all { it.isAnyOrNullableAny() })
for (extensionFunction in allExtensionFunctions) {
@@ -492,53 +224,9 @@ class DocumentationBuilder
?: emptyList()
if (isIgnoredReceiverType(extensionReceiverParameter.type)) continue
- val subclasses =
- classHierarchy.filter { (key) -> key.isExtensionApplicable(extensionFunction) }
- if (subclasses.isEmpty()) continue
- subclasses.values.flatten().forEach { subclass ->
- if (subclass.isExtensionApplicable(extensionFunction) &&
- possiblyShadowingFunctions.none { subclass.isExtensionApplicable(it) }) {
-
- val hasExternalLink =
- linkResolver.externalDocumentationLinkResolver.buildExternalDocumentationLink(
- extensionFunction
- ) != null
- if (hasExternalLink) {
- val containerDesc =
- extensionFunction.containingDeclaration as? PackageFragmentDescriptor
- if (containerDesc != null) {
- val container = refGraph.lookup(containerDesc.signature())
- ?: containerDesc.buildExternal()
- container.append(extensionFunction.buildExternal(), RefKind.Member)
- }
- }
-
- refGraph.link(subclass.signature(), extensionFunction.signature(), RefKind.Extension)
- }
- }
}
}
- private fun ClassDescriptor.isExtensionApplicable(extensionFunction: CallableMemberDescriptor): Boolean {
- val receiverType = extensionFunction.fuzzyExtensionReceiverType()?.makeNotNullable()
- val classType = defaultType.toFuzzyType(declaredTypeParameters)
- return receiverType != null && classType.checkIsSubtypeOf(receiverType) != null
- }
-
- private fun buildClassHierarchy(classes: List<ClassDescriptor>): Map<ClassDescriptor, List<ClassDescriptor>> {
- val result = hashMapOf<ClassDescriptor, MutableList<ClassDescriptor>>()
- classes.forEach { cls ->
- TypeUtils.getAllSupertypes(cls.defaultType).forEach { supertype ->
- val classDescriptor = supertype.constructor.declarationDescriptor as? ClassDescriptor
- if (classDescriptor != null) {
- val subtypesList = result.getOrPut(classDescriptor) { arrayListOf() }
- subtypesList.add(cls)
- }
- }
- }
- return result
- }
-
private fun CallableMemberDescriptor.canShadow(other: CallableMemberDescriptor): Boolean {
if (this == other) return false
if (this is PropertyDescriptor && other is PropertyDescriptor) {
@@ -570,89 +258,47 @@ class DocumentationBuilder
else -> throw IllegalStateException("Descriptor $this is not known")
}
- fun PackageFragmentDescriptor.buildExternal(): DocumentationNode {
- val node = DocumentationNode(fqName.asString(), Content.Empty, NodeKind.Package)
-
- val externalLink = linkResolver.externalDocumentationLinkResolver.buildExternalDocumentationLink(this)
- if (externalLink != null) {
- node.append(DocumentationNode(externalLink, Content.Empty, NodeKind.ExternalLink), RefKind.Link)
- }
- register(this, node)
- return node
- }
-
- fun CallableDescriptor.buildExternal(): DocumentationNode = when(this) {
- is FunctionDescriptor -> build(true)
- is PropertyDescriptor -> build(true)
- else -> throw IllegalStateException("Descriptor $this is not known")
- }
-
-
fun ClassifierDescriptor.build(external: Boolean = false): DocumentationNode = when (this) {
- is ClassDescriptor -> build(external)
- is TypeAliasDescriptor -> build(external)
+ is ClassDescriptor -> build(this, external)
+ is TypeAliasDescriptor -> build()
is TypeParameterDescriptor -> build()
else -> throw IllegalStateException("Descriptor $this is not known")
}
- fun TypeAliasDescriptor.build(external: Boolean = false): DocumentationNode {
- val node = nodeForDescriptor(this, NodeKind.TypeAlias)
-
- if (!external) {
- node.appendDefaultSinceKotlin()
- node.appendAnnotations(this)
- }
- node.appendModifiers(this)
- node.appendInPageChildren(typeConstructor.parameters, RefKind.Detail)
-
- node.appendType(underlyingType, NodeKind.TypeAliasUnderlyingType)
-
- if (!external) {
- node.appendSourceLink(source)
- node.appendDefaultPlatforms(this)
- }
- register(this, node)
+ fun TypeAliasDescriptor.build(): DocumentationNode {
+ val node = DocumentationNodes.TypeAlias(name.asString(), this)
+ node.appendType(underlyingType, this, DocumentationNodes.TypeAliasUnderlyingType::class)
return node
}
- fun ClassDescriptor.build(external: Boolean = false): DocumentationNode {
- val kind = when {
- kind == ClassKind.OBJECT -> NodeKind.Object
- kind == ClassKind.INTERFACE -> NodeKind.Interface
- kind == ClassKind.ENUM_CLASS -> NodeKind.Enum
- kind == ClassKind.ANNOTATION_CLASS -> NodeKind.AnnotationClass
- kind == ClassKind.ENUM_ENTRY -> NodeKind.EnumItem
- isSubclassOfThrowable() -> NodeKind.Exception
- else -> NodeKind.Class
+ fun ClassDescriptor.build(descriptor: DeclarationDescriptor, external: Boolean = false): DocumentationNode {
+ val node = when {
+ kind == ClassKind.OBJECT -> DocumentationNodes.Object(descriptor.name.asString(), descriptor)
+ kind == ClassKind.INTERFACE -> DocumentationNodes.Interface(descriptor.name.asString(), descriptor)
+ kind == ClassKind.ENUM_CLASS -> DocumentationNodes.Enum(descriptor.name.asString(), descriptor)
+ kind == ClassKind.ANNOTATION_CLASS -> DocumentationNodes.AnnotationClass(descriptor.name.asString(), descriptor)
+ kind == ClassKind.ENUM_ENTRY -> DocumentationNodes.EnumItem(descriptor.name.asString(), descriptor)
+ isSubclassOfThrowable() -> DocumentationNodes.Exception(descriptor.name.asString(), descriptor)
+ else -> DocumentationNodes.Class(descriptor.name.asString(), descriptor)
}
- val node = nodeForDescriptor(this, kind, external)
- register(this, node)
supertypesWithAnyPrecise().forEach {
node.appendSupertype(this, it, !external)
}
- if (getKind() != ClassKind.OBJECT && getKind() != ClassKind.ENUM_ENTRY) {
- node.appendInPageChildren(typeConstructor.parameters, RefKind.Detail)
- }
if (!external) {
- for ((descriptor, inheritedLinkKind, extraModifier) in collectMembersToDocument()) {
- node.appendClassMember(descriptor, inheritedLinkKind, extraModifier)
+ for ((membersDescriptor, _, _) in collectMembersToDocument()) {
+ node.appendClassMember(membersDescriptor)
}
- node.appendDefaultSinceKotlin()
- node.appendAnnotations(this)
- }
- node.appendModifiers(this)
- if (!external) {
- node.appendSourceLink(source)
- node.appendDefaultPlatforms(this)
}
return node
}
- data class ClassMember(val descriptor: DeclarationDescriptor,
- val inheritedLinkKind: RefKind = RefKind.InheritedMember,
- val extraModifier: String? = null)
+ data class ClassMember(
+ val descriptor: DeclarationDescriptor,
+ val inheritedLinkKind: RefKind = RefKind.InheritedMember,
+ val extraModifier: String? = null
+ )
- fun ClassDescriptor.collectMembersToDocument(): List<ClassMember> {
+ private fun ClassDescriptor.collectMembersToDocument(): List<ClassMember> {
val result = arrayListOf<ClassMember>()
if (kind != ClassKind.OBJECT && kind != ClassKind.ENUM_ENTRY) {
val constructorsToDocument = if (kind == ClassKind.ENUM_CLASS)
@@ -663,11 +309,11 @@ class DocumentationBuilder
}
defaultType.memberScope.getContributedDescriptors()
- .filter { it != companionObjectDescriptor }
- .mapTo(result) { ClassMember(it) }
+ .filter { it != companionObjectDescriptor }
+ .mapTo(result) { ClassMember(it) }
staticScope.getContributedDescriptors()
- .mapTo(result) { ClassMember(it, extraModifier = "static") }
+ .mapTo(result) { ClassMember(it, extraModifier = "static") }
val companionObjectDescriptor = companionObjectDescriptor
if (companionObjectDescriptor != null && companionObjectDescriptor.isDocumented(passConfiguration)) {
@@ -678,274 +324,51 @@ class DocumentationBuilder
}
if (companionObjectDescriptor.getAllSuperclassesWithoutAny().isNotEmpty()
- || companionObjectDescriptor.getSuperInterfaces().isNotEmpty()) {
+ || companionObjectDescriptor.getSuperInterfaces().isNotEmpty()) {
result += ClassMember(companionObjectDescriptor)
}
}
return result
}
- fun CallableDescriptor.isInheritedFromAny(): Boolean {
+ private fun CallableDescriptor.isInheritedFromAny(): Boolean {
return findTopMostOverriddenDescriptors().any {
DescriptorUtils.getFqNameSafe(it.containingDeclaration).asString() == "kotlin.Any"
}
}
- fun ClassDescriptor.isSubclassOfThrowable(): Boolean =
- defaultType.supertypes().any { it.constructor.declarationDescriptor == builtIns.throwable }
+ private fun ClassDescriptor.isSubclassOfThrowable(): Boolean =
+ defaultType.supertypes().any { it.constructor.declarationDescriptor == builtIns.throwable }
- fun ConstructorDescriptor.build(): DocumentationNode {
- val node = nodeForDescriptor(this, NodeKind.Constructor)
- node.appendInPageChildren(valueParameters, RefKind.Detail)
- node.appendDefaultPlatforms(this)
- node.appendDefaultSinceKotlin()
- register(this, node)
- return node
- }
+ fun ConstructorDescriptor.build(): DocumentationNode =
+ DocumentationNodes.Constructor(name.asString(), this)
private fun CallableMemberDescriptor.inCompanionObject(): Boolean {
val containingDeclaration = containingDeclaration
- if ((containingDeclaration as? ClassDescriptor)?.isCompanionObject ?: false) {
+ if ((containingDeclaration as? ClassDescriptor)?.isCompanionObject == true) {
return true
}
val receiver = extensionReceiverParameter
return (receiver?.type?.constructor?.declarationDescriptor as? ClassDescriptor)?.isCompanionObject ?: false
}
- fun FunctionDescriptor.build(external: Boolean = false): DocumentationNode {
- if (ErrorUtils.containsErrorType(this)) {
- logger.warn("Found an unresolved type in ${signatureWithSourceLocation()}")
- }
-
- val node = nodeForDescriptor(this, if (inCompanionObject()) NodeKind.CompanionObjectFunction else NodeKind.Function, external)
-
- node.appendInPageChildren(typeParameters, RefKind.Detail)
- extensionReceiverParameter?.let { node.appendChild(it, RefKind.Detail) }
- node.appendInPageChildren(valueParameters, RefKind.Detail)
- node.appendType(returnType)
- if (!external) {
- node.appendDefaultSinceKotlin()
- }
- node.appendAnnotations(this)
- node.appendModifiers(this)
- if (!external) {
- node.appendSourceLink(source)
- node.appendDefaultPlatforms(this)
- } else {
- node.appendExternalLink(this)
- }
-
- overriddenDescriptors.forEach {
- addOverrideLink(it, this)
- }
-
- register(this, node)
- return node
- }
-
- fun addOverrideLink(baseClassFunction: CallableMemberDescriptor, overridingFunction: CallableMemberDescriptor) {
- val source = baseClassFunction.original.source.getPsi()
- if (source != null) {
- link(overridingFunction, baseClassFunction, RefKind.Override)
- } else {
- baseClassFunction.overriddenDescriptors.forEach {
- addOverrideLink(it, overridingFunction)
- }
- }
- }
-
- fun PropertyDescriptor.build(external: Boolean = false): DocumentationNode {
- val node = nodeForDescriptor(
- this,
- if (inCompanionObject()) NodeKind.CompanionObjectProperty else NodeKind.Property,
- external
- )
- node.appendInPageChildren(typeParameters, RefKind.Detail)
- extensionReceiverParameter?.let { node.appendChild(it, RefKind.Detail) }
- node.appendType(returnType)
- if (!external) {
- node.appendDefaultSinceKotlin()
- }
- node.appendAnnotations(this)
- node.appendModifiers(this)
- if (!external) {
- node.appendSourceLink(source)
- if (isVar) {
- node.appendTextNode("var", NodeKind.Modifier)
- }
-
- if (isConst) {
- this.compileTimeInitializer?.toDocumentationNode()?.let { node.append(it, RefKind.Detail) }
- }
-
-
- getter?.let {
- if (!it.isDefault) {
- node.addAccessorDocumentation(descriptorDocumentationParser.parseDocumentation(it), "Getter")
- }
- }
- setter?.let {
- if (!it.isDefault) {
- node.addAccessorDocumentation(descriptorDocumentationParser.parseDocumentation(it), "Setter")
- }
- }
- node.appendDefaultPlatforms(this)
- }
- if (external) {
- node.appendExternalLink(this)
- }
-
- overriddenDescriptors.forEach {
- addOverrideLink(it, this)
- }
-
- register(this, node)
- return node
- }
-
- fun DocumentationNode.addAccessorDocumentation(documentation: Content, prefix: String) {
- if (documentation == Content.Empty) return
- updateContent {
- if (!documentation.children.isEmpty()) {
- val section = addSection(prefix, null)
- documentation.children.forEach { section.append(it) }
- }
- documentation.sections.forEach {
- val section = addSection("$prefix ${it.tag}", it.subjectName)
- it.children.forEach { section.append(it) }
- }
- }
- }
-
- fun ValueParameterDescriptor.build(): DocumentationNode {
- val node = nodeForDescriptor(this, NodeKind.Parameter)
- node.appendType(varargElementType ?: type)
- if (declaresDefaultValue()) {
- val psi = source.getPsi() as? KtParameter
- if (psi != null) {
- val defaultValueText = psi.defaultValue?.text
- if (defaultValueText != null) {
- node.appendTextNode(defaultValueText, NodeKind.Value)
- }
- }
- }
- node.appendDefaultSinceKotlin()
- node.appendAnnotations(this)
- node.appendModifiers(this)
- if (varargElementType != null && node.details(NodeKind.Modifier).none { it.name == "vararg" }) {
- node.appendTextNode("vararg", NodeKind.Modifier)
- }
- register(this, node)
- return node
- }
-
- fun TypeParameterDescriptor.build(): DocumentationNode {
- val doc = descriptorDocumentationParser.parseDocumentation(this)
- val name = name.asString()
- val prefix = variance.label
-
- val node = DocumentationNode(name, doc, NodeKind.TypeParameter)
- if (prefix != "") {
- node.appendTextNode(prefix, NodeKind.Modifier)
- }
- if (isReified) {
- node.appendTextNode("reified", NodeKind.Modifier)
- }
-
- for (constraint in upperBounds) {
- if (KotlinBuiltIns.isDefaultBound(constraint)) {
- continue
- }
- node.appendType(constraint, NodeKind.UpperBound)
- }
- register(this, node)
- return node
- }
+ fun FunctionDescriptor.build(): DocumentationNode =
+ if (inCompanionObject())
+ DocumentationNodes.CompanionObjectFunction(name.asString(),this)
+ else
+ DocumentationNodes.Function(name.asString(),this)
- fun ReceiverParameterDescriptor.build(): DocumentationNode {
- var receiverClass: DeclarationDescriptor = type.constructor.declarationDescriptor!!
- if ((receiverClass as? ClassDescriptor)?.isCompanionObject ?: false) {
- receiverClass = receiverClass.containingDeclaration!!
- } else if (receiverClass is TypeParameterDescriptor) {
- val upperBoundClass = receiverClass.upperBounds.singleOrNull()?.constructor?.declarationDescriptor
- if (upperBoundClass != null) {
- receiverClass = upperBoundClass
- }
- }
+ fun PropertyDescriptor.build(): DocumentationNode =
+ DocumentationNodes.Property(name.asString(), this)
- if ((containingDeclaration as? FunctionDescriptor)?.dispatchReceiverParameter == null) {
- link(receiverClass, containingDeclaration, RefKind.Extension)
- }
-
- val node = DocumentationNode(name.asString(), Content.Empty, NodeKind.Receiver)
- node.appendType(type)
- register(this, node)
- return node
- }
-
- fun AnnotationDescriptor.build(): DocumentationNode? {
- val annotationClass = type.constructor.declarationDescriptor
- if (annotationClass == null || ErrorUtils.isError(annotationClass)) {
- return null
- }
- val node = DocumentationNode(annotationClass.name.asString(), Content.Empty, NodeKind.Annotation)
- allValueArguments.forEach { (name, value) ->
- val valueNode = value.toDocumentationNode()
- if (valueNode != null) {
- val paramNode = DocumentationNode(name.asString(), Content.Empty, NodeKind.Parameter)
- paramNode.append(valueNode, RefKind.Detail)
- node.append(paramNode, RefKind.Detail)
- }
- }
- return node
- }
-
- fun ConstantValue<*>.toDocumentationNode(): DocumentationNode? = value.let { value ->
- val text = when (value) {
- is String ->
- "\"" + StringUtil.escapeStringCharacters(value) + "\""
- is EnumEntrySyntheticClassDescriptor ->
- value.containingDeclaration.name.asString() + "." + value.name.asString()
- is Pair<*, *> -> {
- val (classId, name) = value
- if (classId is ClassId && name is Name) {
- classId.shortClassName.asString() + "." + name.asString()
- } else {
- value.toString()
- }
- }
- else -> "$value"
- }
- DocumentationNode(text, Content.Empty, NodeKind.Value)
- }
+ fun ValueParameterDescriptor.build(): DocumentationNode =
+ DocumentationNodes.Parameter(name.asString(), this)
+ fun TypeParameterDescriptor.build(): DocumentationNode =
+ DocumentationNodes.TypeParameter(name.asString(), this)
- fun DocumentationNode.getParentForPackageMember(
- descriptor: DeclarationDescriptor,
- externalClassNodes: MutableMap<FqName, DocumentationNode>,
- allFqNames: Collection<FqName>,
- packageName: FqName
- ): DocumentationNode {
- if (descriptor is CallableMemberDescriptor) {
- val extensionClassDescriptor = descriptor.getExtensionClassDescriptor()
- if (extensionClassDescriptor != null && isExtensionForExternalClass(descriptor, extensionClassDescriptor, allFqNames) &&
- !ErrorUtils.isError(extensionClassDescriptor)) {
- val fqName = DescriptorUtils.getFqNameSafe(extensionClassDescriptor)
- return externalClassNodes.getOrPut(fqName) {
- val newNode = DocumentationNode(fqName.asString(), Content.Empty, NodeKind.ExternalClass)
- val externalLink = linkResolver.externalDocumentationLinkResolver.buildExternalDocumentationLink(extensionClassDescriptor)
- if (externalLink != null) {
- newNode.append(DocumentationNode(externalLink, Content.Empty, NodeKind.ExternalLink), RefKind.Link)
- }
- append(newNode, RefKind.Member)
- refGraph.register("${packageName.asString()}:${extensionClassDescriptor.signature()}", newNode)
- newNode
- }
- }
- }
- return this
- }
-
+ fun ReceiverParameterDescriptor.build(): DocumentationNode =
+ DocumentationNodes.Receiver(name.asString(), this)
}
fun DeclarationDescriptor.isDocumented(passConfiguration: DokkaConfiguration.PassConfiguration): Boolean {
@@ -956,25 +379,22 @@ fun DeclarationDescriptor.isDocumented(passConfiguration: DokkaConfiguration.Pas
&& (!passConfiguration.effectivePackageOptions(fqNameSafe).skipDeprecated || !isDeprecated())
}
-private fun DeclarationDescriptor.isGenerated() = this is CallableMemberDescriptor && kind != CallableMemberDescriptor.Kind.DECLARATION
+private fun DeclarationDescriptor.isGenerated() =
+ this is CallableMemberDescriptor && kind != CallableMemberDescriptor.Kind.DECLARATION
class KotlinPackageDocumentationBuilder : PackageDocumentationBuilder {
- override fun buildPackageDocumentation(documentationBuilder: DocumentationBuilder,
- packageName: FqName,
- packageNode: DocumentationNode,
- declarations: List<DeclarationDescriptor>,
- allFqNames: Collection<FqName>) {
- val externalClassNodes = hashMapOf<FqName, DocumentationNode>()
+
+ override fun buildPackageDocumentation(
+ documentationBuilder: DocumentationBuilder,
+ packageName: FqName,
+ packageNode: DocumentationNode,
+ declarations: List<DeclarationDescriptor>,
+ allFqNames: Collection<FqName>
+ ) {
declarations.forEach { descriptor ->
with(documentationBuilder) {
if (descriptor.isDocumented(passConfiguration)) {
- val parent = packageNode.getParentForPackageMember(
- descriptor,
- externalClassNodes,
- allFqNames,
- packageName
- )
- parent.appendOrUpdateMember(descriptor)
+ packageNode.appendMember(descriptor)
}
}
}
@@ -982,17 +402,19 @@ class KotlinPackageDocumentationBuilder : PackageDocumentationBuilder {
}
class KotlinJavaDocumentationBuilder
-@Inject constructor(val resolutionFacade: DokkaResolutionFacade,
- val documentationBuilder: DocumentationBuilder,
- val passConfiguration: DokkaConfiguration.PassConfiguration,
- val logger: DokkaLogger) : JavaDocumentationBuilder {
+@Inject constructor(
+ val resolutionFacade: DokkaResolutionFacade,
+ val documentationBuilder: DocumentationBuilder,
+ val passConfiguration: DokkaConfiguration.PassConfiguration,
+ val logger: DokkaLogger
+) : JavaDocumentationBuilder {
override fun appendFile(file: PsiJavaFile, module: DocumentationModule, packageContent: Map<String, Content>) {
val classDescriptors = file.classes.map {
it.getJavaClassDescriptor(resolutionFacade)
}
if (classDescriptors.any { it != null && it.isDocumented(passConfiguration) }) {
- val packageNode = findOrCreatePackageNode(module, file.packageName, packageContent, documentationBuilder.refGraph)
+ val packageNode = documentationBuilder.findOrCreatePackageNode(module, file.packageName)
for (descriptor in classDescriptors.filterNotNull()) {
with(documentationBuilder) {
@@ -1003,24 +425,6 @@ class KotlinJavaDocumentationBuilder
}
}
-private val hiddenAnnotations = setOf(
- KotlinBuiltIns.FQ_NAMES.parameterName.asString()
-)
-
-private fun AnnotationDescriptor.isHiddenInDocumentation() =
- type.constructor.declarationDescriptor?.fqNameSafe?.asString() in hiddenAnnotations
-
-private fun AnnotationDescriptor.isDocumented(): Boolean {
- if (source.getPsi() != null && mustBeDocumented()) return true
- val annotationClassName = type.constructor.declarationDescriptor?.fqNameSafe?.asString()
- return annotationClassName == KotlinBuiltIns.FQ_NAMES.extensionFunctionType.asString()
-}
-
-fun AnnotationDescriptor.mustBeDocumented(): Boolean {
- val annotationClass = type.constructor.declarationDescriptor as? Annotated ?: return false
- return annotationClass.isDocumentedAnnotation()
-}
-
fun DeclarationDescriptor.isDocumentationSuppressed(passConfiguration: DokkaConfiguration.PassConfiguration): Boolean {
if (passConfiguration.effectivePackageOptions(fqNameSafe).suppress) return true
@@ -1037,25 +441,12 @@ fun DeclarationDescriptor.isDocumentationSuppressed(passConfiguration: DokkaConf
}
fun DeclarationDescriptor.sourcePsi() =
- ((original as? DeclarationDescriptorWithSource)?.source as? PsiSourceElement)?.psi
+ ((original as? DeclarationDescriptorWithSource)?.source as? PsiSourceElement)?.psi
fun DeclarationDescriptor.isDeprecated(): Boolean = annotations.any {
DescriptorUtils.getFqName(it.type.constructor.declarationDescriptor!!).asString() == "kotlin.Deprecated"
} || (this is ConstructorDescriptor && containingDeclaration.isDeprecated())
-fun CallableMemberDescriptor.getExtensionClassDescriptor(): ClassifierDescriptor? {
- val extensionReceiver = extensionReceiverParameter
- if (extensionReceiver != null) {
- val type = extensionReceiver.type
- val receiverClass = type.constructor.declarationDescriptor as? ClassDescriptor
- if (receiverClass?.isCompanionObject ?: false) {
- return receiverClass?.containingDeclaration as? ClassifierDescriptor
- }
- return receiverClass
- }
- return null
-}
-
fun DeclarationDescriptor.signature(): String {
if (this != original) return original.signature()
return when (this) {
@@ -1126,28 +517,6 @@ fun DeclarationDescriptor.sourceLocation(): String? {
return null
}
-fun DocumentationModule.prepareForGeneration(configuration: DokkaConfiguration) {
- if (configuration.generateIndexPages) {
- generateAllTypesNode()
- }
- nodeRefGraph.resolveReferences()
-}
-
-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.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)
- for (typeNode in allTypes) {
- allTypesNode.addReferenceTo(typeNode, RefKind.Member)
- }
-
- append(allTypesNode, RefKind.Member)
-}
-
fun ClassDescriptor.supertypesWithAnyPrecise(): Collection<KotlinType> {
if (KotlinBuiltIns.isAny(this)) {
return emptyList()
@@ -1160,5 +529,6 @@ fun PassConfiguration.effectivePackageOptions(pack: String): DokkaConfiguration.
return perPackageOptions.firstOrNull { pack == it.prefix || pack.startsWith(it.prefix + ".") } ?: rootPackageOptions
}
-fun PassConfiguration.effectivePackageOptions(pack: FqName): DokkaConfiguration.PackageOptions = effectivePackageOptions(pack.asString())
+fun PassConfiguration.effectivePackageOptions(pack: FqName): DokkaConfiguration.PackageOptions =
+ effectivePackageOptions(pack.asString())
diff --git a/core/src/main/kotlin/Kotlin/KotlinAsJavaDocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/KotlinAsJavaDocumentationBuilder.kt
index ee9d8c51..70c04da6 100644
--- a/core/src/main/kotlin/Kotlin/KotlinAsJavaDocumentationBuilder.kt
+++ b/core/src/main/kotlin/Kotlin/KotlinAsJavaDocumentationBuilder.kt
@@ -30,8 +30,7 @@ class KotlinAsJavaDocumentationBuilder
return
}
- val javaDocumentationBuilder = JavaPsiDocumentationBuilder(documentationBuilder.passConfiguration,
- documentationBuilder.refGraph,
+ val javaDocumentationBuilder = JavaPsiDocumentationBuilder(documentationBuilder,
kotlinAsJavaDocumentationParser)
psiPackage.classes.filter { it is KtLightElement<*, *> }.filter { it.isVisibleInDocumentation() }.forEach {
diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt
index 66ee33e1..19ba22a6 100644
--- a/core/src/main/kotlin/Model/DocumentationNode.kt
+++ b/core/src/main/kotlin/Model/DocumentationNode.kt
@@ -1,330 +1,75 @@
package org.jetbrains.dokka
-import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
-import java.util.*
-import kotlin.reflect.KClass
-import kotlin.reflect.full.primaryConstructor
+import org.jetbrains.dokka.links.ClassReference
+import org.jetbrains.kotlin.descriptors.*
class DocumentationNodes {
- class Unknown(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor)
+ class Module(name: String, parent: DocumentationNode<*>? = null):
+ DocumentationNode<Nothing>(name, parent = parent)
- class Package(name: String) :
- DocumentationNode(name)
+ class Package(name: String, parent: DocumentationNode<*>):
+ DocumentationNode<Nothing>(name, parent = parent)
- class Class(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor) {
+ class Class(name: String, descriptor: ClassDescriptor, parent: DocumentationNode<*>? = null) :
+ DocumentationNode<ClassDescriptor>(name, descriptor, parent) {
override val classLike: Boolean = true
- }
-
- class Interface(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor) {
- override val classLike: Boolean = true
- override val superclassType: DocumentationNode? = null
- }
-
- class Enum(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor) {
- override val classLike: Boolean = true
- }
-
- class AnnotationClass(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor) {
- override val classLike: Boolean = true
- }
-
- class Exception(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor) {
- override val classLike: Boolean = true
- }
-
- class EnumItem(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor) {
- override val memberLike = true
- }
-
- class Object(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor) {
- override val classLike: Boolean = true
- }
-
- class TypeAlias(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor)
-
- class Constructor(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor) {
+ val supertypes = mutableListOf<ClassReference>()
+ val isInterface: Boolean
+ get() = descriptor?.kind == ClassKind.CLASS
+ val isEnum: Boolean
+ get() = descriptor?.kind == ClassKind.ENUM_CLASS
+ val isEnumEntry: Boolean
+ get() = descriptor?.kind == ClassKind.ENUM_ENTRY
+ val isAnnotationClass: Boolean
+ get() = descriptor?.kind == ClassKind.ANNOTATION_CLASS
+ val isObject: Boolean
+ get() = descriptor?.kind == ClassKind.OBJECT
+ }
+
+ class Constructor(name: String, descriptor: ConstructorDescriptor) :
+ DocumentationNode<ConstructorDescriptor>(name, descriptor) {
override val memberLike = true
}
- class Function(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor) {
+ class Function(name: String, descriptor: FunctionDescriptor) :
+ DocumentationNode<FunctionDescriptor>(name, descriptor) {
override val memberLike = true
}
- class Property(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor) {
+ class Property(name: String, descriptor: PropertyDescriptor) :
+ DocumentationNode<PropertyDescriptor>(name, descriptor) {
override val memberLike = true
}
-
- class Field(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor) {
+/*
+ class Field(name: String, descriptor: FieldDescriptor) :
+ DocumentationNode<FieldDescriptor>(name, descriptor) {
override val memberLike = true
- }
-
- class CompanionObjectProperty(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor) {
- override val memberLike = true
- }
-
- class CompanionObjectFunction(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor) {
- override val memberLike = true
- }
-
- class Parameter(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor)
-
- class Receiver(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor)
-
- class TypeParameter(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor)
-
- class Type(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor)
-
- class Supertype(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor) {
- override val superclassType: DocumentationNode? =
- (links + listOfNotNull(externalType)).firstOrNull { it.classLike }?.superclassType
- }
-
- class UpperBound(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor)
-
- class LowerBound(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor)
-
- class TypeAliasUnderlyingType(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor)
-
- class NullabilityModifier(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor)
-
- class Module(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor)
-
- class ExternalClass(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor)
-
- class Annotation(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor)
-
- class Value(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor)
-
- class SourceUrl(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor)
-
- class SourcePosition(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor)
-
- class ExternalLink(name: String) : DocumentationNode(name)
-
- class QualifiedName(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor)
+ }*/
- class Platform(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor)
-
- class AllTypes(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor)
-
- class OverloadGroupNote(name: String, descriptor: DeclarationDescriptor?) :
- DocumentationNode(name, descriptor)
+ class Parameter(name: String, descriptor: ParameterDescriptor?) :
+ DocumentationNode<ParameterDescriptor>(name, descriptor)
+/*
+ class Annotation(name: String, descriptor: AnnotationDescriptor?) :
+ DocumentationNode<AnnotationDescriptor>(name, descriptor)*/
}
-abstract class DocumentationNode(
+abstract class DocumentationNode<T: DeclarationDescriptor>(
var name: String,
- val descriptor: DeclarationDescriptor? = null
+ val descriptor: T? = null,
+ val parent: DocumentationNode<*>? = null
) {
- private val references = LinkedHashSet<DocumentationReference>()
+ private val children = mutableListOf<DocumentationNode<*>>()
open val classLike = false
open val memberLike = false
- val owner: DocumentationNode?
- get() = references(RefKind.Owner).singleOrNull()?.to
- val details: List<DocumentationNode>
- get() = references(RefKind.Detail).map { it.to }
- val members: List<DocumentationNode>
- get() = references(RefKind.Member).map { it.to }
- val origins: List<DocumentationNode>
- get() = references(RefKind.Origin).map { it.to }
-
- val inheritedMembers: List<DocumentationNode>
- get() = references(RefKind.InheritedMember).map { it.to }
- val allInheritedMembers: List<DocumentationNode>
- get() = recursiveInheritedMembers()
- val inheritedCompanionObjectMembers: List<DocumentationNode>
- get() = references(RefKind.InheritedCompanionObjectMember).map { it.to }
- val extensions: List<DocumentationNode>
- get() = references(RefKind.Extension).map { it.to }
- val inheritors: List<DocumentationNode>
- get() = references(RefKind.Inheritor).map { it.to }
- val overrides: List<DocumentationNode>
- get() = references(RefKind.Override).map { it.to }
- val links: List<DocumentationNode>
- get() = references(RefKind.Link).map { it.to }
- val hiddenLinks: List<DocumentationNode>
- get() = references(RefKind.HiddenLink).map { it.to }
- val annotations: List<DocumentationNode>
- get() = references(RefKind.Annotation).map { it.to }
- val deprecation: DocumentationNode?
- get() = references(RefKind.Deprecation).singleOrNull()?.to
- val platforms: List<String>
- get() = references(RefKind.Platform).map { it.to.name }
- val externalType: DocumentationNode?
- get() = references(RefKind.ExternalType).map { it.to }.firstOrNull()
-
- open val superclassType: DocumentationNode?
- get() = if (classLike) {
- supertypes.firstOrNull {
- (it.links + listOfNotNull(it.externalType)).any { it.isSuperclassFor(this) }
- }
- } else null
-
- val superclassTypeSequence: Sequence<DocumentationNode>
- get() = generateSequence(superclassType) {
- it.superclassType
- }
-
- // TODO: Should we allow node mutation? Model merge will copy by ref, so references are transparent, which could nice
- fun addReferenceTo(to: DocumentationNode, kind: RefKind) {
- references.add(DocumentationReference(this, to, kind))
- }
-
- fun addReference(reference: DocumentationReference) {
- references.add(reference)
- }
-
- fun dropReferences(predicate: (DocumentationReference) -> Boolean) {
- references.removeAll(predicate)
- }
-
- fun addAllReferencesFrom(other: DocumentationNode) {
- references.addAll(other.references)
- }
-
- private fun Collection<DocumentationNode>.filterByKind(kind: KClass<out DocumentationNode>) =
- filter { node: DocumentationNode -> node::class == kind }
-
- private fun Collection<DocumentationNode>.singleByKind(kind: KClass<out DocumentationNode>) =
- single { node: DocumentationNode -> node::class == kind }
-
- fun details(kind: KClass<out DocumentationNode>) = details.filterByKind(kind)
- fun members(kind: KClass<out DocumentationNode>) = members.filterByKind(kind)
- fun inheritedMembers(kind: KClass<out DocumentationNode>): List<DocumentationNode> =
- inheritedMembers.filterByKind(kind)
-
- fun inheritedCompanionObjectMembers(kind: KClass<out DocumentationNode>): List<DocumentationNode> =
- inheritedCompanionObjectMembers.filterByKind(kind)
-
- fun links(kind: KClass<out DocumentationNode>): List<DocumentationNode> = links.filterByKind(kind)
-
- fun detail(kind: KClass<out DocumentationNode>): DocumentationNode = details.singleByKind(kind)
- fun detailOrNull(kind: KClass<out DocumentationNode>): DocumentationNode? =
- details.singleOrNull { it::class == kind }
-
- fun member(kind: KClass<out DocumentationNode>): DocumentationNode = members.singleByKind(kind)
- fun link(kind: KClass<out DocumentationNode>): DocumentationNode = links.singleByKind(kind)
-
-
- fun references(kind: RefKind): List<DocumentationReference> = references.filter { it.kind == kind }
- fun allReferences(): Set<DocumentationReference> = references
+ fun addChild(child: DocumentationNode<*>) =
+ children.add(child)
override fun toString(): String {
return "${javaClass.name}:$name"
}
-}
-
-fun KClass<out DocumentationNode>.createNode(name: String, descriptor: DeclarationDescriptor? = null) =
- primaryConstructor?.call(name, descriptor)
- ?: throw IllegalArgumentException("Cannot create node of type ${this::class}: invalid primary constructor")
-
-val DocumentationNode.supertypes: List<DocumentationNode>
- get() = details(DocumentationNodes.Supertype::class)
-
-class DocumentationModule(name: String) : DocumentationNode(name)
-
-val DocumentationNode.path: List<DocumentationNode>
- get() {
- val parent = owner ?: return listOf(this)
- return parent.path + this
- }
-
-fun DocumentationNode.append(child: DocumentationNode, kind: RefKind) {
- addReferenceTo(child, kind)
- when (kind) {
- 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 */
- }
- }
-}
-
-fun DocumentationNode.appendTextNode(
- text: String,
- kind: KClass<out DocumentationNode>,
- descriptor: DeclarationDescriptor? = null,
- refKind: RefKind = RefKind.Detail
-) {
- append(kind.createNode(text, descriptor), refKind)
-}
-
-fun DocumentationNode.qualifiedName(): String {
- if (this is DocumentationNodes.Type) {
- return qualifiedNameFromType()
- } else if (this is DocumentationNodes.Package) {
- return name
- }
- return path.dropWhile { it is DocumentationNodes.Module }.map { it.name }.filter { it.isNotEmpty() }
- .joinToString(".")
-}
-
-fun DocumentationNode.simpleName() = name.substringAfterLast('.')
-
-private fun DocumentationNode.recursiveInheritedMembers(): List<DocumentationNode> {
- val allInheritedMembers = mutableListOf<DocumentationNode>()
- recursiveInheritedMembers(allInheritedMembers)
- return allInheritedMembers
-}
-
-private fun DocumentationNode.recursiveInheritedMembers(allInheritedMembers: MutableList<DocumentationNode>) {
- allInheritedMembers.addAll(inheritedMembers)
- System.out.println(allInheritedMembers.size)
- inheritedMembers.groupBy { it.owner!! }.forEach { (node, _) ->
- node.recursiveInheritedMembers(allInheritedMembers)
- }
-}
-
-private fun DocumentationNode.isSuperclassFor(node: DocumentationNode): Boolean {
- return when (node) {
- is DocumentationNodes.Object,
- is DocumentationNodes.Class,
- is DocumentationNodes.Enum -> this is DocumentationNodes.Class
- is DocumentationNodes.Exception -> this is DocumentationNodes.Class || this is DocumentationNodes.Exception
- else -> false
- }
-}
-
-fun DocumentationNode.classNodeNameWithOuterClass(): String {
- assert(classLike)
- return path.dropWhile { it is DocumentationNodes.Package || it is DocumentationNodes.Module }
- .joinToString(separator = ".") { it.name }
} \ No newline at end of file
diff --git a/core/src/main/kotlin/Model/DocumentationReference.kt b/core/src/main/kotlin/Model/DocumentationReference.kt
deleted file mode 100644
index e46a4a21..00000000
--- a/core/src/main/kotlin/Model/DocumentationReference.kt
+++ /dev/null
@@ -1,115 +0,0 @@
-package org.jetbrains.dokka
-
-import com.google.inject.Singleton
-
-enum class RefKind {
- Owner,
- Member,
- InheritedMember,
- InheritedCompanionObjectMember,
- Detail,
- Link,
- HiddenLink,
- Extension,
- Inheritor,
- Superclass,
- Override,
- Annotation,
- HiddenAnnotation,
- Deprecation,
- TopLevelPage,
- Platform,
- ExternalType,
- Origin,
- SinceKotlin
-}
-
-data class DocumentationReference(val from: DocumentationNode, val to: DocumentationNode, val kind: RefKind) {
-}
-
-sealed class NodeResolver {
- 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(nodeRephGraph: NodeReferenceGraph): DocumentationNode? {
- return exactNode
- }
- }
-}
-
-class PendingDocumentationReference(val lazyNodeFrom: NodeResolver,
- val lazyNodeTo: NodeResolver,
- val kind: RefKind) {
- fun resolve(nodeRephGraph: NodeReferenceGraph) {
- val fromNode = lazyNodeFrom.resolve(nodeRephGraph)
- val toNode = lazyNodeTo.resolve(nodeRephGraph)
- if (fromNode != null && toNode != null) {
- fromNode.addReferenceTo(toNode, kind)
- }
- }
-}
-
-class NodeReferenceGraph {
- private val nodeMap = hashMapOf<String, DocumentationNode>()
- val nodeMapView: Map<String, DocumentationNode>
- get() = HashMap(nodeMap)
-
- val references = arrayListOf<PendingDocumentationReference>()
-
- fun register(signature: String, node: DocumentationNode) {
- nodeMap[signature] = node
- }
-
- fun link(fromNode: DocumentationNode, toSignature: String, kind: RefKind) {
- references.add(
- PendingDocumentationReference(
- NodeResolver.Exact(fromNode),
- NodeResolver.BySignature(toSignature),
- kind
- ))
- }
-
- fun link(fromSignature: String, toNode: DocumentationNode, kind: RefKind) {
- references.add(
- PendingDocumentationReference(
- NodeResolver.BySignature(fromSignature),
- NodeResolver.Exact(toNode),
- kind
- )
- )
- }
-
- fun link(fromSignature: String, toSignature: String, kind: RefKind) {
- references.add(
- PendingDocumentationReference(
- NodeResolver.BySignature(fromSignature),
- NodeResolver.BySignature(toSignature),
- kind
- )
- )
- }
-
- fun addReference(reference: PendingDocumentationReference) {
- references.add(reference)
- }
-
- fun lookup(signature: String) = nodeMap[signature]
-
- fun lookupOrWarn(signature: String, logger: DokkaLogger): DocumentationNode? {
- val result = nodeMap[signature]
- if (result == null) {
- logger.warn("Can't find node by signature `$signature`." +
- "This is probably caused by invalid configuration of cross-module dependencies")
- }
- return result
- }
-
- fun resolveReferences() {
- references.forEach { it.resolve(this) }
- }
-} \ No newline at end of file
diff --git a/core/src/main/kotlin/Utilities/DokkaModules.kt b/core/src/main/kotlin/Utilities/DokkaModules.kt
index 919ec30f..94fc5c62 100644
--- a/core/src/main/kotlin/Utilities/DokkaModules.kt
+++ b/core/src/main/kotlin/Utilities/DokkaModules.kt
@@ -26,7 +26,6 @@ class DokkaRunModule(val configuration: DokkaConfiguration) : Module {
class DokkaAnalysisModule(val environment: AnalysisEnvironment,
val configuration: DokkaConfiguration,
val defaultPlatformsProvider: DefaultPlatformsProvider,
- val nodeReferenceGraph: NodeReferenceGraph,
val passConfiguration: DokkaConfiguration.PassConfiguration,
val logger: DokkaLogger) : Module {
override fun configure(binder: Binder) {
@@ -43,8 +42,6 @@ class DokkaAnalysisModule(val environment: AnalysisEnvironment,
binder.bind<DefaultPlatformsProvider>().toInstance(defaultPlatformsProvider)
- binder.bind<NodeReferenceGraph>().toInstance(nodeReferenceGraph)
-
val descriptor = ServiceLocator.lookup<FormatDescriptor>("format", configuration.format)
descriptor.configureAnalysis(binder)
}
diff --git a/core/src/main/kotlin/links/DRI.kt b/core/src/main/kotlin/links/DRI.kt
index 64989701..35eb6497 100644
--- a/core/src/main/kotlin/links/DRI.kt
+++ b/core/src/main/kotlin/links/DRI.kt
@@ -66,5 +66,7 @@ data class Callable(val name: String, val receiver: String, val returnType: Stri
}
}
+data class ClassReference(val dri: DRI, val subs: MutableList<ClassReference> = mutableListOf())
+
private operator fun <T> List<T>.component6(): T = get(5)