diff options
-rw-r--r-- | core/src/main/kotlin/Kotlin/DocumentationBuilder.kt | 70 | ||||
-rw-r--r-- | core/src/main/kotlin/Kotlin/KotlinLanguageService.kt | 2 | ||||
-rw-r--r-- | core/src/main/kotlin/Model/DocumentationNode.kt | 19 | ||||
-rw-r--r-- | core/src/main/kotlin/Model/DocumentationReference.kt | 3 | ||||
-rw-r--r-- | core/src/test/kotlin/TestAPI.kt | 48 | ||||
-rw-r--r-- | 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<String> } +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<String> get() = references(RefKind.Platform).map { it.to.name } + val externalType: DocumentationNode? + get() = references(RefKind.ExternalType).map { it.to }.firstOrNull() val supertypes: List<DocumentationNode> 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<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) { 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<DokkaConfiguration.PackageOptions> = 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<ContentRoot>, 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) } } |