aboutsummaryrefslogtreecommitdiff
path: root/core/src/main/kotlin/Kotlin
diff options
context:
space:
mode:
authorBłażej Kardyś <bkardys@virtuslab.com>2019-10-31 11:44:03 +0100
committerBłażej Kardyś <bkardys@virtuslab.com>2019-10-31 11:44:03 +0100
commitc33e8e16a0e446b78496cbcd878ba76ea51c0940 (patch)
tree7362b668c5ee48255e46a7efcb8db3f2525d1e8f /core/src/main/kotlin/Kotlin
parent14a290009098b777521b1dedb551047fb66ba73b (diff)
downloaddokka-c33e8e16a0e446b78496cbcd878ba76ea51c0940.tar.gz
dokka-c33e8e16a0e446b78496cbcd878ba76ea51c0940.tar.bz2
dokka-c33e8e16a0e446b78496cbcd878ba76ea51c0940.zip
Temp changes
Diffstat (limited to 'core/src/main/kotlin/Kotlin')
-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
3 files changed, 186 insertions, 806 deletions
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