Skip to content

Commit

Permalink
Custom doctag extension (#2343)
Browse files Browse the repository at this point in the history
* Add an extension point for rendering custom doc tags

* Iterate over documentable sourcesets when building custom tags

* Extract a nested custom tags brief block into a separate method

* Filter out tag content providers and make since kotlin brief a one-liner

* Add padding to "Since Kotlin" block in brief description
  • Loading branch information
IgnatBeresnev committed Feb 17, 2022
1 parent 2372302 commit 13b8718
Show file tree
Hide file tree
Showing 15 changed files with 210 additions and 38 deletions.
1 change: 1 addition & 0 deletions core/api/core.api
Expand Up @@ -4216,6 +4216,7 @@ public final class org/jetbrains/dokka/pages/TextStyle : java/lang/Enum, org/jet
public static final field BreakableAfter Lorg/jetbrains/dokka/pages/TextStyle;
public static final field Cover Lorg/jetbrains/dokka/pages/TextStyle;
public static final field Indented Lorg/jetbrains/dokka/pages/TextStyle;
public static final field InlineComment Lorg/jetbrains/dokka/pages/TextStyle;
public static final field Italic Lorg/jetbrains/dokka/pages/TextStyle;
public static final field Monospace Lorg/jetbrains/dokka/pages/TextStyle;
public static final field Paragraph Lorg/jetbrains/dokka/pages/TextStyle;
Expand Down
3 changes: 2 additions & 1 deletion core/src/main/kotlin/pages/ContentNodes.kt
Expand Up @@ -383,7 +383,8 @@ enum class TokenStyle : Style {
}

enum class TextStyle : Style {
Bold, Italic, Strong, Strikethrough, Paragraph, Block, Span, Monospace, Indented, Cover, UnderCoverText, BreakableAfter, Breakable
Bold, Italic, Strong, Strikethrough, Paragraph,
Block, Span, Monospace, Indented, Cover, UnderCoverText, BreakableAfter, Breakable, InlineComment
}

enum class ContentStyle : Style {
Expand Down
25 changes: 23 additions & 2 deletions plugins/base/api/base.api
Expand Up @@ -5,6 +5,7 @@ public final class org/jetbrains/dokka/base/DokkaBase : org/jetbrains/dokka/plug
public final fun getBaseSearchbarDataInstaller ()Lorg/jetbrains/dokka/plugability/Extension;
public final fun getCommentsToContentConverter ()Lorg/jetbrains/dokka/plugability/ExtensionPoint;
public final fun getCustomResourceInstaller ()Lorg/jetbrains/dokka/plugability/Extension;
public final fun getCustomTagContentProvider ()Lorg/jetbrains/dokka/plugability/ExtensionPoint;
public final fun getDefaultExternalClasslikesTranslator ()Lorg/jetbrains/dokka/plugability/Extension;
public final fun getDefaultExternalDocumentablesProvider ()Lorg/jetbrains/dokka/plugability/Extension;
public final fun getDefaultKotlinAnalysis ()Lorg/jetbrains/dokka/plugability/Extension;
Expand Down Expand Up @@ -52,6 +53,7 @@ public final class org/jetbrains/dokka/base/DokkaBase : org/jetbrains/dokka/plug
public final fun getSameMethodNameMerger ()Lorg/jetbrains/dokka/plugability/Extension;
public final fun getScriptsInstaller ()Lorg/jetbrains/dokka/plugability/Extension;
public final fun getSignatureProvider ()Lorg/jetbrains/dokka/plugability/ExtensionPoint;
public final fun getSinceKotlinTagContentProvider ()Lorg/jetbrains/dokka/plugability/Extension;
public final fun getSinceKotlinTransformer ()Lorg/jetbrains/dokka/plugability/Extension;
public final fun getSingleGeneration ()Lorg/jetbrains/dokka/plugability/Extension;
public final fun getSourceLinksTransformer ()Lorg/jetbrains/dokka/plugability/Extension;
Expand Down Expand Up @@ -1267,6 +1269,24 @@ public final class org/jetbrains/dokka/base/transformers/pages/sourcelinks/Sourc
public static final fun hasTabbedContent (Lorg/jetbrains/dokka/pages/ContentGroup;)Z
}

public abstract interface class org/jetbrains/dokka/base/transformers/pages/tags/CustomTagContentProvider {
public abstract fun contentForBrief (Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;Lorg/jetbrains/dokka/model/doc/CustomTagWrapper;)V
public abstract fun contentForDescription (Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;Lorg/jetbrains/dokka/model/doc/CustomTagWrapper;)V
public abstract fun isApplicable (Lorg/jetbrains/dokka/model/doc/CustomTagWrapper;)Z
}

public final class org/jetbrains/dokka/base/transformers/pages/tags/CustomTagContentProvider$DefaultImpls {
public static fun contentForBrief (Lorg/jetbrains/dokka/base/transformers/pages/tags/CustomTagContentProvider;Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;Lorg/jetbrains/dokka/model/doc/CustomTagWrapper;)V
public static fun contentForDescription (Lorg/jetbrains/dokka/base/transformers/pages/tags/CustomTagContentProvider;Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;Lorg/jetbrains/dokka/model/doc/CustomTagWrapper;)V
}

public final class org/jetbrains/dokka/base/transformers/pages/tags/SinceKotlinTagContentProvider : org/jetbrains/dokka/base/transformers/pages/tags/CustomTagContentProvider {
public static final field INSTANCE Lorg/jetbrains/dokka/base/transformers/pages/tags/SinceKotlinTagContentProvider;
public fun contentForBrief (Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;Lorg/jetbrains/dokka/model/doc/CustomTagWrapper;)V
public fun contentForDescription (Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;Lorg/jetbrains/dokka/model/doc/CustomTagWrapper;)V
public fun isApplicable (Lorg/jetbrains/dokka/model/doc/CustomTagWrapper;)Z
}

public final class org/jetbrains/dokka/base/translators/descriptors/DRIWithPlatformInfo {
public fun <init> (Lorg/jetbrains/dokka/links/DRI;Ljava/util/Map;)V
public final fun component1 ()Lorg/jetbrains/dokka/links/DRI;
Expand Down Expand Up @@ -1319,7 +1339,8 @@ public final class org/jetbrains/dokka/base/translators/documentables/DefaultDoc
}

public class org/jetbrains/dokka/base/translators/documentables/DefaultPageCreator {
public fun <init> (Lorg/jetbrains/dokka/base/DokkaBaseConfiguration;Lorg/jetbrains/dokka/base/transformers/pages/comments/CommentsToContentConverter;Lorg/jetbrains/dokka/base/signatures/SignatureProvider;Lorg/jetbrains/dokka/utilities/DokkaLogger;)V
public fun <init> (Lorg/jetbrains/dokka/base/DokkaBaseConfiguration;Lorg/jetbrains/dokka/base/transformers/pages/comments/CommentsToContentConverter;Lorg/jetbrains/dokka/base/signatures/SignatureProvider;Lorg/jetbrains/dokka/utilities/DokkaLogger;Ljava/util/List;)V
public synthetic fun <init> (Lorg/jetbrains/dokka/base/DokkaBaseConfiguration;Lorg/jetbrains/dokka/base/transformers/pages/comments/CommentsToContentConverter;Lorg/jetbrains/dokka/base/signatures/SignatureProvider;Lorg/jetbrains/dokka/utilities/DokkaLogger;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
protected fun contentForBrief (Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Lorg/jetbrains/dokka/model/Documentable;)V
protected fun contentForClasslike (Lorg/jetbrains/dokka/model/DClasslike;)Lorg/jetbrains/dokka/pages/ContentGroup;
protected fun contentForComments (Lorg/jetbrains/dokka/model/Documentable;Z)Ljava/util/List;
Expand All @@ -1332,10 +1353,10 @@ public class org/jetbrains/dokka/base/translators/documentables/DefaultPageCreat
protected fun contentForPackage (Lorg/jetbrains/dokka/model/DPackage;)Lorg/jetbrains/dokka/pages/ContentGroup;
protected fun contentForProperty (Lorg/jetbrains/dokka/model/DProperty;)Lorg/jetbrains/dokka/pages/ContentGroup;
protected fun contentForScope (Lorg/jetbrains/dokka/model/WithScope;Lorg/jetbrains/dokka/links/DRI;Ljava/util/Set;)Lorg/jetbrains/dokka/pages/ContentGroup;
protected fun contentForSinceKotlin (Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Lorg/jetbrains/dokka/model/Documentable;)V
protected fun divergentBlock (Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Ljava/lang/String;Ljava/util/Collection;Lorg/jetbrains/dokka/pages/ContentKind;Lorg/jetbrains/dokka/model/properties/PropertyContainer;)V
public static synthetic fun divergentBlock$default (Lorg/jetbrains/dokka/base/translators/documentables/DefaultPageCreator;Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Ljava/lang/String;Ljava/util/Collection;Lorg/jetbrains/dokka/pages/ContentKind;Lorg/jetbrains/dokka/model/properties/PropertyContainer;ILjava/lang/Object;)V
protected fun getContentBuilder ()Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder;
public final fun getCustomTagContentProviders ()Ljava/util/List;
public final fun getLogger ()Lorg/jetbrains/dokka/utilities/DokkaLogger;
protected final fun getSeparateInheritedMembers ()Z
public fun pageForClasslike (Lorg/jetbrains/dokka/model/DClasslike;)Lorg/jetbrains/dokka/pages/ClasslikePageNode;
Expand Down
7 changes: 7 additions & 0 deletions plugins/base/src/main/kotlin/DokkaBase.kt
Expand Up @@ -29,6 +29,8 @@ import org.jetbrains.dokka.base.translators.documentables.DefaultDocumentableToP
import org.jetbrains.dokka.base.translators.psi.DefaultPsiToDocumentableTranslator
import org.jetbrains.dokka.base.generation.SingleModuleGeneration
import org.jetbrains.dokka.base.renderers.html.command.consumers.ReplaceVersionsConsumer
import org.jetbrains.dokka.base.transformers.pages.tags.CustomTagContentProvider
import org.jetbrains.dokka.base.transformers.pages.tags.SinceKotlinTagContentProvider
import org.jetbrains.dokka.base.translators.descriptors.DefaultExternalDocumentablesProvider
import org.jetbrains.dokka.base.translators.descriptors.ExternalClasslikesTranslator
import org.jetbrains.dokka.base.translators.descriptors.ExternalDocumentablesProvider
Expand All @@ -41,6 +43,7 @@ class DokkaBase : DokkaPlugin() {
val preMergeDocumentableTransformer by extensionPoint<PreMergeDocumentableTransformer>()
val pageMergerStrategy by extensionPoint<PageMergerStrategy>()
val commentsToContentConverter by extensionPoint<CommentsToContentConverter>()
val customTagContentProvider by extensionPoint<CustomTagContentProvider>()
val signatureProvider by extensionPoint<SignatureProvider>()
val locationProviderFactory by extensionPoint<LocationProviderFactory>()
val externalLocationProviderFactory by extensionPoint<ExternalLocationProviderFactory>()
Expand Down Expand Up @@ -151,6 +154,10 @@ class DokkaBase : DokkaPlugin() {
commentsToContentConverter with DocTagToContentConverter()
}

val sinceKotlinTagContentProvider by extending {
customTagContentProvider with SinceKotlinTagContentProvider
}

val pageMerger by extending {
CoreExtensions.pageTransformer providing ::PageMerger
}
Expand Down
Expand Up @@ -113,6 +113,7 @@ open class HtmlRenderer(
childrenCallback()
}
}
node.hasStyle(TextStyle.InlineComment) -> div("inline-comment") { childrenCallback() }
node.dci.kind == ContentKind.BriefComment -> div("brief $additionalClasses") { childrenCallback() }
node.dci.kind == ContentKind.Cover -> div("cover $additionalClasses") { //TODO this can be removed
childrenCallback()
Expand Down
@@ -0,0 +1,59 @@
package org.jetbrains.dokka.base.transformers.pages.tags

import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder.DocumentableContentBuilder
import org.jetbrains.dokka.model.doc.CustomTagWrapper
import org.jetbrains.dokka.model.doc.DocTag

/**
* Provides an ability to render custom doc tags
*
* Custom tags can be generated during build, for instance via transformers from converting an annotation
* (such as in [org.jetbrains.dokka.base.transformers.pages.annotations.SinceKotlinTransformer])
*
* Also, custom tags can come from the kdoc itself, where "custom" is defined as unknown to the compiler/spec.
* `@property` and `@throws` are not custom tags - they are defined by the spec and have special meaning
* and separate blocks on the documentation page, it's clear how to render it. Whereas `@usesMathJax` is
* a custom tag - it's application/plugin specific and is not handled by dokka by default.
*
* Using this provider, we can map custom tags (such as `@usesMathJax`) and generate content for it that
* will be displayed on the pages.
*/
interface CustomTagContentProvider {

/**
* Whether this content provider supports given [CustomTagWrapper].
*
* Tags can be filtered out either by name or by nested [DocTag] type
*/
fun isApplicable(customTag: CustomTagWrapper): Boolean

/**
* Full blown content description, most likely to be on a separate page
* dedicated to just one element (i.e one class/function), so any
* amount of detail should be fine.
*/
fun DocumentableContentBuilder.contentForDescription(
sourceSet: DokkaSourceSet,
customTag: CustomTagWrapper
) {}

/**
* Brief comment section, usually displayed as a summary/preview.
*
* For instance, when listing all functions of a class on one page,
* it'll be too much to display complete documentation for each function.
* Instead, a small brief is shown for each one (i.e the first paragraph
* or some other important information) - the user can go to the dedicated
* page for more details if they find the brief interesting.
*
* Tag-wise, it would make sense to include `Since Kotlin`, since it's
* important information for the users of stdlib. It would make little
* sense to include `@usesMathjax` here, as this information seems
* to be more specific and detailed than is needed for a brief.
*/
fun DocumentableContentBuilder.contentForBrief(
sourceSet: DokkaSourceSet,
customTag: CustomTagWrapper
) {}
}
@@ -0,0 +1,34 @@
package org.jetbrains.dokka.base.transformers.pages.tags

import org.jetbrains.dokka.DokkaConfiguration
import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder.DocumentableContentBuilder
import org.jetbrains.dokka.model.doc.CustomTagWrapper
import org.jetbrains.dokka.pages.ContentKind
import org.jetbrains.dokka.pages.TextStyle

object SinceKotlinTagContentProvider : CustomTagContentProvider {

private const val SINCE_KOTLIN_TAG_NAME = "Since Kotlin"

override fun isApplicable(customTag: CustomTagWrapper) = customTag.name == SINCE_KOTLIN_TAG_NAME

override fun DocumentableContentBuilder.contentForDescription(
sourceSet: DokkaConfiguration.DokkaSourceSet,
customTag: CustomTagWrapper
) {
group(sourceSets = setOf(sourceSet), kind = ContentKind.Comment, styles = setOf(TextStyle.Block)) {
header(4, customTag.name)
comment(customTag.root)
}
}

override fun DocumentableContentBuilder.contentForBrief(
sourceSet: DokkaConfiguration.DokkaSourceSet,
customTag: CustomTagWrapper
) {
group(sourceSets = setOf(sourceSet), styles = setOf(TextStyle.InlineComment)) {
text(customTag.name + " ", styles = setOf(TextStyle.Bold))
comment(customTag.root, styles = emptySet())
}
}
}
Expand Up @@ -4,10 +4,7 @@ import org.jetbrains.dokka.base.DokkaBase
import org.jetbrains.dokka.base.DokkaBaseConfiguration
import org.jetbrains.dokka.model.DModule
import org.jetbrains.dokka.pages.ModulePageNode
import org.jetbrains.dokka.plugability.configuration
import org.jetbrains.dokka.plugability.DokkaContext
import org.jetbrains.dokka.plugability.plugin
import org.jetbrains.dokka.plugability.querySingle
import org.jetbrains.dokka.plugability.*
import org.jetbrains.dokka.transformers.documentation.DocumentableToPageTranslator

class DefaultDocumentableToPageTranslator(
Expand All @@ -16,8 +13,15 @@ class DefaultDocumentableToPageTranslator(
private val configuration = configuration<DokkaBase, DokkaBaseConfiguration>(context)
private val commentsToContentConverter = context.plugin<DokkaBase>().querySingle { commentsToContentConverter }
private val signatureProvider = context.plugin<DokkaBase>().querySingle { signatureProvider }
private val customTagContentProviders = context.plugin<DokkaBase>().query { customTagContentProvider }
private val logger = context.logger

override fun invoke(module: DModule): ModulePageNode =
DefaultPageCreator(configuration, commentsToContentConverter, signatureProvider, logger).pageForModule(module)
DefaultPageCreator(
configuration,
commentsToContentConverter,
signatureProvider,
logger,
customTagContentProviders
).pageForModule(module)
}

0 comments on commit 13b8718

Please sign in to comment.