From d458983871a6fa6af10b86bc7529a8851a63b265 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Fri, 15 Dec 2017 00:16:10 +0300 Subject: [backport] Add class hierarchy for JLH Original: 33426ea --- core/src/main/kotlin/Model/DocumentationNode.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index da85cabf..897e3ad3 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -104,6 +104,12 @@ open class DocumentationNode(val name: String, val platforms: List get() = references(RefKind.Platform).map { it.to.name } + val supertypes: List + get() = references(RefKind.Superclass).map { it.to } + + val superclass: DocumentationNode? + get() = supertypes.find { it.kind == NodeKind.Class } + // 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)) -- cgit From 59069606904d297a5b4c9a8a95ad88eb30f7fd4f Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 20 Dec 2017 22:27:47 +0300 Subject: [backport] Make KotlinLanguageService render parameters Original: 7899f8e --- core/src/main/kotlin/Kotlin/KotlinLanguageService.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt index f33c8c96..708facdb 100644 --- a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt +++ b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt @@ -17,6 +17,7 @@ class KotlinLanguageService : LanguageService { NodeKind.EnumItem, NodeKind.ExternalClass -> if (renderMode == RenderMode.FULL) identifier(node.name) + NodeKind.Parameter -> renderParameter(node, renderMode) NodeKind.TypeParameter -> renderTypeParameter(node, renderMode) NodeKind.Type, NodeKind.UpperBound -> renderType(node, renderMode) -- cgit From 63ab561b66974c52a7d13e0823bf94329c0cd7f7 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Fri, 15 Dec 2017 22:05:21 +0300 Subject: [backport] Make possible to generate signatures on output format side Original: 4469044 --- .../src/main/kotlin/Kotlin/DocumentationBuilder.kt | 1 + .../main/kotlin/Kotlin/KotlinLanguageService.kt | 28 ++++++++++++---------- core/src/main/kotlin/Model/DocumentationNode.kt | 1 + 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index 7b50fff5..99d4d888 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -234,6 +234,7 @@ class DocumentationBuilder val externalLink = linkResolver.externalDocumentationLinkResolver.buildExternalDocumentationLink(classifierDescriptor) if (externalLink != null) { node.append(DocumentationNode(externalLink, Content.Empty, NodeKind.ExternalLink), RefKind.Link) + node.append(DocumentationNode(classifierDescriptor.fqNameUnsafe.asString(), Content.Empty, NodeKind.QualifiedName), RefKind.Detail) } else { link(node, classifierDescriptor, if (classifierDescriptor.isBoringBuiltinClass()) RefKind.HiddenLink else RefKind.Link) diff --git a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt index 708facdb..b6f44716 100644 --- a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt +++ b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt @@ -48,8 +48,7 @@ class KotlinLanguageService : LanguageService { val typeParameter = functionWithTypeParameter.details(NodeKind.TypeParameter).first() if (functionWithTypeParameter.kind == NodeKind.Function) { renderFunction(functionWithTypeParameter, RenderMode.SUMMARY, SummarizingMapper(receiverKind, typeParameter.name)) - } - else { + } else { renderProperty(functionWithTypeParameter, RenderMode.SUMMARY, SummarizingMapper(receiverKind, typeParameter.name)) } } @@ -103,7 +102,7 @@ class KotlinLanguageService : LanguageService { fun renderReceiver(receiver: DocumentationNode, to: ContentBlock) } - private class SummarizingMapper(val kind: ReceiverKind, val typeParameterName: String): SignatureMapper { + private class SummarizingMapper(val kind: ReceiverKind, val typeParameterName: String) : SignatureMapper { override fun renderReceiver(receiver: DocumentationNode, to: ContentBlock) { to.append(ContentIdentifier(kind.receiverName, IdentifierKind.SummarizedTypeName)) to.text("<$typeParameterName>") @@ -117,7 +116,7 @@ class KotlinLanguageService : LanguageService { } private fun ContentBlock.renderList(nodes: List, separator: String = ", ", - noWrap: Boolean = false, renderItem: (T) -> Unit) { + noWrap: Boolean = false, renderItem: (T) -> Unit) { if (nodes.none()) return renderItem(nodes.first()) @@ -132,7 +131,7 @@ class KotlinLanguageService : LanguageService { } } - private fun ContentBlock.renderLinked(node: DocumentationNode, body: ContentBlock.(DocumentationNode)->Unit) { + private fun ContentBlock.renderLinked(node: DocumentationNode, body: ContentBlock.(DocumentationNode) -> Unit) { val to = node.links.firstOrNull() if (to == null) body(node) @@ -216,13 +215,13 @@ class KotlinLanguageService : LanguageService { private fun ContentBlock.renderModifier(node: DocumentationNode, nowrap: Boolean = false) { when (node.name) { - "final", "public", "var" -> {} + "final", "public", "var" -> { + } else -> { keyword(node.name) if (nowrap) { nbsp() - } - else { + } else { text(" ") } } @@ -239,11 +238,12 @@ class KotlinLanguageService : LanguageService { nbsp() symbol(":") nbsp() - renderList(constraints, noWrap=true) { + renderList(constraints, noWrap = true) { renderType(it, renderMode) } } } + private fun ContentBlock.renderParameter(node: DocumentationNode, renderMode: RenderMode) { if (renderMode == RenderMode.FULL) { renderAnnotationsForNode(node) @@ -402,8 +402,7 @@ class KotlinLanguageService : LanguageService { symbol(")") symbol(": ") renderType(node.detail(NodeKind.Type), renderMode) - } - else { + } else { symbol(")") } renderExtraTypeParameterConstraints(node, renderMode) @@ -429,7 +428,7 @@ class KotlinLanguageService : LanguageService { } } - private fun needReturnType(node: DocumentationNode) = when(node.kind) { + private fun needReturnType(node: DocumentationNode) = when (node.kind) { NodeKind.Constructor -> false else -> !node.isUnitReturnType() } @@ -476,4 +475,7 @@ class KotlinLanguageService : LanguageService { } } -fun DocumentationNode.qualifiedNameFromType() = (links.firstOrNull() ?: hiddenLinks.firstOrNull())?.qualifiedName() ?: name +fun DocumentationNode.qualifiedNameFromType() = + details.firstOrNull { it.kind == NodeKind.QualifiedName }?.name + ?: (links.firstOrNull() ?: hiddenLinks.firstOrNull())?.qualifiedName() + ?: name diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index 897e3ad3..4b108798 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -48,6 +48,7 @@ enum class NodeKind { Signature, ExternalLink, + QualifiedName, Platform, AllTypes, -- cgit From e4d3abee285844c002a8984efbae0bf0be23d237 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Thu, 28 Dec 2017 19:44:56 +0300 Subject: Build supertypes via Supertype nodes, not reference --- core/src/main/kotlin/Model/DocumentationNode.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index 4b108798..813ff0f5 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -1,5 +1,6 @@ package org.jetbrains.dokka +import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult import java.util.* enum class NodeKind { @@ -106,10 +107,10 @@ open class DocumentationNode(val name: String, get() = references(RefKind.Platform).map { it.to.name } val supertypes: List - get() = references(RefKind.Superclass).map { it.to } + get() = details(NodeKind.Supertype) val superclass: DocumentationNode? - get() = supertypes.find { it.kind == NodeKind.Class } + get() = supertypes.firstNotNullResult { it.links.firstOrNull { it.kind in NodeKind.classLike } } // 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) { -- cgit From 93ce43340730111df977921e62cae93c2bcc4a5b Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Thu, 28 Dec 2017 20:27:28 +0300 Subject: [backport] Add uri.relativeTo Original: cca63f7 --- core/src/main/kotlin/Utilities/Uri.kt | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 core/src/main/kotlin/Utilities/Uri.kt diff --git a/core/src/main/kotlin/Utilities/Uri.kt b/core/src/main/kotlin/Utilities/Uri.kt new file mode 100644 index 00000000..5b520188 --- /dev/null +++ b/core/src/main/kotlin/Utilities/Uri.kt @@ -0,0 +1,40 @@ +package org.jetbrains.dokka + +import java.net.URI + + +fun URI.relativeTo(uri: URI): URI { + // Normalize paths to remove . and .. segments + val base = uri.normalize() + val child = this.normalize() + + fun StringBuilder.appendRelativePath() { + // Split paths into segments + var bParts = base.path.split('/').dropLastWhile { it.isEmpty() } + val cParts = child.path.split('/').dropLastWhile { it.isEmpty() } + + // Discard trailing segment of base path + if (bParts.isNotEmpty() && !base.path.endsWith("/")) { + bParts = bParts.dropLast(1) + } + + // Compute common prefix + val commonPartsSize = bParts.zip(cParts).count { (basePart, childPart) -> basePart == childPart } + bParts.drop(commonPartsSize).joinTo(this, separator = "") { "../" } + cParts.drop(commonPartsSize).joinTo(this, separator = "/") + } + + return URI.create(buildString { + if (base.path != child.path) { + appendRelativePath() + } + child.rawQuery?.let { + append("?") + append(it) + } + child.rawFragment?.let { + append("#") + append(it) + } + }) +} \ No newline at end of file -- cgit From 87705bf24f6f7e541dbdb14c44e00d0b90a81f37 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Thu, 28 Dec 2017 21:23:27 +0300 Subject: [backport] Add package list support for JLH Original: 4256adf --- .../JavaLayoutHtmlPackageListService.kt | 28 ++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 core/src/main/kotlin/Formats/JavaLayoutHtml/JavaLayoutHtmlPackageListService.kt diff --git a/core/src/main/kotlin/Formats/JavaLayoutHtml/JavaLayoutHtmlPackageListService.kt b/core/src/main/kotlin/Formats/JavaLayoutHtml/JavaLayoutHtmlPackageListService.kt new file mode 100644 index 00000000..398758f2 --- /dev/null +++ b/core/src/main/kotlin/Formats/JavaLayoutHtml/JavaLayoutHtmlPackageListService.kt @@ -0,0 +1,28 @@ +package org.jetbrains.dokka.Formats + +import org.jetbrains.dokka.DocumentationModule +import org.jetbrains.dokka.ExternalDocumentationLinkResolver.Companion.DOKKA_PARAM_PREFIX +import org.jetbrains.dokka.NodeKind +import org.jetbrains.dokka.PackageListService + +class JavaLayoutHtmlPackageListService: PackageListService { + + private fun StringBuilder.appendParam(name: String, value: String) { + append(DOKKA_PARAM_PREFIX) + append(name) + append(":") + appendln(value) + } + + override fun formatPackageList(module: DocumentationModule): String { + val packages = module.members(NodeKind.Package).map { it.name } + + return buildString { + appendParam("format", "java-layout-html") + for (p in packages) { + appendln(p) + } + } + } + +} \ No newline at end of file -- cgit From bd30fa4c84d749976568be00307297ab015d9b2e Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Sun, 7 Jan 2018 01:49:34 +0300 Subject: [backport] Show type parameters substitution in class hierarchy Original: a06d6a8 --- core/src/main/kotlin/Model/DocumentationNode.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index 813ff0f5..a145ae8d 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -1,6 +1,5 @@ package org.jetbrains.dokka -import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult import java.util.* enum class NodeKind { @@ -110,7 +109,7 @@ open class DocumentationNode(val name: String, get() = details(NodeKind.Supertype) val superclass: DocumentationNode? - get() = supertypes.firstNotNullResult { it.links.firstOrNull { it.kind in NodeKind.classLike } } + get() = supertypes.firstOrNull { it.links.any { it.kind in NodeKind.classLike } } // 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) { @@ -163,7 +162,7 @@ val DocumentationNode.path: List } fun DocumentationNode.findOrCreatePackageNode(packageName: String, packageContent: Map, refGraph: NodeReferenceGraph): DocumentationNode { - val existingNode = members(NodeKind.Package).firstOrNull { it.name == packageName } + val existingNode = members(NodeKind.Package).firstOrNull { it.name == packageName } if (existingNode != null) { return existingNode } @@ -181,7 +180,8 @@ fun DocumentationNode.append(child: DocumentationNode, kind: RefKind) { RefKind.Detail -> child.addReferenceTo(this, RefKind.Owner) RefKind.Member -> child.addReferenceTo(this, RefKind.Owner) RefKind.Owner -> child.addReferenceTo(this, RefKind.Member) - else -> { /* Do not add any links back for other types */ } + else -> { /* Do not add any links back for other types */ + } } } -- cgit From c776aaab9af80987e3c073a40f92de748dbd38ca Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Thu, 11 Jan 2018 22:22:36 +0300 Subject: [backport] Support deep inheritance with external classes Original: 9e65c3d --- .../src/main/kotlin/Kotlin/DocumentationBuilder.kt | 70 ++++++++++++++-------- .../main/kotlin/Kotlin/KotlinLanguageService.kt | 2 +- core/src/main/kotlin/Model/DocumentationNode.kt | 19 +++++- .../main/kotlin/Model/DocumentationReference.kt | 3 +- core/src/test/kotlin/TestAPI.kt | 48 ++++++++------- core/src/test/kotlin/model/JavaTest.kt | 2 +- 6 files changed, 92 insertions(+), 52 deletions(-) diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index 99d4d888..11a36a4f 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -103,6 +103,10 @@ interface DefaultPlatformsProvider { fun getDefaultPlatforms(descriptor: DeclarationDescriptor): List } +val ignoredSupertypes = setOf( + "kotlin.Annotation", "kotlin.Enum", "kotlin.Any" +) + class DocumentationBuilder @Inject constructor(val resolutionFacade: DokkaResolutionFacade, val descriptorDocumentationParser: DescriptorDocumentationParser, @@ -173,7 +177,7 @@ class DocumentationBuilder val unwrappedType = superType.unwrap() if (unwrappedType is AbbreviatedType) { appendSupertype(descriptor, unwrappedType.abbreviation) - } else if (!ignoreSupertype(unwrappedType)) { + } else { appendType(unwrappedType, NodeKind.Supertype) val superclass = unwrappedType.constructor.declarationDescriptor link(superclass, descriptor, RefKind.Inheritor) @@ -181,15 +185,6 @@ class DocumentationBuilder } } - private fun ignoreSupertype(superType: KotlinType): Boolean { - val superClass = superType.constructor.declarationDescriptor as? ClassDescriptor - if (superClass != null) { - val fqName = DescriptorUtils.getFqNameSafe(superClass).asString() - return fqName == "kotlin.Annotation" || fqName == "kotlin.Enum" || fqName == "kotlin.Any" - } - return false - } - fun DocumentationNode.appendProjection(projection: TypeProjection, kind: NodeKind = NodeKind.Type) { if (projection.isStarProjection) { appendTextNode("*", NodeKind.Type) @@ -233,14 +228,25 @@ class DocumentationBuilder if (classifierDescriptor != null) { val externalLink = linkResolver.externalDocumentationLinkResolver.buildExternalDocumentationLink(classifierDescriptor) if (externalLink != null) { + val targetNode = refGraph.lookup(classifierDescriptor.signature()) ?: classifierDescriptor.build(true) node.append(DocumentationNode(externalLink, Content.Empty, NodeKind.ExternalLink), RefKind.Link) - node.append(DocumentationNode(classifierDescriptor.fqNameUnsafe.asString(), Content.Empty, NodeKind.QualifiedName), RefKind.Detail) + node.append(targetNode, RefKind.ExternalType) } 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 + ) + } } + append(node, RefKind.Detail) node.appendAnnotations(kotlinType) for (typeArgument in kotlinType.arguments) { @@ -496,34 +502,42 @@ class DocumentationBuilder } fun DeclarationDescriptor.build(): DocumentationNode = when (this) { - is ClassDescriptor -> build() + is ClassifierDescriptor -> build() is ConstructorDescriptor -> build() is PropertyDescriptor -> build() is FunctionDescriptor -> build() - is TypeParameterDescriptor -> build() is ValueParameterDescriptor -> build() is ReceiverParameterDescriptor -> build() - is TypeAliasDescriptor -> build() else -> throw IllegalStateException("Descriptor $this is not known") } - fun TypeAliasDescriptor.build(): DocumentationNode { + fun ClassifierDescriptor.build(external: Boolean = false): DocumentationNode = when (this) { + is ClassDescriptor -> build(external) + is TypeAliasDescriptor -> build(external) + is TypeParameterDescriptor -> build() + else -> throw IllegalStateException("Descriptor $this is not known") + } + + fun TypeAliasDescriptor.build(external: Boolean = false): DocumentationNode { val node = nodeForDescriptor(this, NodeKind.TypeAlias) - node.appendAnnotations(this) + if (!external) { + node.appendAnnotations(this) + } node.appendModifiers(this) node.appendInPageChildren(typeConstructor.parameters, RefKind.Detail) node.appendType(underlyingType, NodeKind.TypeAliasUnderlyingType) - node.appendSourceLink(source) - node.appendDefaultPlatforms(this) - + if (!external) { + node.appendSourceLink(source) + node.appendDefaultPlatforms(this) + } register(this, node) return node } - fun ClassDescriptor.build(): DocumentationNode { + fun ClassDescriptor.build(external: Boolean = false): DocumentationNode { val kind = when { kind == ClassKind.OBJECT -> NodeKind.Object kind == ClassKind.INTERFACE -> NodeKind.Interface @@ -534,20 +548,24 @@ class DocumentationBuilder else -> NodeKind.Class } val node = nodeForDescriptor(this, kind) + register(this, node) typeConstructor.supertypes.forEach { node.appendSupertype(this, it) } if (getKind() != ClassKind.OBJECT && getKind() != ClassKind.ENUM_ENTRY) { node.appendInPageChildren(typeConstructor.parameters, RefKind.Detail) } - for ((descriptor, inheritedLinkKind, extraModifier) in collectMembersToDocument()) { - node.appendClassMember(descriptor, inheritedLinkKind, extraModifier) + if (!external) { + for ((descriptor, inheritedLinkKind, extraModifier) in collectMembersToDocument()) { + node.appendClassMember(descriptor, inheritedLinkKind, extraModifier) + } + node.appendAnnotations(this) } - node.appendAnnotations(this) node.appendModifiers(this) - node.appendSourceLink(source) - node.appendDefaultPlatforms(this) - register(this, node) + if (!external) { + node.appendSourceLink(source) + node.appendDefaultPlatforms(this) + } return node } diff --git a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt index b6f44716..aa185de7 100644 --- a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt +++ b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt @@ -291,7 +291,7 @@ class KotlinLanguageService : LanguageService { } private fun ContentBlock.renderSupertypesForNode(node: DocumentationNode, renderMode: RenderMode) { - val supertypes = node.details(NodeKind.Supertype) + val supertypes = node.details(NodeKind.Supertype).filterNot { it.qualifiedNameFromType() in ignoredSupertypes } if (supertypes.any()) { nbsp() symbol(":") diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index a145ae8d..a792460f 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -104,12 +104,27 @@ open class DocumentationNode(val name: String, get() = references(RefKind.Deprecation).singleOrNull()?.to val platforms: List get() = references(RefKind.Platform).map { it.to.name } + val externalType: DocumentationNode? + get() = references(RefKind.ExternalType).map { it.to }.firstOrNull() val supertypes: List get() = details(NodeKind.Supertype) - val superclass: DocumentationNode? - get() = supertypes.firstOrNull { it.links.any { it.kind in NodeKind.classLike } } + val superclassType: DocumentationNode? + get() = when (kind) { + NodeKind.Supertype -> (links.firstOrNull { it.kind in NodeKind.classLike } ?: externalType)?.superclassType + NodeKind.Interface -> null + in NodeKind.classLike -> supertypes.firstOrNull { + it.links.any { it.kind in NodeKind.classLike } || + it.externalType != null + } + else -> null + } + + val superclassTypeSequence: Sequence + 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) { diff --git a/core/src/main/kotlin/Model/DocumentationReference.kt b/core/src/main/kotlin/Model/DocumentationReference.kt index a968f400..b0f011be 100644 --- a/core/src/main/kotlin/Model/DocumentationReference.kt +++ b/core/src/main/kotlin/Model/DocumentationReference.kt @@ -18,7 +18,8 @@ enum class RefKind { HiddenAnnotation, Deprecation, TopLevelPage, - Platform + Platform, + ExternalType } data class DocumentationReference(val from: DocumentationNode, val to: DocumentationNode, val kind: RefKind) { diff --git a/core/src/test/kotlin/TestAPI.kt b/core/src/test/kotlin/TestAPI.kt index aa3eff48..559b715e 100644 --- a/core/src/test/kotlin/TestAPI.kt +++ b/core/src/test/kotlin/TestAPI.kt @@ -6,7 +6,6 @@ import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.io.FileUtil import com.intellij.rt.execution.junit.FileComparisonFailure import org.jetbrains.dokka.* -import org.jetbrains.dokka.DokkaConfiguration.SourceLinkDefinition import org.jetbrains.dokka.Utilities.DokkaAnalysisModule import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity @@ -25,6 +24,7 @@ fun verifyModel(vararg roots: ContentRoot, format: String = "html", includeNonPublic: Boolean = true, perPackageOptions: List = emptyList(), + noStdlibLink: Boolean = true, verifier: (DocumentationModule) -> Unit) { val documentation = DocumentationModule("test") @@ -37,7 +37,7 @@ fun verifyModel(vararg roots: ContentRoot, sourceLinks = listOf(), perPackageOptions = perPackageOptions, generateIndexPages = false, - noStdlibLink = true, + noStdlibLink = noStdlibLink, cacheRoot = "default", languageVersion = null, apiVersion = null @@ -161,13 +161,15 @@ fun verifyOutput(roots: Array, withKotlinRuntime: Boolean = false, format: String = "html", includeNonPublic: Boolean = true, + noStdlibLink: Boolean = true, outputGenerator: (DocumentationModule, StringBuilder) -> Unit) { verifyModel( - *roots, - withJdk = withJdk, - withKotlinRuntime = withKotlinRuntime, - format = format, - includeNonPublic = includeNonPublic + *roots, + withJdk = withJdk, + withKotlinRuntime = withKotlinRuntime, + format = format, + includeNonPublic = includeNonPublic, + noStdlibLink = noStdlibLink ) { verifyModelOutput(it, outputExtension, roots.first().path, outputGenerator) } @@ -184,21 +186,25 @@ fun verifyModelOutput(it: DocumentationModule, assertEqualsIgnoringSeparators(expectedFile, output.toString()) } -fun verifyOutput(path: String, - outputExtension: String, - withJdk: Boolean = false, - withKotlinRuntime: Boolean = false, - format: String = "html", - includeNonPublic: Boolean = true, - outputGenerator: (DocumentationModule, StringBuilder) -> Unit) { +fun verifyOutput( + path: String, + outputExtension: String, + withJdk: Boolean = false, + withKotlinRuntime: Boolean = false, + format: String = "html", + includeNonPublic: Boolean = true, + noStdlibLink: Boolean = true, + outputGenerator: (DocumentationModule, StringBuilder) -> Unit +) { verifyOutput( - arrayOf(contentRootFromPath(path)), - outputExtension, - withJdk, - withKotlinRuntime, - format, - includeNonPublic, - outputGenerator + arrayOf(contentRootFromPath(path)), + outputExtension, + withJdk, + withKotlinRuntime, + format, + includeNonPublic, + noStdlibLink, + outputGenerator ) } diff --git a/core/src/test/kotlin/model/JavaTest.kt b/core/src/test/kotlin/model/JavaTest.kt index e6c22ee4..c2ede8f0 100644 --- a/core/src/test/kotlin/model/JavaTest.kt +++ b/core/src/test/kotlin/model/JavaTest.kt @@ -193,7 +193,7 @@ public class JavaTest { @Test fun enumValues() { verifyJavaPackageMember("testdata/java/enumValues.java") { cls -> val superTypes = cls.details(NodeKind.Supertype) - assertEquals(0, superTypes.size) + assertEquals(1, superTypes.size) assertEquals(1, cls.members(NodeKind.EnumItem).size) } } -- cgit From 1391dcca35a871881420c53755fed08bf47e4087 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 17 Jan 2018 20:01:20 +0300 Subject: [backport] Support propagating inherited extensions from libraries Original: bf2945d --- core/src/main/kotlin/DokkaBootstrapImpl.kt | 3 +- core/src/main/kotlin/Generation/DokkaGenerator.kt | 2 + .../main/kotlin/Generation/configurationImpl.kt | 47 ++--- .../src/main/kotlin/Kotlin/DocumentationBuilder.kt | 200 ++++++++++++++++----- .../Kotlin/ExternalDocumentationLinkResolver.kt | 2 +- core/src/main/kotlin/Model/DocumentationNode.kt | 2 + core/src/test/kotlin/TestAPI.kt | 32 ++-- .../kotlin/org/jetbrains/dokka/configuration.kt | 48 ++--- runners/cli/src/main/kotlin/cli/main.kt | 28 +-- runners/gradle-plugin/src/main/kotlin/main.kt | 51 +++--- 10 files changed, 273 insertions(+), 142 deletions(-) diff --git a/core/src/main/kotlin/DokkaBootstrapImpl.kt b/core/src/main/kotlin/DokkaBootstrapImpl.kt index aeaca8be..b7787be8 100644 --- a/core/src/main/kotlin/DokkaBootstrapImpl.kt +++ b/core/src/main/kotlin/DokkaBootstrapImpl.kt @@ -69,7 +69,8 @@ class DokkaBootstrapImpl : DokkaBootstrap { languageVersion, apiVersion, cacheRoot, - suppressedFiles.map { File(it) }.toSet() + suppressedFiles.map { File(it) }.toSet(), + collectInheritedExtensionsFromLibraries ) ) } diff --git a/core/src/main/kotlin/Generation/DokkaGenerator.kt b/core/src/main/kotlin/Generation/DokkaGenerator.kt index 09e5cedf..33170f35 100644 --- a/core/src/main/kotlin/Generation/DokkaGenerator.kt +++ b/core/src/main/kotlin/Generation/DokkaGenerator.kt @@ -160,6 +160,8 @@ fun buildDocumentationModule(injector: Injector, with(injector.getInstance(DocumentationBuilder::class.java)) { documentationModule.appendFragments(fragments, packageDocs.packageContent, injector.getInstance(PackageDocumentationBuilder::class.java)) + + propagateExtensionFunctionsToSubclasses(fragments, resolutionFacade) } val javaFiles = coreEnvironment.getJavaSourceFiles().filter(filesToDocumentFilter) diff --git a/core/src/main/kotlin/Generation/configurationImpl.kt b/core/src/main/kotlin/Generation/configurationImpl.kt index 34d4154e..52e8446f 100644 --- a/core/src/main/kotlin/Generation/configurationImpl.kt +++ b/core/src/main/kotlin/Generation/configurationImpl.kt @@ -36,27 +36,28 @@ data class PackageOptionsImpl(override val prefix: String, override val suppress: Boolean = false) : DokkaConfiguration.PackageOptions data class DokkaConfigurationImpl( - override val moduleName: String, - override val classpath: List, - override val sourceRoots: List, - override val samples: List, - override val includes: List, - override val outputDir: String, - override val format: String, - override val includeNonPublic: Boolean, - override val includeRootPackage: Boolean, - override val reportUndocumented: Boolean, - override val skipEmptyPackages: Boolean, - override val skipDeprecated: Boolean, - override val jdkVersion: Int, - override val generateIndexPages: Boolean, - override val sourceLinks: List, - override val impliedPlatforms: List, - override val perPackageOptions: List, - override val externalDocumentationLinks: List, - override val noStdlibLink: Boolean, - override val cacheRoot: String?, - override val suppressedFiles: List, - override val languageVersion: String?, - override val apiVersion: String? + override val moduleName: String, + override val classpath: List, + override val sourceRoots: List, + override val samples: List, + override val includes: List, + override val outputDir: String, + override val format: String, + override val includeNonPublic: Boolean, + override val includeRootPackage: Boolean, + override val reportUndocumented: Boolean, + override val skipEmptyPackages: Boolean, + override val skipDeprecated: Boolean, + override val jdkVersion: Int, + override val generateIndexPages: Boolean, + override val sourceLinks: List, + override val impliedPlatforms: List, + override val perPackageOptions: List, + override val externalDocumentationLinks: List, + override val noStdlibLink: Boolean, + override val cacheRoot: String?, + override val suppressedFiles: List, + override val languageVersion: String?, + override val apiVersion: String?, + override val collectInheritedExtensionsFromLibraries: Boolean ) : DokkaConfiguration \ No newline at end of file diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index 11a36a4f..125f9fd4 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -11,6 +11,9 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotated import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.impl.EnumEntrySyntheticClassDescriptor import org.jetbrains.kotlin.idea.kdoc.findKDoc +import org.jetbrains.kotlin.idea.util.fuzzyExtensionReceiverType +import org.jetbrains.kotlin.idea.util.makeNotNullable +import org.jetbrains.kotlin.idea.util.toFuzzyType import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi import org.jetbrains.kotlin.kdoc.psi.impl.KDocSection import org.jetbrains.kotlin.lexer.KtTokens @@ -25,10 +28,11 @@ import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.descriptorUtil.* import org.jetbrains.kotlin.resolve.findTopMostOverriddenDescriptors import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver +import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter +import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered import org.jetbrains.kotlin.resolve.source.PsiSourceElement import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.types.* -import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf import org.jetbrains.kotlin.types.typeUtil.supertypes import java.io.File import java.nio.file.Path @@ -53,7 +57,8 @@ class DocumentationOptions(val outputDir: String, val languageVersion: String?, val apiVersion: String?, cacheRoot: String? = null, - val suppressedFiles: Set = emptySet()) { + val suppressedFiles: Set = emptySet(), + val collectInheritedExtensionsFromLibraries: Boolean = false) { init { if (perPackageOptions.any { it.prefix == "" }) throw IllegalArgumentException("Please do not register packageOptions with all match pattern, use global settings instead") @@ -138,8 +143,20 @@ class DocumentationBuilder refGraph.register(descriptor.signature(), node) } - fun nodeForDescriptor(descriptor: T, kind: NodeKind): DocumentationNode where T : DeclarationDescriptor, T : Named { - val (doc, callback) = descriptorDocumentationParser.parseDocumentationAndDetails(descriptor, kind == NodeKind.Parameter) + fun nodeForDescriptor( + descriptor: T, + kind: NodeKind, + external: Boolean = false + ): DocumentationNode where T : DeclarationDescriptor, T : Named { + val (doc, callback) = + if (external) { + Content.Empty to { node -> } + } else { + descriptorDocumentationParser.parseDocumentationAndDetails( + descriptor, + kind == NodeKind.Parameter + ) + } val node = DocumentationNode(descriptor.name.asString(), doc, kind).withModifiers(descriptor) node.appendSignature(descriptor) callback(node) @@ -226,14 +243,20 @@ class DocumentationBuilder node.appendTextNode("?", NodeKind.NullabilityModifier) } if (classifierDescriptor != null) { - val externalLink = linkResolver.externalDocumentationLinkResolver.buildExternalDocumentationLink(classifierDescriptor) + val externalLink = + linkResolver.externalDocumentationLinkResolver.buildExternalDocumentationLink(classifierDescriptor) if (externalLink != null) { - val targetNode = refGraph.lookup(classifierDescriptor.signature()) ?: classifierDescriptor.build(true) - node.append(DocumentationNode(externalLink, Content.Empty, NodeKind.ExternalLink), RefKind.Link) - node.append(targetNode, RefKind.ExternalType) + if (classifierDescriptor !is TypeParameterDescriptor) { + val targetNode = + refGraph.lookup(classifierDescriptor.signature()) ?: classifierDescriptor.build(true) + node.append(targetNode, RefKind.ExternalType) + node.append(DocumentationNode(externalLink, Content.Empty, NodeKind.ExternalLink), RefKind.Link) + } } else { - link(node, classifierDescriptor, - if (classifierDescriptor.isBoringBuiltinClass()) RefKind.HiddenLink else RefKind.Link) + link( + node, classifierDescriptor, + if (classifierDescriptor.isBoringBuiltinClass()) RefKind.HiddenLink else RefKind.Link + ) } if (classifierDescriptor !is TypeParameterDescriptor) { node.append( @@ -280,6 +303,17 @@ class DocumentationBuilder } } + fun DocumentationNode.appendExternalLink(externalLink: String) { + append(DocumentationNode(externalLink, Content.Empty, NodeKind.ExternalLink), RefKind.Link) + } + + fun DocumentationNode.appendExternalLink(descriptor: DeclarationDescriptor) { + val target = linkResolver.externalDocumentationLinkResolver.buildExternalDocumentationLink(descriptor) + if (target != null) { + appendExternalLink(target) + } + } + fun DocumentationNode.appendSinceKotlin(annotation: DocumentationNode) { val kotlinVersion = annotation .detail(NodeKind.Parameter) @@ -426,15 +460,44 @@ class DocumentationBuilder declarations, allFqNames) } - propagateExtensionFunctionsToSubclasses(fragments) } - private fun propagateExtensionFunctionsToSubclasses(fragments: Collection) { - val allDescriptors = fragments.flatMap { it.getMemberScope().getContributedDescriptors() } - val allClasses = allDescriptors.filterIsInstance() - val classHierarchy = buildClassHierarchy(allClasses) + fun propagateExtensionFunctionsToSubclasses( + fragments: Collection, + resolutionFacade: DokkaResolutionFacade + ) { + + val moduleDescriptor = resolutionFacade.moduleDescriptor + + // Wide-collect all view descriptors + val allPackageViewDescriptors = generateSequence(listOf(moduleDescriptor.getPackage(FqName.ROOT))) { packages -> + packages + .flatMap { pkg -> + moduleDescriptor.getSubPackagesOf(pkg.fqName) { true } + }.map { fqName -> + moduleDescriptor.getPackage(fqName) + }.takeUnless { it.isEmpty() } + }.flatten() + + val allDescriptors = + if (options.collectInheritedExtensionsFromLibraries) { + allPackageViewDescriptors.map { it.memberScope } + } else { + fragments.asSequence().map { it.getMemberScope() } + }.flatMap { + it.getDescriptorsFiltered( + DescriptorKindFilter.CALLABLES + ).asSequence() + } + - val allExtensionFunctions = allDescriptors + val documentingDescriptors = fragments.flatMap { it.getMemberScope().getContributedDescriptors() } + val documentingClasses = documentingDescriptors.filterIsInstance() + + val classHierarchy = buildClassHierarchy(documentingClasses) + + val allExtensionFunctions = + allDescriptors .filterIsInstance() .filter { it.extensionReceiverParameter != null } val extensionFunctionsByName = allExtensionFunctions.groupBy { it.name } @@ -442,15 +505,31 @@ class DocumentationBuilder for (extensionFunction in allExtensionFunctions) { if (extensionFunction.dispatchReceiverParameter != null) continue val possiblyShadowingFunctions = extensionFunctionsByName[extensionFunction.name] - ?.filter { fn -> fn.canShadow(extensionFunction) } + ?.filter { fn -> fn.canShadow(extensionFunction) } ?: emptyList() if (extensionFunction.extensionReceiverParameter?.type?.isDynamic() == true) continue - val classDescriptor = extensionFunction.getExtensionClassDescriptor() ?: continue - val subclasses = classHierarchy[classDescriptor] ?: continue - subclasses.forEach { subclass -> + val subclasses = + classHierarchy.filter { (key) -> key.isExtensionApplicable(extensionFunction) } + if (subclasses.isEmpty()) continue + subclasses.values.flatten().forEach { subclass -> if (subclass.isExtensionApplicable(extensionFunction) && - possiblyShadowingFunctions.none { subclass.isExtensionApplicable(it) }) { + possiblyShadowingFunctions.none { subclass.isExtensionApplicable(it) }) { + + val hasExternalLink = + linkResolver.externalDocumentationLinkResolver.buildExternalDocumentationLink( + extensionFunction + ) != null + if (hasExternalLink) { + val containerDesc = + extensionFunction.containingDeclaration as? PackageFragmentDescriptor + if (containerDesc != null) { + val container = refGraph.lookup(containerDesc.signature()) + ?: containerDesc.buildExternal() + container.append(extensionFunction.buildExternal(), RefKind.Member) + } + } + refGraph.link(subclass.signature(), extensionFunction.signature(), RefKind.Extension) } } @@ -458,12 +537,9 @@ class DocumentationBuilder } private fun ClassDescriptor.isExtensionApplicable(extensionFunction: CallableMemberDescriptor): Boolean { - val receiverType = extensionFunction.extensionReceiverParameter!!.type - if (receiverType.arguments.any { it.type.constructor.declarationDescriptor is TypeParameterDescriptor }) { - val receiverClass = receiverType.constructor.declarationDescriptor - return receiverClass is ClassDescriptor && DescriptorUtils.isSubclass(this, receiverClass) - } - return defaultType.isSubtypeOf(receiverType) + val receiverType = extensionFunction.fuzzyExtensionReceiverType()?.makeNotNullable() + val classType = defaultType.toFuzzyType(declaredTypeParameters) + return receiverType != null && classType.checkIsSubtypeOf(receiverType) != null } private fun buildClassHierarchy(classes: List): Map> { @@ -511,6 +587,24 @@ class DocumentationBuilder else -> throw IllegalStateException("Descriptor $this is not known") } + fun PackageFragmentDescriptor.buildExternal(): DocumentationNode { + val node = DocumentationNode(fqName.asString(), Content.Empty, NodeKind.Package) + + val externalLink = linkResolver.externalDocumentationLinkResolver.buildExternalDocumentationLink(this) + if (externalLink != null) { + node.append(DocumentationNode(externalLink, Content.Empty, NodeKind.ExternalLink), RefKind.Link) + } + register(this, node) + return node + } + + fun CallableDescriptor.buildExternal(): DocumentationNode = when(this) { + is FunctionDescriptor -> build(true) + is PropertyDescriptor -> build(true) + else -> throw IllegalStateException("Descriptor $this is not known") + } + + fun ClassifierDescriptor.build(external: Boolean = false): DocumentationNode = when (this) { is ClassDescriptor -> build(external) is TypeAliasDescriptor -> build(external) @@ -547,7 +641,7 @@ class DocumentationBuilder isSubclassOfThrowable() -> NodeKind.Exception else -> NodeKind.Class } - val node = nodeForDescriptor(this, kind) + val node = nodeForDescriptor(this, kind, external) register(this, node) typeConstructor.supertypes.forEach { node.appendSupertype(this, it) @@ -632,12 +726,12 @@ class DocumentationBuilder return (receiver?.type?.constructor?.declarationDescriptor as? ClassDescriptor)?.isCompanionObject ?: false } - fun FunctionDescriptor.build(): DocumentationNode { + fun FunctionDescriptor.build(external: Boolean = false): DocumentationNode { if (ErrorUtils.containsErrorType(this)) { logger.warn("Found an unresolved type in ${signatureWithSourceLocation()}") } - val node = nodeForDescriptor(this, if (inCompanionObject()) NodeKind.CompanionObjectFunction else NodeKind.Function) + val node = nodeForDescriptor(this, if (inCompanionObject()) NodeKind.CompanionObjectFunction else NodeKind.Function, external) node.appendInPageChildren(typeParameters, RefKind.Detail) extensionReceiverParameter?.let { node.appendChild(it, RefKind.Detail) } @@ -645,8 +739,12 @@ class DocumentationBuilder node.appendType(returnType) node.appendAnnotations(this) node.appendModifiers(this) - node.appendSourceLink(source) - node.appendDefaultPlatforms(this) + if (!external) { + node.appendSourceLink(source) + node.appendDefaultPlatforms(this) + } else { + node.appendExternalLink(this) + } overriddenDescriptors.forEach { addOverrideLink(it, this) @@ -667,32 +765,42 @@ class DocumentationBuilder } } - fun PropertyDescriptor.build(): DocumentationNode { - val node = nodeForDescriptor(this, if (inCompanionObject()) NodeKind.CompanionObjectProperty else NodeKind.Property) + fun PropertyDescriptor.build(external: Boolean = false): DocumentationNode { + val node = nodeForDescriptor( + this, + if (inCompanionObject()) NodeKind.CompanionObjectProperty else NodeKind.Property, + external + ) node.appendInPageChildren(typeParameters, RefKind.Detail) extensionReceiverParameter?.let { node.appendChild(it, RefKind.Detail) } node.appendType(returnType) node.appendAnnotations(this) node.appendModifiers(this) - node.appendSourceLink(source) - if (isVar) { - node.appendTextNode("var", NodeKind.Modifier) - } - getter?.let { - if (!it.isDefault) { - node.addAccessorDocumentation(descriptorDocumentationParser.parseDocumentation(it), "Getter") + if (!external) { + node.appendSourceLink(source) + if (isVar) { + node.appendTextNode("var", NodeKind.Modifier) } - } - setter?.let { - if (!it.isDefault) { - node.addAccessorDocumentation(descriptorDocumentationParser.parseDocumentation(it), "Setter") + + getter?.let { + if (!it.isDefault) { + node.addAccessorDocumentation(descriptorDocumentationParser.parseDocumentation(it), "Getter") + } } + setter?.let { + if (!it.isDefault) { + node.addAccessorDocumentation(descriptorDocumentationParser.parseDocumentation(it), "Setter") + } + } + node.appendDefaultPlatforms(this) + } + if (external) { + node.appendExternalLink(this) } overriddenDescriptors.forEach { addOverrideLink(it, this) } - node.appendDefaultPlatforms(this) register(this, node) return node diff --git a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt index e19ecf76..400326d2 100644 --- a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt +++ b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt @@ -155,8 +155,8 @@ class ExternalDocumentationLinkResolver @Inject constructor( fun buildExternalDocumentationLink(symbol: DeclarationDescriptor): String? { val packageFqName: FqName = when (symbol) { - is DeclarationDescriptorNonRoot -> symbol.parents.firstOrNull { it is PackageFragmentDescriptor }?.fqNameSafe ?: return null is PackageFragmentDescriptor -> symbol.fqName + is DeclarationDescriptorNonRoot -> symbol.parents.firstOrNull { it is PackageFragmentDescriptor }?.fqNameSafe ?: return null else -> return null } diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index a792460f..85ecdf87 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -209,6 +209,8 @@ fun DocumentationNode.appendTextNode(text: String, fun DocumentationNode.qualifiedName(): String { if (kind == NodeKind.Type) { return qualifiedNameFromType() + } else if (kind == NodeKind.Package) { + return name } return path.drop(1).map { it.name }.filter { it.length > 0 }.joinToString(".") } diff --git a/core/src/test/kotlin/TestAPI.kt b/core/src/test/kotlin/TestAPI.kt index 559b715e..aeff9284 100644 --- a/core/src/test/kotlin/TestAPI.kt +++ b/core/src/test/kotlin/TestAPI.kt @@ -25,22 +25,24 @@ fun verifyModel(vararg roots: ContentRoot, includeNonPublic: Boolean = true, perPackageOptions: List = emptyList(), noStdlibLink: Boolean = true, + collectInheritedExtensionsFromLibraries: Boolean = false, verifier: (DocumentationModule) -> Unit) { val documentation = DocumentationModule("test") val options = DocumentationOptions( - "", - format, - includeNonPublic = includeNonPublic, - skipEmptyPackages = false, - includeRootPackage = true, - sourceLinks = listOf(), - perPackageOptions = perPackageOptions, - generateIndexPages = false, - noStdlibLink = noStdlibLink, - cacheRoot = "default", - languageVersion = null, - apiVersion = null + "", + format, + includeNonPublic = includeNonPublic, + skipEmptyPackages = false, + includeRootPackage = true, + sourceLinks = listOf(), + perPackageOptions = perPackageOptions, + generateIndexPages = false, + noStdlibLink = noStdlibLink, + cacheRoot = "default", + languageVersion = null, + apiVersion = null, + collectInheritedExtensionsFromLibraries = collectInheritedExtensionsFromLibraries ) appendDocumentation(documentation, *roots, @@ -162,6 +164,7 @@ fun verifyOutput(roots: Array, format: String = "html", includeNonPublic: Boolean = true, noStdlibLink: Boolean = true, + collectInheritedExtensionsFromLibraries: Boolean = false, outputGenerator: (DocumentationModule, StringBuilder) -> Unit) { verifyModel( *roots, @@ -169,7 +172,8 @@ fun verifyOutput(roots: Array, withKotlinRuntime = withKotlinRuntime, format = format, includeNonPublic = includeNonPublic, - noStdlibLink = noStdlibLink + noStdlibLink = noStdlibLink, + collectInheritedExtensionsFromLibraries = collectInheritedExtensionsFromLibraries ) { verifyModelOutput(it, outputExtension, roots.first().path, outputGenerator) } @@ -194,6 +198,7 @@ fun verifyOutput( format: String = "html", includeNonPublic: Boolean = true, noStdlibLink: Boolean = true, + collectInheritedExtensionsFromLibraries: Boolean = false, outputGenerator: (DocumentationModule, StringBuilder) -> Unit ) { verifyOutput( @@ -204,6 +209,7 @@ fun verifyOutput( format, includeNonPublic, noStdlibLink, + collectInheritedExtensionsFromLibraries, outputGenerator ) } diff --git a/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt b/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt index 90e5b5fc..46a57278 100644 --- a/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt +++ b/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt @@ -41,6 +41,7 @@ interface DokkaConfiguration { val noStdlibLink: Boolean val cacheRoot: String? val suppressedFiles: List + val collectInheritedExtensionsFromLibraries: Boolean interface SourceRoot { val path: String @@ -82,29 +83,30 @@ interface DokkaConfiguration { } data class SerializeOnlyDokkaConfiguration( - override val moduleName: String, - override val classpath: List, - override val sourceRoots: List, - override val samples: List, - override val includes: List, - override val outputDir: String, - override val format: String, - override val includeNonPublic: Boolean, - override val includeRootPackage: Boolean, - override val reportUndocumented: Boolean, - override val skipEmptyPackages: Boolean, - override val skipDeprecated: Boolean, - override val jdkVersion: Int, - override val generateIndexPages: Boolean, - override val sourceLinks: List, - override val impliedPlatforms: List, - override val perPackageOptions: List, - override val externalDocumentationLinks: List, - override val noStdlibLink: Boolean, - override val cacheRoot: String?, - override val suppressedFiles: List, - override val languageVersion: String?, - override val apiVersion: String? + override val moduleName: String, + override val classpath: List, + override val sourceRoots: List, + override val samples: List, + override val includes: List, + override val outputDir: String, + override val format: String, + override val includeNonPublic: Boolean, + override val includeRootPackage: Boolean, + override val reportUndocumented: Boolean, + override val skipEmptyPackages: Boolean, + override val skipDeprecated: Boolean, + override val jdkVersion: Int, + override val generateIndexPages: Boolean, + override val sourceLinks: List, + override val impliedPlatforms: List, + override val perPackageOptions: List, + override val externalDocumentationLinks: List, + override val noStdlibLink: Boolean, + override val cacheRoot: String?, + override val suppressedFiles: List, + override val languageVersion: String?, + override val apiVersion: String?, + override val collectInheritedExtensionsFromLibraries: Boolean ) : DokkaConfiguration diff --git a/runners/cli/src/main/kotlin/cli/main.kt b/runners/cli/src/main/kotlin/cli/main.kt index fe945ed3..111e1420 100644 --- a/runners/cli/src/main/kotlin/cli/main.kt +++ b/runners/cli/src/main/kotlin/cli/main.kt @@ -62,6 +62,9 @@ class DokkaArguments { @set:Argument(value = "apiVersion", description = "Kotlin Api Version to pass to Kotlin Analysis") var apiVersion: String? = null + @set:Argument(value = "collectInheritedExtensionsFromLibraries", description = "Search for applicable extensions in libraries") + var collectInheritedExtensionsFromLibraries: Boolean = false + } @@ -106,18 +109,19 @@ object MainKt { val classPath = arguments.classpath.split(File.pathSeparatorChar).toList() val documentationOptions = DocumentationOptions( - arguments.outputDir.let { if (it.endsWith('/')) it else it + '/' }, - arguments.outputFormat, - skipDeprecated = arguments.nodeprecated, - sourceLinks = sourceLinks, - impliedPlatforms = arguments.impliedPlatforms.split(','), - perPackageOptions = parsePerPackageOptions(arguments.packageOptions), - jdkVersion = arguments.jdkVersion, - externalDocumentationLinks = parseLinks(arguments.links), - noStdlibLink = arguments.noStdlibLink, - cacheRoot = arguments.cacheRoot, - languageVersion = arguments.languageVersion, - apiVersion = arguments.apiVersion + arguments.outputDir.let { if (it.endsWith('/')) it else it + '/' }, + arguments.outputFormat, + skipDeprecated = arguments.nodeprecated, + sourceLinks = sourceLinks, + impliedPlatforms = arguments.impliedPlatforms.split(','), + perPackageOptions = parsePerPackageOptions(arguments.packageOptions), + jdkVersion = arguments.jdkVersion, + externalDocumentationLinks = parseLinks(arguments.links), + noStdlibLink = arguments.noStdlibLink, + cacheRoot = arguments.cacheRoot, + languageVersion = arguments.languageVersion, + apiVersion = arguments.apiVersion, + collectInheritedExtensionsFromLibraries = arguments.collectInheritedExtensionsFromLibraries ) val generator = DokkaGenerator( diff --git a/runners/gradle-plugin/src/main/kotlin/main.kt b/runners/gradle-plugin/src/main/kotlin/main.kt index 5f02cd0e..4812e217 100644 --- a/runners/gradle-plugin/src/main/kotlin/main.kt +++ b/runners/gradle-plugin/src/main/kotlin/main.kt @@ -134,6 +134,9 @@ open class DokkaTask : DefaultTask() { @Optional @Input var apiVersion: String? = null + @Input + var collectInheritedExtensionsFromLibraries: Boolean = false + @get:Internal internal val kotlinCompileBasedClasspathAndSourceRoots: ClasspathAndSourceRoots by lazy { extractClasspathAndSourceRootsFromKotlinTasks() } @@ -287,29 +290,31 @@ open class DokkaTask : DefaultTask() { val bootstrapProxy: DokkaBootstrap = automagicTypedProxy(javaClass.classLoader, bootstrapInstance) val configuration = SerializeOnlyDokkaConfiguration( - moduleName, - fullClasspath.map { it.absolutePath }, - sourceRoots, - samples.filterNotNull().map { project.file(it).absolutePath }, - includes.filterNotNull().map { project.file(it).absolutePath }, - outputDirectory, - outputFormat, - includeNonPublic, - false, - reportUndocumented, - skipEmptyPackages, - skipDeprecated, - jdkVersion, - true, - linkMappings, - impliedPlatforms, - perPackageOptions, - externalDocumentationLinks, - noStdlibLink, - cacheRoot, - collectSuppressedFiles(sourceRoots), - languageVersion, - apiVersion) + moduleName, + fullClasspath.map { it.absolutePath }, + sourceRoots, + samples.filterNotNull().map { project.file(it).absolutePath }, + includes.filterNotNull().map { project.file(it).absolutePath }, + outputDirectory, + outputFormat, + includeNonPublic, + false, + reportUndocumented, + skipEmptyPackages, + skipDeprecated, + jdkVersion, + true, + linkMappings, + impliedPlatforms, + perPackageOptions, + externalDocumentationLinks, + noStdlibLink, + cacheRoot, + collectSuppressedFiles(sourceRoots), + languageVersion, + apiVersion, + collectInheritedExtensionsFromLibraries + ) bootstrapProxy.configure( -- cgit From 2f1512f5ec7f23181cf5fcad96d9ee66507de472 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Sat, 20 Jan 2018 16:44:35 +0300 Subject: [backport] Add value for constants from Kotlin Original: fab0890 --- core/src/main/kotlin/Kotlin/DocumentationBuilder.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index 125f9fd4..39202173 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.name.FqName import or