aboutsummaryrefslogtreecommitdiff
path: root/plugins/base/src/main/kotlin
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/base/src/main/kotlin')
-rw-r--r--plugins/base/src/main/kotlin/DokkaBase.kt299
-rw-r--r--plugins/base/src/main/kotlin/DokkaBaseConfiguration.kt28
-rw-r--r--plugins/base/src/main/kotlin/deprecated/AnalysisApiDeprecatedError.kt16
-rw-r--r--plugins/base/src/main/kotlin/deprecated/KotlinAnalysisDeprecatedApi.kt77
-rw-r--r--plugins/base/src/main/kotlin/deprecated/ParsersDeprecatedAPI.kt42
-rw-r--r--plugins/base/src/main/kotlin/deprecated/ParsersFactoriesDeprecatedAPI.kt24
-rw-r--r--plugins/base/src/main/kotlin/deprecated/TranslatorDescriptorsDeprecatedAPI.kt50
-rw-r--r--plugins/base/src/main/kotlin/deprecated/TranslatorPsiDeprecatedAPI.kt25
-rw-r--r--plugins/base/src/main/kotlin/generation/SingleModuleGeneration.kt131
-rw-r--r--plugins/base/src/main/kotlin/renderers/DefaultRenderer.kt257
-rw-r--r--plugins/base/src/main/kotlin/renderers/FileWriter.kt109
-rw-r--r--plugins/base/src/main/kotlin/renderers/OutputWriter.kt11
-rw-r--r--plugins/base/src/main/kotlin/renderers/PackageListService.kt80
-rw-r--r--plugins/base/src/main/kotlin/renderers/TabSortingStrategy.kt11
-rw-r--r--plugins/base/src/main/kotlin/renderers/contentTypeChecking.kt24
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/HtmlContent.kt18
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt1013
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/NavigationDataProvider.kt134
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/NavigationPage.kt129
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/SearchbarDataInstaller.kt128
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/Tags.kt82
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/command/consumers/ImmediateResolutionTagConsumer.kt37
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/command/consumers/PathToRootConsumer.kt26
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/command/consumers/ReplaceVersionsConsumer.kt29
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/command/consumers/ResolveLinkConsumer.kt34
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/htmlFormatingUtils.kt67
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/htmlPreprocessors.kt172
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/innerTemplating/DefaultTemplateModelFactory.kt234
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/innerTemplating/DefaultTemplateModelMerger.kt20
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/innerTemplating/HtmlTemplater.kt82
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/innerTemplating/TemplateModelFactory.kt19
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/innerTemplating/TemplateModelMerger.kt9
-rw-r--r--plugins/base/src/main/kotlin/renderers/html/shouldRenderSourceSetBubbles.kt20
-rw-r--r--plugins/base/src/main/kotlin/renderers/pageId.kt31
-rw-r--r--plugins/base/src/main/kotlin/renderers/preprocessors.kt41
-rw-r--r--plugins/base/src/main/kotlin/resolvers/anchors/AnchorsHint.kt19
-rw-r--r--plugins/base/src/main/kotlin/resolvers/external/DefaultExternalLocationProvider.kt46
-rw-r--r--plugins/base/src/main/kotlin/resolvers/external/DefaultExternalLocationProviderFactory.kt28
-rw-r--r--plugins/base/src/main/kotlin/resolvers/external/Dokka010ExternalLocationProvider.kt46
-rw-r--r--plugins/base/src/main/kotlin/resolvers/external/ExternalLocationProvider.kt18
-rw-r--r--plugins/base/src/main/kotlin/resolvers/external/ExternalLocationProviderFactory.kt11
-rw-r--r--plugins/base/src/main/kotlin/resolvers/external/ExternalLocationProviderFactoryWithCache.kt21
-rw-r--r--plugins/base/src/main/kotlin/resolvers/external/javadoc/AndroidExternalLocationProvider.kt18
-rw-r--r--plugins/base/src/main/kotlin/resolvers/external/javadoc/JavadocExternalLocationProvider.kt62
-rw-r--r--plugins/base/src/main/kotlin/resolvers/external/javadoc/JavadocExternalLocationProviderFactory.kt39
-rw-r--r--plugins/base/src/main/kotlin/resolvers/local/DefaultLocationProvider.kt82
-rw-r--r--plugins/base/src/main/kotlin/resolvers/local/DokkaBaseLocationProvider.kt27
-rw-r--r--plugins/base/src/main/kotlin/resolvers/local/DokkaLocationProvider.kt182
-rw-r--r--plugins/base/src/main/kotlin/resolvers/local/DokkaLocationProviderFactory.kt26
-rw-r--r--plugins/base/src/main/kotlin/resolvers/local/LocationProvider.kt47
-rw-r--r--plugins/base/src/main/kotlin/resolvers/local/LocationProviderFactory.kt11
-rw-r--r--plugins/base/src/main/kotlin/resolvers/shared/ExternalDocumentation.kt9
-rw-r--r--plugins/base/src/main/kotlin/resolvers/shared/LinkFormat.kt10
-rw-r--r--plugins/base/src/main/kotlin/resolvers/shared/PackageList.kt83
-rw-r--r--plugins/base/src/main/kotlin/resolvers/shared/RecognizedLinkFormat.kt29
-rw-r--r--plugins/base/src/main/kotlin/resolvers/shared/utils.kt41
-rw-r--r--plugins/base/src/main/kotlin/signatures/JvmSignatureUtils.kt231
-rw-r--r--plugins/base/src/main/kotlin/signatures/KotlinSignatureProvider.kt503
-rw-r--r--plugins/base/src/main/kotlin/signatures/KotlinSignatureUtils.kt86
-rw-r--r--plugins/base/src/main/kotlin/signatures/SignatureProvider.kt12
-rw-r--r--plugins/base/src/main/kotlin/templating/AddToNavigationCommand.kt9
-rw-r--r--plugins/base/src/main/kotlin/templating/AddToSearch.kt12
-rw-r--r--plugins/base/src/main/kotlin/templating/AddToSourcesetDependencies.kt10
-rw-r--r--plugins/base/src/main/kotlin/templating/Command.kt15
-rw-r--r--plugins/base/src/main/kotlin/templating/ImmediateHtmlCommandConsumer.kt17
-rw-r--r--plugins/base/src/main/kotlin/templating/InsertTemplateExtra.kt16
-rw-r--r--plugins/base/src/main/kotlin/templating/PathToRootSubstitutionCommand.kt10
-rw-r--r--plugins/base/src/main/kotlin/templating/ProjectNameSubstitutionCommand.kt10
-rw-r--r--plugins/base/src/main/kotlin/templating/ReplaceVersionsCommand.kt7
-rw-r--r--plugins/base/src/main/kotlin/templating/ResolveLinkCommand.kt11
-rw-r--r--plugins/base/src/main/kotlin/templating/jsonMapperForPlugins.kt62
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/ActualTypealiasAdder.kt127
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/ClashingDriIdentifier.kt12
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/DeprecatedDocumentableFilterTransformer.kt62
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/DocumentableReplacerTransformer.kt239
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/DocumentableVisibilityFilterTransformer.kt388
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/EmptyModulesFilterTransformer.kt14
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/EmptyPackagesFilterTransformer.kt30
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/ExtensionExtractorTransformer.kt160
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/InheritedEntriesDocumentableFilterTransformer.kt23
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/InheritorsExtractorTransformer.kt91
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/KotlinArrayDocumentableReplacerTransformer.kt68
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/ModuleAndPackageDocumentationTransformer.kt47
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/ObviousFunctionsDocumentableFilterTransformer.kt17
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/ReportUndocumentedTransformer.kt143
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/SuppressTagDocumentableFilter.kt17
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/SuppressedByConditionDocumentableFilterTransformer.kt146
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/SuppressedByConfigurationDocumentableFilterTransformer.kt57
-rw-r--r--plugins/base/src/main/kotlin/transformers/documentables/utils.kt35
-rw-r--r--plugins/base/src/main/kotlin/transformers/pages/DefaultSamplesTransformer.kt117
-rw-r--r--plugins/base/src/main/kotlin/transformers/pages/annotations/SinceKotlinTransformer.kt186
-rw-r--r--plugins/base/src/main/kotlin/transformers/pages/comments/CommentsToContentConverter.kt22
-rw-r--r--plugins/base/src/main/kotlin/transformers/pages/comments/DocTagToContentConverter.kt270
-rw-r--r--plugins/base/src/main/kotlin/transformers/pages/merger/FallbackPageMergerStrategy.kt22
-rw-r--r--plugins/base/src/main/kotlin/transformers/pages/merger/PageMerger.kt40
-rw-r--r--plugins/base/src/main/kotlin/transformers/pages/merger/PageMergerStrategy.kt13
-rw-r--r--plugins/base/src/main/kotlin/transformers/pages/merger/SameMethodNamePageMergerStrategy.kt68
-rw-r--r--plugins/base/src/main/kotlin/transformers/pages/merger/SourceSetMergingPageTransformer.kt43
-rw-r--r--plugins/base/src/main/kotlin/transformers/pages/sourcelinks/SourceLinksTransformer.kt140
-rw-r--r--plugins/base/src/main/kotlin/transformers/pages/tags/CustomTagContentProvider.kt63
-rw-r--r--plugins/base/src/main/kotlin/transformers/pages/tags/SinceKotlinTagContentProvider.kt38
-rw-r--r--plugins/base/src/main/kotlin/translators/documentables/DefaultDocumentableToPageTranslator.kt34
-rw-r--r--plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt779
-rw-r--r--plugins/base/src/main/kotlin/translators/documentables/DeprecationSectionCreator.kt194
-rw-r--r--plugins/base/src/main/kotlin/translators/documentables/DescriptionSections.kt349
-rw-r--r--plugins/base/src/main/kotlin/translators/documentables/DriClashAwareName.kt13
-rw-r--r--plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt781
-rw-r--r--plugins/base/src/main/kotlin/translators/documentables/briefFromContentNodes.kt62
-rw-r--r--plugins/base/src/main/kotlin/utils/CollectionExtensions.kt16
-rw-r--r--plugins/base/src/main/kotlin/utils/alphabeticalOrder.kt11
110 files changed, 0 insertions, 10312 deletions
diff --git a/plugins/base/src/main/kotlin/DokkaBase.kt b/plugins/base/src/main/kotlin/DokkaBase.kt
deleted file mode 100644
index ca86d4d5..00000000
--- a/plugins/base/src/main/kotlin/DokkaBase.kt
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base
-
-import org.jetbrains.dokka.CoreExtensions
-import org.jetbrains.dokka.base.generation.SingleModuleGeneration
-import org.jetbrains.dokka.base.renderers.*
-import org.jetbrains.dokka.base.renderers.html.*
-import org.jetbrains.dokka.base.renderers.html.command.consumers.PathToRootConsumer
-import org.jetbrains.dokka.base.renderers.html.command.consumers.ReplaceVersionsConsumer
-import org.jetbrains.dokka.base.renderers.html.command.consumers.ResolveLinkConsumer
-import org.jetbrains.dokka.base.resolvers.external.DefaultExternalLocationProviderFactory
-import org.jetbrains.dokka.base.resolvers.external.ExternalLocationProviderFactory
-import org.jetbrains.dokka.base.resolvers.external.javadoc.JavadocExternalLocationProviderFactory
-import org.jetbrains.dokka.base.resolvers.local.DokkaLocationProviderFactory
-import org.jetbrains.dokka.base.resolvers.local.LocationProviderFactory
-import org.jetbrains.dokka.base.resolvers.shared.RecognizedLinkFormat
-import org.jetbrains.dokka.base.signatures.KotlinSignatureProvider
-import org.jetbrains.dokka.base.signatures.SignatureProvider
-import org.jetbrains.dokka.base.templating.ImmediateHtmlCommandConsumer
-import org.jetbrains.dokka.base.transformers.documentables.*
-import org.jetbrains.dokka.base.transformers.pages.DefaultSamplesTransformer
-import org.jetbrains.dokka.base.transformers.pages.annotations.SinceKotlinTransformer
-import org.jetbrains.dokka.base.transformers.pages.comments.CommentsToContentConverter
-import org.jetbrains.dokka.base.transformers.pages.comments.DocTagToContentConverter
-import org.jetbrains.dokka.base.transformers.pages.merger.*
-import org.jetbrains.dokka.base.transformers.pages.sourcelinks.SourceLinksTransformer
-import org.jetbrains.dokka.base.transformers.pages.tags.CustomTagContentProvider
-import org.jetbrains.dokka.base.transformers.pages.tags.SinceKotlinTagContentProvider
-import org.jetbrains.dokka.base.translators.documentables.DefaultDocumentableToPageTranslator
-import org.jetbrains.dokka.generation.Generation
-import org.jetbrains.dokka.plugability.*
-import org.jetbrains.dokka.renderers.Renderer
-import org.jetbrains.dokka.transformers.documentation.*
-import org.jetbrains.dokka.transformers.pages.PageTransformer
-
-@Suppress("unused")
-public class DokkaBase : DokkaPlugin() {
-
- public val preMergeDocumentableTransformer: ExtensionPoint<PreMergeDocumentableTransformer> by extensionPoint()
- public val pageMergerStrategy: ExtensionPoint<PageMergerStrategy> by extensionPoint()
- public val commentsToContentConverter: ExtensionPoint<CommentsToContentConverter> by extensionPoint()
- public val customTagContentProvider: ExtensionPoint<CustomTagContentProvider> by extensionPoint()
- public val signatureProvider: ExtensionPoint<SignatureProvider> by extensionPoint()
- public val locationProviderFactory: ExtensionPoint<LocationProviderFactory> by extensionPoint()
- public val externalLocationProviderFactory: ExtensionPoint<ExternalLocationProviderFactory> by extensionPoint()
- public val outputWriter: ExtensionPoint<OutputWriter> by extensionPoint()
- public val htmlPreprocessors: ExtensionPoint<PageTransformer> by extensionPoint()
-
- @Deprecated("It is not used anymore")
- public val tabSortingStrategy: ExtensionPoint<TabSortingStrategy> by extensionPoint()
- public val immediateHtmlCommandConsumer: ExtensionPoint<ImmediateHtmlCommandConsumer> by extensionPoint()
-
-
- public val singleGeneration: Extension<Generation, *, *> by extending {
- CoreExtensions.generation providing ::SingleModuleGeneration
- }
-
- public val documentableMerger: Extension<DocumentableMerger, *, *> by extending {
- CoreExtensions.documentableMerger providing ::DefaultDocumentableMerger
- }
-
- public val deprecatedDocumentableFilter: Extension<PreMergeDocumentableTransformer, *, *> by extending {
- preMergeDocumentableTransformer providing ::DeprecatedDocumentableFilterTransformer
- }
-
- public val suppressedDocumentableFilter: Extension<PreMergeDocumentableTransformer, *, *> by extending {
- preMergeDocumentableTransformer providing ::SuppressedByConfigurationDocumentableFilterTransformer
- }
-
- public val suppressedBySuppressTagDocumentableFilter: Extension<PreMergeDocumentableTransformer, *, *> by extending {
- preMergeDocumentableTransformer providing ::SuppressTagDocumentableFilter
- }
-
- public val documentableVisibilityFilter: Extension<PreMergeDocumentableTransformer, *, *> by extending {
- preMergeDocumentableTransformer providing ::DocumentableVisibilityFilterTransformer
- }
-
- public val obviousFunctionsVisbilityFilter: Extension<PreMergeDocumentableTransformer, *, *> by extending {
- preMergeDocumentableTransformer providing ::ObviousFunctionsDocumentableFilterTransformer
- }
-
- public val inheritedEntriesVisbilityFilter: Extension<PreMergeDocumentableTransformer, *, *> by extending {
- preMergeDocumentableTransformer providing ::InheritedEntriesDocumentableFilterTransformer
- }
-
- public val kotlinArrayDocumentableReplacer: Extension<PreMergeDocumentableTransformer, *, *> by extending {
- preMergeDocumentableTransformer providing ::KotlinArrayDocumentableReplacerTransformer
- }
-
- public val emptyPackagesFilter: Extension<PreMergeDocumentableTransformer, *, *> by extending {
- preMergeDocumentableTransformer providing ::EmptyPackagesFilterTransformer order {
- after(
- deprecatedDocumentableFilter,
- suppressedDocumentableFilter,
- documentableVisibilityFilter,
- suppressedBySuppressTagDocumentableFilter,
- obviousFunctionsVisbilityFilter,
- inheritedEntriesVisbilityFilter,
- )
- }
- }
-
- public val emptyModulesFilter: Extension<PreMergeDocumentableTransformer, *, *> by extending {
- preMergeDocumentableTransformer with EmptyModulesFilterTransformer() order {
- after(emptyPackagesFilter)
- }
- }
-
- public val modulesAndPackagesDocumentation: Extension<PreMergeDocumentableTransformer, *, *> by extending {
- preMergeDocumentableTransformer providing ::ModuleAndPackageDocumentationTransformer
- }
-
- public val actualTypealiasAdder: Extension<DocumentableTransformer, *, *> by extending {
- CoreExtensions.documentableTransformer with ActualTypealiasAdder()
- }
-
- public val kotlinSignatureProvider: Extension<SignatureProvider, *, *> by extending {
- signatureProvider providing ::KotlinSignatureProvider
- }
-
- public val sinceKotlinTransformer: Extension<DocumentableTransformer, *, *> by extending {
- CoreExtensions.documentableTransformer providing ::SinceKotlinTransformer applyIf {
- SinceKotlinTransformer.shouldDisplaySinceKotlin()
- } order {
- before(extensionsExtractor)
- }
- }
-
- public val inheritorsExtractor: Extension<DocumentableTransformer, *, *> by extending {
- CoreExtensions.documentableTransformer with InheritorsExtractorTransformer()
- }
-
- public val undocumentedCodeReporter: Extension<DocumentableTransformer, *, *> by extending {
- CoreExtensions.documentableTransformer with ReportUndocumentedTransformer()
- }
-
- public val extensionsExtractor: Extension<DocumentableTransformer, *, *> by extending {
- CoreExtensions.documentableTransformer with ExtensionExtractorTransformer()
- }
-
- public val documentableToPageTranslator: Extension<DocumentableToPageTranslator, *, *> by extending {
- CoreExtensions.documentableToPageTranslator providing ::DefaultDocumentableToPageTranslator
- }
-
- public val docTagToContentConverter: Extension<CommentsToContentConverter, *, *> by extending {
- commentsToContentConverter with DocTagToContentConverter()
- }
-
- public val sinceKotlinTagContentProvider: Extension<CustomTagContentProvider, *, *> by extending {
- customTagContentProvider with SinceKotlinTagContentProvider applyIf {
- SinceKotlinTransformer.shouldDisplaySinceKotlin()
- }
- }
-
- public val pageMerger: Extension<PageTransformer, *, *> by extending {
- CoreExtensions.pageTransformer providing ::PageMerger
- }
-
- public val sourceSetMerger: Extension<PageTransformer, *, *> by extending {
- CoreExtensions.pageTransformer providing ::SourceSetMergingPageTransformer
- }
-
- public val fallbackMerger: Extension<PageMergerStrategy, *, *> by extending {
- pageMergerStrategy providing { ctx -> FallbackPageMergerStrategy(ctx.logger) }
- }
-
- public val sameMethodNameMerger: Extension<PageMergerStrategy, *, *> by extending {
- pageMergerStrategy providing { ctx -> SameMethodNamePageMergerStrategy(ctx.logger) } order {
- before(fallbackMerger)
- }
- }
-
- public val htmlRenderer: Extension<Renderer, *, *> by extending {
- CoreExtensions.renderer providing ::HtmlRenderer
- }
-
- public val locationProvider: Extension<LocationProviderFactory, *, *> by extending {
- locationProviderFactory providing ::DokkaLocationProviderFactory
- }
-
- public val javadocLocationProvider: Extension<ExternalLocationProviderFactory, *, *> by extending {
- externalLocationProviderFactory providing ::JavadocExternalLocationProviderFactory
- }
-
- public val dokkaLocationProvider: Extension<ExternalLocationProviderFactory, *, *> by extending {
- externalLocationProviderFactory providing ::DefaultExternalLocationProviderFactory
- }
-
- public val fileWriter: Extension<OutputWriter, *, *> by extending {
- outputWriter providing ::FileWriter
- }
-
- public val rootCreator: Extension<PageTransformer, *, *> by extending {
- htmlPreprocessors with RootCreator applyIf { !delayTemplateSubstitution }
- }
-
- public val defaultSamplesTransformer: Extension<PageTransformer, *, *> by extending {
- CoreExtensions.pageTransformer providing ::DefaultSamplesTransformer order {
- before(pageMerger)
- }
- }
-
- public val sourceLinksTransformer: Extension<PageTransformer, *, *> by extending {
- htmlPreprocessors providing ::SourceLinksTransformer order { after(rootCreator) }
- }
-
- public val navigationPageInstaller: Extension<PageTransformer, *, *> by extending {
- htmlPreprocessors providing ::NavigationPageInstaller order { after(rootCreator) }
- }
-
- public val scriptsInstaller: Extension<PageTransformer, *, *> by extending {
- htmlPreprocessors providing ::ScriptsInstaller order { after(rootCreator) }
- }
-
- public val stylesInstaller: Extension<PageTransformer, *, *> by extending {
- htmlPreprocessors providing ::StylesInstaller order { after(rootCreator) }
- }
-
- public val assetsInstaller: Extension<PageTransformer, *, *> by extending {
- htmlPreprocessors with AssetsInstaller order { after(rootCreator) } applyIf { !delayTemplateSubstitution }
- }
-
- public val customResourceInstaller: Extension<PageTransformer, *, *> by extending {
- htmlPreprocessors providing { ctx -> CustomResourceInstaller(ctx) } order {
- after(stylesInstaller)
- after(scriptsInstaller)
- after(assetsInstaller)
- }
- }
-
- public val packageListCreator: Extension<PageTransformer, *, *> by extending {
- htmlPreprocessors providing {
- PackageListCreator(it, RecognizedLinkFormat.DokkaHtml)
- } order { after(rootCreator) }
- }
-
- public val sourcesetDependencyAppender: Extension<PageTransformer, *, *> by extending {
- htmlPreprocessors providing ::SourcesetDependencyAppender order { after(rootCreator) }
- }
-
- public val resolveLinkConsumer: Extension<ImmediateHtmlCommandConsumer, *, *> by extending {
- immediateHtmlCommandConsumer with ResolveLinkConsumer
- }
- public val replaceVersionConsumer: Extension<ImmediateHtmlCommandConsumer, *, *> by extending {
- immediateHtmlCommandConsumer providing ::ReplaceVersionsConsumer
- }
- public val pathToRootConsumer: Extension<ImmediateHtmlCommandConsumer, *, *> by extending {
- immediateHtmlCommandConsumer with PathToRootConsumer
- }
- public val baseSearchbarDataInstaller: Extension<PageTransformer, *, *> by extending {
- htmlPreprocessors providing ::SearchbarDataInstaller order { after(sourceLinksTransformer) }
- }
-
- //<editor-fold desc="Deprecated API left for compatibility">
- @Suppress("DEPRECATION_ERROR")
- @Deprecated(message = org.jetbrains.dokka.base.deprecated.ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
- public val kotlinAnalysis: ExtensionPoint<org.jetbrains.dokka.analysis.KotlinAnalysis> by extensionPoint()
-
- @Suppress("DEPRECATION_ERROR")
- @Deprecated(message = org.jetbrains.dokka.base.deprecated.ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
- public val externalDocumentablesProvider: ExtensionPoint<org.jetbrains.dokka.base.translators.descriptors.ExternalDocumentablesProvider> by extensionPoint()
-
- @Suppress("DEPRECATION_ERROR")
- @Deprecated(message = org.jetbrains.dokka.base.deprecated.ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
- public val externalClasslikesTranslator: ExtensionPoint<org.jetbrains.dokka.base.translators.descriptors.ExternalClasslikesTranslator> by extensionPoint()
-
- @Suppress("DeprecatedCallableAddReplaceWith")
- @Deprecated(message = org.jetbrains.dokka.base.deprecated.ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
- public val descriptorToDocumentableTranslator: org.jetbrains.dokka.plugability.Extension<org.jetbrains.dokka.transformers.sources.SourceToDocumentableTranslator, *, *>
- get() = throw org.jetbrains.dokka.base.deprecated.AnalysisApiDeprecatedError()
-
- @Suppress("DeprecatedCallableAddReplaceWith")
- @Deprecated(message = org.jetbrains.dokka.base.deprecated.ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
- public val psiToDocumentableTranslator: org.jetbrains.dokka.plugability.Extension<org.jetbrains.dokka.transformers.sources.SourceToDocumentableTranslator, *, *>
- get() = throw org.jetbrains.dokka.base.deprecated.AnalysisApiDeprecatedError()
-
- @Suppress("DEPRECATION_ERROR", "DeprecatedCallableAddReplaceWith")
- @Deprecated(message = org.jetbrains.dokka.base.deprecated.ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
- public val defaultKotlinAnalysis: org.jetbrains.dokka.plugability.Extension<org.jetbrains.dokka.analysis.KotlinAnalysis, *, *>
- get() = throw org.jetbrains.dokka.base.deprecated.AnalysisApiDeprecatedError()
-
- @Suppress("DEPRECATION_ERROR", "DeprecatedCallableAddReplaceWith")
- @Deprecated(message = org.jetbrains.dokka.base.deprecated.ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
- public val defaultExternalDocumentablesProvider: org.jetbrains.dokka.plugability.Extension<org.jetbrains.dokka.base.translators.descriptors.ExternalDocumentablesProvider, *, *>
- get() = throw org.jetbrains.dokka.base.deprecated.AnalysisApiDeprecatedError()
-
- @Suppress("DEPRECATION_ERROR", "DeprecatedCallableAddReplaceWith")
- @Deprecated(message = org.jetbrains.dokka.base.deprecated.ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
- public val defaultExternalClasslikesTranslator: org.jetbrains.dokka.plugability.Extension<org.jetbrains.dokka.base.translators.descriptors.ExternalClasslikesTranslator, *, *>
- get() = throw org.jetbrains.dokka.base.deprecated.AnalysisApiDeprecatedError()
- //</editor-fold>
-
- @OptIn(DokkaPluginApiPreview::class)
- override fun pluginApiPreviewAcknowledgement(): PluginApiPreviewAcknowledgement =
- PluginApiPreviewAcknowledgement
-}
diff --git a/plugins/base/src/main/kotlin/DokkaBaseConfiguration.kt b/plugins/base/src/main/kotlin/DokkaBaseConfiguration.kt
deleted file mode 100644
index 34195f65..00000000
--- a/plugins/base/src/main/kotlin/DokkaBaseConfiguration.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base
-
-import org.jetbrains.dokka.plugability.ConfigurableBlock
-import java.io.File
-import java.time.Year
-
-public data class DokkaBaseConfiguration(
- var customStyleSheets: List<File> = defaultCustomStyleSheets,
- var customAssets: List<File> = defaultCustomAssets,
- var separateInheritedMembers: Boolean = separateInheritedMembersDefault,
- var footerMessage: String = defaultFooterMessage,
- var mergeImplicitExpectActualDeclarations: Boolean = mergeImplicitExpectActualDeclarationsDefault,
- var templatesDir: File? = defaultTemplatesDir,
- var homepageLink: String? = null,
-) : ConfigurableBlock {
- public companion object {
- public val defaultFooterMessage: String = "© ${Year.now().value} Copyright"
- public val defaultCustomStyleSheets: List<File> = emptyList()
- public val defaultCustomAssets: List<File> = emptyList()
- public const val separateInheritedMembersDefault: Boolean = false
- public const val mergeImplicitExpectActualDeclarationsDefault: Boolean = false
- public val defaultTemplatesDir: File? = null
- }
-}
diff --git a/plugins/base/src/main/kotlin/deprecated/AnalysisApiDeprecatedError.kt b/plugins/base/src/main/kotlin/deprecated/AnalysisApiDeprecatedError.kt
deleted file mode 100644
index 52280b3e..00000000
--- a/plugins/base/src/main/kotlin/deprecated/AnalysisApiDeprecatedError.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.deprecated
-
-import org.jetbrains.dokka.InternalDokkaApi
-
-// TODO all API that mentions this message or error can be removed in Dokka >= 2.1
-
-internal const val ANALYSIS_API_DEPRECATION_MESSAGE =
- "Dokka's Analysis API has been reworked. Please, see the following issue for details and migration options: " +
- "https://github.com/Kotlin/dokka/issues/3099"
-
-@InternalDokkaApi
-public class AnalysisApiDeprecatedError : Error(ANALYSIS_API_DEPRECATION_MESSAGE)
diff --git a/plugins/base/src/main/kotlin/deprecated/KotlinAnalysisDeprecatedApi.kt b/plugins/base/src/main/kotlin/deprecated/KotlinAnalysisDeprecatedApi.kt
deleted file mode 100644
index 1d9e7e9f..00000000
--- a/plugins/base/src/main/kotlin/deprecated/KotlinAnalysisDeprecatedApi.kt
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-@file:Suppress("PackageDirectoryMismatch", "FunctionName", "UNUSED_PARAMETER", "unused", "DEPRECATION_ERROR",
- "DeprecatedCallableAddReplaceWith", "unused"
-)
-
-package org.jetbrains.dokka.analysis
-
-import org.jetbrains.dokka.DokkaConfiguration
-import org.jetbrains.dokka.DokkaSourceSetID
-import org.jetbrains.dokka.base.deprecated.ANALYSIS_API_DEPRECATION_MESSAGE
-import org.jetbrains.dokka.base.deprecated.AnalysisApiDeprecatedError
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.utilities.DokkaLogger
-import java.io.Closeable
-
-@Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
-public abstract class KotlinAnalysis(
- private val parent: KotlinAnalysis? = null
-) : Closeable {
- @Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
- public operator fun get(key: DokkaConfiguration.DokkaSourceSet): AnalysisContext = throw AnalysisApiDeprecatedError()
-
- @Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
- public operator fun get(key: DokkaSourceSetID): AnalysisContext = throw AnalysisApiDeprecatedError()
-
- @Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
- protected abstract fun find(sourceSetID: DokkaSourceSetID): AnalysisContext?
-}
-
-public class AnalysisContext(environment: Any, facade: Any, private val analysisEnvironment: Any) : Closeable {
- @Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
- public val environment: Any get() = throw AnalysisApiDeprecatedError()
-
- @Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
- public val facade: Any get() = throw AnalysisApiDeprecatedError()
-
- @Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
- public operator fun component1(): Any = throw AnalysisApiDeprecatedError()
-
- @Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
- public operator fun component2(): Any = throw AnalysisApiDeprecatedError()
-
- @Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
- override fun close() { throw AnalysisApiDeprecatedError() }
-}
-
-@Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
-public class DokkaAnalysisConfiguration(public val ignoreCommonBuiltIns: Boolean = false)
-
-@Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
-public fun KotlinAnalysis(context: DokkaContext): KotlinAnalysis = throw AnalysisApiDeprecatedError()
-
-@Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
-public fun KotlinAnalysis(
- sourceSets: List<DokkaConfiguration.DokkaSourceSet>,
- logger: DokkaLogger,
- analysisConfiguration: DokkaAnalysisConfiguration = DokkaAnalysisConfiguration()
-): KotlinAnalysis = throw AnalysisApiDeprecatedError()
-
-@Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
-public fun ProjectKotlinAnalysis(
- sourceSets: List<DokkaConfiguration.DokkaSourceSet>,
- logger: DokkaLogger,
- analysisConfiguration: DokkaAnalysisConfiguration = DokkaAnalysisConfiguration()
-): KotlinAnalysis = throw AnalysisApiDeprecatedError()
-
-@Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
-public fun SamplesKotlinAnalysis(
- sourceSets: List<DokkaConfiguration.DokkaSourceSet>,
- logger: DokkaLogger,
- projectKotlinAnalysis: KotlinAnalysis,
- analysisConfiguration: DokkaAnalysisConfiguration = DokkaAnalysisConfiguration()
-): KotlinAnalysis = throw AnalysisApiDeprecatedError()
-
diff --git a/plugins/base/src/main/kotlin/deprecated/ParsersDeprecatedAPI.kt b/plugins/base/src/main/kotlin/deprecated/ParsersDeprecatedAPI.kt
deleted file mode 100644
index 55b1daab..00000000
--- a/plugins/base/src/main/kotlin/deprecated/ParsersDeprecatedAPI.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-@file:Suppress("PackageDirectoryMismatch", "DEPRECATION_ERROR", "DeprecatedCallableAddReplaceWith", "unused")
-
-package org.jetbrains.dokka.base.parsers
-
-import org.jetbrains.dokka.base.deprecated.ANALYSIS_API_DEPRECATION_MESSAGE
-import org.jetbrains.dokka.base.deprecated.AnalysisApiDeprecatedError
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.model.doc.DocTag
-import org.jetbrains.dokka.model.doc.DocumentationNode
-import org.jetbrains.dokka.model.doc.TagWrapper
-
-@Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
-public abstract class Parser {
- @Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
- public open fun parseStringToDocNode(extractedString: String): DocTag = throw AnalysisApiDeprecatedError()
-
- @Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
- public open fun preparse(text: String): String = throw AnalysisApiDeprecatedError()
-
- @Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
- public open fun parseTagWithBody(tagName: String, content: String): TagWrapper = throw AnalysisApiDeprecatedError()
-}
-
-@Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
-public open class MarkdownParser(
- private val externalDri: (String) -> DRI?,
- private val kdocLocation: String?,
-) : Parser() {
- public companion object {
- @Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
- public fun parseFromKDocTag(
- @Suppress("UNUSED_PARAMETER") kDocTag: Any?,
- @Suppress("UNUSED_PARAMETER") externalDri: (String) -> DRI?,
- @Suppress("UNUSED_PARAMETER") kdocLocation: String?,
- @Suppress("UNUSED_PARAMETER") parseWithChildren: Boolean = true
- ): DocumentationNode = throw AnalysisApiDeprecatedError()
- }
-}
diff --git a/plugins/base/src/main/kotlin/deprecated/ParsersFactoriesDeprecatedAPI.kt b/plugins/base/src/main/kotlin/deprecated/ParsersFactoriesDeprecatedAPI.kt
deleted file mode 100644
index 7b84803c..00000000
--- a/plugins/base/src/main/kotlin/deprecated/ParsersFactoriesDeprecatedAPI.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-@file:Suppress("DeprecatedCallableAddReplaceWith", "PackageDirectoryMismatch", "unused")
-
-package org.jetbrains.dokka.base.parsers.factories
-
-import org.jetbrains.dokka.base.deprecated.ANALYSIS_API_DEPRECATION_MESSAGE
-import org.jetbrains.dokka.base.deprecated.AnalysisApiDeprecatedError
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.model.doc.DocTag
-
-@Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
-public object DocTagsFromStringFactory {
- @Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
- public fun getInstance(
- @Suppress("UNUSED_PARAMETER") name: String,
- @Suppress("UNUSED_PARAMETER") children: List<DocTag> = emptyList(),
- @Suppress("UNUSED_PARAMETER") params: Map<String, String> = emptyMap(),
- @Suppress("UNUSED_PARAMETER") body: String? = null,
- @Suppress("UNUSED_PARAMETER") dri: DRI? = null,
- ): DocTag = throw AnalysisApiDeprecatedError()
-}
diff --git a/plugins/base/src/main/kotlin/deprecated/TranslatorDescriptorsDeprecatedAPI.kt b/plugins/base/src/main/kotlin/deprecated/TranslatorDescriptorsDeprecatedAPI.kt
deleted file mode 100644
index 87d82ccf..00000000
--- a/plugins/base/src/main/kotlin/deprecated/TranslatorDescriptorsDeprecatedAPI.kt
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-@file:Suppress("PackageDirectoryMismatch", "DEPRECATION_ERROR", "DeprecatedCallableAddReplaceWith", "unused")
-
-package org.jetbrains.dokka.base.translators.descriptors
-
-import org.jetbrains.dokka.DokkaConfiguration
-import org.jetbrains.dokka.base.deprecated.ANALYSIS_API_DEPRECATION_MESSAGE
-import org.jetbrains.dokka.base.deprecated.AnalysisApiDeprecatedError
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.model.DClasslike
-import org.jetbrains.dokka.model.DModule
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.transformers.sources.AsyncSourceToDocumentableTranslator
-
-@Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
-public fun interface ExternalDocumentablesProvider {
- @Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
- public fun findClasslike(dri: DRI, sourceSet: DokkaConfiguration.DokkaSourceSet): DClasslike?
-}
-
-@Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
-public class DefaultExternalDocumentablesProvider(
- @Suppress("UNUSED_PARAMETER") context: DokkaContext
-) : ExternalDocumentablesProvider {
- @Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
- override fun findClasslike(dri: DRI, sourceSet: DokkaConfiguration.DokkaSourceSet): DClasslike =
- throw AnalysisApiDeprecatedError()
-}
-
-@Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
-public fun interface ExternalClasslikesTranslator {
- @Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
- public fun translateClassDescriptor(descriptor: Any, sourceSet: DokkaConfiguration.DokkaSourceSet): DClasslike
-}
-
-@Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
-public class DefaultDescriptorToDocumentableTranslator(
- private val context: DokkaContext
-) : AsyncSourceToDocumentableTranslator, ExternalClasslikesTranslator {
- @Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
- override suspend fun invokeSuspending(sourceSet: DokkaConfiguration.DokkaSourceSet, context: DokkaContext, ): DModule =
- throw AnalysisApiDeprecatedError()
-
- @Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
- override fun translateClassDescriptor(descriptor: Any, sourceSet: DokkaConfiguration.DokkaSourceSet): DClasslike =
- throw AnalysisApiDeprecatedError()
-}
diff --git a/plugins/base/src/main/kotlin/deprecated/TranslatorPsiDeprecatedAPI.kt b/plugins/base/src/main/kotlin/deprecated/TranslatorPsiDeprecatedAPI.kt
deleted file mode 100644
index 1906a7b1..00000000
--- a/plugins/base/src/main/kotlin/deprecated/TranslatorPsiDeprecatedAPI.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-@file:Suppress("PackageDirectoryMismatch", "DeprecatedCallableAddReplaceWith", "unused")
-
-package org.jetbrains.dokka.base.translators.psi
-
-import org.jetbrains.dokka.DokkaConfiguration
-import org.jetbrains.dokka.base.deprecated.ANALYSIS_API_DEPRECATION_MESSAGE
-import org.jetbrains.dokka.base.deprecated.AnalysisApiDeprecatedError
-import org.jetbrains.dokka.model.DModule
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.transformers.sources.AsyncSourceToDocumentableTranslator
-
-@Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
-public class DefaultPsiToDocumentableTranslator(
- @Suppress("UNUSED_PARAMETER") context: DokkaContext,
-) : AsyncSourceToDocumentableTranslator {
- @Deprecated(message = ANALYSIS_API_DEPRECATION_MESSAGE, level = DeprecationLevel.ERROR)
- override suspend fun invokeSuspending(
- sourceSet: DokkaConfiguration.DokkaSourceSet,
- context: DokkaContext,
- ): DModule = throw AnalysisApiDeprecatedError()
-}
diff --git a/plugins/base/src/main/kotlin/generation/SingleModuleGeneration.kt b/plugins/base/src/main/kotlin/generation/SingleModuleGeneration.kt
deleted file mode 100644
index 8ea109b9..00000000
--- a/plugins/base/src/main/kotlin/generation/SingleModuleGeneration.kt
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.generation
-
-import kotlinx.coroutines.*
-import org.jetbrains.dokka.CoreExtensions
-import org.jetbrains.dokka.DokkaConfiguration
-import org.jetbrains.dokka.DokkaException
-import org.jetbrains.dokka.Timer
-import org.jetbrains.dokka.base.DokkaBase
-import org.jetbrains.dokka.generation.Generation
-import org.jetbrains.dokka.generation.exitGenerationGracefully
-import org.jetbrains.dokka.model.DModule
-import org.jetbrains.dokka.pages.RootPageNode
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.plugability.plugin
-import org.jetbrains.dokka.plugability.query
-import org.jetbrains.dokka.transformers.sources.AsyncSourceToDocumentableTranslator
-import org.jetbrains.dokka.utilities.parallelMap
-import org.jetbrains.dokka.utilities.report
-
-public class SingleModuleGeneration(private val context: DokkaContext) : Generation {
-
- override fun Timer.generate() {
- report("Validity check")
- validityCheck(context)
-
- // Step 1: translate sources into documentables & transform documentables (change internally)
- report("Creating documentation models")
- val modulesFromPlatforms = createDocumentationModels()
-
- report("Transforming documentation model before merging")
- val transformedDocumentationBeforeMerge = transformDocumentationModelBeforeMerge(modulesFromPlatforms)
-
- report("Merging documentation models")
- val transformedDocumentationAfterMerge = mergeDocumentationModels(transformedDocumentationBeforeMerge)
- ?: exitGenerationGracefully("Nothing to document")
-
- report("Transforming documentation model after merging")
- val transformedDocumentation = transformDocumentationModelAfterMerge(transformedDocumentationAfterMerge)
-
- // Step 2: Generate pages & transform them (change internally)
- report("Creating pages")
- val pages = createPages(transformedDocumentation)
-
- report("Transforming pages")
- val transformedPages = transformPages(pages)
-
- // Step 3: Rendering
- report("Rendering")
- render(transformedPages)
-
- report("Running post-actions")
- runPostActions()
-
- reportAfterRendering()
- }
-
- override val generationName: String = "documentation for ${context.configuration.moduleName}"
-
- /**
- * Implementation note: it runs in a separated single thread due to existing support of coroutines (see #2936)
- */
- @OptIn(DelicateCoroutinesApi::class, ExperimentalCoroutinesApi::class)
- public fun createDocumentationModels(): List<DModule> = newSingleThreadContext("Generating documentable model").use { coroutineContext -> // see https://github.com/Kotlin/dokka/issues/3151
- runBlocking(coroutineContext) {
- context.configuration.sourceSets.parallelMap { sourceSet -> translateSources(sourceSet, context) }.flatten()
- .also { modules -> if (modules.isEmpty()) exitGenerationGracefully("Nothing to document") }
- }
- }
-
-
- public fun transformDocumentationModelBeforeMerge(modulesFromPlatforms: List<DModule>): List<DModule> {
- return context.plugin<DokkaBase>()
- .query { preMergeDocumentableTransformer }
- .fold(modulesFromPlatforms) { acc, t -> t(acc) }
- }
-
- public fun mergeDocumentationModels(modulesFromPlatforms: List<DModule>): DModule? =
- context.single(CoreExtensions.documentableMerger).invoke(modulesFromPlatforms)
-
- public fun transformDocumentationModelAfterMerge(documentationModel: DModule): DModule =
- context[CoreExtensions.documentableTransformer].fold(documentationModel) { acc, t -> t(acc, context) }
-
- public fun createPages(transformedDocumentation: DModule): RootPageNode =
- context.single(CoreExtensions.documentableToPageTranslator).invoke(transformedDocumentation)
-
- public fun transformPages(pages: RootPageNode): RootPageNode =
- context[CoreExtensions.pageTransformer].fold(pages) { acc, t -> t(acc) }
-
- public fun render(transformedPages: RootPageNode) {
- context.single(CoreExtensions.renderer).render(transformedPages)
- }
-
- public fun runPostActions() {
- context[CoreExtensions.postActions].forEach { it() }
- }
-
- public fun validityCheck(context: DokkaContext) {
- val (preGenerationCheckResult, checkMessages) = context[CoreExtensions.preGenerationCheck].fold(
- Pair(true, emptyList<String>())
- ) { acc, checker -> checker() + acc }
- if (!preGenerationCheckResult) throw DokkaException(
- "Pre-generation validity check failed: ${checkMessages.joinToString(",")}"
- )
- }
-
- public fun reportAfterRendering() {
- context.unusedPoints.takeIf { it.isNotEmpty() }?.also {
- context.logger.info("Unused extension points found: ${it.joinToString(", ")}")
- }
-
- context.logger.report()
-
- if (context.configuration.failOnWarning && (context.logger.warningsCount > 0 || context.logger.errorsCount > 0)) {
- throw DokkaException(
- "Failed with warningCount=${context.logger.warningsCount} and errorCount=${context.logger.errorsCount}"
- )
- }
- }
-
- private suspend fun translateSources(sourceSet: DokkaConfiguration.DokkaSourceSet, context: DokkaContext) =
- context[CoreExtensions.sourceToDocumentableTranslator].parallelMap { translator ->
- when (translator) {
- is AsyncSourceToDocumentableTranslator -> translator.invokeSuspending(sourceSet, context)
- else -> translator.invoke(sourceSet, context)
- }
- }
-}
diff --git a/plugins/base/src/main/kotlin/renderers/DefaultRenderer.kt b/plugins/base/src/main/kotlin/renderers/DefaultRenderer.kt
deleted file mode 100644
index eed7794e..00000000
--- a/plugins/base/src/main/kotlin/renderers/DefaultRenderer.kt
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.renderers
-
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.coroutineScope
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.runBlocking
-import org.jetbrains.dokka.DokkaException
-import org.jetbrains.dokka.base.DokkaBase
-import org.jetbrains.dokka.base.resolvers.local.LocationProvider
-import org.jetbrains.dokka.model.DisplaySourceSet
-import org.jetbrains.dokka.pages.*
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.plugability.plugin
-import org.jetbrains.dokka.plugability.querySingle
-import org.jetbrains.dokka.renderers.Renderer
-import org.jetbrains.dokka.transformers.pages.PageTransformer
-
-public abstract class DefaultRenderer<T>(
- protected val context: DokkaContext
-) : Renderer {
-
- protected val outputWriter: OutputWriter = context.plugin<DokkaBase>().querySingle { outputWriter }
-
- protected lateinit var locationProvider: LocationProvider
- private set
-
- protected open val preprocessors: Iterable<PageTransformer> = emptyList()
-
- public abstract fun T.buildHeader(level: Int, node: ContentHeader, content: T.() -> Unit)
- public abstract fun T.buildLink(address: String, content: T.() -> Unit)
- public abstract fun T.buildList(
- node: ContentList,
- pageContext: ContentPage,
- sourceSetRestriction: Set<DisplaySourceSet>? = null
- )
-
- public abstract fun T.buildLineBreak()
- public open fun T.buildLineBreak(node: ContentBreakLine, pageContext: ContentPage) {
- buildLineBreak()
- }
-
- public abstract fun T.buildResource(node: ContentEmbeddedResource, pageContext: ContentPage)
- public abstract fun T.buildTable(
- node: ContentTable,
- pageContext: ContentPage,
- sourceSetRestriction: Set<DisplaySourceSet>? = null
- )
-
- public abstract fun T.buildText(textNode: ContentText)
- public abstract fun T.buildNavigation(page: PageNode)
-
- public abstract fun buildPage(page: ContentPage, content: (T, ContentPage) -> Unit): String
- public abstract fun buildError(node: ContentNode)
-
- public open fun T.buildPlatformDependent(
- content: PlatformHintedContent,
- pageContext: ContentPage,
- sourceSetRestriction: Set<DisplaySourceSet>?
- ) {
- buildContentNode(content.inner, pageContext)
- }
-
- public open fun T.buildGroup(
- node: ContentGroup,
- pageContext: ContentPage,
- sourceSetRestriction: Set<DisplaySourceSet>? = null
- ) {
- wrapGroup(node, pageContext) { node.children.forEach { it.build(this, pageContext, sourceSetRestriction) } }
- }
-
- public open fun T.buildDivergent(node: ContentDivergentGroup, pageContext: ContentPage) {
- node.children.forEach { it.build(this, pageContext) }
- }
-
- public open fun T.wrapGroup(node: ContentGroup, pageContext: ContentPage, childrenCallback: T.() -> Unit) {
- childrenCallback()
- }
-
- public open fun T.buildText(
- nodes: List<ContentNode>,
- pageContext: ContentPage,
- sourceSetRestriction: Set<DisplaySourceSet>? = null
- ) {
- nodes.forEach { it.build(this, pageContext, sourceSetRestriction) }
- }
-
- public open fun T.buildCodeBlock(code: ContentCodeBlock, pageContext: ContentPage) {
- code.children.forEach { it.build(this, pageContext) }
- }
-
- public open fun T.buildCodeInline(code: ContentCodeInline, pageContext: ContentPage) {
- code.children.forEach { it.build(this, pageContext) }
- }
-
- public open fun T.buildHeader(
- node: ContentHeader,
- pageContext: ContentPage,
- sourceSetRestriction: Set<DisplaySourceSet>? = null
- ) {
- buildHeader(node.level, node) { node.children.forEach { it.build(this, pageContext, sourceSetRestriction) } }
- }
-
- public open fun ContentNode.build(
- builder: T,
- pageContext: ContentPage,
- sourceSetRestriction: Set<DisplaySourceSet>? = null
- ) {
- builder.buildContentNode(this, pageContext, sourceSetRestriction)
- }
-
- public fun T.buildContentNode(
- node: ContentNode,
- pageContext: ContentPage,
- sourceSetRestriction: DisplaySourceSet
- ) {
- buildContentNode(node, pageContext, setOf(sourceSetRestriction))
- }
-
- public open fun T.buildContentNode(
- node: ContentNode,
- pageContext: ContentPage,
- sourceSetRestriction: Set<DisplaySourceSet>? = null
- ) {
- if (sourceSetRestriction.isNullOrEmpty() || node.sourceSets.any { it in sourceSetRestriction }) {
- when (node) {
- is ContentText -> buildText(node)
- is ContentHeader -> buildHeader(node, pageContext, sourceSetRestriction)
- is ContentCodeBlock -> buildCodeBlock(node, pageContext)
- is ContentCodeInline -> buildCodeInline(node, pageContext)
- is ContentDRILink -> buildDRILink(node, pageContext, sourceSetRestriction)
- is ContentResolvedLink -> buildResolvedLink(node, pageContext, sourceSetRestriction)
- is ContentEmbeddedResource -> buildResource(node, pageContext)
- is ContentList -> buildList(node, pageContext, sourceSetRestriction)
- is ContentTable -> buildTable(node, pageContext, sourceSetRestriction)
- is ContentGroup -> buildGroup(node, pageContext, sourceSetRestriction)
- is ContentBreakLine -> buildLineBreak(node, pageContext)
- is PlatformHintedContent -> buildPlatformDependent(node, pageContext, sourceSetRestriction)
- is ContentDivergentGroup -> buildDivergent(node, pageContext)
- is ContentDivergentInstance -> buildDivergentInstance(node, pageContext)
- else -> buildError(node)
- }
- }
- }
-
- public open fun T.buildDRILink(
- node: ContentDRILink,
- pageContext: ContentPage,
- sourceSetRestriction: Set<DisplaySourceSet>?
- ) {
- locationProvider.resolve(node.address, node.sourceSets, pageContext)?.let { address ->
- buildLink(address) {
- buildText(node.children, pageContext, sourceSetRestriction)
- }
- } ?: buildText(node.children, pageContext, sourceSetRestriction)
- }
-
- public open fun T.buildResolvedLink(
- node: ContentResolvedLink,
- pageContext: ContentPage,
- sourceSetRestriction: Set<DisplaySourceSet>?
- ) {
- buildLink(node.address) {
- buildText(node.children, pageContext, sourceSetRestriction)
- }
- }
-
- public open fun T.buildDivergentInstance(node: ContentDivergentInstance, pageContext: ContentPage) {
- node.before?.build(this, pageContext)
- node.divergent.build(this, pageContext)
- node.after?.build(this, pageContext)
- }
-
- public open fun buildPageContent(context: T, page: ContentPage) {
- context.buildNavigation(page)
- page.content.build(context, page)
- }
-
- public open suspend fun renderPage(page: PageNode) {
- val path by lazy {
- locationProvider.resolve(page, skipExtension = true)
- ?: throw DokkaException("Cannot resolve path for ${page.name}")
- }
- when (page) {
- is ContentPage -> outputWriter.write(path, buildPage(page) { c, p -> buildPageContent(c, p) }, ".html")
- is RendererSpecificPage -> when (val strategy = page.strategy) {
- is RenderingStrategy.Copy -> outputWriter.writeResources(strategy.from, path)
- is RenderingStrategy.Write -> outputWriter.write(path, strategy.text, "")
- is RenderingStrategy.Callback -> outputWriter.write(path, strategy.instructions(this, page), ".html")
- is RenderingStrategy.DriLocationResolvableWrite -> outputWriter.write(
- path,
- strategy.contentToResolve { dri, sourcesets ->
- locationProvider.resolve(dri, sourcesets)
- },
- ""
- )
- is RenderingStrategy.PageLocationResolvableWrite -> outputWriter.write(
- path,
- strategy.contentToResolve { pageToLocate, context ->
- locationProvider.resolve(pageToLocate, context)
- },
- ""
- )
- RenderingStrategy.DoNothing -> Unit
- }
- else -> throw AssertionError(
- "Page ${page.name} cannot be rendered by renderer as it is not renderer specific nor contains content"
- )
- }
- }
-
- private suspend fun renderPages(root: PageNode) {
- coroutineScope {
- renderPage(root)
-
- root.children.forEach {
- launch { renderPages(it) }
- }
- }
- }
-
- override fun render(root: RootPageNode) {
- val newRoot = preprocessors.fold(root) { acc, t -> t(acc) }
-
- locationProvider =
- context.plugin<DokkaBase>().querySingle { locationProviderFactory }.getLocationProvider(newRoot)
-
- runBlocking(Dispatchers.Default) {
- renderPages(newRoot)
- }
- }
-
- protected fun ContentDivergentGroup.groupDivergentInstances(
- pageContext: ContentPage,
- beforeTransformer: (ContentDivergentInstance, ContentPage, DisplaySourceSet) -> String,
- afterTransformer: (ContentDivergentInstance, ContentPage, DisplaySourceSet) -> String
- ): Map<SerializedBeforeAndAfter, List<InstanceWithSource>> =
- children.flatMap { instance ->
- instance.sourceSets.map { sourceSet ->
- Pair(instance, sourceSet) to Pair(
- beforeTransformer(instance, pageContext, sourceSet),
- afterTransformer(instance, pageContext, sourceSet)
- )
- }
- }.groupBy(
- Pair<InstanceWithSource, SerializedBeforeAndAfter>::second,
- Pair<InstanceWithSource, SerializedBeforeAndAfter>::first
- )
-}
-
-internal typealias SerializedBeforeAndAfter = Pair<String, String>
-internal typealias InstanceWithSource = Pair<ContentDivergentInstance, DisplaySourceSet>
-
-public fun ContentPage.sourceSets(): Set<DisplaySourceSet> = this.content.sourceSets
diff --git a/plugins/base/src/main/kotlin/renderers/FileWriter.kt b/plugins/base/src/main/kotlin/renderers/FileWriter.kt
deleted file mode 100644
index 1a1c3b42..00000000
--- a/plugins/base/src/main/kotlin/renderers/FileWriter.kt
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.renderers
-
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.sync.Mutex
-import kotlinx.coroutines.sync.withLock
-import kotlinx.coroutines.withContext
-import org.jetbrains.dokka.plugability.DokkaContext
-import java.io.File
-import java.io.IOException
-import java.net.URI
-import java.nio.file.*
-
-public class FileWriter(
- public val context: DokkaContext
-): OutputWriter {
- private val createdFiles: MutableSet<String> = mutableSetOf()
- private val createdFilesMutex = Mutex()
- private val jarUriPrefix = "jar:file:"
- private val root = context.configuration.outputDir
-
- override suspend fun write(path: String, text: String, ext: String) {
- if (checkFileCreated(path)) return
-
- try {
- val dir = Paths.get(root.absolutePath, path.dropLastWhile { it != '/' }).toFile()
- withContext(Dispatchers.IO) {
- dir.mkdirsOrFail()
- Files.write(Paths.get(root.absolutePath, "$path$ext"), text.lines())
- }
- } catch (e: Throwable) {
- context.logger.error("Failed to write $this. ${e.message}")
- e.printStackTrace()
- }
- }
-
- private suspend fun checkFileCreated(path: String): Boolean = createdFilesMutex.withLock {
- if (createdFiles.contains(path)) {
- context.logger.error("An attempt to write ${root}/$path several times!")
- return true
- }
- createdFiles.add(path)
- return false
- }
-
- override suspend fun writeResources(pathFrom: String, pathTo: String) {
- if (javaClass.getResource(pathFrom)?.toURI()?.toString()?.startsWith(jarUriPrefix) == true) {
- copyFromJar(pathFrom, pathTo)
- } else {
- copyFromDirectory(pathFrom, pathTo)
- }
- }
-
-
- private suspend fun copyFromDirectory(pathFrom: String, pathTo: String) {
- val dest = Paths.get(root.path, pathTo).toFile()
- val uri = javaClass.getResource(pathFrom)?.toURI()
- val file = uri?.let { File(it) } ?: File(pathFrom)
- withContext(Dispatchers.IO) {
- file.copyRecursively(dest, true)
- }
- }
-
- private suspend fun copyFromJar(pathFrom: String, pathTo: String) {
- val rebase = fun(path: String) =
- "$pathTo/${path.removePrefix(pathFrom)}"
- val dest = Paths.get(root.path, pathTo).toFile()
- if(dest.isDirectory){
- dest.mkdirsOrFail()
- } else {
- dest.parentFile.mkdirsOrFail()
- }
- val uri = javaClass.getResource(pathFrom).toURI()
- val fs = getFileSystemForURI(uri)
- val path = fs.getPath(pathFrom)
- for (file in Files.walk(path).iterator()) {
- if (Files.isDirectory(file)) {
- val dirPath = file.toAbsolutePath().toString()
- withContext(Dispatchers.IO) {
- Paths.get(root.path, rebase(dirPath)).toFile().mkdirsOrFail()
- }
- } else {
- val filePath = file.toAbsolutePath().toString()
- withContext(Dispatchers.IO) {
- Paths.get(root.path, rebase(filePath)).toFile().writeBytes(
- this@FileWriter.javaClass.getResourceAsStream(filePath).use { it?.readBytes() }
- ?: throw IllegalStateException("Can not get a resource from $filePath")
- )
- }
- }
- }
- }
-
- private fun File.mkdirsOrFail() {
- if (!mkdirs() && !exists()) {
- throw IOException("Failed to create directory $this")
- }
- }
-
- private fun getFileSystemForURI(uri: URI): FileSystem =
- try {
- FileSystems.newFileSystem(uri, emptyMap<String, Any>())
- } catch (e: FileSystemAlreadyExistsException) {
- FileSystems.getFileSystem(uri)
- }
-}
diff --git a/plugins/base/src/main/kotlin/renderers/OutputWriter.kt b/plugins/base/src/main/kotlin/renderers/OutputWriter.kt
deleted file mode 100644
index 3fdd1802..00000000
--- a/plugins/base/src/main/kotlin/renderers/OutputWriter.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.renderers
-
-public interface OutputWriter {
-
- public suspend fun write(path: String, text: String, ext: String)
- public suspend fun writeResources(pathFrom: String, pathTo: String)
-}
diff --git a/plugins/base/src/main/kotlin/renderers/PackageListService.kt b/plugins/base/src/main/kotlin/renderers/PackageListService.kt
deleted file mode 100644
index 3ed6cd21..00000000
--- a/plugins/base/src/main/kotlin/renderers/PackageListService.kt
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.renderers
-
-import org.jetbrains.dokka.base.DokkaBase
-import org.jetbrains.dokka.base.resolvers.shared.LinkFormat
-import org.jetbrains.dokka.base.resolvers.shared.PackageList.Companion.DOKKA_PARAM_PREFIX
-import org.jetbrains.dokka.base.resolvers.shared.PackageList.Companion.MODULE_DELIMITER
-import org.jetbrains.dokka.base.resolvers.shared.PackageList.Companion.SINGLE_MODULE_NAME
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.pages.*
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.plugability.plugin
-import org.jetbrains.dokka.plugability.querySingle
-
-public class PackageListService(
- public val context: DokkaContext,
- public val rootPage: RootPageNode
-) {
-
- public fun createPackageList(module: ModulePage, format: LinkFormat): String {
-
- val packages = mutableSetOf<String>()
- val nonStandardLocations = mutableMapOf<String, String>()
-
- val locationProvider =
- context.plugin<DokkaBase>().querySingle { locationProviderFactory }.getLocationProvider(rootPage)
-
- fun visit(node: PageNode) {
- if (node is PackagePage) {
- node.name
- .takeUnless { name -> name.startsWith("[") && name.endsWith("]") } // Do not include the package name for declarations without one
- ?.let { packages.add(it) }
- }
-
- val contentPage = node as? ContentPage
- contentPage?.dri?.forEach { dri ->
- val nodeLocation = locationProvider.resolve(node, context = module, skipExtension = true)
- ?: run { context.logger.error("Cannot resolve path for ${node.name}!"); null }
-
- if (dri != DRI.topLevel && locationProvider.expectedLocationForDri(dri) != nodeLocation) {
- nonStandardLocations[dri.toString()] = "$nodeLocation.${format.linkExtension}"
- }
- }
-
- node.children.forEach { visit(it) }
- }
-
- visit(module)
- return renderPackageList(
- nonStandardLocations = nonStandardLocations,
- modules = mapOf(SINGLE_MODULE_NAME to packages),
- format = format.formatName,
- linkExtension = format.linkExtension
- )
- }
-
- public companion object {
- public fun renderPackageList(
- nonStandardLocations: Map<String, String>,
- modules: Map<String, Set<String>>,
- format: String,
- linkExtension: String
- ): String = buildString {
- appendLine("$DOKKA_PARAM_PREFIX.format:${format}")
- appendLine("$DOKKA_PARAM_PREFIX.linkExtension:${linkExtension}")
- nonStandardLocations.map { (signature, location) ->
- "$DOKKA_PARAM_PREFIX.location:$signature\u001f$location"
- }.sorted().joinTo(this, separator = "\n", postfix = "\n")
-
- modules.mapNotNull { (module, packages) ->
- ("$MODULE_DELIMITER$module\n".takeIf { module != SINGLE_MODULE_NAME }.orEmpty() +
- packages.filter(String::isNotBlank).sorted().joinToString(separator = "\n"))
- .takeIf { packages.isNotEmpty() }
- }.joinTo(this, separator = "\n", postfix = "\n")
- }
- }
-}
diff --git a/plugins/base/src/main/kotlin/renderers/TabSortingStrategy.kt b/plugins/base/src/main/kotlin/renderers/TabSortingStrategy.kt
deleted file mode 100644
index 665b6717..00000000
--- a/plugins/base/src/main/kotlin/renderers/TabSortingStrategy.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.renderers
-
-import org.jetbrains.dokka.pages.ContentNode
-
-public interface TabSortingStrategy {
- public fun <T: ContentNode> sort(tabs: Collection<T>) : List<T>
-}
diff --git a/plugins/base/src/main/kotlin/renderers/contentTypeChecking.kt b/plugins/base/src/main/kotlin/renderers/contentTypeChecking.kt
deleted file mode 100644
index 0fcb0efb..00000000
--- a/plugins/base/src/main/kotlin/renderers/contentTypeChecking.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.renderers
-
-import org.jetbrains.dokka.base.renderers.HtmlFileExtensions.imageExtensions
-import org.jetbrains.dokka.pages.ContentEmbeddedResource
-import java.io.File
-
-public fun ContentEmbeddedResource.isImage(): Boolean {
- return File(address).extension.toLowerCase() in imageExtensions
-}
-
-public val String.URIExtension: String
- get() = substringBefore('?').substringAfterLast('.')
-
-public fun String.isImage(): Boolean =
- URIExtension in imageExtensions
-
-public object HtmlFileExtensions {
- public val imageExtensions: Set<String> = setOf("png", "jpg", "jpeg", "gif", "bmp", "tif", "webp", "svg")
-}
-
diff --git a/plugins/base/src/main/kotlin/renderers/html/HtmlContent.kt b/plugins/base/src/main/kotlin/renderers/html/HtmlContent.kt
deleted file mode 100644
index 1ef6e04c..00000000
--- a/plugins/base/src/main/kotlin/renderers/html/HtmlContent.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.renderers.html
-
-import org.jetbrains.dokka.pages.ContentBreakLine
-import org.jetbrains.dokka.pages.Style
-
-
-/**
- * Html-specific style that represents <hr> tag if used in conjunction with [ContentBreakLine]
- */
-internal object HorizontalBreakLineStyle : Style {
- // this exists as a simple internal solution to avoid introducing unnecessary public API on content level.
- // If you have the need to implement proper horizontal divider (i.e to support `---` markdown element),
- // consider removing this and providing proper API for all formats and levels
-}
diff --git a/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt b/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt
deleted file mode 100644
index 083876d5..00000000
--- a/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt
+++ /dev/null
@@ -1,1013 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.renderers.html
-
-import kotlinx.html.*
-import kotlinx.html.stream.createHTML
-import org.jetbrains.dokka.DokkaSourceSetID
-import org.jetbrains.dokka.Platform
-import org.jetbrains.dokka.base.DokkaBase
-import org.jetbrains.dokka.base.renderers.*
-import org.jetbrains.dokka.base.renderers.html.command.consumers.ImmediateResolutionTagConsumer
-import org.jetbrains.dokka.base.renderers.html.innerTemplating.DefaultTemplateModelFactory
-import org.jetbrains.dokka.base.renderers.html.innerTemplating.DefaultTemplateModelMerger
-import org.jetbrains.dokka.base.renderers.html.innerTemplating.DokkaTemplateTypes
-import org.jetbrains.dokka.base.renderers.html.innerTemplating.HtmlTemplater
-import org.jetbrains.dokka.base.resolvers.anchors.SymbolAnchorHint
-import org.jetbrains.dokka.base.resolvers.local.DokkaBaseLocationProvider
-import org.jetbrains.dokka.base.templating.*
-import org.jetbrains.dokka.base.transformers.documentables.CallableExtensions
-import org.jetbrains.dokka.base.translators.documentables.shouldDocumentConstructors
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.model.*
-import org.jetbrains.dokka.model.properties.PropertyContainer
-import org.jetbrains.dokka.model.properties.WithExtraProperties
-import org.jetbrains.dokka.pages.*
-import org.jetbrains.dokka.pages.HtmlContent
-import org.jetbrains.dokka.plugability.*
-import org.jetbrains.dokka.transformers.pages.PageTransformer
-import org.jetbrains.dokka.utilities.htmlEscape
-
-internal const val TEMPLATE_REPLACEMENT: String = "###"
-internal const val TOGGLEABLE_CONTENT_TYPE_ATTR = "data-togglable"
-
-public open class HtmlRenderer(
- context: DokkaContext
-) : DefaultRenderer<FlowContent>(context) {
- private val sourceSetDependencyMap: Map<DokkaSourceSetID, List<DokkaSourceSetID>> =
- context.configuration.sourceSets.associate { sourceSet ->
- sourceSet.sourceSetID to context.configuration.sourceSets
- .map { it.sourceSetID }
- .filter { it in sourceSet.dependentSourceSets }
- }
-
- private val templateModelFactories = listOf(DefaultTemplateModelFactory(context)) // TODO: Make extension point
- private val templateModelMerger = DefaultTemplateModelMerger()
- private val templater = HtmlTemplater(context).apply {
- setupSharedModel(templateModelMerger.invoke(templateModelFactories) { buildSharedModel() })
- }
-
- private var shouldRenderSourceSetTabs: Boolean = false
-
- override val preprocessors: List<PageTransformer> = context.plugin<DokkaBase>().query { htmlPreprocessors }
-
- /**
- * Tabs themselves are created in HTML plugin since, currently, only HTML format supports them.
- * [TabbedContentType] is used to mark content that should be inside tab content.
- * A tab can display multiple [TabbedContentType].
- * The content style [ContentStyle.TabbedContent] is used to determine where tabs will be generated.
- *
- * @see TabbedContentType
- * @see ContentStyle.TabbedContent
- */
- private fun createTabs(pageContext: ContentPage): List<ContentTab> {
- return when(pageContext) {
- is ClasslikePage -> createTabsForClasslikes(pageContext)
- is PackagePage -> createTabsForPackage(pageContext)
- else -> throw IllegalArgumentException("Page ${pageContext.name} cannot have tabs")
- }
- }
-
- private fun createTabsForClasslikes(page: ClasslikePage): List<ContentTab> {
- val documentables = page.documentables
- val csEnum = documentables.filterIsInstance<DEnum>()
- val csWithConstructor = documentables.filterIsInstance<WithConstructors>()
- val scopes = documentables.filterIsInstance<WithScope>()
- val constructorsToDocumented = csWithConstructor.flatMap { it.constructors }
-
- val containsRenderableConstructors = constructorsToDocumented.isNotEmpty() && documentables.shouldDocumentConstructors()
- val containsRenderableMembers =
- containsRenderableConstructors || scopes.any { it.classlikes.isNotEmpty() || it.functions.isNotEmpty() || it.properties.isNotEmpty() }
-
- @Suppress("UNCHECKED_CAST")
- val extensions = (documentables as List<WithExtraProperties<DClasslike>>).flatMap {
- it.extra[CallableExtensions]?.extensions
- ?.filterIsInstance<Documentable>().orEmpty()
- }
- .distinctBy { it.sourceSets to it.dri } // [Documentable] has expensive equals/hashCode at the moment, see #2620
- return listOfNotNull(
- if(!containsRenderableMembers) null else
- ContentTab(
- "Members",
- listOf(
- BasicTabbedContentType.CONSTRUCTOR,
- BasicTabbedContentType.TYPE,
- BasicTabbedContentType.PROPERTY,
- BasicTabbedContentType.FUNCTION
- )
- ),
- if (extensions.isEmpty()) null else ContentTab(
- "Members & Extensions",
- listOf(
- BasicTabbedContentType.CONSTRUCTOR,
- BasicTabbedContentType.TYPE,
- BasicTabbedContentType.PROPERTY,
- BasicTabbedContentType.FUNCTION,
- BasicTabbedContentType.EXTENSION_PROPERTY,
- BasicTabbedContentType.EXTENSION_FUNCTION
- )
- ),
- if(csEnum.isEmpty()) null else ContentTab(
- "Entries",
- listOf(
- BasicTabbedContentType.ENTRY
- )
- )
- )
- }
-
- private fun createTabsForPackage(page: PackagePage): List<ContentTab> {
- val p = page.documentables.single() as DPackage
- return listOfNotNull(
- if (p.typealiases.isEmpty() && p.classlikes.isEmpty()) null else ContentTab(
- "Types",
- listOf(
- BasicTabbedContentType.TYPE,
- )
- ),
- if (p.functions.isEmpty()) null else ContentTab(
- "Functions",
- listOf(
- BasicTabbedContentType.FUNCTION,
- BasicTabbedContentType.EXTENSION_FUNCTION,
- )
- ),
- if (p.properties.isEmpty()) null else ContentTab(
- "Properties",
- listOf(
- BasicTabbedContentType.PROPERTY,
- BasicTabbedContentType.EXTENSION_PROPERTY,
- )
- )
- )
- }
-
- private fun <R> TagConsumer<R>.prepareForTemplates() =
- if (context.configuration.delayTemplateSubstitution || this is ImmediateResolutionTagConsumer) this
- else ImmediateResolutionTagConsumer(this, context)
-
- override fun FlowContent.wrapGroup(
- node: ContentGroup,
- pageContext: ContentPage,
- childrenCallback: FlowContent.() -> Unit
- ) {
- val additionalClasses = node.style.joinToString(" ") { it.toString().toLowerCase() }
- return when {
- node.hasStyle(ContentStyle.TabbedContent) -> div(additionalClasses) {
- val contentTabs = createTabs(pageContext)
-
- div(classes = "tabs-section") {
- attributes["tabs-section"] = "tabs-section"
- contentTabs.forEachIndexed { index, contentTab ->
- button(classes = "section-tab") {
- if (index == 0) attributes["data-active"] = ""
- attributes[TOGGLEABLE_CONTENT_TYPE_ATTR] =
- contentTab.tabbedContentTypes.joinToString(",") { it.toHtmlAttribute() }
- text(contentTab.text)
- }
- }
- }
- div(classes = "tabs-section-body") {
- childrenCallback()
- }
- }
- node.hasStyle(ContentStyle.WithExtraAttributes) -> div {
- node.extra.extraHtmlAttributes().forEach { attributes[it.extraKey] = it.extraValue }
- childrenCallback()
- }
- node.dci.kind in setOf(ContentKind.Symbol) -> div("symbol $additionalClasses") {
- childrenCallback()
- }
- node.hasStyle(ContentStyle.KDocTag) -> span("kdoc-tag") { childrenCallback() }
- node.hasStyle(ContentStyle.Footnote) -> div("footnote") { childrenCallback() }
- node.hasStyle(TextStyle.BreakableAfter) -> {
- span { childrenCallback() }
- wbr { }
- }
- node.hasStyle(TextStyle.Breakable) -> {
- span("breakable-word") { childrenCallback() }
- }
- node.hasStyle(TextStyle.Span) -> span { childrenCallback() }
- node.dci.kind == ContentKind.Symbol -> div("symbol $additionalClasses") {
- childrenCallback()
- }
- node.dci.kind == SymbolContentKind.Parameters -> {
- span("parameters $additionalClasses") {
- childrenCallback()
- }
- }
- node.dci.kind == SymbolContentKind.Parameter -> {
- span("parameter $additionalClasses") {
- 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()
- }
- node.dci.kind == ContentKind.Deprecation -> div("deprecation-content") { childrenCallback() }
- node.hasStyle(TextStyle.Paragraph) -> p(additionalClasses) { childrenCallback() }
- node.hasStyle(TextStyle.Block) -> div(additionalClasses) {
- childrenCallback()
- }
- node.hasStyle(TextStyle.Quotation) -> blockQuote(additionalClasses) { childrenCallback() }
- node.hasStyle(TextStyle.FloatingRight) -> span("clearfix") { span("floating-right") { childrenCallback() } }
- node.hasStyle(TextStyle.Strikethrough) -> strike { childrenCallback() }
- node.isAnchorable -> buildAnchor(
- node.anchor!!,
- node.anchorLabel!!,
- node.buildSourceSetFilterValues()
- ) { childrenCallback() }
- node.extra[InsertTemplateExtra] != null -> node.extra[InsertTemplateExtra]?.let { templateCommand(it.command) }
- ?: Unit
- node.hasStyle(ListStyle.DescriptionTerm) -> DT(emptyMap(), consumer).visit {
- this@wrapGroup.childrenCallback()
- }
- node.hasStyle(ListStyle.DescriptionDetails) -> DD(emptyMap(), consumer).visit {
- this@wrapGroup.childrenCallback()
- }
- node.extra.extraTabbedContentType() != null -> div() {
- node.extra.extraTabbedContentType()?.let { attributes[TOGGLEABLE_CONTENT_TYPE_ATTR] = it.value.toHtmlAttribute() }
- this@wrapGroup.childrenCallback()
- }
- else -> childrenCallback()
- }
- }
-
- private fun FlowContent.copyButton() = span(classes = "top-right-position") {
- span("copy-icon")
- copiedPopup("Content copied to clipboard", "popup-to-left")
- }
-
- private fun FlowContent.copiedPopup(notificationContent: String, additionalClasses: String = "") =
- div("copy-popup-wrapper $additionalClasses") {
- span("copy-popup-icon")
- span {
- text(notificationContent)
- }
- }
-
- override fun FlowContent.buildPlatformDependent(
- content: PlatformHintedContent,
- pageContext: ContentPage,
- sourceSetRestriction: Set<DisplaySourceSet>?
- ) {
- buildPlatformDependent(
- content.sourceSets.filter {
- sourceSetRestriction == null || it in sourceSetRestriction
- }.associateWith { setOf(content.inner) },
- pageContext,
- content.extra,
- content.style
- )
- }
-
- private fun FlowContent.buildPlatformDependent(
- nodes: Map<DisplaySourceSet, Collection<ContentNode>>,
- pageContext: ContentPage,
- extra: PropertyContainer<ContentNode> = PropertyContainer.empty(),
- styles: Set<Style> = emptySet(),
- shouldHaveTabs: Boolean = shouldRenderSourceSetTabs
- ) {
- val contents = contentsForSourceSetDependent(nodes, pageContext)
- val isOnlyCommonContent = contents.singleOrNull()?.let { (sourceSet, _) ->
- sourceSet.platform == Platform.common
- && sourceSet.name.equals("common", ignoreCase = true)
- && sourceSet.sourceSetIDs.all.all { sourceSetDependencyMap[it]?.isEmpty() == true }
- } ?: false
-
- // little point in rendering a single "common" tab - it can be
- // assumed that code without any tabs is common by default
- val renderTabs = shouldHaveTabs && !isOnlyCommonContent
-
- val divStyles = "platform-hinted ${styles.joinToString()}" + if (renderTabs) " with-platform-tabs" else ""
- div(divStyles) {
- attributes["data-platform-hinted"] = "data-platform-hinted"
- extra.extraHtmlAttributes().forEach { attributes[it.extraKey] = it.extraValue }
- if (renderTabs) {
- div("platform-bookmarks-row") {
- attributes["data-toggle-list"] = "data-toggle-list"
- contents.forEachIndexed { index, pair ->
- button(classes = "platform-bookmark") {
- attributes["data-filterable-current"] = pair.first.sourceSetIDs.merged.toString()
- attributes["data-filterable-set"] = pair.first.sourceSetIDs.merged.toString()
- if (index == 0) attributes["data-active"] = ""
- attributes["data-toggle"] = pair.first.sourceSetIDs.merged.toString()
- text(pair.first.name)
- }
- }
- }
- }
- contents.forEach {
- consumer.onTagContentUnsafe { +it.second }
- }
- }
- }
-
- private fun contentsForSourceSetDependent(
- nodes: Map<DisplaySourceSet, Collection<ContentNode>>,
- pageContext: ContentPage,
- ): List<Pair<DisplaySourceSet, String>> {
- var counter = 0
- return nodes.toList().map { (sourceSet, elements) ->
- val htmlContent = createHTML(prettyPrint = false).prepareForTemplates().div {
- elements.forEach {
- buildContentNode(it, pageContext, sourceSet)
- }
- }.stripDiv()
- sourceSet to createHTML(prettyPrint = false).prepareForTemplates()
- .div(classes = "content sourceset-dependent-content") {
- if (counter++ == 0) attributes["data-active"] = ""
- attributes["data-togglable"] = sourceSet.sourceSetIDs.merged.toString()
- unsafe {
- +htmlContent
- }
- }
- }.sortedBy { it.first.comparableKey }
- }
-
- override fun FlowContent.buildDivergent(node: ContentDivergentGroup, pageContext: ContentPage) {
- if (node.implicitlySourceSetHinted) {
- val groupedInstancesBySourceSet = node.children.flatMap { instance ->
- instance.sourceSets.map { sourceSet -> instance to sourceSet }
- }.groupBy(
- Pair<ContentDivergentInstance, DisplaySourceSet>::second,
- Pair<ContentDivergentInstance, DisplaySourceSet>::first
- )
-
- val nodes = groupedInstancesBySourceSet.mapValues {
- val distinct =
- groupDivergentInstancesWithSourceSet(it.value, it.key, pageContext,
- beforeTransformer = { instance, _, sourceSet ->
- createHTML(prettyPrint = false).prepareForTemplates().div {
- instance.before?.let { before ->
- buildContentNode(before, pageContext, sourceSet)
- }
- }.stripDiv()
- },
- afterTransformer = { instance, _, sourceSet ->
- createHTML(prettyPrint = false).prepareForTemplates().div {
- instance.after?.let { after ->
- buildContentNode(after, pageContext, sourceSet)
- }
- }.stripDiv()
- })
-
- val isPageWithOverloadedMembers = pageContext is MemberPage && pageContext.documentables().size > 1
-
- val contentOfSourceSet = mutableListOf<ContentNode>()
- distinct.onEachIndexed{ index, (_, distinctInstances) ->
- distinctInstances.firstOrNull()?.before?.let { contentOfSourceSet.add(it) }
- contentOfSourceSet.addAll(distinctInstances.map { it.divergent })
- (distinctInstances.firstOrNull()?.after ?: if (index != distinct.size - 1) ContentBreakLine(setOf(it.key)) else null)
- ?.let { contentOfSourceSet.add(it) }
-
- // content kind main is important for declarations list to avoid double line breaks
- if (node.dci.kind == ContentKind.Main && index != distinct.size - 1) {
- if (isPageWithOverloadedMembers) {
- // add some spacing and distinction between function/property overloads.
- // not ideal, but there's no other place to modify overloads page atm
- contentOfSourceSet.add(ContentBreakLine(setOf(it.key), style = setOf(HorizontalBreakLineStyle)))
- } else {
- contentOfSourceSet.add(ContentBreakLine(setOf(it.key)))
- }
- }
- }
- contentOfSourceSet
- }
- buildPlatformDependent(nodes, pageContext)
- } else {
- node.children.forEach {
- buildContentNode(it.divergent, pageContext, it.sourceSets)
- }
- }
- }
-
- private fun groupDivergentInstancesWithSourceSet(
- instances: List<ContentDivergentInstance>,
- sourceSet: DisplaySourceSet,
- pageContext: ContentPage,
- beforeTransformer: (ContentDivergentInstance, ContentPage, DisplaySourceSet) -> String,
- afterTransformer: (ContentDivergentInstance, ContentPage, DisplaySourceSet) -> String
- ): Map<SerializedBeforeAndAfter, List<ContentDivergentInstance>> =
- instances.map { instance ->
- instance to Pair(
- beforeTransformer(instance, pageContext, sourceSet),
- afterTransformer(instance, pageContext, sourceSet)
- )
- }.groupBy(
- Pair<ContentDivergentInstance, SerializedBeforeAndAfter>::second,
- Pair<ContentDivergentInstance, SerializedBeforeAndAfter>::first
- )
-
- private fun ContentPage.documentables(): List<Documentable> {
- return (this as? WithDocumentables)?.documentables ?: emptyList()
- }
-
- override fun FlowContent.buildList(
- node: ContentList,
- pageContext: ContentPage,
- sourceSetRestriction: Set<DisplaySourceSet>?
- ) {
- return when {
- node.ordered -> {
- ol { buildListItems(node.children, pageContext, sourceSetRestriction) }
- }
- node.hasStyle(ListStyle.DescriptionList) -> {
- dl { node.children.forEach { it.build(this, pageContext, sourceSetRestriction) } }
- }
- else -> {
- ul { buildListItems(node.children, pageContext, sourceSetRestriction) }
- }
- }
- }
-
- public open fun OL.buildListItems(
- items: List<ContentNode>,
- pageContext: ContentPage,
- sourceSetRestriction: Set<DisplaySourceSet>? = null
- ) {
- items.forEach {
- if (it is ContentList)
- buildList(it, pageContext)
- else
- li { it.build(this, pageContext, sourceSetRestriction) }
- }
- }
-
- public open fun UL.buildListItems(
- items: List<ContentNode>,
- pageContext: ContentPage,
- sourceSetRestriction: Set<DisplaySourceSet>? = null
- ) {
- items.forEach {
- if (it is ContentList)
- buildList(it, pageContext)
- else
- li { it.build(this, pageContext) }
- }
- }
-
- override fun FlowContent.buildResource(
- node: ContentEmbeddedResource,
- pageContext: ContentPage
- ) { // TODO: extension point there
- if (node.isImage()) {
- img(src = node.address, alt = node.altText)
- } else {
- println("Unrecognized resource type: $node")
- }
- }
-
- private fun FlowContent.buildRow(
- node: ContentGroup,
- pageContext: ContentPage,
- sourceSetRestriction: Set<DisplaySourceSet>?
- ) {
- node.children
- .filter { sourceSetRestriction == null || it.sourceSets.any { s -> s in sourceSetRestriction } }
- .takeIf { it.isNotEmpty() }
- ?.let {
- when (pageContext) {
- is MultimoduleRootPage -> buildRowForMultiModule(node, it, pageContext, sourceSetRestriction)
- is ModulePage -> buildRowForModule(node, it, pageContext, sourceSetRestriction)
- else -> buildRowForContent(node, it, pageContext, sourceSetRestriction)
- }
- }
- }
-
- private fun FlowContent.buildRowForMultiModule(
- contextNode: ContentGroup,
- toRender: List<ContentNode>,
- pageContext: ContentPage,
- sourceSetRestriction: Set<DisplaySourceSet>?
- ) {
- buildAnchor(contextNode)
- div(classes = "table-row") {
- div("main-subrow " + contextNode.style.joinToString(separator = " ")) {
- buildRowHeaderLink(toRender, pageContext, sourceSetRestriction, contextNode.anchor, "w-100")
- div {
- buildRowBriefSectionForDocs(toRender, pageContext, sourceSetRestriction)
- }
- }
- }
- }
-
- private fun FlowContent.buildRowForModule(
- contextNode: ContentGroup,
- toRender: List<ContentNode>,
- pageContext: ContentPage,
- sourceSetRestriction: Set<DisplaySourceSet>?
- ) {
- buildAnchor(contextNode)
- div(classes = "table-row") {
- addSourceSetFilteringAttributes(contextNode)
- div {
- div("main-subrow " + contextNode.style.joinToString(separator = " ")) {
- buildRowHeaderLink(toRender, pageContext, sourceSetRestriction, contextNode.anchor)
- div("pull-right") {
- if (ContentKind.shouldBePlatformTagged(contextNode.dci.kind)) {
- createPlatformTags(contextNode, cssClasses = "no-gutters")
- }
- }
- }
- div {
- buildRowBriefSectionForDocs(toRender, pageContext, sourceSetRestriction)
- }
- }
- }
- }
-
- private fun FlowContent.buildRowForContent(
- contextNode: ContentGroup,
- toRender: List<ContentNode>,
- pageContext: ContentPage,
- sourceSetRestriction: Set<DisplaySourceSet>?
- ) {
- buildAnchor(contextNode)
- div(classes = "table-row") {
- contextNode.extra.extraTabbedContentType()?.let { attributes[TOGGLEABLE_CONTENT_TYPE_ATTR] = it.value.toHtmlAttribute() }
- addSourceSetFilteringAttributes(contextNode)
- div("main-subrow keyValue " + contextNode.style.joinToString(separator = " ")) {
- buildRowHeaderLink(toRender, pageContext, sourceSetRestriction, contextNode.anchor)
- div {
- toRender.filter { it !is ContentLink && !it.hasStyle(ContentStyle.RowTitle) }
- .takeIf { it.isNotEmpty() }?.let {
- div("title") {
- it.forEach {
- it.build(this, pageContext, sourceSetRestriction)
- }
- }
- }
- }
- }
- }
- }
-
- private fun FlowContent.buildRowHeaderLink(
- toRender: List<ContentNode>,
- pageContext: ContentPage,
- sourceSetRestriction: Set<DisplaySourceSet>?,
- anchorDestination: String?,
- classes: String = ""
- ) {
- toRender.filter { it is ContentLink || it.hasStyle(ContentStyle.RowTitle) }.takeIf { it.isNotEmpty() }?.let {
- div(classes) {
- it.filter { sourceSetRestriction == null || it.sourceSets.any { s -> s in sourceSetRestriction } }
- .forEach {
- span("inline-flex") {
- div {
- it.build(this, pageContext, sourceSetRestriction)
- }
- if (it is ContentLink && !anchorDestination.isNullOrBlank()) {
- buildAnchorCopyButton(anchorDestination)
- }
- }
- }
- }
- }
- }
-
- private fun FlowContent.addSourceSetFilteringAttributes(
- contextNode: ContentGroup,
- ) {
- attributes["data-filterable-current"] = contextNode.buildSourceSetFilterValues()
- attributes["data-filterable-set"] = contextNode.buildSourceSetFilterValues()
- }
-
- private fun ContentNode.buildSourceSetFilterValues(): String {
- // This value is used in HTML and JS for filtering out source set declarations,
- // it is expected that the separator is the same here and there.
- // See https://github.com/Kotlin/dokka/issues/3011#issuecomment-1568620493
- return this.sourceSets.joinToString(",") {
- it.sourceSetIDs.merged.toString()
- }
- }
-
- private fun FlowContent.buildRowBriefSectionForDocs(
- toRender: List<ContentNode>,
- pageContext: ContentPage,
- sourceSetRestriction: Set<DisplaySourceSet>?,
- ) {
- toRender.filter { it !is ContentLink }.takeIf { it.isNotEmpty() }?.let {
- it.forEach {
- span(classes = if (it.dci.kind == ContentKind.Comment) "brief-comment" else "") {
- it.build(this, pageContext, sourceSetRestriction)
- }
- }
- }
- }
-
- private fun FlowContent.createPlatformTagBubbles(sourceSets: List<DisplaySourceSet>, cssClasses: String = "") {
- div("platform-tags $cssClasses") {
- sourceSets.sortedBy { it.name }.forEach {
- div("platform-tag") {
- when (it.platform.key) {
- "common" -> classes = classes + "common-like"
- "native" -> classes = classes + "native-like"
- "jvm" -> classes = classes + "jvm-like"
- "js" -> classes = classes + "js-like"
- "wasm" -> classes = classes + "wasm-like"
- }
- text(it.name)
- }
- }
- }
- }
-
- private fun FlowContent.createPlatformTags(
- node: ContentNode,
- sourceSetRestriction: Set<DisplaySourceSet>? = null,
- cssClasses: String = ""
- ) {
- node.takeIf { sourceSetRestriction == null || it.sourceSets.any { s -> s in sourceSetRestriction } }?.let {
- createPlatformTagBubbles(node.sourceSets.filter {
- sourceSetRestriction == null || it in sourceSetRestriction
- }.sortedBy { it.name }, cssClasses)
- }
- }
-
- override fun FlowContent.buildTable(
- node: ContentTable,
- pageContext: ContentPage,
- sourceSetRestriction: Set<DisplaySourceSet>?
- ) {
- when {
- node.style.contains(CommentTable) -> buildDefaultTable(node, pageContext, sourceSetRestriction)
- else -> div(classes = "table") {
- node.extra.extraHtmlAttributes().forEach { attributes[it.extraKey] = it.extraValue }
- node.children.forEach {
- buildRow(it, pageContext, sourceSetRestriction)
- }
- }
- }
-
- }
-
- public fun FlowContent.buildDefaultTable(
- node: ContentTable,
- pageContext: ContentPage,
- sourceSetRestriction: Set<DisplaySourceSet>?
- ) {
- table {
- thead {
- node.header.forEach {
- tr {
- it.children.forEach {
- th {
- it.build(this@table, pageContext, sourceSetRestriction)
- }
- }
- }
- }
- }
- tbody {
- node.children.forEach {
- tr {
- it.children.forEach {
- td {
- it.build(this, pageContext, sourceSetRestriction)
- }
- }
- }
- }
- }
- }
- }
-
-
- override fun FlowContent.buildHeader(level: Int, node: ContentHeader, content: FlowContent.() -> Unit) {
- val classes = node.style.joinToString { it.toString() }.toLowerCase()
- when (level) {
- 1 -> h1(classes = classes, content)
- 2 -> h2(classes = classes, content)
- 3 -> h3(classes = classes, content)
- 4 -> h4(classes = classes, content)
- 5 -> h5(classes = classes, content)
- else -> h6(classes = classes, content)
- }
- }
-
- private fun FlowContent.buildAnchor(
- anchor: String,
- anchorLabel: String,
- sourceSets: String,
- content: FlowContent.() -> Unit
- ) {
- a {
- attributes["data-name"] = anchor
- attributes["anchor-label"] = anchorLabel
- attributes["id"] = anchor
- attributes["data-filterable-set"] = sourceSets
- }
- content()
- }
-
- private fun FlowContent.buildAnchor(anchor: String, anchorLabel: String, sourceSets: String) =
- buildAnchor(anchor, anchorLabel, sourceSets) {}
-
- private fun FlowContent.buildAnchor(node: ContentNode) {
- node.anchorLabel?.let { label -> buildAnchor(node.anchor!!, label, node.buildSourceSetFilterValues()) }
- }
-
-
- override fun FlowContent.buildNavigation(page: PageNode) {
- div(classes = "breadcrumbs") {
- val path = locationProvider.ancestors(page).filterNot { it is RendererSpecificPage }.asReversed()
- if (path.size > 1) {
- buildNavigationElement(path.first(), page)
- path.drop(1).forEach { node ->
- span(classes = "delimiter") {
- text("/")
- }
- buildNavigationElement(node, page)
- }
- }
- }
- }
-
- private fun FlowContent.buildNavigationElement(node: PageNode, page: PageNode) =
- if (node.isNavigable) {
- val isCurrentPage = (node == page)
- if (isCurrentPage) {
- span(classes = "current") {
- text(node.name)
- }
- } else {
- buildLink(node, page)
- }
- } else {
- text(node.name)
- }
-
- private fun FlowContent.buildLink(to: PageNode, from: PageNode) =
- locationProvider.resolve(to, from)?.let { path ->
- buildLink(path) {
- text(to.name)
- }
- } ?: span {
- attributes["data-unresolved-link"] = to.name.htmlEscape()
- text(to.name)
- }
-
- public fun FlowContent.buildAnchorCopyButton(pointingTo: String) {
- span(classes = "anchor-wrapper") {
- span(classes = "anchor-icon") {
- attributes["pointing-to"] = pointingTo
- }
- copiedPopup("Link copied to clipboard")
- }
- }
-
- public fun FlowContent.buildLink(
- to: DRI,
- platforms: List<DisplaySourceSet>,
- from: PageNode? = null,
- block: FlowContent.() -> Unit
- ) {
- locationProvider.resolve(to, platforms.toSet(), from)?.let { buildLink(it, block) }
- ?: run { context.logger.error("Cannot resolve path for `$to` from `$from`"); block() }
- }
-
- override fun buildError(node: ContentNode) {
- context.logger.error("Unknown ContentNode type: $node")
- }
-
- override fun FlowContent.buildLineBreak() {
- br()
- }
- override fun FlowContent.buildLineBreak(node: ContentBreakLine, pageContext: ContentPage) {
- if (node.style.contains(HorizontalBreakLineStyle)) {
- hr()
- } else {
- buildLineBreak()
- }
- }
-
- override fun FlowContent.buildLink(address: String, content: FlowContent.() -> Unit) {
- a(href = address, block = content)
- }
-
- override fun FlowContent.buildDRILink(
- node: ContentDRILink,
- pageContext: ContentPage,
- sourceSetRestriction: Set<DisplaySourceSet>?
- ) {
- locationProvider.resolve(node.address, node.sourceSets, pageContext)?.let { address ->
- buildLink(address) {
- buildText(node.children, pageContext, sourceSetRestriction)
- }
- } ?: if (isPartial) {
- templateCommand(ResolveLinkCommand(node.address)) {
- buildText(node.children, pageContext, sourceSetRestriction)
- }
- } else {
- span {
- attributes["data-unresolved-link"] = node.address.toString().htmlEscape()
- buildText(node.children, pageContext, sourceSetRestriction)
- }
- }
- }
-
- override fun FlowContent.buildCodeBlock(
- code: ContentCodeBlock,
- pageContext: ContentPage
- ) {
- div("sample-container") {
- val codeLang = "lang-" + code.language.ifEmpty { "kotlin" }
- val stylesWithBlock = code.style + TextStyle.Block + codeLang
- pre {
- code(stylesWithBlock.joinToString(" ") { it.toString().toLowerCase() }) {
- attributes["theme"] = "idea"
- code.children.forEach { buildContentNode(it, pageContext) }
- }
- }
- /*
- Disable copy button on samples as:
- - it is useless
- - it overflows with playground's run button
- */
- if (!code.style.contains(ContentStyle.RunnableSample)) copyButton()
- }
- }
-
- override fun FlowContent.buildCodeInline(
- code: ContentCodeInline,
- pageContext: ContentPage
- ) {
- val codeLang = "lang-" + code.language.ifEmpty { "kotlin" }
- val stylesWithBlock = code.style + codeLang
- code(stylesWithBlock.joinToString(" ") { it.toString().toLowerCase() }) {
- code.children.forEach { buildContentNode(it, pageContext) }
- }
- }
-
- override fun FlowContent.buildText(textNode: ContentText) {
- buildText(textNode, textNode.style)
- }
-
- private fun FlowContent.buildText(textNode: ContentText, unappliedStyles: Set<Style>) {
- when {
- textNode.extra[HtmlContent] != null -> {
- consumer.onTagContentUnsafe { raw(textNode.text) }
- }
- unappliedStyles.contains(TextStyle.Indented) -> {
- consumer.onTagContentEntity(Entities.nbsp)
- buildText(textNode, unappliedStyles - TextStyle.Indented)
- }
- unappliedStyles.isNotEmpty() -> {
- val styleToApply = unappliedStyles.first()
- applyStyle(styleToApply) {
- buildText(textNode, unappliedStyles - styleToApply)
- }
- }
- textNode.hasStyle(ContentStyle.RowTitle) || textNode.hasStyle(TextStyle.Cover) ->
- buildBreakableText(textNode.text)
- else -> text(textNode.text)
- }
- }
-
- private inline fun FlowContent.applyStyle(styleToApply: Style, crossinline body: FlowContent.() -> Unit) {
- when (styleToApply) {
- TextStyle.Bold -> b { body() }
- TextStyle.Italic -> i { body() }
- TextStyle.Strikethrough -> strike { body() }
- TextStyle.Strong -> strong { body() }
- TextStyle.Var -> htmlVar { body() }
- TextStyle.Underlined -> underline { body() }
- is TokenStyle -> span("token ${styleToApply.prismJsClass()}") { body() }
- else -> body()
- }
- }
-
- private fun TokenStyle.prismJsClass(): String = when(this) {
- // Prism.js parser adds Builtin token instead of Annotation
- // for some reason, so we also add it for consistency and correct coloring
- TokenStyle.Annotation -> "annotation builtin"
- else -> this.toString().toLowerCase()
- }
-
- override fun render(root: RootPageNode) {
- shouldRenderSourceSetTabs = shouldRenderSourceSetTabs(root)
- super.render(root)
- }
-
- override fun buildPage(page: ContentPage, content: (FlowContent, ContentPage) -> Unit): String =
- buildHtml(page, page.embeddedResources) {
- content(this, page)
- }
-
- private fun PageNode.getDocumentableType(): String? =
- when(this) {
- is PackagePage -> "package"
- is ClasslikePage -> "classlike"
- is MemberPage -> "member"
- else -> null
- }
-
- public open fun buildHtml(
- page: PageNode,
- resources: List<String>, content: FlowContent.() -> Unit
- ): String {
- return templater.renderFromTemplate(DokkaTemplateTypes.BASE) {
- val generatedContent =
- createHTML().div("main-content") {
- page.getDocumentableType()?.let { attributes["data-page-type"] = it }
- id = "content"
- (page as? ContentPage)?.let {
- attributes["pageIds"] = "${context.configuration.moduleName}::${page.pageId}"
- }
- content()
- }
-
- templateModelMerger.invoke(templateModelFactories) {
- buildModel(
- page,
- resources,
- locationProvider,
- generatedContent
- )
- }
- }
- }
-
- /**
- * This is deliberately left open for plugins that have some other pages above ours and would like to link to them
- * instead of ours when clicking the logo
- */
- public open fun FlowContent.clickableLogo(page: PageNode, pathToRoot: String) {
- if (context.configuration.delayTemplateSubstitution && page is ContentPage) {
- templateCommand(PathToRootSubstitutionCommand(pattern = "###", default = pathToRoot)) {
- a {
- href = "###index.html"
- templateCommand(
- ProjectNameSubstitutionCommand(
- pattern = "@@@",
- default = context.configuration.moduleName
- )
- ) {
- span {
- text("@@@")
- }
- }
- }
- }
- } else {
- a {
- href = pathToRoot + "index.html"
- text(context.configuration.moduleName)
- }
- }
- }
-
- private val ContentNode.isAnchorable: Boolean
- get() = anchorLabel != null
-
- private val ContentNode.anchorLabel: String?
- get() = extra[SymbolAnchorHint]?.anchorName
-
- private val ContentNode.anchor: String?
- get() = extra[SymbolAnchorHint]?.contentKind?.let { contentKind ->
- (locationProvider as DokkaBaseLocationProvider).anchorForDCI(DCI(dci.dri, contentKind), sourceSets)
- }
-
- private val isPartial = context.configuration.delayTemplateSubstitution
-}
-
-private fun TabbedContentType.toHtmlAttribute(): String =
- when(this) {
- is BasicTabbedContentType ->
- when(this) {
- BasicTabbedContentType.ENTRY -> "ENTRY"
- BasicTabbedContentType.TYPE -> "TYPE"
- BasicTabbedContentType.CONSTRUCTOR -> "CONSTRUCTOR"
- BasicTabbedContentType.FUNCTION -> "FUNCTION"
- BasicTabbedContentType.PROPERTY -> "PROPERTY"
- BasicTabbedContentType.EXTENSION_PROPERTY -> "EXTENSION_PROPERTY"
- BasicTabbedContentType.EXTENSION_FUNCTION -> "EXTENSION_FUNCTION"
- }
- else -> throw IllegalStateException("Unknown TabbedContentType $this")
- }
-
-/**
- * Tabs for a content with [ContentStyle.TabbedContent].
- *
- * @see ContentStyle.TabbedContent]
- */
-private data class ContentTab(val text: String, val tabbedContentTypes: List<TabbedContentType>)
-
-public fun List<SimpleAttr>.joinAttr(): String = joinToString(" ") { it.extraKey + "=" + it.extraValue }
-
-private fun String.stripDiv() = drop(5).dropLast(6) // TODO: Find a way to do it without arbitrary trims
-
-private val PageNode.isNavigable: Boolean
- get() = this !is RendererSpecificPage || strategy != RenderingStrategy.DoNothing
-
-private fun PropertyContainer<ContentNode>.extraHtmlAttributes() = allOfType<SimpleAttr>()
-private fun PropertyContainer<ContentNode>.extraTabbedContentType() = this[TabbedContentTypeExtra]
-
-private val DisplaySourceSet.comparableKey
- get() = sourceSetIDs.merged.let { it.scopeId + it.sourceSetName }
diff --git a/plugins/base/src/main/kotlin/renderers/html/NavigationDataProvider.kt b/plugins/base/src/main/kotlin/renderers/html/NavigationDataProvider.kt
deleted file mode 100644
index fccfd145..00000000
--- a/plugins/base/src/main/kotlin/renderers/html/NavigationDataProvider.kt
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.renderers.html
-
-import org.jetbrains.dokka.base.renderers.sourceSets
-import org.jetbrains.dokka.base.signatures.KotlinSignatureUtils.annotations
-import org.jetbrains.dokka.base.transformers.documentables.isDeprecated
-import org.jetbrains.dokka.base.transformers.documentables.isException
-import org.jetbrains.dokka.base.utils.canonicalAlphabeticalOrder
-import org.jetbrains.dokka.model.*
-import org.jetbrains.dokka.pages.*
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.plugability.plugin
-import org.jetbrains.dokka.plugability.querySingle
-import org.jetbrains.dokka.analysis.kotlin.internal.DocumentableLanguage
-import org.jetbrains.dokka.analysis.kotlin.internal.InternalKotlinAnalysisPlugin
-
-public abstract class NavigationDataProvider(
- dokkaContext: DokkaContext
-) {
- private val documentableSourceLanguageParser = dokkaContext.plugin<InternalKotlinAnalysisPlugin>().querySingle { documentableSourceLanguageParser }
-
- public open fun navigableChildren(input: RootPageNode): NavigationNode = input.withDescendants()
- .first { it is ModulePage || it is MultimoduleRootPage }.let { visit(it as ContentPage) }
-
- public open fun visit(page: ContentPage): NavigationNode =
- NavigationNode(
- name = page.displayableName(),
- dri = page.dri.first(),
- sourceSets = page.sourceSets(),
- icon = chooseNavigationIcon(page),
- styles = chooseStyles(page),
- children = page.navigableChildren()
- )
-
- /**
- * Parenthesis is applied in 1 case:
- * - page only contains functions (therefore documentable from this page is [DFunction])
- */
- private fun ContentPage.displayableName(): String =
- if (this is WithDocumentables && documentables.all { it is DFunction }) {
- "$name()"
- } else {
- name
- }
-
- private fun chooseNavigationIcon(contentPage: ContentPage): NavigationNodeIcon? =
- if (contentPage is WithDocumentables) {
- val documentable = contentPage.documentables.firstOrNull()
- val isJava = documentable?.hasAnyJavaSources() ?: false
-
- when (documentable) {
- is DTypeAlias -> NavigationNodeIcon.TYPEALIAS_KT
- is DClass -> when {
- documentable.isException -> NavigationNodeIcon.EXCEPTION
- documentable.isAbstract() -> {
- if (isJava) NavigationNodeIcon.ABSTRACT_CLASS else NavigationNodeIcon.ABSTRACT_CLASS_KT
- }
- else -> if (isJava) NavigationNodeIcon.CLASS else NavigationNodeIcon.CLASS_KT
- }
- is DFunction -> NavigationNodeIcon.FUNCTION
- is DProperty -> {
- val isVar = documentable.extra[IsVar] != null
- if (isVar) NavigationNodeIcon.VAR else NavigationNodeIcon.VAL
- }
- is DInterface -> if (isJava) NavigationNodeIcon.INTERFACE else NavigationNodeIcon.INTERFACE_KT
- is DEnum,
- is DEnumEntry -> if (isJava) NavigationNodeIcon.ENUM_CLASS else NavigationNodeIcon.ENUM_CLASS_KT
- is DAnnotation -> {
- if (isJava) NavigationNodeIcon.ANNOTATION_CLASS else NavigationNodeIcon.ANNOTATION_CLASS_KT
- }
- is DObject -> NavigationNodeIcon.OBJECT
- else -> null
- }
- } else {
- null
- }
-
- private fun Documentable.hasAnyJavaSources(): Boolean {
- return this.sourceSets.any { sourceSet ->
- documentableSourceLanguageParser.getLanguage(this, sourceSet) == DocumentableLanguage.JAVA
- }
- }
-
- private fun DClass.isAbstract() =
- modifier.values.all { it is KotlinModifier.Abstract || it is JavaModifier.Abstract }
-
- private fun chooseStyles(page: ContentPage): Set<Style> =
- if (page.containsOnlyDeprecatedDocumentables()) setOf(TextStyle.Strikethrough) else emptySet()
-
- private fun ContentPage.containsOnlyDeprecatedDocumentables(): Boolean {
- if (this !is WithDocumentables) {
- return false
- }
- return this.documentables.isNotEmpty() && this.documentables.all { it.isDeprecatedForAllSourceSets() }
- }
-
- private fun Documentable.isDeprecatedForAllSourceSets(): Boolean {
- val sourceSetAnnotations = this.annotations()
- return sourceSetAnnotations.isNotEmpty() && sourceSetAnnotations.all { (_, annotations) ->
- annotations.any { it.isDeprecated() }
- }
- }
-
- private val navigationNodeOrder: Comparator<NavigationNode> =
- compareBy(canonicalAlphabeticalOrder) { it.name }
-
- private fun ContentPage.navigableChildren() =
- if (this is ClasslikePage) {
- this.navigableChildren()
- } else {
- children
- .filterIsInstance<ContentPage>()
- .map { visit(it) }
- .sortedWith(navigationNodeOrder)
- }
-
- private fun ClasslikePage.navigableChildren(): List<NavigationNode> {
- // Classlikes should only have other classlikes as navigable children
- val navigableChildren = children
- .filterIsInstance<ClasslikePage>()
- .map { visit(it) }
-
- val isEnumPage = documentables.any { it is DEnum }
- return if (isEnumPage) {
- // no sorting for enum entries, should be the same order as in source code
- navigableChildren
- } else {
- navigableChildren.sortedWith(navigationNodeOrder)
- }
- }
-}
diff --git a/plugins/base/src/main/kotlin/renderers/html/NavigationPage.kt b/plugins/base/src/main/kotlin/renderers/html/NavigationPage.kt
deleted file mode 100644
index eae43daf..00000000
--- a/plugins/base/src/main/kotlin/renderers/html/NavigationPage.kt
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.renderers.html
-
-import kotlinx.html.*
-import kotlinx.html.stream.createHTML
-import org.jetbrains.dokka.base.renderers.html.NavigationNodeIcon.CLASS
-import org.jetbrains.dokka.base.renderers.html.NavigationNodeIcon.CLASS_KT
-import org.jetbrains.dokka.base.renderers.pageId
-import org.jetbrains.dokka.base.templating.AddToNavigationCommand
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.model.DisplaySourceSet
-import org.jetbrains.dokka.model.WithChildren
-import org.jetbrains.dokka.pages.*
-import org.jetbrains.dokka.plugability.DokkaContext
-
-public class NavigationPage(
- public val root: NavigationNode,
- public val moduleName: String,
- public val context: DokkaContext
-) : RendererSpecificPage {
-
- override val name: String = "navigation"
-
- override val children: List<PageNode> = emptyList()
-
- override fun modified(name: String, children: List<PageNode>): NavigationPage = this
-
- override val strategy: RenderingStrategy = RenderingStrategy<HtmlRenderer> {
- createHTML().visit(root, this)
- }
-
- private fun <R> TagConsumer<R>.visit(node: NavigationNode, renderer: HtmlRenderer): R = with(renderer) {
- if (context.configuration.delayTemplateSubstitution) {
- templateCommand(AddToNavigationCommand(moduleName)) {
- visit(node, "${moduleName}-nav-submenu", renderer)
- }
- } else {
- visit(node, "${moduleName}-nav-submenu", renderer)
- }
- }
-
- private fun <R> TagConsumer<R>.visit(node: NavigationNode, navId: String, renderer: HtmlRenderer): R =
- with(renderer) {
- div("sideMenuPart") {
- id = navId
- attributes["pageId"] = "${moduleName}::${node.pageId}"
- div("overview") {
- if (node.children.isNotEmpty()) {
- span("navButton") {
- onClick = """document.getElementById("$navId").classList.toggle("hidden");"""
- span("navButtonContent")
- }
- }
- buildLink(node.dri, node.sourceSets.toList()) {
- val withIcon = node.icon != null
- if (withIcon) {
- // in case link text is so long that it needs to have word breaks,
- // and it stretches to two or more lines, make sure the icon
- // is always on the left in the grid and is not wrapped with text
- span("nav-link-grid") {
- span("nav-link-child ${node.icon?.style()}")
- span("nav-link-child") {
- nodeText(node)
- }
- }
- } else {
- nodeText(node)
- }
- }
- }
- node.children.withIndex().forEach { (n, p) -> visit(p, "$navId-$n", renderer) }
- }
- }
-
- private fun FlowContent.nodeText(node: NavigationNode) {
- if (node.styles.contains(TextStyle.Strikethrough)) {
- strike {
- buildBreakableText(node.name)
- }
- } else {
- buildBreakableText(node.name)
- }
- }
-}
-
-public data class NavigationNode(
- val name: String,
- val dri: DRI,
- val sourceSets: Set<DisplaySourceSet>,
- val icon: NavigationNodeIcon?,
- val styles: Set<Style> = emptySet(),
- override val children: List<NavigationNode>
-) : WithChildren<NavigationNode>
-
-/**
- * [CLASS] represents a neutral (a.k.a Java-style) icon,
- * whereas [CLASS_KT] should be Kotlin-styled
- */
-public enum class NavigationNodeIcon(
- private val cssClass: String
-) {
- CLASS("class"),
- CLASS_KT("class-kt"),
- ABSTRACT_CLASS("abstract-class"),
- ABSTRACT_CLASS_KT("abstract-class-kt"),
- ENUM_CLASS("enum-class"),
- ENUM_CLASS_KT("enum-class-kt"),
- ANNOTATION_CLASS("annotation-class"),
- ANNOTATION_CLASS_KT("annotation-class-kt"),
- INTERFACE("interface"),
- INTERFACE_KT("interface-kt"),
- FUNCTION("function"),
- EXCEPTION("exception-class"),
- OBJECT("object"),
- TYPEALIAS_KT("typealias-kt"),
- VAL("val"),
- VAR("var");
-
- internal fun style(): String = "nav-icon $cssClass"
-}
-
-public fun NavigationPage.transform(block: (NavigationNode) -> NavigationNode): NavigationPage =
- NavigationPage(root.transform(block), moduleName, context)
-
-public fun NavigationNode.transform(block: (NavigationNode) -> NavigationNode): NavigationNode =
- run(block).let { NavigationNode(it.name, it.dri, it.sourceSets, it.icon, it.styles, it.children.map(block)) }
diff --git a/plugins/base/src/main/kotlin/renderers/html/SearchbarDataInstaller.kt b/plugins/base/src/main/kotlin/renderers/html/SearchbarDataInstaller.kt
deleted file mode 100644
index 83d4b24f..00000000
--- a/plugins/base/src/main/kotlin/renderers/html/SearchbarDataInstaller.kt
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.renderers.html
-
-import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
-import org.jetbrains.dokka.Platform
-import org.jetbrains.dokka.base.renderers.sourceSets
-import org.jetbrains.dokka.base.templating.AddToSearch
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.model.DisplaySourceSet
-import org.jetbrains.dokka.model.dfs
-import org.jetbrains.dokka.model.withDescendants
-import org.jetbrains.dokka.pages.*
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.transformers.pages.PageTransformer
-
-public data class SearchRecord(
- val name: String,
- val description: String? = null,
- val location: String,
- val searchKeys: List<String> = listOf(name)
-) {
- public companion object
-}
-
-public open class SearchbarDataInstaller(
- public val context: DokkaContext
-) : PageTransformer {
-
- public data class DRIWithSourceSets(val dri: DRI, val sourceSet: Set<DisplaySourceSet>)
-
- public data class SignatureWithId(val driWithSourceSets: DRIWithSourceSets, val displayableSignature: String) {
- public constructor(dri: DRI, page: ContentPage) : this( DRIWithSourceSets(dri, page.sourceSets()),
- getSymbolSignature(page, dri)?.let { flattenToText(it) } ?: page.name)
-
- val id: String
- get() = with(driWithSourceSets.dri) {
- listOfNotNull(
- packageName?.takeIf { it.isNotBlank() },
- classNames,
- callable?.name
- ).joinToString(".")
- }
- }
-
- private val mapper = jacksonObjectMapper()
-
- public open fun generatePagesList(
- pages: List<SignatureWithId>,
- locationResolver: DriResolver
- ): List<SearchRecord> =
- pages.map { pageWithId ->
- createSearchRecord(
- name = pageWithId.displayableSignature,
- description = pageWithId.id,
- location = resolveLocation(locationResolver, pageWithId.driWithSourceSets).orEmpty(),
- searchKeys = listOf(
- pageWithId.id.substringAfterLast("."),
- pageWithId.displayableSignature,
- pageWithId.id,
- )
- )
- }.sortedWith(compareBy({ it.name }, { it.description }))
-
- public open fun createSearchRecord(
- name: String,
- description: String?,
- location: String,
- searchKeys: List<String>
- ): SearchRecord =
- SearchRecord(name, description, location, searchKeys)
-
- public open fun processPage(page: PageNode): List<SignatureWithId> =
- when (page) {
- is ContentPage -> page.takeIf { page !is ModulePageNode && page !is PackagePageNode }?.dri
- ?.map { dri -> SignatureWithId(dri, page) }.orEmpty()
- else -> emptyList()
- }
-
- private fun resolveLocation(locationResolver: DriResolver, driWithSourceSets: DRIWithSourceSets): String? =
- locationResolver(driWithSourceSets.dri, driWithSourceSets.sourceSet).also { location ->
- if (location.isNullOrBlank()) context.logger.warn("Cannot resolve path for ${driWithSourceSets.dri}")
- }
-
- override fun invoke(input: RootPageNode): RootPageNode {
- val signatureWithIds = input.withDescendants().fold(emptyList<SignatureWithId>()) { pageList, page ->
- pageList + processPage(page)
- }
- val page = RendererSpecificResourcePage(
- name = "scripts/pages.json",
- children = emptyList(),
- strategy = RenderingStrategy.DriLocationResolvableWrite { resolver ->
- val content = signatureWithIds.run {
- generatePagesList(this, resolver)
- }
-
- if (context.configuration.delayTemplateSubstitution) {
- mapper.writeValueAsString(AddToSearch(context.configuration.moduleName, content))
- } else {
- mapper.writeValueAsString(content)
- }
- })
-
- return input.modified(children = input.children + page)
- }
-}
-
-private fun getSymbolSignature(page: ContentPage, dri: DRI) =
- page.content.dfs { it.dci.kind == ContentKind.Symbol && it.dci.dri.contains(dri) }
-
-private fun flattenToText(node: ContentNode): String {
- fun getContentTextNodes(node: ContentNode, sourceSetRestriction: DisplaySourceSet): List<ContentText> =
- when (node) {
- is ContentText -> listOf(node)
- is ContentComposite -> node.children
- .filter { sourceSetRestriction in it.sourceSets }
- .flatMap { getContentTextNodes(it, sourceSetRestriction) }
- .takeIf { node.dci.kind != ContentKind.Annotations && node.dci.kind != ContentKind.Source }
- .orEmpty()
- else -> emptyList()
- }
-
- val sourceSetRestriction =
- node.sourceSets.find { it.platform == Platform.common } ?: node.sourceSets.first()
- return getContentTextNodes(node, sourceSetRestriction).joinToString("") { it.text }
-}
diff --git a/plugins/base/src/main/kotlin/renderers/html/Tags.kt b/plugins/base/src/main/kotlin/renderers/html/Tags.kt
deleted file mode 100644
index 7d6fc390..00000000
--- a/plugins/base/src/main/kotlin/renderers/html/Tags.kt
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.renderers.html
-
-import kotlinx.html.*
-import kotlinx.html.stream.createHTML
-import org.jetbrains.dokka.base.renderers.html.command.consumers.ImmediateResolutionTagConsumer
-import org.jetbrains.dokka.base.templating.Command
-import org.jetbrains.dokka.base.templating.toJsonString
-
-public typealias TemplateBlock = TemplateCommand.() -> Unit
-
-@HtmlTagMarker
-public fun FlowOrPhrasingContent.wbr(classes: String? = null, block: WBR.() -> Unit = {}): Unit =
- WBR(attributesMapOf("class", classes), consumer).visit(block)
-
-@Suppress("unused")
-public open class WBR(initialAttributes: Map<String, String>, consumer: TagConsumer<*>) :
- HTMLTag("wbr", consumer, initialAttributes, namespace = null, inlineTag = true, emptyTag = false),
- HtmlBlockInlineTag
-
-/**
- * Work-around until next version of kotlinx.html doesn't come out
- */
-@HtmlTagMarker
-public inline fun FlowOrPhrasingContent.strike(classes : String? = null, crossinline block : STRIKE.() -> Unit = {}) : Unit = STRIKE(attributesMapOf("class", classes), consumer).visit(block)
-
-public open class STRIKE(initialAttributes: Map<String, String>, override val consumer: TagConsumer<*>) :
- HTMLTag("strike", consumer, initialAttributes, null, false, false), HtmlBlockInlineTag
-
-@HtmlTagMarker
-public inline fun FlowOrPhrasingContent.underline(classes : String? = null, crossinline block : UNDERLINE.() -> Unit = {}) : Unit = UNDERLINE(attributesMapOf("class", classes), consumer).visit(block)
-
-public open class UNDERLINE(initialAttributes: Map<String, String>, override val consumer: TagConsumer<*>) :
- HTMLTag("u", consumer, initialAttributes, null, false, false), HtmlBlockInlineTag
-
-public const val TEMPLATE_COMMAND_SEPARATOR: String = ":"
-public const val TEMPLATE_COMMAND_BEGIN_BORDER: String = "[+]cmd"
-public const val TEMPLATE_COMMAND_END_BORDER: String = "[-]cmd"
-
-public fun FlowOrMetaDataContent.templateCommandAsHtmlComment(data: Command, block: FlowOrMetaDataContent.() -> Unit = {}): Unit =
- (consumer as? ImmediateResolutionTagConsumer)?.processCommand(data, block)
- ?: let{
- comment( "$TEMPLATE_COMMAND_BEGIN_BORDER$TEMPLATE_COMMAND_SEPARATOR${toJsonString(data)}")
- block()
- comment(TEMPLATE_COMMAND_END_BORDER)
- }
-
-public fun <T: Appendable> T.templateCommandAsHtmlComment(command: Command, action: T.() -> Unit ) {
- append("<!--$TEMPLATE_COMMAND_BEGIN_BORDER$TEMPLATE_COMMAND_SEPARATOR${toJsonString(command)}-->")
- action()
- append("<!--$TEMPLATE_COMMAND_END_BORDER-->")
-}
-
-public fun FlowOrMetaDataContent.templateCommand(data: Command, block: TemplateBlock = {}): Unit =
- (consumer as? ImmediateResolutionTagConsumer)?.processCommand(data, block)
- ?: TemplateCommand(attributesMapOf("data", toJsonString(data)), consumer).visit(block)
-
-public fun <T> TagConsumer<T>.templateCommand(data: Command, block: TemplateBlock = {}): T =
- (this as? ImmediateResolutionTagConsumer)?.processCommandAndFinalize(data, block)
- ?: TemplateCommand(attributesMapOf("data", toJsonString(data)), this).visitAndFinalize(this, block)
-
-public fun templateCommandFor(data: Command, consumer: TagConsumer<*>): TemplateCommand =
- TemplateCommand(attributesMapOf("data", toJsonString(data)), consumer)
-
-public class TemplateCommand(initialAttributes: Map<String, String>, consumer: TagConsumer<*>) :
- HTMLTag(
- "dokka-template-command",
- consumer,
- initialAttributes,
- namespace = null,
- inlineTag = true,
- emptyTag = false
- ),
- CommonAttributeGroupFacadeFlowInteractivePhrasingContent
-
-// This hack is outrageous. I hate it but I cannot find any other way around `kotlinx.html` type system.
-public fun TemplateBlock.buildAsInnerHtml(): String = createHTML(prettyPrint = false).run {
- TemplateCommand(emptyMap, this).visitAndFinalize(this, this@buildAsInnerHtml).substringAfter(">").substringBeforeLast("<")
-}
diff --git a/plugins/base/src/main/kotlin/renderers/html/command/consumers/ImmediateResolutionTagConsumer.kt b/plugins/base/src/main/kotlin/renderers/html/command/consumers/ImmediateResolutionTagConsumer.kt
deleted file mode 100644
index 9cde1fca..00000000
--- a/plugins/base/src/main/kotlin/renderers/html/command/consumers/ImmediateResolutionTagConsumer.kt
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.renderers.html.command.consumers
-
-import kotlinx.html.TagConsumer
-import kotlinx.html.visit
-import org.jetbrains.dokka.base.DokkaBase
-import org.jetbrains.dokka.base.renderers.html.TemplateBlock
-import org.jetbrains.dokka.base.renderers.html.templateCommand
-import org.jetbrains.dokka.base.renderers.html.templateCommandFor
-import org.jetbrains.dokka.base.templating.Command
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.plugability.plugin
-import org.jetbrains.dokka.plugability.query
-
-public class ImmediateResolutionTagConsumer<out R>(
- private val downstream: TagConsumer<R>,
- private val context: DokkaContext
-): TagConsumer<R> by downstream {
-
- public fun processCommand(command: Command, block: TemplateBlock) {
- context.plugin<DokkaBase>().query { immediateHtmlCommandConsumer }
- .find { it.canProcess(command) }
- ?.processCommand(command, block, this)
- ?: run { templateCommandFor(command, downstream).visit(block) }
- }
-
- public fun processCommandAndFinalize(command: Command, block: TemplateBlock): R {
- return context.plugin<DokkaBase>().query { immediateHtmlCommandConsumer }
- .find { it.canProcess(command) }
- ?.processCommandAndFinalize(command, block, this)
- ?: downstream.templateCommand(command, block)
- }
-}
-
diff --git a/plugins/base/src/main/kotlin/renderers/html/command/consumers/PathToRootConsumer.kt b/plugins/base/src/main/kotlin/renderers/html/command/consumers/PathToRootConsumer.kt
deleted file mode 100644
index 9ac6eb91..00000000
--- a/plugins/base/src/main/kotlin/renderers/html/command/consumers/PathToRootConsumer.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.renderers.html.command.consumers
-
-import org.jetbrains.dokka.base.renderers.html.TemplateBlock
-import org.jetbrains.dokka.base.renderers.html.buildAsInnerHtml
-import org.jetbrains.dokka.base.templating.Command
-import org.jetbrains.dokka.base.templating.ImmediateHtmlCommandConsumer
-import org.jetbrains.dokka.base.templating.PathToRootSubstitutionCommand
-
-public object PathToRootConsumer: ImmediateHtmlCommandConsumer {
- override fun canProcess(command: Command): Boolean = command is PathToRootSubstitutionCommand
-
- override fun <R> processCommand(command: Command, block: TemplateBlock, tagConsumer: ImmediateResolutionTagConsumer<R>) {
- command as PathToRootSubstitutionCommand
- tagConsumer.onTagContentUnsafe { +block.buildAsInnerHtml().replace(command.pattern, command.default) }
- }
-
- override fun <R> processCommandAndFinalize(command: Command, block: TemplateBlock, tagConsumer: ImmediateResolutionTagConsumer<R>): R {
- processCommand(command, block, tagConsumer)
- return tagConsumer.finalize()
- }
-
-}
diff --git a/plugins/base/src/main/kotlin/renderers/html/command/consumers/ReplaceVersionsConsumer.kt b/plugins/base/src/main/kotlin/renderers/html/command/consumers/ReplaceVersionsConsumer.kt
deleted file mode 100644
index dd95c202..00000000
--- a/plugins/base/src/main/kotlin/renderers/html/command/consumers/ReplaceVersionsConsumer.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.renderers.html.command.consumers
-
-import org.jetbrains.dokka.base.renderers.html.TemplateBlock
-import org.jetbrains.dokka.base.templating.Command
-import org.jetbrains.dokka.base.templating.ImmediateHtmlCommandConsumer
-import org.jetbrains.dokka.base.templating.ReplaceVersionsCommand
-import org.jetbrains.dokka.plugability.DokkaContext
-
-public class ReplaceVersionsConsumer(private val context: DokkaContext) : ImmediateHtmlCommandConsumer {
- override fun canProcess(command: Command): Boolean = command is ReplaceVersionsCommand
-
- override fun <R> processCommand(
- command: Command,
- block: TemplateBlock,
- tagConsumer: ImmediateResolutionTagConsumer<R>
- ) {
- command as ReplaceVersionsCommand
- tagConsumer.onTagContentUnsafe { +context.configuration.moduleVersion.orEmpty() }
- }
-
- override fun <R> processCommandAndFinalize(command: Command, block: TemplateBlock, tagConsumer: ImmediateResolutionTagConsumer<R>): R {
- processCommand(command, block, tagConsumer)
- return tagConsumer.finalize()
- }
-}
diff --git a/plugins/base/src/main/kotlin/renderers/html/command/consumers/ResolveLinkConsumer.kt b/plugins/base/src/main/kotlin/renderers/html/command/consumers/ResolveLinkConsumer.kt
deleted file mode 100644
index 292e88b0..00000000
--- a/plugins/base/src/main/kotlin/renderers/html/command/consumers/ResolveLinkConsumer.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.renderers.html.command.consumers
-
-import kotlinx.html.SPAN
-import kotlinx.html.span
-import kotlinx.html.unsafe
-import kotlinx.html.visit
-import org.jetbrains.dokka.base.renderers.html.TemplateBlock
-import org.jetbrains.dokka.base.renderers.html.buildAsInnerHtml
-import org.jetbrains.dokka.base.templating.Command
-import org.jetbrains.dokka.base.templating.ImmediateHtmlCommandConsumer
-import org.jetbrains.dokka.base.templating.ResolveLinkCommand
-import org.jetbrains.dokka.utilities.htmlEscape
-
-public object ResolveLinkConsumer: ImmediateHtmlCommandConsumer {
- override fun canProcess(command: Command): Boolean = command is ResolveLinkCommand
-
- override fun <R> processCommand(command: Command, block: TemplateBlock, tagConsumer: ImmediateResolutionTagConsumer<R>) {
- command as ResolveLinkCommand
- SPAN(mapOf("data-unresolved-link" to command.dri.toString().htmlEscape()), tagConsumer).visit {
- unsafe { block.buildAsInnerHtml() }
- }
- }
-
- override fun <R> processCommandAndFinalize(command: Command, block: TemplateBlock, tagConsumer: ImmediateResolutionTagConsumer<R>): R {
- command as ResolveLinkCommand
- return tagConsumer.span {
- attributes["data-unresolved-link"] = command.dri.toString().htmlEscape()
- }
- }
-}
diff --git a/plugins/base/src/main/kotlin/renderers/html/htmlFormatingUtils.kt b/plugins/base/src/main/kotlin/renderers/html/htmlFormatingUtils.kt
deleted file mode 100644
index b6ce4147..00000000
--- a/plugins/base/src/main/kotlin/renderers/html/htmlFormatingUtils.kt
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.renderers.html
-
-import kotlinx.html.FlowContent
-import kotlinx.html.span
-
-public fun FlowContent.buildTextBreakableAfterCapitalLetters(name: String, hasLastElement: Boolean = false) {
- if (name.contains(" ")) {
- val withOutSpaces = name.split(" ")
- withOutSpaces.dropLast(1).forEach {
- buildBreakableText(it)
- +" "
- }
- buildBreakableText(withOutSpaces.last())
- } else {
- val content = name.replace(Regex("(?<=[a-z])([A-Z])"), " $1").split(" ")
- joinToHtml(content, hasLastElement) {
- it
- }
- }
-}
-
-public fun FlowContent.buildBreakableDotSeparatedHtml(name: String) {
- val phrases = name.split(".")
- phrases.forEachIndexed { i, e ->
- val elementWithOptionalDot = e.takeIf { i == phrases.lastIndex } ?: "$e."
- if (e.length > 10) {
- buildTextBreakableAfterCapitalLetters(elementWithOptionalDot, hasLastElement = i == phrases.lastIndex)
- } else {
- buildBreakableHtmlElement(elementWithOptionalDot, i == phrases.lastIndex)
- }
- }
-}
-
-private fun FlowContent.joinToHtml(elements: List<String>, hasLastElement: Boolean = true, onEach: (String) -> String) {
- elements.dropLast(1).forEach {
- buildBreakableHtmlElement(onEach(it))
- }
- elements.takeIf { it.isNotEmpty() && it.last().isNotEmpty() }?.let {
- if (hasLastElement) {
- span {
- buildBreakableHtmlElement(it.last(), last = true)
- }
- } else {
- buildBreakableHtmlElement(it.last(), last = false)
- }
- }
-}
-
-private fun FlowContent.buildBreakableHtmlElement(element: String, last: Boolean = false) {
- element.takeIf { it.isNotBlank() }?.let {
- span {
- +it
- }
- }
- if (!last) {
- wbr { }
- }
-}
-
-public fun FlowContent.buildBreakableText(name: String) {
- if (name.contains(".")) buildBreakableDotSeparatedHtml(name)
- else buildTextBreakableAfterCapitalLetters(name, hasLastElement = true)
-}
diff --git a/plugins/base/src/main/kotlin/renderers/html/htmlPreprocessors.kt b/plugins/base/src/main/kotlin/renderers/html/htmlPreprocessors.kt
deleted file mode 100644
index dad013e2..00000000
--- a/plugins/base/src/main/kotlin/renderers/html/htmlPreprocessors.kt
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.renderers.html
-
-import org.jetbrains.dokka.base.DokkaBase
-import org.jetbrains.dokka.base.DokkaBaseConfiguration
-import org.jetbrains.dokka.base.templating.AddToSourcesetDependencies
-import org.jetbrains.dokka.base.templating.toJsonString
-import org.jetbrains.dokka.pages.RendererSpecificResourcePage
-import org.jetbrains.dokka.pages.RenderingStrategy
-import org.jetbrains.dokka.pages.RootPageNode
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.plugability.configuration
-import org.jetbrains.dokka.transformers.pages.PageTransformer
-
-public open class NavigationPageInstaller(
- public val context: DokkaContext
-) : NavigationDataProvider(context), PageTransformer {
- override fun invoke(input: RootPageNode): RootPageNode =
- input.modified(
- children = input.children + NavigationPage(
- root = navigableChildren(input),
- moduleName = context.configuration.moduleName,
- context = context
- )
- )
-}
-
-public class CustomResourceInstaller(
- public val dokkaContext: DokkaContext
-) : PageTransformer {
- private val configuration = configuration<DokkaBase, DokkaBaseConfiguration>(dokkaContext)
-
- private val customAssets = configuration?.customAssets?.map {
- RendererSpecificResourcePage("images/${it.name}", emptyList(), RenderingStrategy.Copy(it.absolutePath))
- }.orEmpty()
-
- private val customStylesheets = configuration?.customStyleSheets?.map {
- RendererSpecificResourcePage("styles/${it.name}", emptyList(), RenderingStrategy.Copy(it.absolutePath))
- }.orEmpty()
-
- override fun invoke(input: RootPageNode): RootPageNode {
- val customResourcesPaths = (customAssets + customStylesheets).map { it.name }.toSet()
- val withEmbeddedResources =
- input.transformContentPagesTree { it.modified(embeddedResources = it.embeddedResources + customResourcesPaths) }
- if(dokkaContext.configuration.delayTemplateSubstitution)
- return withEmbeddedResources
- val (currentResources, otherPages) = withEmbeddedResources.children.partition { it is RendererSpecificResourcePage }
- return input.modified(children = otherPages + currentResources.filterNot { it.name in customResourcesPaths } + customAssets + customStylesheets)
- }
-}
-
-public class ScriptsInstaller(private val dokkaContext: DokkaContext) : PageTransformer {
-
- // scripts ending with `_deferred.js` are loaded with `defer`, otherwise `async`
- private val scriptsPages = listOf(
- "scripts/clipboard.js",
- "scripts/navigation-loader.js",
- "scripts/platform-content-handler.js",
- "scripts/main.js",
- "scripts/prism.js",
-
- // It's important for this script to be deferred because it has logic that makes decisions based on
- // rendered elements (for instance taking their clientWidth), and if not all styles are loaded/applied
- // at the time of inspecting them, it will give incorrect results and might lead to visual bugs.
- // should be easy to test if you open any page in incognito or by reloading it (Ctrl+Shift+R)
- "scripts/symbol-parameters-wrapper_deferred.js",
- )
-
- override fun invoke(input: RootPageNode): RootPageNode =
- input.let { root ->
- if (dokkaContext.configuration.delayTemplateSubstitution) root
- else root.modified(children = input.children + scriptsPages.toRenderSpecificResourcePage())
- }.transformContentPagesTree {
- it.modified(
- embeddedResources = it.embeddedResources + scriptsPages
- )
- }
-}
-
-public class StylesInstaller(private val dokkaContext: DokkaContext) : PageTransformer {
- private val stylesPages = listOf(
- "styles/style.css",
- "styles/main.css",
- "styles/prism.css",
- "styles/logo-styles.css",
- "styles/font-jb-sans-auto.css"
- )
-
- override fun invoke(input: RootPageNode): RootPageNode =
- input.let { root ->
- if (dokkaContext.configuration.delayTemplateSubstitution) root
- else root.modified(children = input.children + stylesPages.toRenderSpecificResourcePage())
- }.transformContentPagesTree {
- it.modified(
- embeddedResources = it.embeddedResources + stylesPages
- )
- }
-}
-
-public object AssetsInstaller : PageTransformer {
- private val imagesPages = listOf(
- "images/arrow_down.svg",
- "images/logo-icon.svg",
- "images/go-to-top-icon.svg",
- "images/footer-go-to-link.svg",
- "images/anchor-copy-button.svg",
- "images/copy-icon.svg",
- "images/copy-successful-icon.svg",
- "images/theme-toggle.svg",
- "images/burger.svg",
- "images/homepage.svg",
-
- // navigation icons
- "images/nav-icons/abstract-class.svg",
- "images/nav-icons/abstract-class-kotlin.svg",
- "images/nav-icons/annotation.svg",
- "images/nav-icons/annotation-kotlin.svg",
- "images/nav-icons/class.svg",
- "images/nav-icons/class-kotlin.svg",
- "images/nav-icons/enum.svg",
- "images/nav-icons/enum-kotlin.svg",
- "images/nav-icons/exception-class.svg",
- "images/nav-icons/field-value.svg",
- "images/nav-icons/field-variable.svg",
- "images/nav-icons/function.svg",
- "images/nav-icons/interface.svg",
- "images/nav-icons/interface-kotlin.svg",
- "images/nav-icons/object.svg",
- "images/nav-icons/typealias-kotlin.svg",
- )
-
- override fun invoke(input: RootPageNode): RootPageNode = input.modified(
- children = input.children + imagesPages.toRenderSpecificResourcePage()
- )
-}
-
-private fun List<String>.toRenderSpecificResourcePage(): List<RendererSpecificResourcePage> =
- map { RendererSpecificResourcePage(it, emptyList(), RenderingStrategy.Copy("/dokka/$it")) }
-
-public class SourcesetDependencyAppender(
- public val context: DokkaContext
-) : PageTransformer {
- private val name = "scripts/sourceset_dependencies.js"
- override fun invoke(input: RootPageNode): RootPageNode {
- val dependenciesMap = context.configuration.sourceSets.associate {
- it.sourceSetID to it.dependentSourceSets
- }
-
- fun createDependenciesJson(): String =
- dependenciesMap.map { (key, values) -> key.toString() to values.map { it.toString() } }.toMap()
- .let { content ->
- if (context.configuration.delayTemplateSubstitution) {
- toJsonString(AddToSourcesetDependencies(context.configuration.moduleName, content))
- } else {
- "sourceset_dependencies='${toJsonString(content)}'"
- }
- }
-
- val deps = RendererSpecificResourcePage(
- name = name,
- children = emptyList(),
- strategy = RenderingStrategy.Write(createDependenciesJson())
- )
-
- return input.modified(
- children = input.children + deps
- ).transformContentPagesTree { it.modified(embeddedResources = it.embeddedResources + name) }
- }
-}
diff --git a/plugins/base/src/main/kotlin/renderers/html/innerTemplating/DefaultTemplateModelFactory.kt b/plugins/base/src/main/kotlin/renderers/html/innerTemplating/DefaultTemplateModelFactory.kt
deleted file mode 100644
index fe6f0089..00000000
--- a/plugins/base/src/main/kotlin/renderers/html/innerTemplating/DefaultTemplateModelFactory.kt
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.renderers.html.innerTemplating
-
-import freemarker.core.Environment
-import freemarker.template.*
-import kotlinx.html.*
-import kotlinx.html.stream.createHTML
-import org.jetbrains.dokka.DokkaConfiguration
-import org.jetbrains.dokka.base.DokkaBase
-import org.jetbrains.dokka.base.DokkaBaseConfiguration
-import org.jetbrains.dokka.base.renderers.URIExtension
-import org.jetbrains.dokka.base.renderers.html.TEMPLATE_REPLACEMENT
-import org.jetbrains.dokka.base.renderers.html.command.consumers.ImmediateResolutionTagConsumer
-import org.jetbrains.dokka.base.renderers.html.templateCommand
-import org.jetbrains.dokka.base.renderers.html.templateCommandAsHtmlComment
-import org.jetbrains.dokka.base.renderers.isImage
-import org.jetbrains.dokka.base.resolvers.local.LocationProvider
-import org.jetbrains.dokka.base.templating.PathToRootSubstitutionCommand
-import org.jetbrains.dokka.base.templating.ProjectNameSubstitutionCommand
-import org.jetbrains.dokka.base.templating.ReplaceVersionsCommand
-import org.jetbrains.dokka.base.templating.SubstitutionCommand
-import org.jetbrains.dokka.model.DisplaySourceSet
-import org.jetbrains.dokka.model.withDescendants
-import org.jetbrains.dokka.pages.ContentPage
-import org.jetbrains.dokka.pages.PageNode
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.plugability.configuration
-import java.net.URI
-
-public class DefaultTemplateModelFactory(
- public val context: DokkaContext
-) : TemplateModelFactory {
- private val configuration = configuration<DokkaBase, DokkaBaseConfiguration>(context)
- private val isPartial = context.configuration.delayTemplateSubstitution
-
- private fun <R> TagConsumer<R>.prepareForTemplates() =
- if (context.configuration.delayTemplateSubstitution || this is ImmediateResolutionTagConsumer) this
- else ImmediateResolutionTagConsumer(this, context)
-
- public data class SourceSetModel(val name: String, val platform: String, val filter: String)
-
- override fun buildModel(
- page: PageNode,
- resources: List<String>,
- locationProvider: LocationProvider,
- content: String
- ): TemplateMap {
- val path = locationProvider.resolve(page)
- val pathToRoot = locationProvider.pathToRoot(page)
- val mapper = mutableMapOf<String, Any>()
- mapper["pageName"] = page.name
- mapper["resources"] = PrintDirective {
- val sb = StringBuilder()
- if (isPartial)
- sb.templateCommandAsHtmlComment(
- PathToRootSubstitutionCommand(
- TEMPLATE_REPLACEMENT,
- default = pathToRoot
- )
- ) { resourcesForPage(TEMPLATE_REPLACEMENT, resources) }
- else
- sb.resourcesForPage(pathToRoot, resources)
- sb.toString()
- }
- mapper["content"] = PrintDirective { content }
- mapper["version"] = PrintDirective {
- createHTML().prepareForTemplates().templateCommand(ReplaceVersionsCommand(path.orEmpty()))
- }
- mapper["template_cmd"] = TemplateDirective(context.configuration, pathToRoot)
-
- if (page is ContentPage) {
- val sourceSets = page.content.withDescendants()
- .flatMap { it.sourceSets }
- .distinct()
- .sortedBy { it.comparableKey }
- .map { SourceSetModel(it.name, it.platform.key, it.sourceSetIDs.merged.toString()) }
- .toList()
-
- if (sourceSets.isNotEmpty()) {
- mapper["sourceSets"] = sourceSets
- }
- }
- return mapper
- }
-
- override fun buildSharedModel(): TemplateMap {
- val mapper = mutableMapOf<String, Any>()
-
- mapper["footerMessage"] =
- (configuration?.footerMessage?.takeIf(String::isNotBlank) ?: DokkaBaseConfiguration.defaultFooterMessage)
-
- configuration?.homepageLink?.takeIf(String::isNotBlank)?.let { mapper["homepageLink"] = it }
-
- return mapper
- }
-
- private val DisplaySourceSet.comparableKey
- get() = sourceSetIDs.merged.let { it.scopeId + it.sourceSetName }
- private val String.isAbsolute: Boolean
- get() = URI(this).isAbsolute
-
- private fun Appendable.resourcesForPage(pathToRoot: String, resources: List<String>): Unit =
- resources.forEach { resource ->
-
- val resourceHtml = with(createHTML()) {
- when {
-
- resource.URIExtension == "css" ->
- link(
- rel = LinkRel.stylesheet,
- href = if (resource.isAbsolute) resource else "$pathToRoot$resource"
- )
-
- resource.URIExtension == "js" ->
- script(
- type = ScriptType.textJavaScript,
- src = if (resource.isAbsolute) resource else "$pathToRoot$resource"
- ) {
- if (resource == "scripts/main.js" || resource.endsWith("_deferred.js"))
- defer = true
- else
- async = true
- }
-
- resource.isImage() -> link(href = if (resource.isAbsolute) resource else "$pathToRoot$resource")
- else -> null
- }
- }
- if (resourceHtml != null) {
- append(resourceHtml)
- }
- }
-
-}
-
-private class PrintDirective(val generateData: () -> String) : TemplateDirectiveModel {
- override fun execute(
- env: Environment,
- params: MutableMap<Any?, Any?>?,
- loopVars: Array<TemplateModel>?,
- body: TemplateDirectiveBody?
- ) {
- if (params?.isNotEmpty() == true) throw TemplateModelException(
- "Parameters are not allowed"
- )
- if (loopVars?.isNotEmpty() == true) throw TemplateModelException(
- "Loop variables are not allowed"
- )
- env.out.write(generateData())
- }
-}
-
-private class TemplateDirective(
- val configuration: DokkaConfiguration,
- val pathToRoot: String
-) : TemplateDirectiveModel {
- override fun execute(
- env: Environment,
- params: MutableMap<Any?, Any?>?,
- loopVars: Array<TemplateModel>?,
- body: TemplateDirectiveBody?
- ) {
- val commandName = params?.get(PARAM_NAME) ?: throw TemplateModelException(
- "The required $PARAM_NAME parameter is missing."
- )
- val replacement = (params[PARAM_REPLACEMENT] as? SimpleScalar)?.asString ?: TEMPLATE_REPLACEMENT
-
- when ((commandName as? SimpleScalar)?.asString) {
- "pathToRoot" -> {
- body ?: throw TemplateModelException(
- "No directive body for $commandName command."
- )
- executeSubstituteCommand(
- PathToRootSubstitutionCommand(
- replacement, pathToRoot
- ),
- "pathToRoot",
- pathToRoot,
- Context(env, body)
- )
- }
-
- "projectName" -> {
- body ?: throw TemplateModelException(
- "No directive body $commandName command."
- )
- executeSubstituteCommand(
- ProjectNameSubstitutionCommand(
- replacement, configuration.moduleName
- ),
- "projectName",
- configuration.moduleName,
- Context(env, body)
- )
- }
-
- else -> throw TemplateModelException(
- "The parameter $PARAM_NAME $commandName is unknown"
- )
- }
- }
-
- private data class Context(val env: Environment, val body: TemplateDirectiveBody)
-
- private fun executeSubstituteCommand(
- command: SubstitutionCommand,
- name: String,
- value: String,
- ctx: Context
- ) {
- if (configuration.delayTemplateSubstitution)
- ctx.env.out.templateCommandAsHtmlComment(command) {
- renderWithLocalVar(name, command.pattern, ctx)
- }
- else {
- renderWithLocalVar(name, value, ctx)
- }
- }
-
- private fun renderWithLocalVar(name: String, value: String, ctx: Context) =
- with(ctx) {
- env.setVariable(name, SimpleScalar(value))
- body.render(env.out)
- env.setVariable(name, null)
- }
-
- companion object {
- const val PARAM_NAME = "name"
- const val PARAM_REPLACEMENT = "replacement"
- }
-}
diff --git a/plugins/base/src/main/kotlin/renderers/html/innerTemplating/DefaultTemplateModelMerger.kt b/plugins/base/src/main/kotlin/renderers/html/innerTemplating/DefaultTemplateModelMerger.kt
deleted file mode 100644
index 2f17183d..00000000
--- a/plugins/base/src/main/kotlin/renderers/html/innerTemplating/DefaultTemplateModelMerger.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.renderers.html.innerTemplating
-
-public class DefaultTemplateModelMerger : TemplateModelMerger {
- override fun invoke(
- factories: List<TemplateModelFactory>,
- buildModel: TemplateModelFactory.() -> TemplateMap
- ): TemplateMap {
- val mapper = mutableMapOf<String, Any?>()
- factories.map(buildModel).forEach { partialModel ->
- partialModel.forEach { (k, v) ->
- mapper[k] = v
- }
- }
- return mapper
- }
-}
diff --git a/plugins/base/src/main/kotlin/renderers/html/innerTemplating/HtmlTemplater.kt b/plugins/base/src/main/kotlin/renderers/html/innerTemplating/HtmlTemplater.kt
deleted file mode 100644
index 1638c9c0..00000000
--- a/plugins/base/src/main/kotlin/renderers/html/innerTemplating/HtmlTemplater.kt
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.renderers.html.innerTemplating
-
-import freemarker.cache.ClassTemplateLoader
-import freemarker.cache.FileTemplateLoader
-import freemarker.cache.MultiTemplateLoader
-import freemarker.log.Logger
-import freemarker.template.Configuration
-import freemarker.template.TemplateExceptionHandler
-import org.jetbrains.dokka.base.DokkaBase
-import org.jetbrains.dokka.base.DokkaBaseConfiguration
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.plugability.configuration
-import java.io.StringWriter
-
-
-public enum class DokkaTemplateTypes(
- public val path: String
-) {
- BASE("base.ftl")
-}
-
-public typealias TemplateMap = Map<String, Any?>
-
-public class HtmlTemplater(
- context: DokkaContext
-) {
-
- init {
- // to disable logging, but it isn't reliable see [Logger.SYSTEM_PROPERTY_NAME_LOGGER_LIBRARY]
- // (use SLF4j further)
- System.setProperty(
- Logger.SYSTEM_PROPERTY_NAME_LOGGER_LIBRARY,
- System.getProperty(Logger.SYSTEM_PROPERTY_NAME_LOGGER_LIBRARY) ?: Logger.LIBRARY_NAME_NONE
- )
- }
-
- private val configuration = configuration<DokkaBase, DokkaBaseConfiguration>(context)
- private val templaterConfiguration =
- Configuration(Configuration.VERSION_2_3_31).apply { configureTemplateEngine() }
-
- private fun Configuration.configureTemplateEngine() {
- val loaderFromResources = ClassTemplateLoader(javaClass, "/dokka/templates")
- templateLoader = configuration?.templatesDir?.let {
- MultiTemplateLoader(
- arrayOf(
- FileTemplateLoader(it),
- loaderFromResources
- )
- )
- } ?: loaderFromResources
-
- unsetLocale()
- defaultEncoding = "UTF-8"
- templateExceptionHandler = TemplateExceptionHandler.RETHROW_HANDLER
- logTemplateExceptions = false
- wrapUncheckedExceptions = true
- fallbackOnNullLoopVariable = false
- templateUpdateDelayMilliseconds = Long.MAX_VALUE
- }
-
- public fun setupSharedModel(model: TemplateMap) {
- templaterConfiguration.setSharedVariables(model)
- }
-
- public fun renderFromTemplate(
- templateType: DokkaTemplateTypes,
- generateModel: () -> TemplateMap
- ): String {
- val out = StringWriter()
- // Freemarker has own thread-safe cache to keep templates
- val template = templaterConfiguration.getTemplate(templateType.path)
- val model = generateModel()
- template.process(model, out)
-
- return out.toString()
- }
-}
-
diff --git a/plugins/base/src/main/kotlin/renderers/html/innerTemplating/TemplateModelFactory.kt b/plugins/base/src/main/kotlin/renderers/html/innerTemplating/TemplateModelFactory.kt
deleted file mode 100644
index 3af11bf9..00000000
--- a/plugins/base/src/main/kotlin/renderers/html/innerTemplating/TemplateModelFactory.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.renderers.html.innerTemplating
-
-import org.jetbrains.dokka.base.resolvers.local.LocationProvider
-import org.jetbrains.dokka.pages.PageNode
-
-public interface TemplateModelFactory {
- public fun buildModel(
- page: PageNode,
- resources: List<String>,
- locationProvider: LocationProvider,
- content: String
- ): TemplateMap
-
- public fun buildSharedModel(): TemplateMap
-}
diff --git a/plugins/base/src/main/kotlin/renderers/html/innerTemplating/TemplateModelMerger.kt b/plugins/base/src/main/kotlin/renderers/html/innerTemplating/TemplateModelMerger.kt
deleted file mode 100644
index ada0c6cd..00000000
--- a/plugins/base/src/main/kotlin/renderers/html/innerTemplating/TemplateModelMerger.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.renderers.html.innerTemplating
-
-public fun interface TemplateModelMerger {
- public fun invoke(factories: List<TemplateModelFactory>, buildModel: TemplateModelFactory.() -> TemplateMap): TemplateMap
-}
diff --git a/plugins/base/src/main/kotlin/renderers/html/shouldRenderSourceSetBubbles.kt b/plugins/base/src/main/kotlin/renderers/html/shouldRenderSourceSetBubbles.kt
deleted file mode 100644
index a7bafadb..00000000
--- a/plugins/base/src/main/kotlin/renderers/html/shouldRenderSourceSetBubbles.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.renderers.html
-
-import org.jetbrains.dokka.model.withDescendants
-import org.jetbrains.dokka.pages.ContentPage
-import org.jetbrains.dokka.pages.RootPageNode
-
-internal fun shouldRenderSourceSetTabs(page: RootPageNode): Boolean {
- return page.withDescendants()
- .flatMap { pageNode ->
- if (pageNode is ContentPage) pageNode.content.withDescendants()
- else emptySequence()
- }
- .flatMap { contentNode -> contentNode.sourceSets }
- .distinct()
- .count() > 1
-}
diff --git a/plugins/base/src/main/kotlin/renderers/pageId.kt b/plugins/base/src/main/kotlin/renderers/pageId.kt
deleted file mode 100644
index f5d75cfc..00000000
--- a/plugins/base/src/main/kotlin/renderers/pageId.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.renderers
-
-import org.jetbrains.dokka.base.renderers.html.NavigationNode
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.model.DisplaySourceSet
-import org.jetbrains.dokka.pages.ContentPage
-
-internal val ContentPage.pageId: String
- get() = pageId(dri.first(), sourceSets())
-
-internal val NavigationNode.pageId: String
- get() = pageId(dri, sourceSets)
-
-@JvmName("shortenSourceSetsToUrl")
-internal fun Set<DisplaySourceSet>.shortenToUrl() =
- sortedBy { it.sourceSetIDs.merged.let { it.scopeId + it.sourceSetName } }.joinToString().hashCode()
-
-internal fun DRI.shortenToUrl() = toString()
-
-@JvmName("shortenDrisToUrl")
-internal fun Set<DRI>.shortenToUrl() = sortedBy { it.toString() }.joinToString().hashCode()
-
-/**
- * Page Id is required to have a sourceSet in order to distinguish between different pages that has same DRI but different sourceSet
- * like main functions that are not expect/actual
- */
-private fun pageId(dri: DRI, sourceSets: Set<DisplaySourceSet>): String = "${dri.shortenToUrl()}/${sourceSets.shortenToUrl()}"
diff --git a/plugins/base/src/main/kotlin/renderers/preprocessors.kt b/plugins/base/src/main/kotlin/renderers/preprocessors.kt
deleted file mode 100644
index a3a32651..00000000
--- a/plugins/base/src/main/kotlin/renderers/preprocessors.kt
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.renderers
-
-import org.jetbrains.dokka.base.resolvers.shared.LinkFormat
-import org.jetbrains.dokka.pages.*
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.transformers.pages.PageTransformer
-
-public object RootCreator : PageTransformer {
- override fun invoke(input: RootPageNode): RootPageNode =
- RendererSpecificRootPage("", listOf(input), RenderingStrategy.DoNothing)
-}
-
-public class PackageListCreator(
- public val context: DokkaContext,
- public val format: LinkFormat,
- public val outputFilesNames: List<String> = listOf("package-list")
-) : PageTransformer {
- override fun invoke(input: RootPageNode): RootPageNode {
- return input.transformPageNodeTree { pageNode ->
- pageNode.takeIf { it is ModulePage }?.let { it.modified(children = it.children + packageList(input, it as ModulePage)) } ?: pageNode
- }
- }
-
- private fun packageList(rootPageNode: RootPageNode, module: ModulePage): List<RendererSpecificPage> {
- val content = PackageListService(context, rootPageNode).createPackageList(
- module,
- format
- )
- return outputFilesNames.map { fileName ->
- RendererSpecificResourcePage(
- fileName,
- emptyList(),
- RenderingStrategy.Write(content)
- )
- }
- }
-}
diff --git a/plugins/base/src/main/kotlin/resolvers/anchors/AnchorsHint.kt b/plugins/base/src/main/kotlin/resolvers/anchors/AnchorsHint.kt
deleted file mode 100644
index c9218947..00000000
--- a/plugins/base/src/main/kotlin/resolvers/anchors/AnchorsHint.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.resolvers.anchors
-
-import org.jetbrains.dokka.model.Documentable
-import org.jetbrains.dokka.model.properties.ExtraProperty
-import org.jetbrains.dokka.pages.ContentNode
-import org.jetbrains.dokka.pages.Kind
-
-public data class SymbolAnchorHint(val anchorName: String, val contentKind: Kind) : ExtraProperty<ContentNode> {
- override val key: ExtraProperty.Key<ContentNode, SymbolAnchorHint> = SymbolAnchorHint
-
- public companion object : ExtraProperty.Key<ContentNode, SymbolAnchorHint> {
- public fun from(d: Documentable, contentKind: Kind): SymbolAnchorHint? =
- d.name?.let { SymbolAnchorHint(it, contentKind) }
- }
-}
diff --git a/plugins/base/src/main/kotlin/resolvers/external/DefaultExternalLocationProvider.kt b/plugins/base/src/main/kotlin/resolvers/external/DefaultExternalLocationProvider.kt
deleted file mode 100644
index 32825303..00000000
--- a/plugins/base/src/main/kotlin/resolvers/external/DefaultExternalLocationProvider.kt
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.resolvers.external
-
-import org.jetbrains.dokka.base.resolvers.local.DokkaLocationProvider.Companion.identifierToFilename
-import org.jetbrains.dokka.base.resolvers.shared.ExternalDocumentation
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.plugability.DokkaContext
-
-public open class DefaultExternalLocationProvider(
- public val externalDocumentation: ExternalDocumentation,
- public val extension: String,
- public val dokkaContext: DokkaContext
-) : ExternalLocationProvider {
- public val docURL: String = externalDocumentation.documentationURL.toString().removeSuffix("/") + "/"
-
- override fun resolve(dri: DRI): String? {
- externalDocumentation.packageList.locations[dri.toString()]?.let { path -> return "$docURL$path" }
-
- if (dri.packageName !in externalDocumentation.packageList.packages)
- return null
-
- return dri.constructPath()
- }
-
- protected open fun DRI.constructPath(): String {
- val modulePart = packageName?.let { packageName ->
- externalDocumentation.packageList.moduleFor(packageName)?.let {
- if (it.isNotBlank())
- "$it/"
- else
- ""
- }
- }.orEmpty()
-
- val docWithModule = docURL + modulePart
- val classNamesChecked = classNames ?: return "$docWithModule${packageName ?: ""}/index$extension"
- val classLink = (listOfNotNull(packageName) + classNamesChecked.split('.'))
- .joinToString("/", transform = ::identifierToFilename)
-
- val fileName = callable?.let { identifierToFilename(it.name) } ?: "index"
- return "$docWithModule$classLink/$fileName$extension"
- }
-}
diff --git a/plugins/base/src/main/kotlin/resolvers/external/DefaultExternalLocationProviderFactory.kt b/plugins/base/src/main/kotlin/resolvers/external/DefaultExternalLocationProviderFactory.kt
deleted file mode 100644
index 09ddca01..00000000
--- a/plugins/base/src/main/kotlin/resolvers/external/DefaultExternalLocationProviderFactory.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.resolvers.external
-
-import org.jetbrains.dokka.base.resolvers.shared.RecognizedLinkFormat
-import org.jetbrains.dokka.plugability.DokkaContext
-
-public class DefaultExternalLocationProviderFactory(
- public val context: DokkaContext,
-) : ExternalLocationProviderFactory by ExternalLocationProviderFactoryWithCache(
- { doc ->
- when (doc.packageList.linkFormat) {
- RecognizedLinkFormat.KotlinWebsite,
- RecognizedLinkFormat.KotlinWebsiteHtml,
- RecognizedLinkFormat.DokkaOldHtml,
- -> Dokka010ExternalLocationProvider(doc, ".html", context)
-
- RecognizedLinkFormat.DokkaHtml -> DefaultExternalLocationProvider(doc, ".html", context)
- RecognizedLinkFormat.DokkaGFM,
- RecognizedLinkFormat.DokkaJekyll,
- -> DefaultExternalLocationProvider(doc, ".md", context)
-
- else -> null
- }
- }
-)
diff --git a/plugins/base/src/main/kotlin/resolvers/external/Dokka010ExternalLocationProvider.kt b/plugins/base/src/main/kotlin/resolvers/external/Dokka010ExternalLocationProvider.kt
deleted file mode 100644
index f887c9bc..00000000
--- a/plugins/base/src/main/kotlin/resolvers/external/Dokka010ExternalLocationProvider.kt
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.resolvers.external
-
-import org.jetbrains.dokka.base.resolvers.local.DokkaLocationProvider.Companion.identifierToFilename
-import org.jetbrains.dokka.base.resolvers.shared.ExternalDocumentation
-import org.jetbrains.dokka.links.Callable
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.plugability.DokkaContext
-
-public open class Dokka010ExternalLocationProvider(
- public val externalDocumentation: ExternalDocumentation,
- public val extension: String,
- public val dokkaContext: DokkaContext
-) : ExternalLocationProvider {
- public val docURL: String = externalDocumentation.documentationURL.toString().removeSuffix("/") + "/"
-
- override fun resolve(dri: DRI): String? {
-
- val fqName = listOfNotNull(
- dri.packageName.takeIf { it?.isNotBlank() == true },
- dri.classNames.takeIf { it?.isNotBlank() == true }?.removeCompanion()
- ).joinToString(".")
- val relocationId =
- fqName.let { if (dri.callable != null) it + "$" + dri.callable!!.toOldString() else it }
- externalDocumentation.packageList.locations[relocationId]?.let { path -> return "$docURL$path" }
-
- if (dri.packageName !in externalDocumentation.packageList.packages)
- return null
-
- val classNamesChecked = dri.classNames?.removeCompanion()
- ?: return "$docURL${dri.packageName ?: ""}/index$extension"
-
- val classLink = (listOfNotNull(dri.packageName) + classNamesChecked.split('.'))
- .joinToString("/", transform = ::identifierToFilename)
-
- val callableChecked = dri.callable ?: return "$docURL$classLink/index$extension"
- return "$docURL$classLink/" + identifierToFilename(callableChecked.name) + extension
- }
-
- private fun String.removeCompanion() = removeSuffix(".Companion")
-
- private fun Callable.toOldString() = name + params.joinToString(", ", "(", ")") + (receiver?.let { "#$it" } ?: "")
-}
diff --git a/plugins/base/src/main/kotlin/resolvers/external/ExternalLocationProvider.kt b/plugins/base/src/main/kotlin/resolvers/external/ExternalLocationProvider.kt
deleted file mode 100644
index 238b6342..00000000
--- a/plugins/base/src/main/kotlin/resolvers/external/ExternalLocationProvider.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.resolvers.external
-
-import org.jetbrains.dokka.links.DRI
-
-/**
- * Provides the path to the page documenting a [DRI] in an external documentation source
- */
-public fun interface ExternalLocationProvider {
- /**
- * @return Path to the page containing the [dri] or null if the path cannot be created
- * (eg. when the package-list does not contain [dri]'s package)
- */
- public fun resolve(dri: DRI): String?
-}
diff --git a/plugins/base/src/main/kotlin/resolvers/external/ExternalLocationProviderFactory.kt b/plugins/base/src/main/kotlin/resolvers/external/ExternalLocationProviderFactory.kt
deleted file mode 100644
index 952f4d51..00000000
--- a/plugins/base/src/main/kotlin/resolvers/external/ExternalLocationProviderFactory.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.resolvers.external
-
-import org.jetbrains.dokka.base.resolvers.shared.ExternalDocumentation
-
-public fun interface ExternalLocationProviderFactory {
- public fun getExternalLocationProvider(doc: ExternalDocumentation): ExternalLocationProvider?
-}
diff --git a/plugins/base/src/main/kotlin/resolvers/external/ExternalLocationProviderFactoryWithCache.kt b/plugins/base/src/main/kotlin/resolvers/external/ExternalLocationProviderFactoryWithCache.kt
deleted file mode 100644
index 0b56e174..00000000
--- a/plugins/base/src/main/kotlin/resolvers/external/ExternalLocationProviderFactoryWithCache.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.resolvers.external
-
-import org.jetbrains.dokka.base.resolvers.shared.ExternalDocumentation
-import java.util.concurrent.ConcurrentHashMap
-
-public class ExternalLocationProviderFactoryWithCache(
- public val ext: ExternalLocationProviderFactory
-) : ExternalLocationProviderFactory {
-
- private val locationProviders = ConcurrentHashMap<ExternalDocumentation, CacheWrapper>()
-
- override fun getExternalLocationProvider(doc: ExternalDocumentation): ExternalLocationProvider? =
- locationProviders.getOrPut(doc) { CacheWrapper(ext.getExternalLocationProvider(doc)) }.provider
-
- private class CacheWrapper(val provider: ExternalLocationProvider?)
-}
-
diff --git a/plugins/base/src/main/kotlin/resolvers/external/javadoc/AndroidExternalLocationProvider.kt b/plugins/base/src/main/kotlin/resolvers/external/javadoc/AndroidExternalLocationProvider.kt
deleted file mode 100644
index 8c18be0c..00000000
--- a/plugins/base/src/main/kotlin/resolvers/external/javadoc/AndroidExternalLocationProvider.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.resolvers.external.javadoc
-
-import org.jetbrains.dokka.base.resolvers.shared.ExternalDocumentation
-import org.jetbrains.dokka.links.Callable
-import org.jetbrains.dokka.plugability.DokkaContext
-
-public open class AndroidExternalLocationProvider(
- externalDocumentation: ExternalDocumentation,
- dokkaContext: DokkaContext
-) : JavadocExternalLocationProvider(externalDocumentation, "", "", dokkaContext) {
-
- override fun anchorPart(callable: Callable): String = callable.name.toLowerCase()
-
-}
diff --git a/plugins/base/src/main/kotlin/resolvers/external/javadoc/JavadocExternalLocationProvider.kt b/plugins/base/src/main/kotlin/resolvers/external/javadoc/JavadocExternalLocationProvider.kt
deleted file mode 100644
index 65ee0e02..00000000
--- a/plugins/base/src/main/kotlin/resolvers/external/javadoc/JavadocExternalLocationProvider.kt
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.resolvers.external.javadoc
-
-import org.jetbrains.dokka.base.resolvers.external.DefaultExternalLocationProvider
-import org.jetbrains.dokka.base.resolvers.shared.ExternalDocumentation
-import org.jetbrains.dokka.links.Callable
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.links.DRIExtraContainer
-import org.jetbrains.dokka.links.EnumEntryDRIExtra
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.utilities.htmlEscape
-
-public open class JavadocExternalLocationProvider(
- externalDocumentation: ExternalDocumentation,
- public val brackets: String,
- public val separator: String,
- dokkaContext: DokkaContext
-) : DefaultExternalLocationProvider(externalDocumentation, ".html", dokkaContext) {
-
- override fun DRI.constructPath(): String {
- val packageLink = packageName?.replace(".", "/")
- val modulePart = packageName?.let { packageName ->
- externalDocumentation.packageList.moduleFor(packageName)?.let {
- if (it.isNotBlank())
- "$it/"
- else
- ""
- }
- }.orEmpty()
-
- val docWithModule = docURL + modulePart
-
- if (classNames == null) {
- return "$docWithModule$packageLink/package-summary$extension".htmlEscape()
- }
-
- if (DRIExtraContainer(extra)[EnumEntryDRIExtra] != null) {
- val lastIndex = classNames?.lastIndexOf(".") ?: 0
- val (classSplit, enumEntityAnchor) =
- classNames?.substring(0, lastIndex) to classNames?.substring(lastIndex + 1)
-
- val classLink =
- if (packageLink == null) "${classSplit}$extension" else "$packageLink/${classSplit}$extension"
- return "$docWithModule$classLink#$enumEntityAnchor".htmlEscape()
- }
-
- val classLink = if (packageLink == null) "${classNames}$extension" else "$packageLink/${classNames}$extension"
- val callableChecked = callable ?: return "$docWithModule$classLink".htmlEscape()
-
- return ("$docWithModule$classLink#" + anchorPart(callableChecked)).htmlEscape()
- }
-
- protected open fun anchorPart(callable: Callable): String {
- return callable.name +
- "${brackets.first()}" +
- callable.params.joinToString(separator) +
- "${brackets.last()}"
- }
-}
diff --git a/plugins/base/src/main/kotlin/resolvers/external/javadoc/JavadocExternalLocationProviderFactory.kt b/plugins/base/src/main/kotlin/resolvers/external/javadoc/JavadocExternalLocationProviderFactory.kt
deleted file mode 100644
index dc184e49..00000000
--- a/plugins/base/src/main/kotlin/resolvers/external/javadoc/JavadocExternalLocationProviderFactory.kt
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.resolvers.external.javadoc
-
-import org.jetbrains.dokka.DokkaConfiguration
-import org.jetbrains.dokka.androidSdk
-import org.jetbrains.dokka.androidX
-import org.jetbrains.dokka.base.resolvers.external.ExternalLocationProviderFactory
-import org.jetbrains.dokka.base.resolvers.external.ExternalLocationProviderFactoryWithCache
-import org.jetbrains.dokka.base.resolvers.shared.RecognizedLinkFormat
-import org.jetbrains.dokka.plugability.DokkaContext
-
-public class JavadocExternalLocationProviderFactory(
- public val context: DokkaContext,
-) : ExternalLocationProviderFactory by ExternalLocationProviderFactoryWithCache(
- { doc ->
- when (doc.packageList.url) {
- DokkaConfiguration.ExternalDocumentationLink.androidX().packageListUrl,
- DokkaConfiguration.ExternalDocumentationLink.androidSdk().packageListUrl,
- ->
- AndroidExternalLocationProvider(doc, context)
-
- else ->
- when (doc.packageList.linkFormat) {
- RecognizedLinkFormat.Javadoc1 ->
- JavadocExternalLocationProvider(doc, "()", ", ", context) // Covers JDK 1 - 7
- RecognizedLinkFormat.Javadoc8 ->
- JavadocExternalLocationProvider(doc, "--", "-", context) // Covers JDK 8 - 9
- RecognizedLinkFormat.Javadoc10,
- RecognizedLinkFormat.DokkaJavadoc,
- ->
- JavadocExternalLocationProvider(doc, "()", ",", context) // Covers JDK 10
- else -> null
- }
- }
- }
-)
diff --git a/plugins/base/src/main/kotlin/resolvers/local/DefaultLocationProvider.kt b/plugins/base/src/main/kotlin/resolvers/local/DefaultLocationProvider.kt
deleted file mode 100644
index 24d0f13e..00000000
--- a/plugins/base/src/main/kotlin/resolvers/local/DefaultLocationProvider.kt
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.resolvers.local
-
-import org.jetbrains.dokka.base.DokkaBase
-import org.jetbrains.dokka.base.resolvers.external.DefaultExternalLocationProvider
-import org.jetbrains.dokka.base.resolvers.external.Dokka010ExternalLocationProvider
-import org.jetbrains.dokka.base.resolvers.external.ExternalLocationProvider
-import org.jetbrains.dokka.base.resolvers.external.ExternalLocationProviderFactory
-import org.jetbrains.dokka.base.resolvers.external.javadoc.AndroidExternalLocationProvider
-import org.jetbrains.dokka.base.resolvers.external.javadoc.JavadocExternalLocationProvider
-import org.jetbrains.dokka.base.resolvers.shared.ExternalDocumentation
-import org.jetbrains.dokka.base.resolvers.shared.PackageList
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.model.DisplaySourceSet
-import org.jetbrains.dokka.pages.RootPageNode
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.plugability.plugin
-import org.jetbrains.dokka.plugability.query
-
-public abstract class DefaultLocationProvider(
- protected val pageGraphRoot: RootPageNode,
- protected val dokkaContext: DokkaContext
-) : LocationProvider {
- protected val externalLocationProviderFactories: List<ExternalLocationProviderFactory> =
- dokkaContext.plugin<DokkaBase>().query { externalLocationProviderFactory }
-
- protected val externalLocationProviders: Map<ExternalDocumentation, ExternalLocationProvider?> = dokkaContext
- .configuration
- .sourceSets
- .flatMap { sourceSet ->
- sourceSet.externalDocumentationLinks.map {
- PackageList.load(it.packageListUrl, sourceSet.jdkVersion, dokkaContext.configuration.offlineMode)
- ?.let { packageList -> ExternalDocumentation(it.url, packageList) }
- }
- }
- .filterNotNull().associateWith { extDocInfo ->
- externalLocationProviderFactories
- .mapNotNull { it.getExternalLocationProvider(extDocInfo) }
- .firstOrNull()
- ?: run { dokkaContext.logger.error("No ExternalLocationProvider for '${extDocInfo.packageList.url}' found"); null }
- }
-
- protected val packagesIndex: Map<String, ExternalLocationProvider?> =
- externalLocationProviders
- .flatMap { (extDocInfo, externalLocationProvider) ->
- extDocInfo.packageList.packages.map { packageName -> packageName to externalLocationProvider }
- }.groupBy { it.first }.mapValues { (_, lst) ->
- lst.map { it.second }
- .sortedWith(compareBy(nullsLast(ExternalLocationProviderOrdering)) { it })
- .firstOrNull()
- }
- .filterKeys(String::isNotBlank)
-
-
- protected val locationsIndex: Map<String, ExternalLocationProvider?> = externalLocationProviders
- .flatMap { (extDocInfo, externalLocationProvider) ->
- extDocInfo.packageList.locations.keys.map { relocatedDri -> relocatedDri to externalLocationProvider }
- }
- .toMap()
- .filterKeys(String::isNotBlank)
-
- protected open fun getExternalLocation(dri: DRI, sourceSets: Set<DisplaySourceSet>): String? =
- packagesIndex[dri.packageName]?.resolve(dri)
- ?: locationsIndex[dri.toString()]?.resolve(dri)
- ?: externalLocationProviders.values.mapNotNull { it?.resolve(dri) }.firstOrNull()
-
- private object ExternalLocationProviderOrdering : Comparator<ExternalLocationProvider> {
- private val desiredOrdering = listOf(
- DefaultExternalLocationProvider::class,
- Dokka010ExternalLocationProvider::class,
- AndroidExternalLocationProvider::class,
- JavadocExternalLocationProvider::class
- )
-
- override fun compare(o1: ExternalLocationProvider, o2: ExternalLocationProvider): Int =
- desiredOrdering.indexOf(o1::class).compareTo(desiredOrdering.indexOf(o2::class))
- }
-
-}
diff --git a/plugins/base/src/main/kotlin/resolvers/local/DokkaBaseLocationProvider.kt b/plugins/base/src/main/kotlin/resolvers/local/DokkaBaseLocationProvider.kt
deleted file mode 100644
index ca3786ad..00000000
--- a/plugins/base/src/main/kotlin/resolvers/local/DokkaBaseLocationProvider.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.resolvers.local
-
-import org.jetbrains.dokka.base.renderers.shortenToUrl
-import org.jetbrains.dokka.model.DisplaySourceSet
-import org.jetbrains.dokka.pages.DCI
-import org.jetbrains.dokka.pages.RootPageNode
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.utilities.urlEncoded
-
-public abstract class DokkaBaseLocationProvider(
- pageGraphRoot: RootPageNode,
- dokkaContext: DokkaContext
-) : DefaultLocationProvider(pageGraphRoot, dokkaContext) {
-
- /**
- * Anchors should be unique and should contain sourcesets, dri and contentKind.
- * The idea is to make them as short as possible and just use a hashCode from sourcesets in order to match the
- * 2040 characters limit
- */
- public open fun anchorForDCI(dci: DCI, sourceSets: Set<DisplaySourceSet>): String =
- (dci.dri.shortenToUrl().toString() + "/" + dci.kind + "/" + sourceSets.shortenToUrl()).urlEncoded()
-
-}
diff --git a/plugins/base/src/main/kotlin/resolvers/local/DokkaLocationProvider.kt b/plugins/base/src/main/kotlin/resolvers/local/DokkaLocationProvider.kt
deleted file mode 100644
index aedbfb88..00000000
--- a/plugins/base/src/main/kotlin/resolvers/local/DokkaLocationProvider.kt
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.resolvers.local
-
-import org.jetbrains.dokka.base.renderers.sourceSets
-import org.jetbrains.dokka.base.resolvers.anchors.SymbolAnchorHint
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.links.PointingToDeclaration
-import org.jetbrains.dokka.model.*
-import org.jetbrains.dokka.pages.*
-import org.jetbrains.dokka.plugability.DokkaContext
-import java.util.*
-
-public open class DokkaLocationProvider(
- pageGraphRoot: RootPageNode,
- dokkaContext: DokkaContext,
- public val extension: String = ".html"
-) : DokkaBaseLocationProvider(pageGraphRoot, dokkaContext) {
- protected open val PAGE_WITH_CHILDREN_SUFFIX: String = "index"
-
- protected open val pathsIndex: Map<PageNode, List<String>> = IdentityHashMap<PageNode, List<String>>().apply {
- fun registerPath(page: PageNode, prefix: List<String>) {
- if (page is RootPageNode && page.forceTopLevelName) {
- put(page, prefix + PAGE_WITH_CHILDREN_SUFFIX)
- page.children.forEach { registerPath(it, prefix) }
- } else {
- val newPrefix = prefix + page.pathName
- put(page, if (page is ModulePageNode) prefix else newPrefix)
- page.children.forEach { registerPath(it, newPrefix) }
- }
-
- }
- put(pageGraphRoot, emptyList())
- pageGraphRoot.children.forEach { registerPath(it, emptyList()) }
- }
-
- protected val pagesIndex: Map<DRIWithSourceSets, ContentPage> =
- pageGraphRoot.withDescendants().filterIsInstance<ContentPage>()
- .flatMap { page ->
- page.dri.flatMap { dri ->
- page.sourceSets().ifEmpty { setOf(null) }
- .map { sourceSet -> DRIWithSourceSets(dri, setOfNotNull(sourceSet)) to page }
- .let {
- if (it.size > 1) {
- it + (DRIWithSourceSets(dri, page.sourceSets()) to page)
- } else {
- it
- }
- }
- }
- }
- .groupingBy { it.first }
- .aggregate { key, _, (_, page), first ->
- if (first) page else throw AssertionError("Multiple pages associated with key: ${key.dri}/${key.sourceSet}")
- }
-
- protected val anchorsIndex: Map<DRIWithSourceSets, PageWithKind> =
- pageGraphRoot.withDescendants().filterIsInstance<ContentPage>()
- .flatMap { page ->
- page.content.withDescendants()
- .filter { it.extra[SymbolAnchorHint] != null && it.dci.dri.any() }
- .flatMap { content ->
- content.dci.dri.map { dri ->
- (dri to content.sourceSets) to content.extra[SymbolAnchorHint]?.contentKind!!
- }
- }
- .distinct()
- .flatMap { (pair, kind) ->
- val (dri, sourceSets) = pair
- sourceSets.ifEmpty { setOf(null) }.map { sourceSet ->
- DRIWithSourceSets(dri, setOfNotNull(sourceSet)) to PageWithKind(page, kind)
- }
- }
- }.toMap()
-
- override fun resolve(node: PageNode, context: PageNode?, skipExtension: Boolean): String =
- pathTo(node, context) + if (!skipExtension) extension else ""
-
- override fun resolve(dri: DRI, sourceSets: Set<DisplaySourceSet>, context: PageNode?): String? =
- sourceSets.ifEmpty { setOf(null) }.mapNotNull { sourceSet ->
- val driWithSourceSets = DRIWithSourceSets(dri, setOfNotNull(sourceSet))
- getLocalLocation(driWithSourceSets, context)
- ?: getLocalLocation(driWithSourceSets.copy(dri = dri.copy(target = PointingToDeclaration)), context)
- // Not found in PageGraph, that means it's an external link
- ?: getExternalLocation(dri, sourceSets)
- ?: getExternalLocation(dri.copy(target = PointingToDeclaration), sourceSets)
- }.distinct().singleOrNull()
-
- private fun getLocalLocation(driWithSourceSets: DRIWithSourceSets, context: PageNode?): String? {
- val (dri, originalSourceSet) = driWithSourceSets
- val allSourceSets: List<Set<DisplaySourceSet>> =
- listOf(originalSourceSet) + originalSourceSet.let { oss ->
- val ossIds = oss.computeSourceSetIds()
- dokkaContext.configuration.sourceSets.filter { it.sourceSetID in ossIds }
- .flatMap { it.dependentSourceSets }
- .mapNotNull { ssid ->
- dokkaContext.configuration.sourceSets.find { it.sourceSetID == ssid }?.toDisplaySourceSet()
- }.map {
- setOf(it)
- }
- }
-
- return getLocalPageLink(dri, allSourceSets, context)
- ?: getLocalAnchor(dri, allSourceSets, context)
- }
-
- private fun getLocalPageLink(dri: DRI, allSourceSets: Iterable<Set<DisplaySourceSet>>, context: PageNode?) =
- allSourceSets.mapNotNull { displaySourceSet ->
- pagesIndex[DRIWithSourceSets(dri, displaySourceSet)]
- }.firstOrNull()?.let { page -> resolve(page, context) }
-
- private fun getLocalAnchor(dri: DRI, allSourceSets: Iterable<Set<DisplaySourceSet>>, context: PageNode?) =
- allSourceSets.mapNotNull { displaySourceSet ->
- anchorsIndex[DRIWithSourceSets(dri, displaySourceSet)]?.let { (page, kind) ->
- val dci = DCI(setOf(dri), kind)
- resolve(page, context) + "#" + anchorForDCI(dci, displaySourceSet)
- }
- }.firstOrNull()
-
- override fun pathToRoot(from: PageNode): String =
- pathTo(pageGraphRoot, from).removeSuffix(PAGE_WITH_CHILDREN_SUFFIX)
-
- override fun ancestors(node: PageNode): List<PageNode> =
- generateSequence(node) { it.parent() }.toList()
-
- protected open fun pathTo(node: PageNode, context: PageNode?): String {
- fun pathFor(page: PageNode) = pathsIndex[page] ?: throw AssertionError(
- "${page::class.simpleName}(${page.name}) does not belong to the current page graph so it is impossible to compute its path"
- )
-
- val nodePath = pathFor(node)
- val contextPath = context?.let { pathFor(it) }.orEmpty()
- val endedContextPath = if (context?.isIndexPage() == false)
- contextPath.toMutableList().also { it.removeLastOrNull() }
- else contextPath
-
- val commonPathElements = nodePath.asSequence().zip(endedContextPath.asSequence())
- .takeWhile { (a, b) -> a == b }.count()
-
- return (List(endedContextPath.size - commonPathElements) { ".." } + nodePath.drop(commonPathElements) +
- if (node.isIndexPage())
- listOf(PAGE_WITH_CHILDREN_SUFFIX)
- else
- emptyList()
- ).joinToString("/")
- }
-
- private fun PageNode.isIndexPage() = this is ClasslikePageNode || children.isNotEmpty()
-
- private fun PageNode.parent() = pageGraphRoot.parentMap[this]
-
- private val PageNode.pathName: String
- get() = if (this is PackagePageNode || this is RendererSpecificResourcePage) name else identifierToFilename(name)
-
- protected data class DRIWithSourceSets(val dri: DRI, val sourceSet: Set<DisplaySourceSet>)
-
- protected data class PageWithKind(val page: ContentPage, val kind: Kind)
-
- public companion object {
- public val reservedFilenames: Set<String> = setOf("index", "con", "aux", "lst", "prn", "nul", "eof", "inp", "out")
-
- //Taken from: https://stackoverflow.com/questions/1976007/what-characters-are-forbidden-in-windows-and-linux-directory-names
- internal val reservedCharacters = setOf('|', '>', '<', '*', ':', '"', '?', '%')
-
- public fun identifierToFilename(name: String): String {
- if (name.isEmpty()) return "--root--"
- return sanitizeFileName(name, reservedFilenames, reservedCharacters)
- }
- }
-}
-
-internal fun sanitizeFileName(name: String, reservedFileNames: Set<String>, reservedCharacters: Set<Char>): String {
- val lowercase = name.replace("[A-Z]".toRegex()) { matchResult -> "-" + matchResult.value.toLowerCase() }
- val withoutReservedFileNames = if (lowercase in reservedFileNames) "--$lowercase--" else lowercase
- return reservedCharacters.fold(withoutReservedFileNames) { acc, character ->
- if (character in acc) acc.replace(character.toString(), "[${character.toInt()}]")
- else acc
- }
-}
-
diff --git a/plugins/base/src/main/kotlin/resolvers/local/DokkaLocationProviderFactory.kt b/plugins/base/src/main/kotlin/resolvers/local/DokkaLocationProviderFactory.kt
deleted file mode 100644
index bd9fa1bb..00000000
--- a/plugins/base/src/main/kotlin/resolvers/local/DokkaLocationProviderFactory.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.resolvers.local
-
-import org.jetbrains.dokka.pages.RootPageNode
-import org.jetbrains.dokka.plugability.DokkaContext
-import java.util.concurrent.ConcurrentHashMap
-
-public class DokkaLocationProviderFactory(
- private val context: DokkaContext
-) : LocationProviderFactory {
- private val cache = ConcurrentHashMap<CacheWrapper, LocationProvider>()
-
- override fun getLocationProvider(pageNode: RootPageNode): LocationProvider {
- return cache.computeIfAbsent(CacheWrapper(pageNode)) {
- DokkaLocationProvider(pageNode, context)
- }
- }
-
- private class CacheWrapper(val pageNode: RootPageNode) {
- override fun equals(other: Any?) = other is CacheWrapper && other.pageNode == this.pageNode
- override fun hashCode() = System.identityHashCode(pageNode)
- }
-}
diff --git a/plugins/base/src/main/kotlin/resolvers/local/LocationProvider.kt b/plugins/base/src/main/kotlin/resolvers/local/LocationProvider.kt
deleted file mode 100644
index dbcd5c76..00000000
--- a/plugins/base/src/main/kotlin/resolvers/local/LocationProvider.kt
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.resolvers.local
-
-import org.jetbrains.dokka.DokkaException
-import org.jetbrains.dokka.base.resolvers.local.DokkaLocationProvider.Companion.identifierToFilename
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.model.DisplaySourceSet
-import org.jetbrains.dokka.pages.PageNode
-
-public interface LocationProvider {
- public fun resolve(dri: DRI, sourceSets: Set<DisplaySourceSet>, context: PageNode? = null): String?
- public fun resolve(node: PageNode, context: PageNode? = null, skipExtension: Boolean = false): String?
- public fun pathToRoot(from: PageNode): String
- public fun ancestors(node: PageNode): List<PageNode>
-
- /**
- * This method should return guessed filesystem location for a given [DRI]
- * It is used to decide if a [DRI] should be present in the relocation list of the
- * generated package-list so it is ok if the path differs from the one returned by [resolve]
- * @return Path to a giver [DRI] or null if path should not be considered for relocations
- */
- public fun expectedLocationForDri(dri: DRI): String =
- (listOf(dri.packageName) +
- dri.classNames?.split(".")?.map { identifierToFilename(it) }.orEmpty() +
- listOf(dri.callable?.let { identifierToFilename(it.name) } ?: "index")
- ).filterNotNull().joinToString("/")
-}
-
-public fun LocationProvider.resolveOrThrow(
- dri: DRI, sourceSets: Set<DisplaySourceSet>,
- context: PageNode? = null
-): String {
- return resolve(dri = dri, sourceSets = sourceSets, context = context)
- ?: throw DokkaException("Cannot resolve path for $dri")
-}
-
-public fun LocationProvider.resolveOrThrow(
- node: PageNode,
- context: PageNode? = null,
- skipExtension: Boolean = false
-): String {
- return resolve(node = node, context = context, skipExtension = skipExtension)
- ?: throw DokkaException("Cannot resolve path for ${node.name}")
-}
diff --git a/plugins/base/src/main/kotlin/resolvers/local/LocationProviderFactory.kt b/plugins/base/src/main/kotlin/resolvers/local/LocationProviderFactory.kt
deleted file mode 100644
index 31cac868..00000000
--- a/plugins/base/src/main/kotlin/resolvers/local/LocationProviderFactory.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.resolvers.local
-
-import org.jetbrains.dokka.pages.RootPageNode
-
-public fun interface LocationProviderFactory {
- public fun getLocationProvider(pageNode: RootPageNode): LocationProvider
-}
diff --git a/plugins/base/src/main/kotlin/resolvers/shared/ExternalDocumentation.kt b/plugins/base/src/main/kotlin/resolvers/shared/ExternalDocumentation.kt
deleted file mode 100644
index db0c5492..00000000
--- a/plugins/base/src/main/kotlin/resolvers/shared/ExternalDocumentation.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.resolvers.shared
-
-import java.net.URL
-
-public data class ExternalDocumentation(val documentationURL: URL, val packageList: PackageList)
diff --git a/plugins/base/src/main/kotlin/resolvers/shared/LinkFormat.kt b/plugins/base/src/main/kotlin/resolvers/shared/LinkFormat.kt
deleted file mode 100644
index 4f0d4932..00000000
--- a/plugins/base/src/main/kotlin/resolvers/shared/LinkFormat.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.resolvers.shared
-
-public interface LinkFormat {
- public val formatName: String
- public val linkExtension: String
-}
diff --git a/plugins/base/src/main/kotlin/resolvers/shared/PackageList.kt b/plugins/base/src/main/kotlin/resolvers/shared/PackageList.kt
deleted file mode 100644
index 8297f875..00000000
--- a/plugins/base/src/main/kotlin/resolvers/shared/PackageList.kt
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.resolvers.shared
-
-import java.net.URL
-
-public typealias Module = String
-
-public data class PackageList(
- val linkFormat: RecognizedLinkFormat,
- val modules: Map<Module, Set<String>>,
- val locations: Map<String, String>,
- val url: URL
-) {
- val packages: Set<String>
- get() = modules.values.flatten().toSet()
-
- public fun moduleFor(packageName: String): Module? {
- return modules.asSequence()
- .filter { it.value.contains(packageName) }
- .firstOrNull()?.key
- }
-
- public companion object {
- public const val PACKAGE_LIST_NAME: String = "package-list"
- public const val MODULE_DELIMITER: String = "module:"
- public const val DOKKA_PARAM_PREFIX: String = "\$dokka"
- public const val SINGLE_MODULE_NAME: String = ""
-
- public fun load(url: URL, jdkVersion: Int, offlineMode: Boolean = false): PackageList? {
- if (offlineMode && url.protocol.toLowerCase() != "file")
- return null
-
- val packageListStream = runCatching { url.readContent() }.onFailure {
- println("Failed to download package-list from $url, this might suggest that remote resource is not available," +
- " module is empty or dokka output got corrupted")
- return null
- }.getOrThrow()
-
- val (params, packages) = packageListStream
- .bufferedReader()
- .useLines { lines -> lines.partition { it.startsWith(DOKKA_PARAM_PREFIX) } }
-
- val paramsMap = splitParams(params)
- val format = linkFormat(paramsMap["format"]?.singleOrNull(), jdkVersion)
- val locations = splitLocations(paramsMap["location"].orEmpty()).filterKeys(String::isNotEmpty)
-
- val modulesMap = splitPackages(packages)
- return PackageList(format, modulesMap, locations, url)
- }
-
- private fun splitParams(params: List<String>) = params.asSequence()
- .map { it.removePrefix("$DOKKA_PARAM_PREFIX.").split(":", limit = 2) }
- .groupBy({ (key, _) -> key }, { (_, value) -> value })
-
- private fun splitLocations(locations: List<String>) = locations.map { it.split("\u001f", limit = 2) }
- .associate { (key, value) -> key to value }
-
- private fun splitPackages(packages: List<String>): Map<Module, Set<String>> =
- packages.fold(("" to mutableMapOf<Module, Set<String>>())) { (lastModule, acc), el ->
- val currentModule : String
- when {
- el.startsWith(MODULE_DELIMITER) -> currentModule = el.substringAfter(MODULE_DELIMITER)
- el.isNotBlank() -> {
- currentModule = lastModule
- acc[currentModule] = acc.getOrDefault(lastModule, emptySet()) + el
- }
- else -> currentModule = lastModule
- }
- currentModule to acc
- }.second
-
- private fun linkFormat(formatName: String?, jdkVersion: Int) =
- formatName?.let { RecognizedLinkFormat.fromString(it) }
- ?: when {
- jdkVersion < 8 -> RecognizedLinkFormat.Javadoc1 // Covers JDK 1 - 7
- jdkVersion < 10 -> RecognizedLinkFormat.Javadoc8 // Covers JDK 8 - 9
- else -> RecognizedLinkFormat.Javadoc10 // Covers JDK 10+
- }
- }
-}
diff --git a/plugins/base/src/main/kotlin/resolvers/shared/RecognizedLinkFormat.kt b/plugins/base/src/main/kotlin/resolvers/shared/RecognizedLinkFormat.kt
deleted file mode 100644
index 4810c9e5..00000000
--- a/plugins/base/src/main/kotlin/resolvers/shared/RecognizedLinkFormat.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.resolvers.shared
-
-public enum class RecognizedLinkFormat(
- override val formatName: String,
- override val linkExtension: String
-) : LinkFormat {
- DokkaHtml("html-v1", "html"),
- DokkaJavadoc("javadoc-v1", "html"),
- DokkaGFM("gfm-v1", "md"),
- DokkaJekyll("jekyll-v1", "html"),
- Javadoc1("javadoc1", "html"),
- Javadoc8("javadoc8", "html"),
- Javadoc10("javadoc10", "html"),
- DokkaOldHtml("html", "html"),
- KotlinWebsite("kotlin-website", "html"),
- KotlinWebsiteHtml("kotlin-website-html", "html");
-
- public companion object {
- private val values = values()
-
- public fun fromString(formatName: String): RecognizedLinkFormat? {
- return values.firstOrNull { it.formatName == formatName }
- }
- }
-}
diff --git a/plugins/base/src/main/kotlin/resolvers/shared/utils.kt b/plugins/base/src/main/kotlin/resolvers/shared/utils.kt
deleted file mode 100644
index a6d9afc6..00000000
--- a/plugins/base/src/main/kotlin/resolvers/shared/utils.kt
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.resolvers.shared
-
-import java.io.InputStream
-import java.net.HttpURLConnection
-import java.net.URL
-import java.net.URLConnection
-
-internal fun URL.readContent(timeout: Int = 10000, redirectsAllowed: Int = 16): InputStream {
- fun URL.doOpenConnection(timeout: Int, redirectsAllowed: Int): URLConnection {
- val connection = this.openConnection().apply {
- connectTimeout = timeout
- readTimeout = timeout
- }
-
- when (connection) {
- is HttpURLConnection -> return when (connection.responseCode) {
- in 200..299 -> connection
-
- HttpURLConnection.HTTP_MOVED_PERM,
- HttpURLConnection.HTTP_MOVED_TEMP,
- HttpURLConnection.HTTP_SEE_OTHER -> {
- if (redirectsAllowed > 0) {
- val newUrl = connection.getHeaderField("Location")
- URL(newUrl).doOpenConnection(timeout, redirectsAllowed - 1)
- } else {
- throw RuntimeException("Too many redirects")
- }
- }
-
- else -> throw RuntimeException("Unhandled HTTP code: ${connection.responseCode}")
- }
-
- else -> return connection
- }
- }
- return doOpenConnection(timeout, redirectsAllowed).getInputStream()
-}
diff --git a/plugins/base/src/main/kotlin/signatures/JvmSignatureUtils.kt b/plugins/base/src/main/kotlin/signatures/JvmSignatureUtils.kt
deleted file mode 100644
index e5f85803..00000000
--- a/plugins/base/src/main/kotlin/signatures/JvmSignatureUtils.kt
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.signatures
-
-import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
-import org.jetbrains.dokka.base.signatures.KotlinSignatureUtils.drisOfAllNestedBounds
-import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.model.*
-import org.jetbrains.dokka.model.AnnotationTarget
-import org.jetbrains.dokka.model.properties.WithExtraProperties
-import org.jetbrains.dokka.pages.*
-
-public interface JvmSignatureUtils {
-
- public fun PageContentBuilder.DocumentableContentBuilder.annotationsBlock(d: AnnotationTarget)
-
- public fun PageContentBuilder.DocumentableContentBuilder.annotationsInline(d: AnnotationTarget)
-
- public fun <T : Documentable> WithExtraProperties<T>.modifiers(): SourceSetDependent<Set<ExtraModifiers>>
-
- public fun Collection<ExtraModifiers>.toSignatureString(): String =
- joinToString("") { it.name.toLowerCase() + " " }
-
- @Suppress("UNCHECKED_CAST")
- public fun Documentable.annotations(): Map<DokkaSourceSet, List<Annotations.Annotation>> {
- return (this as? WithExtraProperties<Documentable>)?.annotations() ?: emptyMap()
- }
-
- public fun <T : AnnotationTarget> WithExtraProperties<T>.annotations(): SourceSetDependent<List<Annotations.Annotation>> =
- extra[Annotations]?.directAnnotations ?: emptyMap()
-
- @Suppress("UNCHECKED_CAST")
- public operator fun <T : Iterable<*>> SourceSetDependent<T>.plus(other: SourceSetDependent<T>): SourceSetDependent<T> {
- return LinkedHashMap(this).apply {
- for ((k, v) in other) {
- put(k, get(k).let { if (it != null) (it + v) as T else v })
- }
- }
- }
-
- public fun DProperty.annotations(): SourceSetDependent<List<Annotations.Annotation>> {
- return (extra[Annotations]?.directAnnotations ?: emptyMap()) +
- (getter?.annotations() ?: emptyMap()).mapValues { it.value.map { it.copy( scope = Annotations.AnnotationScope.GETTER) } } +
- (setter?.annotations() ?: emptyMap()).mapValues { it.value.map { it.copy( scope = Annotations.AnnotationScope.SETTER) } }
- }
-
- private fun PageContentBuilder.DocumentableContentBuilder.annotations(
- d: AnnotationTarget,
- ignored: Set<Annotations.Annotation>,
- styles: Set<Style>,
- operation: PageContentBuilder.DocumentableContentBuilder.(Annotations.Annotation) -> Unit
- ): Unit = when (d) {
- is DFunction -> d.annotations()
- is DProperty -> d.annotations()
- is DClass -> d.annotations()
- is DInterface -> d.annotations()
- is DObject -> d.annotations()
- is DEnum -> d.annotations()
- is DAnnotation -> d.annotations()
- is DTypeParameter -> d.annotations()
- is DEnumEntry -> d.annotations()
- is DTypeAlias -> d.annotations()
- is DParameter -> d.annotations()
- is TypeParameter -> d.annotations()
- is GenericTypeConstructor -> d.annotations()
- is FunctionalTypeConstructor -> d.annotations()
- is JavaObject -> d.annotations()
- else -> null
- }?.let {
- it.entries.forEach {
- it.value.filter { it !in ignored && it.mustBeDocumented }.takeIf { it.isNotEmpty() }?.let { annotations ->
- group(sourceSets = setOf(it.key), styles = styles, kind = ContentKind.Annotations) {
- annotations.forEach {
- operation(it)
- }
- }
- }
- }
- } ?: Unit
-
- public fun PageContentBuilder.DocumentableContentBuilder.toSignatureString(
- a: Annotations.Annotation,
- renderAtStrategy: AtStrategy,
- listBrackets: Pair<Char, Char>,
- classExtension: String
- ) {
-
- when (renderAtStrategy) {
- is All, is OnlyOnce -> {
- when(a.scope) {
- Annotations.AnnotationScope.GETTER -> text("@get:", styles = mainStyles + TokenStyle.Annotation)
- Annotations.AnnotationScope.SETTER -> text("@set:", styles = mainStyles + TokenStyle.Annotation)
- else -> text("@", styles = mainStyles + TokenStyle.Annotation)
- }
- link(a.dri.classNames!!, a.dri, styles = mainStyles + TokenStyle.Annotation)
- }
- is Never -> link(a.dri.classNames!!, a.dri)
- }
- val isNoWrappedBrackets = a.params.entries.isEmpty() && renderAtStrategy is OnlyOnce
- listParams(
- a.params.entries,
- if (isNoWrappedBrackets) null else Pair('(', ')')
- ) {
- text(it.key)
- text(" = ", styles = mainStyles + TokenStyle.Operator)
- when (renderAtStrategy) {
- is All -> All
- is Never, is OnlyOnce -> Never
- }.let { strategy ->
- valueToSignature(it.value, strategy, listBrackets, classExtension)
- }
- }
- }
-
- private fun PageContentBuilder.DocumentableContentBuilder.valueToSignature(
- a: AnnotationParameterValue,
- renderAtStrategy: AtStrategy,
- listBrackets: Pair<Char, Char>,
- classExtension: String
- ): Unit = when (a) {
- is AnnotationValue -> toSignatureString(a.annotation, renderAtStrategy, listBrackets, classExtension)
- is ArrayValue -> {
- listParams(a.value, listBrackets) { valueToSignature(it, renderAtStrategy, listBrackets, classExtension) }
- }
- is EnumValue -> link(a.enumName, a.enumDri)
- is ClassValue -> link(a.className + classExtension, a.classDRI)
- is StringValue -> group(styles = setOf(TextStyle.Breakable)) { stringLiteral( "\"${a.text()}\"") }
- is BooleanValue -> group(styles = setOf(TextStyle.Breakable)) { booleanLiteral(a.value) }
- is LiteralValue -> group(styles = setOf(TextStyle.Breakable)) { constant(a.text()) }
- }
-
- private fun<T> PageContentBuilder.DocumentableContentBuilder.listParams(
- params: Collection<T>,
- listBrackets: Pair<Char, Char>?,
- outFn: PageContentBuilder.DocumentableContentBuilder.(T) -> Unit
- ) {
- listBrackets?.let{ punctuation(it.first.toString()) }
- params.forEachIndexed { i, it ->
- group(styles = setOf(TextStyle.BreakableAfter)) {
- this.outFn(it)
- if (i != params.size - 1) punctuation(", ")
- }
- }
- listBrackets?.let{ punctuation(it.second.toString()) }
- }
-
- public fun PageContentBuilder.DocumentableContentBuilder.annotationsBlockWithIgnored(
- d: AnnotationTarget,
- ignored: Set<Annotations.Annotation>,
- renderAtStrategy: AtStrategy,
- listBrackets: Pair<Char, Char>,
- classExtension: String
- ) {
- annotations(d, ignored, setOf(TextStyle.Block)) {
- group {
- toSignatureString(it, renderAtStrategy, listBrackets, classExtension)
- }
- }
- }
-
- public fun PageContentBuilder.DocumentableContentBuilder.annotationsInlineWithIgnored(
- d: AnnotationTarget,
- ignored: Set<Annotations.Annotation>,
- renderAtStrategy: AtStrategy,
- listBrackets: Pair<Char, Char>,
- classExtension: String
- ) {
- annotations(d, ignored, setOf(TextStyle.Span)) {
- toSignatureString(it, renderAtStrategy, listBrackets, classExtension)
- text(Typography.nbsp.toString())
- }
- }
-
- public fun <T : Documentable> WithExtraProperties<T>.stylesIfDeprecated(sourceSetData: DokkaSourceSet): Set<TextStyle> {
- val directAnnotations = extra[Annotations]?.directAnnotations?.get(sourceSetData) ?: emptyList()
- val hasAnyDeprecatedAnnotation =
- directAnnotations.any { it.dri == DRI("kotlin", "Deprecated") || it.dri == DRI("java.lang", "Deprecated") }
-
- return if (hasAnyDeprecatedAnnotation) setOf(TextStyle.Strikethrough) else emptySet()
- }
-
- public infix fun DFunction.uses(typeParameter: DTypeParameter): Boolean {
- val parameterDris = parameters.flatMap { listOf(it.dri) + it.type.drisOfAllNestedBounds }
- val receiverDris =
- listOfNotNull(
- receiver?.dri,
- *receiver?.type?.drisOfAllNestedBounds?.toTypedArray() ?: emptyArray()
- )
- val allDris = parameterDris + receiverDris
- return typeParameter.dri in allDris
- }
-
- /**
- * Builds a distinguishable [function] parameters block, so that it
- * can be processed or custom rendered down the road.
- *
- * Resulting structure:
- * ```
- * SymbolContentKind.Parameters(style = wrapped) {
- * SymbolContentKind.Parameter(style = indented) { param, }
- * SymbolContentKind.Parameter(style = indented) { param, }
- * SymbolContentKind.Parameter(style = indented) { param }
- * }
- * ```
- * Wrapping and indentation of parameters is applied conditionally, see [shouldWrapParams]
- */
- public fun PageContentBuilder.DocumentableContentBuilder.parametersBlock(
- function: DFunction,
- paramBuilder: PageContentBuilder.DocumentableContentBuilder.(DParameter) -> Unit
- ) {
- group(kind = SymbolContentKind.Parameters, styles = emptySet()) {
- function.parameters.dropLast(1).forEach {
- group(kind = SymbolContentKind.Parameter) {
- paramBuilder(it)
- punctuation(", ")
- }
- }
- group(kind = SymbolContentKind.Parameter) {
- paramBuilder(function.parameters.last())
- }
- }
- }
-}
-
-public sealed class AtStrategy
-public object All : AtStrategy()
-public object OnlyOnce : AtStrategy()
-public object Never : AtStrategy()
diff --git a/plugins/base/src/main/kotlin/signatures/KotlinSignatureProvider.kt b/plugins/base/src/main/kotlin/signatures/KotlinSignatureProvider.kt
deleted file mode 100644
index 2180e776..00000000
--- a/plugins/base/src/main/kotlin/signatures/KotlinSignatureProvider.kt
+++ /dev/null
@@ -1,503 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.signatures
-
-import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
-import org.jetbrains.dokka.Platform
-import org.jetbrains.dokka.base.DokkaBase
-import org.jetbrains.dokka.base.signatures.KotlinSignatureUtils.dri
-import org.jetbrains.dokka.base.signatures.KotlinSignatureUtils.driOrNull
-import org.jetbrains.dokka.base.transformers.pages.comments.CommentsToContentConverter
-import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder
-import org.jetbrains.dokka.links.*
-import org.jetbrains.dokka.model.*
-import org.jetbrains.dokka.model.Nullable
-import org.jetbrains.dokka.model.TypeConstructor
-import org.jetbrains.dokka.model.properties.WithExtraProperties
-import org.jetbrains.dokka.pages.*
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.plugability.plugin
-import org.jetbrains.dokka.plugability.querySingle
-import org.jetbrains.dokka.utilities.DokkaLogger
-import kotlin.text.Typography.nbsp
-
-public class KotlinSignatureProvider(
- ctcc: CommentsToContentConverter,
- logger: DokkaLogger
-) : SignatureProvider, JvmSignatureUtils by KotlinSignatureUtils {
-
- public constructor(context: DokkaContext) : this(
- context.plugin<DokkaBase>().querySingle { commentsToContentConverter },
- context.logger,
- )
-
- private val contentBuilder = PageContentBuilder(ctcc, this, logger)
-
- private val ignoredVisibilities = setOf(JavaVisibility.Public, KotlinVisibility.Public)
- private val ignoredModifiers = setOf(JavaModifier.Final, KotlinModifier.Final)
- private val ignoredExtraModifiers = setOf(
- ExtraModifiers.KotlinOnlyModifiers.TailRec,
- ExtraModifiers.KotlinOnlyModifiers.External
- )
- private val platformSpecificModifiers: Map<ExtraModifiers, Set<Platform>> = mapOf(
- ExtraModifiers.KotlinOnlyModifiers.External to setOf(Platform.js, Platform.wasm)
- )
-
- override fun signature(documentable: Documentable): List<ContentNode> = when (documentable) {
- is DFunction -> functionSignature(documentable)
- is DProperty -> propertySignature(documentable)
- is DClasslike -> classlikeSignature(documentable)
- is DTypeParameter -> signature(documentable)
- is DEnumEntry -> signature(documentable)
- is DTypeAlias -> signature(documentable)
- else -> throw NotImplementedError(
- "Cannot generate signature for ${documentable::class.qualifiedName} ${documentable.name}"
- )
- }
-
- private fun <T> PageContentBuilder.DocumentableContentBuilder.processExtraModifiers(t: T)
- where T : Documentable, T : WithExtraProperties<T> {
- sourceSetDependentText(
- t.modifiers()
- .mapValues { entry ->
- entry.value.filter {
- it !in ignoredExtraModifiers || entry.key.analysisPlatform in (platformSpecificModifiers[it]
- ?: emptySet())
- }
- }, styles = mainStyles + TokenStyle.Keyword
- ) {
- it.toSignatureString()
- }
- }
-
- private fun signature(e: DEnumEntry): List<ContentNode> =
- e.sourceSets.map {
- contentBuilder.contentFor(
- e,
- ContentKind.Symbol,
- setOf(TextStyle.Monospace),
- sourceSets = setOf(it)
- ) {
- group(styles = setOf(TextStyle.Block)) {
- annotationsBlock(e)
- link(e.name, e.dri, styles = mainStyles + e.stylesIfDeprecated(it))
- }
- }
- }
-
- private fun classlikeSignature(c: DClasslike): List<ContentNode> {
- @Suppress("UNCHECKED_CAST")
- val typeAlias = (c as? WithExtraProperties<DClasslike>)
- ?.extra
- ?.get(ActualTypealias)
- ?.typeAlias
-
- return c.sourceSets.map { sourceSetData ->
- if (typeAlias != null && sourceSetData in typeAlias.sourceSets) {
- regularSignature(typeAlias, sourceSetData)
- } else {
- regularSignature(c, sourceSetData)
- }
- }
- }
-
- private fun <T : Documentable> PageContentBuilder.DocumentableContentBuilder.defaultValueAssign(
- d: WithExtraProperties<T>,
- sourceSet: DokkaSourceSet
- ) {
- // a default value of parameter can be got from expect source set
- // but expect properties cannot have a default value
- d.extra[DefaultValue]?.expression?.let {
- it[sourceSet] ?: if (d is DParameter) it[d.expectPresentInSet] else null
- }?.let { expr ->
- operator(" = ")
- highlightValue(expr)
- }
- }
-
- private fun regularSignature(c: DClasslike, sourceSet: DokkaSourceSet): ContentGroup {
- @Suppress("UNCHECKED_CAST")
- val deprecationStyles = (c as? WithExtraProperties<out Documentable>)
- ?.stylesIfDeprecated(sourceSet)
- ?: emptySet()
-
- return contentBuilder.contentFor(
- c,
- ContentKind.Symbol,
- setOf(TextStyle.Monospace),
- sourceSets = setOf(sourceSet)
- ) {
- annotationsBlock(c)
- c.visibility[sourceSet]?.takeIf { it !in ignoredVisibilities }?.name?.let { keyword("$it ") }
- if (c.isExpectActual) keyword(if (sourceSet == c.expectPresentInSet) "expect " else "actual ")
- if (c is DClass) {
- val modifier =
- if (c.modifier[sourceSet] !in ignoredModifiers) {
- when {
- c.extra[AdditionalModifiers]?.content?.get(sourceSet)?.contains(ExtraModifiers.KotlinOnlyModifiers.Data) == true -> ""
- c.modifier[sourceSet] is JavaModifier.Empty -> "${KotlinModifier.Open.name} "
- else -> c.modifier[sourceSet]?.name?.let { "$it " }
- }
- } else {
- null
- }
- modifier?.takeIf { it.isNotEmpty() }?.let { keyword(it) }
- }
- when (c) {
- is DClass -> {
- processExtraModifiers(c)
- keyword("class ")
- }
- is DInterface -> {
- processExtraModifiers(c)
- keyword("interface ")
- }
- is DEnum -> {
- processExtraModifiers(c)
- keyword("enum ")
- }
- is DObject -> {
- processExtraModifiers(c)
- keyword("object ")
- }
- is DAnnotation -> {
- processExtraModifiers(c)
- keyword("annotation class ")
- }
- }
- link(c.name!!, c.dri, styles = mainStyles + deprecationStyles)
- if (c is WithGenerics) {
- list(c.generics, prefix = "<", suffix = ">",
- separatorStyles = mainStyles + TokenStyle.Punctuation,
- surroundingCharactersStyle = mainStyles + TokenStyle.Operator) {
- annotationsInline(it)
- +buildSignature(it)
- }
- }
- if (c is WithConstructors) {
- val pConstructor = c.constructors.singleOrNull { it.extra[PrimaryConstructorExtra] != null }
- if (pConstructor?.sourceSets?.contains(sourceSet) == true) {
- if (pConstructor.annotations().values.any { it.isNotEmpty() }) {
- text(nbsp.toString())
- annotationsInline(pConstructor)
- keyword("constructor")
- }
-
- // for primary constructor, opening and closing parentheses
- // should be present only if it has parameters. If there are
- // no parameters, it should result in `class Example`
- if (pConstructor.parameters.isNotEmpty()) {
- val parameterPropertiesByName = c.properties
- .filter { it.isAlsoParameter(sourceSet) }
- .associateBy { it.name }
-
- punctuation("(")
- parametersBlock(pConstructor) { param ->
- annotationsInline(param)
- parameterPropertiesByName[param.name]?.let { property ->
- property.setter?.let { keyword("var ") } ?: keyword("val ")
- }
- text(param.name.orEmpty())
- operator(": ")
- signatureForProjection(param.type)
- defaultValueAssign(param, sourceSet)
- }
- punctuation(")")
- }
- }
- }
- if (c is WithSupertypes) {
- c.supertypes.filter { it.key == sourceSet }.map { (s, typeConstructors) ->
- list(typeConstructors, prefix = " : ", sourceSets = setOf(s)) {
- link(it.typeConstructor.dri.sureClassNames, it.typeConstructor.dri, sourceSets = setOf(s))
- list(it.typeConstructor.projections, prefix = "<", suffix = "> ",
- separatorStyles = mainStyles + TokenStyle.Punctuation,
- surroundingCharactersStyle = mainStyles + TokenStyle.Operator) {
- signatureForProjection(it)
- }
- }
- }
- }
- }
- }
-
- /**
- * An example would be a primary constructor `class A(val s: String)`,
- * where `s` is both a function parameter and a property
- */
- private fun DProperty.isAlsoParameter(sourceSet: DokkaSourceSet): Boolean {
- return this.extra[IsAlsoParameter]
- ?.inSourceSets
- ?.any { it.sourceSetID == sourceSet.sourceSetID }
- ?: false
- }
-
- private fun propertySignature(p: DProperty) =
- p.sourceSets.map { sourceSet ->
- contentBuilder.contentFor(
- p,
- ContentKind.Symbol,
- setOf(TextStyle.Monospace),
- sourceSets = setOf(sourceSet)
- ) {
- annotationsBlock(p)
- p.visibility[sourceSet].takeIf { it !in ignoredVisibilities }?.name?.let { keyword("$it ") }
- if (p.isExpectActual) keyword(if (sourceSet == p.expectPresentInSet) "expect " else "actual ")
- p.modifier[sourceSet].takeIf { it !in ignoredModifiers }?.let {
- if (it is JavaModifier.Empty) KotlinModifier.Open else it
- }?.name?.let { keyword("$it ") }
- p.modifiers()[sourceSet]?.toSignatureString()?.let { keyword(it) }
- if (p.isMutable()) keyword("var ") else keyword("val ")
- list(p.generics, prefix = "<", suffix = "> ",
- separatorStyles = mainStyles + TokenStyle.Punctuation,
- surroundingCharactersStyle = mainStyles + TokenStyle.Operator) {
- annotationsInline(it)
- +buildSignature(it)
- }
- p.receiver?.also {
- signatureForProjection(it.type)
- punctuation(".")
- }
- link(p.name, p.dri, styles = mainStyles + p.stylesIfDeprecated(sourceSet))
- operator(": ")
- signatureForProjection(p.type)
-
- if (p.isNotMutable()) {
- defaultValueAssign(p, sourceSet)
- }
- }
- }
-
- private fun DProperty.isNotMutable(): Boolean = !isMutable()
-
- private fun DProperty.isMutable(): Boolean {
- return this.extra[IsVar] != null || this.setter != null
- }
-
- private fun PageContentBuilder.DocumentableContentBuilder.highlightValue(expr: Expression) = when (expr) {
- is IntegerConstant -> constant(expr.value.toString())
- is FloatConstant -> constant(expr.value.toString() + "f")
- is DoubleConstant -> constant(expr.value.toString())
- is BooleanConstant -> booleanLiteral(expr.value)
- is StringConstant -> stringLiteral("\"${expr.value}\"")
- is ComplexExpression -> text(expr.value)
- else -> Unit
- }
-
- private fun functionSignature(f: DFunction) =
- f.sourceSets.map { sourceSet ->
- contentBuilder.contentFor(
- f,
- ContentKind.Symbol,
- setOf(TextStyle.Monospace),
- sourceSets = setOf(sourceSet)
- ) {
- annotationsBlock(f)
- f.visibility[sourceSet]?.takeIf { it !in ignoredVisibilities }?.name?.let { keyword("$it ") }
- if (f.isExpectActual) keyword(if (sourceSet == f.expectPresentInSet) "expect " else "actual ")
- if (f.isConstructor) {
- keyword("constructor")
- } else {
- f.modifier[sourceSet]?.takeIf { it !in ignoredModifiers }?.let {
- if (it is JavaModifier.Empty) KotlinModifier.Open else it
- }?.name?.let { keyword("$it ") }
- f.modifiers()[sourceSet]?.toSignatureString()?.let { keyword(it) }
- keyword("fun ")
- list(
- f.generics, prefix = "<", suffix = "> ",
- separatorStyles = mainStyles + TokenStyle.Punctuation,
- surroundingCharactersStyle = mainStyles + TokenStyle.Operator
- ) {
- annotationsInline(it)
- +buildSignature(it)
- }
- f.receiver?.also {
- signatureForProjection(it.type)
- punctuation(".")
- }
- link(f.name, f.dri, styles = mainStyles + TokenStyle.Function + f.stylesIfDeprecated(sourceSet))
- }
- // for a function, opening and closing parentheses must be present
- // anyway, even if it has no parameters, resulting in `fun test(): R`
- punctuation("(")
- if (f.parameters.isNotEmpty()) {
- parametersBlock(f) { param ->
- annotationsInline(param)
- processExtraModifiers(param)
- text(param.name!!)
- operator(": ")
- signatureForProjection(param.type)
- defaultValueAssign(param, sourceSet)
- }
- }
- punctuation(")")
- if (f.documentReturnType()) {
- operator(": ")
- signatureForProjection(f.type)
- }
- }
- }
-
- private fun DFunction.documentReturnType() = when {
- this.isConstructor -> false
- this.type is TypeConstructor && (this.type as TypeConstructor).dri == DriOfUnit -> false
- this.type is Void -> false
- else -> true
- }
-
- private fun signature(t: DTypeAlias) =
- t.sourceSets.map {
- regularSignature(t, it)
- }
-
- private fun regularSignature(
- t: DTypeAlias,
- sourceSet: DokkaSourceSet
- ) = contentBuilder.contentFor(t, sourceSets = setOf(sourceSet)) {
- t.underlyingType.entries.groupBy({ it.value }, { it.key }).map { (type, platforms) ->
- +contentBuilder.contentFor(
- t,
- ContentKind.Symbol,
- setOf(TextStyle.Monospace),
- sourceSets = platforms.toSet()
- ) {
- annotationsBlock(t)
- t.visibility[sourceSet]?.takeIf { it !in ignoredVisibilities }?.name?.let { keyword("$it ") }
- if (t.expectPresentInSet != null) keyword("actual ")
- processExtraModifiers(t)
- keyword("typealias ")
- group(styles = mainStyles + t.stylesIfDeprecated(sourceSet)) {
- signatureForProjection(t.type)
- }
- operator(" = ")
- signatureForTypealiasTarget(t, type)
- }
- }
- }
-
- private fun signature(t: DTypeParameter) =
- t.sourceSets.map {
- contentBuilder.contentFor(t, sourceSets = setOf(it)) {
- group(styles = mainStyles + t.stylesIfDeprecated(it)) {
- signatureForProjection(t.variantTypeParameter.withDri(t.dri.withTargetToDeclaration()))
- }
- list(
- elements = t.nontrivialBounds,
- prefix = " : ",
- surroundingCharactersStyle = mainStyles + TokenStyle.Operator
- ) { bound ->
- signatureForProjection(bound)
- }
- }
- }
-
- private fun PageContentBuilder.DocumentableContentBuilder.signatureForTypealiasTarget(
- typeAlias: DTypeAlias, bound: Bound
- ) {
- signatureForProjection(
- p = bound,
- showFullyQualifiedName = bound.driOrNull?.classNames == typeAlias.dri.classNames
- )
- }
-
- private fun PageContentBuilder.DocumentableContentBuilder.signatureForProjection(
- p: Projection, showFullyQualifiedName: Boolean = false
- ) {
- return when (p) {
- is TypeParameter -> {
- if (p.presentableName != null) {
- text(p.presentableName!!)
- operator(": ")
- }
- annotationsInline(p)
- link(p.name, p.dri)
- }
- is FunctionalTypeConstructor -> +funType(mainDRI.single(), mainSourcesetData, p)
- is GenericTypeConstructor ->
- group(styles = emptySet()) {
- val linkText = if (showFullyQualifiedName && p.dri.packageName != null) {
- "${p.dri.packageName}.${p.dri.classNames.orEmpty()}"
- } else p.dri.classNames.orEmpty()
- if (p.presentableName != null) {
- text(p.presentableName!!)
- operator(": ")
- }
- annotationsInline(p)
- link(linkText, p.dri)
- list(p.projections, prefix = "<", suffix = ">",
- separatorStyles = mainStyles + TokenStyle.Punctuation,
- surroundingCharactersStyle = mainStyles + TokenStyle.Operator) {
- signatureForProjection(it, showFullyQualifiedName)
- }
- }
-
- is Variance<*> -> group(styles = emptySet()) {
- keyword("$p ".takeIf { it.isNotBlank() } ?: "")
- signatureForProjection(p.inner, showFullyQualifiedName)
- }
-
- is Star -> operator("*")
-
- is Nullable -> group(styles = emptySet()) {
- signatureForProjection(p.inner, showFullyQualifiedName)
- operator("?")
- }
- is DefinitelyNonNullable -> group(styles = emptySet()) {
- signatureForProjection(p.inner, showFullyQualifiedName)
- operator(" & ")
- link("Any", DriOfAny)
- }
-
- is TypeAliased -> signatureForProjection(p.typeAlias)
- is JavaObject -> {
- annotationsInline(p)
- link("Any", DriOfAny)
- }
- is Void -> link("Unit", DriOfUnit)
- is PrimitiveJavaType -> signatureForProjection(p.translateToKotlin(), showFullyQualifiedName)
- is Dynamic -> text("dynamic")
- is UnresolvedBound -> text(p.name)
- }
- }
-
- private fun funType(dri: DRI, sourceSets: Set<DokkaSourceSet>, type: FunctionalTypeConstructor) =
- contentBuilder.contentFor(dri, sourceSets, ContentKind.Main) {
-
- if (type.presentableName != null) {
- text(type.presentableName!!)
- operator(": ")
- }
- annotationsInline(type)
- if (type.isSuspendable) keyword("suspend ")
-
- if (type.isExtensionFunction) {
- signatureForProjection(type.projections.first())
- punctuation(".")
- }
-
- val args = if (type.isExtensionFunction)
- type.projections.drop(1)
- else
- type.projections
-
- punctuation("(")
- args.subList(0, args.size - 1).forEachIndexed { i, arg ->
- signatureForProjection(arg)
- if (i < args.size - 2) punctuation(", ")
- }
- punctuation(")")
- operator(" -> ")
- signatureForProjection(args.last())
- }
-}
-
-private fun PrimitiveJavaType.translateToKotlin() = GenericTypeConstructor(
- dri = dri,
- projections = emptyList(),
- presentableName = null
-)
-
-private val DTypeParameter.nontrivialBounds: List<Bound>
- get() = bounds.filterNot { it is Nullable && it.inner.driOrNull == DriOfAny }
diff --git a/plugins/base/src/main/kotlin/signatures/KotlinSignatureUtils.kt b/plugins/base/src/main/kotlin/signatures/KotlinSignatureUtils.kt
deleted file mode 100644
index f16fbeb0..00000000
--- a/plugins/base/src/main/kotlin/signatures/KotlinSignatureUtils.kt
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.signatures
-
-import org.jetbrains.dokka.DokkaConfiguration
-import org.jetbrains.dokka.base.transformers.pages.annotations.SinceKotlinTransformer
-import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.links.DriOfAny
-import org.jetbrains.dokka.links.DriOfUnit
-import org.jetbrains.dokka.model.*
-import org.jetbrains.dokka.model.AnnotationTarget
-import org.jetbrains.dokka.model.properties.WithExtraProperties
-import org.jetbrains.dokka.pages.ContentKind
-
-public object KotlinSignatureUtils : JvmSignatureUtils {
-
- private const val classExtension = "::class"
- private val strategy = OnlyOnce
- private val listBrackets = Pair('[', ']')
- private val ignoredAnnotations = setOf(
- /**
- * Rendered separately, see [SinceKotlinTransformer]
- */
- Annotations.Annotation(DRI("kotlin", "SinceKotlin"), emptyMap()),
-
- /**
- * Rendered separately as its own block, see usage of [ContentKind.Deprecation]
- */
- Annotations.Annotation(DRI("kotlin", "Deprecated"), emptyMap()),
- Annotations.Annotation(DRI("kotlin", "DeprecatedSinceKotlin"), emptyMap()),
- Annotations.Annotation(DRI("java.lang", "Deprecated"), emptyMap()), // could be used as well for interop
- )
-
-
- override fun PageContentBuilder.DocumentableContentBuilder.annotationsBlock(d: AnnotationTarget) {
- annotationsBlockWithIgnored(d, ignoredAnnotations, strategy, listBrackets, classExtension)
- }
-
- override fun PageContentBuilder.DocumentableContentBuilder.annotationsInline(d: AnnotationTarget) {
- annotationsInlineWithIgnored(d, ignoredAnnotations, strategy, listBrackets, classExtension)
- }
-
- override fun <T : Documentable> WithExtraProperties<T>.modifiers(): SourceSetDependent<Set<ExtraModifiers>> {
- return extra[AdditionalModifiers]?.content?.entries?.associate {
- it.key to it.value.filterIsInstance<ExtraModifiers.KotlinOnlyModifiers>().toSet()
- } ?: emptyMap()
- }
-
-
- public val PrimitiveJavaType.dri: DRI get() = DRI("kotlin", name.capitalize())
-
- public val Bound.driOrNull: DRI?
- get() {
- return when (this) {
- is TypeParameter -> dri
- is TypeConstructor -> dri
- is Nullable -> inner.driOrNull
- is DefinitelyNonNullable -> inner.driOrNull
- is PrimitiveJavaType -> dri
- is Void -> DriOfUnit
- is JavaObject -> DriOfAny
- is Dynamic -> null
- is UnresolvedBound -> null
- is TypeAliased -> typeAlias.driOrNull
- }
- }
-
- public val Projection.drisOfAllNestedBounds: List<DRI> get() = when (this) {
- is TypeParameter -> listOf(dri)
- is TypeConstructor -> listOf(dri) + projections.flatMap { it.drisOfAllNestedBounds }
- is Nullable -> inner.drisOfAllNestedBounds
- is DefinitelyNonNullable -> inner.drisOfAllNestedBounds
- is PrimitiveJavaType -> listOf(dri)
- is Void -> listOf(DriOfUnit)
- is JavaObject -> listOf(DriOfAny)
- is Dynamic -> emptyList()
- is UnresolvedBound -> emptyList()
- is Variance<*> -> inner.drisOfAllNestedBounds
- is Star -> emptyList()
- is TypeAliased -> listOfNotNull(typeAlias.driOrNull, inner.driOrNull)
- }
-
-}
diff --git a/plugins/base/src/main/kotlin/signatures/SignatureProvider.kt b/plugins/base/src/main/kotlin/signatures/SignatureProvider.kt
deleted file mode 100644
index 76245a40..00000000
--- a/plugins/base/src/main/kotlin/signatures/SignatureProvider.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.signatures
-
-import org.jetbrains.dokka.model.Documentable
-import org.jetbrains.dokka.pages.ContentNode
-
-public fun interface SignatureProvider {
- public fun signature(documentable: Documentable): List<ContentNode>
-}
diff --git a/plugins/base/src/main/kotlin/templating/AddToNavigationCommand.kt b/plugins/base/src/main/kotlin/templating/AddToNavigationCommand.kt
deleted file mode 100644
index 03bf8e6a..00000000
--- a/plugins/base/src/main/kotlin/templating/AddToNavigationCommand.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.templating
-
-public class AddToNavigationCommand(
- public val moduleName: String
-) : Command
diff --git a/plugins/base/src/main/kotlin/templating/AddToSearch.kt b/plugins/base/src/main/kotlin/templating/AddToSearch.kt
deleted file mode 100644
index 8c2ccc79..00000000
--- a/plugins/base/src/main/kotlin/templating/AddToSearch.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.templating
-
-import org.jetbrains.dokka.base.renderers.html.SearchRecord
-
-public data class AddToSearch(
- val moduleName: String,
- val elements: List<SearchRecord>
-): Command
diff --git a/plugins/base/src/main/kotlin/templating/AddToSourcesetDependencies.kt b/plugins/base/src/main/kotlin/templating/AddToSourcesetDependencies.kt
deleted file mode 100644
index c9774e30..00000000
--- a/plugins/base/src/main/kotlin/templating/AddToSourcesetDependencies.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.templating
-
-public data class AddToSourcesetDependencies(
- val moduleName: String,
- val content: Map<String, List<String>>
-) : Command
diff --git a/plugins/base/src/main/kotlin/templating/Command.kt b/plugins/base/src/main/kotlin/templating/Command.kt
deleted file mode 100644
index 94ed00d4..00000000
--- a/plugins/base/src/main/kotlin/templating/Command.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.templating
-
-import com.fasterxml.jackson.annotation.JsonTypeInfo
-import com.fasterxml.jackson.annotation.JsonTypeInfo.Id.CLASS
-
-@JsonTypeInfo(use = CLASS)
-public interface Command
-
-public abstract class SubstitutionCommand : Command {
- public abstract val pattern: String
-}
diff --git a/plugins/base/src/main/kotlin/templating/ImmediateHtmlCommandConsumer.kt b/plugins/base/src/main/kotlin/templating/ImmediateHtmlCommandConsumer.kt
deleted file mode 100644
index f1735490..00000000
--- a/plugins/base/src/main/kotlin/templating/ImmediateHtmlCommandConsumer.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.templating
-
-import org.jetbrains.dokka.base.renderers.html.TemplateBlock
-import org.jetbrains.dokka.base.renderers.html.command.consumers.ImmediateResolutionTagConsumer
-
-public interface ImmediateHtmlCommandConsumer {
- public fun canProcess(command: Command): Boolean
-
- public fun <R> processCommand(command: Command, block: TemplateBlock, tagConsumer: ImmediateResolutionTagConsumer<R>)
-
- public fun <R> processCommandAndFinalize(command: Command, block: TemplateBlock, tagConsumer: ImmediateResolutionTagConsumer<R>): R
-}
-
diff --git a/plugins/base/src/main/kotlin/templating/InsertTemplateExtra.kt b/plugins/base/src/main/kotlin/templating/InsertTemplateExtra.kt
deleted file mode 100644
index b4316e0f..00000000
--- a/plugins/base/src/main/kotlin/templating/InsertTemplateExtra.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.templating
-
-import org.jetbrains.dokka.model.properties.ExtraProperty
-import org.jetbrains.dokka.pages.ContentNode
-
-public data class InsertTemplateExtra(val command: Command) : ExtraProperty<ContentNode> {
-
- public companion object : ExtraProperty.Key<ContentNode, InsertTemplateExtra>
-
- override val key: ExtraProperty.Key<ContentNode, *>
- get() = Companion
-}
diff --git a/plugins/base/src/main/kotlin/templating/PathToRootSubstitutionCommand.kt b/plugins/base/src/main/kotlin/templating/PathToRootSubstitutionCommand.kt
deleted file mode 100644
index 070a38ee..00000000
--- a/plugins/base/src/main/kotlin/templating/PathToRootSubstitutionCommand.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.templating
-
-public data class PathToRootSubstitutionCommand(
- override val pattern: String,
- val default: String
-): SubstitutionCommand()
diff --git a/plugins/base/src/main/kotlin/templating/ProjectNameSubstitutionCommand.kt b/plugins/base/src/main/kotlin/templating/ProjectNameSubstitutionCommand.kt
deleted file mode 100644
index 6218530e..00000000
--- a/plugins/base/src/main/kotlin/templating/ProjectNameSubstitutionCommand.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.templating
-
-public data class ProjectNameSubstitutionCommand(
- override val pattern: String,
- val default: String
-): SubstitutionCommand()
diff --git a/plugins/base/src/main/kotlin/templating/ReplaceVersionsCommand.kt b/plugins/base/src/main/kotlin/templating/ReplaceVersionsCommand.kt
deleted file mode 100644
index 62a51047..00000000
--- a/plugins/base/src/main/kotlin/templating/ReplaceVersionsCommand.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.templating
-
-public data class ReplaceVersionsCommand(val location: String = ""): Command
diff --git a/plugins/base/src/main/kotlin/templating/ResolveLinkCommand.kt b/plugins/base/src/main/kotlin/templating/ResolveLinkCommand.kt
deleted file mode 100644
index 1669b435..00000000
--- a/plugins/base/src/main/kotlin/templating/ResolveLinkCommand.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.templating
-
-import org.jetbrains.dokka.links.DRI
-
-public class ResolveLinkCommand(
- public val dri: DRI
-): Command
diff --git a/plugins/base/src/main/kotlin/templating/jsonMapperForPlugins.kt b/plugins/base/src/main/kotlin/templating/jsonMapperForPlugins.kt
deleted file mode 100644
index a679a23d..00000000
--- a/plugins/base/src/main/kotlin/templating/jsonMapperForPlugins.kt
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.templating
-
-import com.fasterxml.jackson.core.JsonGenerator
-import com.fasterxml.jackson.databind.DeserializationFeature
-import com.fasterxml.jackson.databind.SerializerProvider
-import com.fasterxml.jackson.databind.module.SimpleModule
-import com.fasterxml.jackson.databind.ser.std.StdScalarSerializer
-import com.fasterxml.jackson.databind.type.TypeFactory
-import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
-import com.fasterxml.jackson.module.kotlin.jacksonTypeRef
-import org.jetbrains.dokka.base.DokkaBase
-import java.io.File
-
-// TODO [beresnev] try to get rid of this copy-paste in #2933
-// THIS IS COPIED FROM BASE SINCE IT NEEDS TO BE INSTANTIATED ON THE SAME CLASS LOADER AS PLUGINS
-
-private val objectMapper = run {
- val module = SimpleModule().apply {
- addSerializer(FileSerializer)
- }
- jacksonObjectMapper()
- .apply {
- typeFactory = PluginTypeFactory()
- }
- .registerModule(module)
- .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
-}
-
-@PublishedApi
-internal class TypeReference<T> @PublishedApi internal constructor(
- internal val jackson: com.fasterxml.jackson.core.type.TypeReference<T>
-) {
- companion object {
- @PublishedApi
- internal inline operator fun <reified T> invoke(): TypeReference<T> = TypeReference(jacksonTypeRef())
- }
-}
-
-public fun toJsonString(value: Any): String = objectMapper.writeValueAsString(value)
-
-public inline fun <reified T : Any> parseJson(json: String): T = parseJson(json, TypeReference())
-
-@PublishedApi
-internal fun <T : Any> parseJson(json: String, typeReference: TypeReference<T>): T =
- objectMapper.readValue(json, typeReference.jackson)
-
-
-private object FileSerializer : StdScalarSerializer<File>(File::class.java) {
- override fun serialize(value: File, g: JsonGenerator, provider: SerializerProvider) {
- g.writeString(value.path)
- }
-}
-
-@Suppress("DEPRECATION") // for TypeFactory constructor, no way to use non-deprecated one, it's essentially identical
-private class PluginTypeFactory: TypeFactory(null) {
- override fun findClass(className: String): Class<out Any>? =
- Class.forName(className, true, DokkaBase::class.java.classLoader) ?: super.findClass(className)
-}
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/ActualTypealiasAdder.kt b/plugins/base/src/main/kotlin/transformers/documentables/ActualTypealiasAdder.kt
deleted file mode 100644
index dde1a2af..00000000
--- a/plugins/base/src/main/kotlin/transformers/documentables/ActualTypealiasAdder.kt
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.transformers.documentables
-
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.model.*
-import org.jetbrains.dokka.model.properties.WithExtraProperties
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.transformers.documentation.DocumentableTransformer
-
-/**
- * Since we can not merge [DClasslike] with [DTypeAlias.underlyingType] and [DTypeAlias.extra],
- * we have this transformer to add [ActualTypealias] extra in expect [DClasslike]
- *
- * The transformer should be applied after merging all documentables
- */
-// TODO assign actual [DTypeAlias.expectPresentInSet] an expect source set, currently, [DTypeAlias.expectPresentInSet] always = null
-public class ActualTypealiasAdder : DocumentableTransformer {
-
- override fun invoke(original: DModule, context: DokkaContext): DModule {
- return original.generateTypealiasesMap().let { aliases ->
- original.copy(packages = original.packages.map {
- it.copy(classlikes = addActualTypeAliasToClasslikes(it.classlikes, aliases))
- })
- }
- }
-
- private fun DModule.generateTypealiasesMap(): Map<DRI, DTypeAlias> =
- packages.flatMap { pkg ->
- pkg.typealiases.map { typeAlias ->
- typeAlias.dri to typeAlias
- }
- }.toMap()
-
-
- private fun addActualTypeAliasToClasslikes(
- elements: Iterable<DClasslike>,
- typealiases: Map<DRI, DTypeAlias>
- ): List<DClasslike> = elements.flatMap {
- when (it) {
- is DClass -> addActualTypeAlias(
- it.copy(
- classlikes = addActualTypeAliasToClasslikes(it.classlikes, typealiases)
- ).let(::listOf),
- typealiases
- )
- is DEnum -> addActualTypeAlias(
- it.copy(
- classlikes = addActualTypeAliasToClasslikes(it.classlikes, typealiases)
- ).let(::listOf),
- typealiases
- )
- is DInterface -> addActualTypeAlias(
- it.copy(
- classlikes = addActualTypeAliasToClasslikes(it.classlikes, typealiases)
- ).let(::listOf),
- typealiases
- )
- is DObject -> addActualTypeAlias(
- it.copy(
- classlikes = addActualTypeAliasToClasslikes(it.classlikes, typealiases)
- ).let(::listOf),
- typealiases
- )
- is DAnnotation -> addActualTypeAlias(
- it.copy(
- classlikes = addActualTypeAliasToClasslikes(it.classlikes, typealiases)
- ).let(::listOf),
- typealiases
- )
- else -> throw IllegalStateException("${it::class.qualifiedName} ${it.name} cannot have extra added")
- }
- }
-
- private fun <T> addActualTypeAlias(
- elements: Iterable<T>,
- typealiases: Map<DRI, DTypeAlias>
- ): List<T> where T : DClasslike, T : WithExtraProperties<T>, T : WithSources =
- elements.map { element ->
- if (element.expectPresentInSet != null) {
- typealiases[element.dri]?.let { ta ->
- val actualTypealiasExtra = ActualTypealias(ta.copy(expectPresentInSet = element.expectPresentInSet))
- val merged = element.withNewExtras(element.extra + actualTypealiasExtra).let {
- when (it) {
- is DClass -> it.copy(
- documentation = element.documentation + ta.documentation,
- sources = element.sources + ta.sources,
- sourceSets = element.sourceSets + ta.sourceSets
- )
-
- is DEnum -> it.copy(
- documentation = element.documentation + ta.documentation,
- sources = element.sources + ta.sources,
- sourceSets = element.sourceSets + ta.sourceSets
- )
-
- is DInterface -> it.copy(
- documentation = element.documentation + ta.documentation,
- sources = element.sources + ta.sources,
- sourceSets = element.sourceSets + ta.sourceSets
- )
-
- is DObject -> it.copy(
- documentation = element.documentation + ta.documentation,
- sources = element.sources + ta.sources,
- sourceSets = element.sourceSets + ta.sourceSets
- )
-
- is DAnnotation -> it.copy(
- documentation = element.documentation + ta.documentation,
- sources = element.sources + ta.sources,
- sourceSets = element.sourceSets + ta.sourceSets
- )
-
- else -> throw IllegalStateException("${it::class.qualifiedName} ${it.name} cannot have copy its sourceSets")
- }
- }
- @Suppress("UNCHECKED_CAST")
- merged as T
- } ?: element
- } else {
- element
- }
- }
-}
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/ClashingDriIdentifier.kt b/plugins/base/src/main/kotlin/transformers/documentables/ClashingDriIdentifier.kt
deleted file mode 100644
index e9c7342e..00000000
--- a/plugins/base/src/main/kotlin/transformers/documentables/ClashingDriIdentifier.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.transformers.documentables
-
-@Deprecated(
- message = "Declaration was moved to dokka-core",
- replaceWith = ReplaceWith("org.jetbrains.dokka.transformers.documentation.ClashingDriIdentifier"),
- level = DeprecationLevel.WARNING // TODO change to error after Kotlin 1.9.20
-)
-public typealias ClashingDriIdentifier = org.jetbrains.dokka.transformers.documentation.ClashingDriIdentifier
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/DeprecatedDocumentableFilterTransformer.kt b/plugins/base/src/main/kotlin/transformers/documentables/DeprecatedDocumentableFilterTransformer.kt
deleted file mode 100644
index 4905e876..00000000
--- a/plugins/base/src/main/kotlin/transformers/documentables/DeprecatedDocumentableFilterTransformer.kt
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.transformers.documentables
-
-import org.jetbrains.dokka.DokkaConfiguration
-import org.jetbrains.dokka.DokkaConfiguration.PackageOptions
-import org.jetbrains.dokka.model.Annotations
-import org.jetbrains.dokka.model.Documentable
-import org.jetbrains.dokka.model.EnumValue
-import org.jetbrains.dokka.model.properties.WithExtraProperties
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.transformers.documentation.perPackageOptions
-import org.jetbrains.dokka.transformers.documentation.sourceSet
-
-/**
- * If [PackageOptions.skipDeprecated] or [DokkaConfiguration.DokkaSourceSet.skipDeprecated] is set
- * to `true`, suppresses documentables marked with [kotlin.Deprecated] or [java.lang.Deprecated].
- * Package options are given preference over global options.
- *
- * Documentables with [kotlin.Deprecated.level] set to [DeprecationLevel.HIDDEN]
- * are suppressed regardless of global and package options.
- */
-public class DeprecatedDocumentableFilterTransformer(
- context: DokkaContext
-) : SuppressedByConditionDocumentableFilterTransformer(context) {
-
- override fun shouldBeSuppressed(d: Documentable): Boolean {
- val annotations = (d as? WithExtraProperties<*>)?.annotations() ?: return false
- if (annotations.isEmpty())
- return false
-
- val deprecatedAnnotations = filterDeprecatedAnnotations(annotations)
- if (deprecatedAnnotations.isEmpty())
- return false
-
- val kotlinDeprecated = deprecatedAnnotations.find { it.dri.packageName == "kotlin" }
- if (kotlinDeprecated?.isHidden() == true)
- return true
-
- return perPackageOptions(d)?.skipDeprecated ?: sourceSet(d).skipDeprecated
- }
-
- private fun WithExtraProperties<*>.annotations(): List<Annotations.Annotation> {
- return this.extra.allOfType<Annotations>().flatMap { annotations ->
- annotations.directAnnotations.values.singleOrNull() ?: emptyList()
- }
- }
-
- private fun filterDeprecatedAnnotations(annotations: List<Annotations.Annotation>): List<Annotations.Annotation> {
- return annotations.filter {
- (it.dri.packageName == "kotlin" && it.dri.classNames == "Deprecated") ||
- (it.dri.packageName == "java.lang" && it.dri.classNames == "Deprecated")
- }
- }
-
- private fun Annotations.Annotation.isHidden(): Boolean {
- val level = (this.params["level"] as? EnumValue) ?: return false
- return level.enumName == "DeprecationLevel.HIDDEN"
- }
-}
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/DocumentableReplacerTransformer.kt b/plugins/base/src/main/kotlin/transformers/documentables/DocumentableReplacerTransformer.kt
deleted file mode 100644
index 10b25a20..00000000
--- a/plugins/base/src/main/kotlin/transformers/documentables/DocumentableReplacerTransformer.kt
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.transformers.documentables
-
-import org.jetbrains.dokka.model.*
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.transformers.documentation.PreMergeDocumentableTransformer
-
-public abstract class DocumentableReplacerTransformer(
- public val context: DokkaContext
-) : PreMergeDocumentableTransformer {
- override fun invoke(modules: List<DModule>): List<DModule> =
- modules.map { module ->
- val (documentable, wasChanged) = processModule(module)
- documentable.takeIf { wasChanged } ?: module
- }
-
- protected open fun processModule(module: DModule): AnyWithChanges<DModule> {
- val afterProcessing = module.packages.map { processPackage(it) }
- val processedModule = module.takeIf { afterProcessing.none { it.changed } }
- ?: module.copy(packages = afterProcessing.mapNotNull { it.target })
- return AnyWithChanges(processedModule, afterProcessing.any { it.changed })
- }
-
- protected open fun processPackage(dPackage: DPackage): AnyWithChanges<DPackage> {
- val classlikes = dPackage.classlikes.map { processClassLike(it) }
- val typeAliases = dPackage.typealiases.map { processTypeAlias(it) }
- val functions = dPackage.functions.map { processFunction(it) }
- val properies = dPackage.properties.map { processProperty(it) }
-
- val wasChanged = (classlikes + typeAliases + functions + properies).any { it.changed }
- return (dPackage.takeIf { !wasChanged } ?: dPackage.copy(
- classlikes = classlikes.mapNotNull { it.target },
- typealiases = typeAliases.mapNotNull { it.target },
- functions = functions.mapNotNull { it.target },
- properties = properies.mapNotNull { it.target }
- )).let { processedPackage -> AnyWithChanges(processedPackage, wasChanged) }
- }
-
- protected open fun processClassLike(classlike: DClasslike): AnyWithChanges<DClasslike> {
- val functions = classlike.functions.map { processFunction(it) }
- val classlikes = classlike.classlikes.map { processClassLike(it) }
- val properties = classlike.properties.map { processProperty(it) }
- val companion = (classlike as? WithCompanion)?.companion?.let { processClassLike(it) }
-
- val wasClasslikeChanged = (functions + classlikes + properties).any { it.changed } || companion?.changed == true
- return when (classlike) {
- is DClass -> {
- val constructors = classlike.constructors.map { processFunction(it) }
- val generics = classlike.generics.map { processTypeParameter(it) }
- val wasClassChange =
- wasClasslikeChanged || constructors.any { it.changed } || generics.any { it.changed }
- (classlike.takeIf { !wasClassChange } ?: classlike.copy(
- functions = functions.mapNotNull { it.target },
- classlikes = classlikes.mapNotNull { it.target },
- properties = properties.mapNotNull { it.target },
- constructors = constructors.mapNotNull { it.target },
- generics = generics.mapNotNull { it.target },
- companion = companion?.target as? DObject
- )).let { AnyWithChanges(it, wasClassChange) }
- }
- is DInterface -> {
- val generics = classlike.generics.map { processTypeParameter(it) }
- val wasInterfaceChange = wasClasslikeChanged || generics.any { it.changed }
- (classlike.takeIf { !wasInterfaceChange } ?: classlike.copy(
- functions = functions.mapNotNull { it.target },
- classlikes = classlikes.mapNotNull { it.target },
- properties = properties.mapNotNull { it.target },
- generics = generics.mapNotNull { it.target },
- companion = companion?.target as? DObject
- )).let { AnyWithChanges(it, wasClasslikeChanged) }
- }
- is DObject -> (classlike.takeIf { !wasClasslikeChanged } ?: classlike.copy(
- functions = functions.mapNotNull { it.target },
- classlikes = classlikes.mapNotNull { it.target },
- properties = properties.mapNotNull { it.target },
- )).let { AnyWithChanges(it, wasClasslikeChanged) }
- is DAnnotation -> {
- val constructors = classlike.constructors.map { processFunction(it) }
- val generics = classlike.generics.map { processTypeParameter(it) }
- val wasClassChange =
- wasClasslikeChanged || constructors.any { it.changed } || generics.any { it.changed }
- (classlike.takeIf { !wasClassChange } ?: classlike.copy(
- functions = functions.mapNotNull { it.target },
- classlikes = classlikes.mapNotNull { it.target },
- properties = properties.mapNotNull { it.target },
- constructors = constructors.mapNotNull { it.target },
- generics = generics.mapNotNull { it.target },
- companion = companion?.target as? DObject
- )).let { AnyWithChanges(it, wasClassChange) }
- }
- is DEnum -> {
- val constructors = classlike.constructors.map { processFunction(it) }
- val entries = classlike.entries.map { processEnumEntry(it) }
- val wasClassChange =
- wasClasslikeChanged || (constructors + entries).any { it.changed }
- (classlike.takeIf { !wasClassChange } ?: classlike.copy(
- functions = functions.mapNotNull { it.target },
- classlikes = classlikes.mapNotNull { it.target },
- properties = properties.mapNotNull { it.target },
- constructors = constructors.mapNotNull { it.target },
- companion = companion?.target as? DObject,
- entries = entries.mapNotNull { it.target }
- )).let { AnyWithChanges(it, wasClassChange) }
- }
- }
- }
-
- protected open fun processEnumEntry(dEnumEntry: DEnumEntry): AnyWithChanges<DEnumEntry> {
- val functions = dEnumEntry.functions.map { processFunction(it) }
- val properties = dEnumEntry.properties.map { processProperty(it) }
- val classlikes = dEnumEntry.classlikes.map { processClassLike(it) }
-
- val wasChanged = (functions + properties + classlikes).any { it.changed }
- return (dEnumEntry.takeIf { !wasChanged } ?: dEnumEntry.copy(
- functions = functions.mapNotNull { it.target },
- classlikes = classlikes.mapNotNull { it.target },
- properties = properties.mapNotNull { it.target },
- )).let { AnyWithChanges(it, wasChanged) }
- }
-
- protected open fun processFunction(dFunction: DFunction): AnyWithChanges<DFunction> {
- val type = processBound(dFunction.type)
- val parameters = dFunction.parameters.map { processParameter(it) }
- val receiver = dFunction.receiver?.let { processParameter(it) }
- val generics = dFunction.generics.map { processTypeParameter(it) }
-
- val wasChanged = parameters.any { it.changed } || receiver?.changed == true
- || type.changed || generics.any { it.changed }
- return (dFunction.takeIf { !wasChanged } ?: dFunction.copy(
- type = type.target ?: dFunction.type,
- parameters = parameters.mapNotNull { it.target },
- receiver = receiver?.target,
- generics = generics.mapNotNull { it.target },
- )).let { AnyWithChanges(it, wasChanged) }
- }
-
- protected open fun processProperty(dProperty: DProperty): AnyWithChanges<DProperty> {
- val getter = dProperty.getter?.let { processFunction(it) }
- val setter = dProperty.setter?.let { processFunction(it) }
- val type = processBound(dProperty.type)
- val generics = dProperty.generics.map { processTypeParameter(it) }
-
- val wasChanged = getter?.changed == true || setter?.changed == true
- || type.changed || generics.any { it.changed }
- return (dProperty.takeIf { !wasChanged } ?: dProperty.copy(
- type = type.target ?: dProperty.type,
- setter = setter?.target,
- getter = getter?.target,
- generics = generics.mapNotNull { it.target }
- )).let { AnyWithChanges(it, wasChanged) }
- }
-
- protected open fun processParameter(dParameter: DParameter): AnyWithChanges<DParameter> {
- val type = processBound(dParameter.type)
-
- val wasChanged = type.changed
- return (dParameter.takeIf { !wasChanged } ?: dParameter.copy(
- type = type.target ?: dParameter.type,
- )).let { AnyWithChanges(it, wasChanged) }
- }
-
- protected open fun processTypeParameter(dTypeParameter: DTypeParameter): AnyWithChanges<DTypeParameter> {
- val bounds = dTypeParameter.bounds.map { processBound(it) }
-
- val wasChanged = bounds.any { it.changed }
- return (dTypeParameter.takeIf { !wasChanged } ?: dTypeParameter.copy(
- bounds = bounds.mapIndexed { i, v -> v.target ?: dTypeParameter.bounds[i] }
- )).let { AnyWithChanges(it, wasChanged) }
- }
-
- protected open fun processBound(bound: Bound): AnyWithChanges<Bound> {
- return when(bound) {
- is GenericTypeConstructor -> processGenericTypeConstructor(bound)
- is FunctionalTypeConstructor -> processFunctionalTypeConstructor(bound)
- else -> AnyWithChanges(bound, false)
- }
- }
-
- protected open fun processVariance(variance: Variance<*>): AnyWithChanges<Variance<*>> {
- val bound = processBound(variance.inner)
- if (!bound.changed)
- return AnyWithChanges(variance, false)
- return when (variance) {
- is Covariance<*> -> AnyWithChanges(
- Covariance(bound.target ?: variance.inner), true)
- is Contravariance<*> -> AnyWithChanges(
- Contravariance(bound.target ?: variance.inner), true)
- is Invariance<*> -> AnyWithChanges(
- Invariance(bound.target ?: variance.inner), true)
- else -> AnyWithChanges(variance, false)
- }
- }
-
- protected open fun processProjection(projection: Projection): AnyWithChanges<Projection> =
- when (projection) {
- is Bound -> processBound(projection)
- is Variance<Bound> -> processVariance(projection)
- else -> AnyWithChanges(projection, false)
- }
-
- protected open fun processGenericTypeConstructor(
- genericTypeConstructor: GenericTypeConstructor
- ): AnyWithChanges<GenericTypeConstructor> {
- val projections = genericTypeConstructor.projections.map { processProjection(it) }
-
- val wasChanged = projections.any { it.changed }
- return (genericTypeConstructor.takeIf { !wasChanged } ?: genericTypeConstructor.copy(
- projections = projections.mapNotNull { it.target }
- )).let { AnyWithChanges(it, wasChanged) }
- }
-
- protected open fun processFunctionalTypeConstructor(
- functionalTypeConstructor: FunctionalTypeConstructor
- ): AnyWithChanges<FunctionalTypeConstructor> {
- val projections = functionalTypeConstructor.projections.map { processProjection(it) }
-
- val wasChanged = projections.any { it.changed }
- return (functionalTypeConstructor.takeIf { !wasChanged } ?: functionalTypeConstructor.copy(
- projections = projections.mapNotNull { it.target }
- )).let { AnyWithChanges(it, wasChanged) }
- }
-
- protected open fun processTypeAlias(dTypeAlias: DTypeAlias): AnyWithChanges<DTypeAlias> {
- val underlyingType = dTypeAlias.underlyingType.mapValues { processBound(it.value) }
- val generics = dTypeAlias.generics.map { processTypeParameter(it) }
-
- val wasChanged = underlyingType.any { it.value.changed } || generics.any { it.changed }
- return (dTypeAlias.takeIf { !wasChanged } ?: dTypeAlias.copy(
- underlyingType = underlyingType.mapValues { it.value.target ?: dTypeAlias.underlyingType.getValue(it.key) },
- generics = generics.mapNotNull { it.target }
- )).let { AnyWithChanges(it, wasChanged) }
- }
-
-
- protected data class AnyWithChanges<out T>(val target: T?, val changed: Boolean = false)
-}
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/DocumentableVisibilityFilterTransformer.kt b/plugins/base/src/main/kotlin/transformers/documentables/DocumentableVisibilityFilterTransformer.kt
deleted file mode 100644
index 6155a71f..00000000
--- a/plugins/base/src/main/kotlin/transformers/documentables/DocumentableVisibilityFilterTransformer.kt
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.transformers.documentables
-
-import org.jetbrains.dokka.DokkaConfiguration
-import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
-import org.jetbrains.dokka.DokkaDefaults
-import org.jetbrains.dokka.model.*
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.transformers.documentation.PreMergeDocumentableTransformer
-
-public class DocumentableVisibilityFilterTransformer(
- public val context: DokkaContext
-) : PreMergeDocumentableTransformer {
-
- override fun invoke(modules: List<DModule>): List<DModule> {
- return modules.map { original ->
- val sourceSet = original.sourceSets.single()
- val packageOptions = sourceSet.perPackageOptions
- DocumentableVisibilityFilter(packageOptions, sourceSet).processModule(original)
- }
- }
-
- private class DocumentableVisibilityFilter(
- val packageOptions: List<DokkaConfiguration.PackageOptions>,
- val globalOptions: DokkaSourceSet
- ) {
- fun Visibility.isAllowedInPackage(packageName: String?) = when (this) {
- is JavaVisibility.Public,
- is KotlinVisibility.Public -> isAllowedInPackage(packageName, DokkaConfiguration.Visibility.PUBLIC)
- is JavaVisibility.Private,
- is KotlinVisibility.Private -> isAllowedInPackage(packageName, DokkaConfiguration.Visibility.PRIVATE)
- is JavaVisibility.Protected,
- is KotlinVisibility.Protected -> isAllowedInPackage(packageName, DokkaConfiguration.Visibility.PROTECTED)
- is KotlinVisibility.Internal -> isAllowedInPackage(packageName, DokkaConfiguration.Visibility.INTERNAL)
- is JavaVisibility.Default -> isAllowedInPackage(packageName, DokkaConfiguration.Visibility.PACKAGE)
- }
-
- private fun isAllowedInPackage(packageName: String?, visibility: DokkaConfiguration.Visibility): Boolean {
- val packageOpts = packageName.takeIf { it != null }?.let { name ->
- packageOptions.firstOrNull { Regex(it.matchingRegex).matches(name) }
- }
-
- val (documentedVisibilities, includeNonPublic) =
- @Suppress("DEPRECATION") // for includeNonPublic, preserve backwards compatibility
- when {
- packageOpts != null -> packageOpts.documentedVisibilities to packageOpts.includeNonPublic
- else -> globalOptions.documentedVisibilities to globalOptions.includeNonPublic
- }
-
- // if `documentedVisibilities` is explicitly overridden by the user (i.e. not default value by reference),
- // deprecated `includeNonPublic` should not be taken into account, so that only one setting prevails
- val isDocumentedVisibilitiesOverridden = documentedVisibilities !== DokkaDefaults.documentedVisibilities
- return documentedVisibilities.contains(visibility) || (!isDocumentedVisibilitiesOverridden && includeNonPublic)
- }
-
- fun processModule(original: DModule) =
- filterPackages(original.packages).let { (modified, packages) ->
- if (!modified) original
- else
- DModule(
- original.name,
- packages = packages,
- documentation = original.documentation,
- sourceSets = original.sourceSets,
- extra = original.extra
- )
- }
-
-
- private fun filterPackages(packages: List<DPackage>): Pair<Boolean, List<DPackage>> {
- var packagesListChanged = false
- val filteredPackages = packages.map {
- var modified = false
- val functions = filterFunctions(it.functions).let { (listModified, list) ->
- modified = modified || listModified
- list
- }
- val properties = filterProperties(it.properties).let { (listModified, list) ->
- modified = modified || listModified
- list
- }
- val classlikes = filterClasslikes(it.classlikes).let { (listModified, list) ->
- modified = modified || listModified
- list
- }
- val typeAliases = filterTypeAliases(it.typealiases).let { (listModified, list) ->
- modified = modified || listModified
- list
- }
- when {
- !modified -> it
- else -> {
- packagesListChanged = true
- DPackage(
- it.dri,
- functions,
- properties,
- classlikes,
- typeAliases,
- it.documentation,
- it.expectPresentInSet,
- it.sourceSets,
- it.extra
- )
- }
- }
- }
- return Pair(packagesListChanged, filteredPackages)
- }
-
- @Suppress("UNUSED_PARAMETER")
- private fun <T : WithVisibility> alwaysTrue(a: T, p: DokkaSourceSet) = true
- @Suppress("UNUSED_PARAMETER")
- private fun <T : WithVisibility> alwaysFalse(a: T, p: DokkaSourceSet) = false
- @Suppress("UNUSED_PARAMETER")
- private fun <T> alwaysNoModify(a: T, sourceSets: Set<DokkaSourceSet>) = false to a
-
- private fun WithVisibility.visibilityForPlatform(data: DokkaSourceSet): Visibility? = visibility[data]
-
- private fun <T> T.filterPlatforms(
- additionalCondition: (T, DokkaSourceSet) -> Boolean = ::alwaysTrue,
- alternativeCondition: (T, DokkaSourceSet) -> Boolean = ::alwaysFalse
- ) where T : Documentable, T : WithVisibility =
- sourceSets.filter { d ->
- visibilityForPlatform(d)?.isAllowedInPackage(dri.packageName) == true &&
- additionalCondition(this, d) ||
- alternativeCondition(this, d)
- }.toSet()
-
- private fun <T> List<T>.transform(
- additionalCondition: (T, DokkaSourceSet) -> Boolean = ::alwaysTrue,
- alternativeCondition: (T, DokkaSourceSet) -> Boolean = ::alwaysFalse,
- modify: (T, Set<DokkaSourceSet>) -> Pair<Boolean, T> = ::alwaysNoModify,
- recreate: (T, Set<DokkaSourceSet>) -> T,
- ): Pair<Boolean, List<T>> where T : Documentable, T : WithVisibility {
- var changed = false
- val values = mapNotNull { t ->
- val filteredPlatforms = t.filterPlatforms(additionalCondition, alternativeCondition)
- when (filteredPlatforms.size) {
- t.visibility.size -> {
- val (wasChanged, element) = modify(t, filteredPlatforms)
- changed = changed || wasChanged
- element
- }
- 0 -> {
- changed = true
- null
- }
- else -> {
- changed = true
- recreate(t, filteredPlatforms)
- }
- }
- }
- return Pair(changed, values)
- }
-
- private fun filterFunctions(
- functions: List<DFunction>,
- additionalCondition: (DFunction, DokkaSourceSet) -> Boolean = ::alwaysTrue
- ) =
- functions.transform(additionalCondition) { original, filteredPlatforms ->
- with(original) {
- copy(
- documentation = documentation.filtered(filteredPlatforms),
- expectPresentInSet = expectPresentInSet.filtered(filteredPlatforms),
- sources = sources.filtered(filteredPlatforms),
- visibility = visibility.filtered(filteredPlatforms),
- generics = generics.mapNotNull { it.filter(filteredPlatforms) },
- sourceSets = filteredPlatforms,
- )
- }
- }
-
- private fun hasVisibleAccessorsForPlatform(property: DProperty, data: DokkaSourceSet) =
- property.getter?.visibilityForPlatform(data)?.isAllowedInPackage(property.dri.packageName) == true ||
- property.setter?.visibilityForPlatform(data)?.isAllowedInPackage(property.dri.packageName) == true
-
- private fun filterProperties(
- properties: List<DProperty>,
- additionalCondition: (DProperty, DokkaSourceSet) -> Boolean = ::alwaysTrue,
- additionalConditionAccessors: (DFunction, DokkaSourceSet) -> Boolean = ::alwaysTrue
- ): Pair<Boolean, List<DProperty>> {
-
- val modifier: (DProperty, Set<DokkaSourceSet>) -> Pair<Boolean, DProperty> =
- { original, _ ->
- val setter = original.setter?.let { filterFunctions(listOf(it), additionalConditionAccessors) }
- val getter = original.getter?.let { filterFunctions(listOf(it), additionalConditionAccessors) }
-
- val modified = setter?.first == true || getter?.first == true
-
- val property =
- if (modified)
- original.copy(
- setter = setter?.second?.firstOrNull(),
- getter = getter?.second?.firstOrNull()
- )
- else original
- modified to property
- }
-
- return properties.transform(
- additionalCondition,
- ::hasVisibleAccessorsForPlatform,
- modifier
- ) { original, filteredPlatforms ->
- val setter = original.setter?.let { filterFunctions(listOf(it), additionalConditionAccessors) }
- val getter = original.getter?.let { filterFunctions(listOf(it), additionalConditionAccessors) }
-
- with(original) {
- copy(
- documentation = documentation.filtered(filteredPlatforms),
- expectPresentInSet = expectPresentInSet.filtered(filteredPlatforms),
- sources = sources.filtered(filteredPlatforms),
- visibility = visibility.filtered(filteredPlatforms),
- sourceSets = filteredPlatforms,
- generics = generics.mapNotNull { it.filter(filteredPlatforms) },
- setter = setter?.second?.firstOrNull(),
- getter = getter?.second?.firstOrNull()
- )
- }
- }
- }
-
- private fun filterEnumEntries(entries: List<DEnumEntry>, filteredPlatforms: Set<DokkaSourceSet>): Pair<Boolean, List<DEnumEntry>> =
- entries.fold(Pair(false, emptyList())) { acc, entry ->
- val intersection = filteredPlatforms.intersect(entry.sourceSets)
- if (intersection.isEmpty()) Pair(true, acc.second)
- else {
- val functions = filterFunctions(entry.functions) { _, data -> data in intersection }
- val properties = filterProperties(entry.properties) { _, data -> data in intersection }
- val classlikes = filterClasslikes(entry.classlikes) { _, data -> data in intersection }
-
- DEnumEntry(
- entry.dri,
- entry.name,
- entry.documentation.filtered(intersection),
- entry.expectPresentInSet.filtered(filteredPlatforms),
- functions.second,
- properties.second,
- classlikes.second,
- intersection,
- entry.extra
- ).let { Pair(functions.first || properties.first || classlikes.first, acc.second + it) }
- }
- }
-
- private fun filterClasslikes(
- classlikeList: List<DClasslike>,
- additionalCondition: (DClasslike, DokkaSourceSet) -> Boolean = ::alwaysTrue
- ): Pair<Boolean, List<DClasslike>> {
- var classlikesListChanged = false
- val filteredClasslikes: List<DClasslike> = classlikeList.mapNotNull {
- with(it) {
- val filteredPlatforms = filterPlatforms(additionalCondition)
- if (filteredPlatforms.isEmpty()) {
- classlikesListChanged = true
- null
- } else {
- var modified = sourceSets.size != filteredPlatforms.size
- val functions =
- filterFunctions(functions) { _, data -> data in filteredPlatforms }.let { (listModified, list) ->
- modified = modified || listModified
- list
- }
- val properties =
- filterProperties(properties) { _, data -> data in filteredPlatforms }.let { (listModified, list) ->
- modified = modified || listModified
- list
- }
- val classlikes =
- filterClasslikes(classlikes) { _, data -> data in filteredPlatforms }.let { (listModified, list) ->
- modified = modified || listModified
- list
- }
- val companion =
- if (this is WithCompanion) filterClasslikes(listOfNotNull(companion)) { _, data -> data in filteredPlatforms }.let { (listModified, list) ->
- modified = modified || listModified
- list.firstOrNull() as DObject?
- } else null
- val constructors = if (this is WithConstructors)
- filterFunctions(constructors) { _, data -> data in filteredPlatforms }.let { (listModified, list) ->
- modified = modified || listModified
- list
- } else emptyList()
- val generics =
- if (this is WithGenerics) generics.mapNotNull { param -> param.filter(filteredPlatforms) } else emptyList()
- val enumEntries =
- if (this is DEnum) filterEnumEntries(entries, filteredPlatforms).let { (listModified, list) ->
- modified = modified || listModified
- list
- } else emptyList()
- classlikesListChanged = classlikesListChanged || modified
- when {
- !modified -> this
- this is DClass -> copy(
- constructors = constructors,
- functions = functions,
- properties = properties,
- classlikes = classlikes,
- sources = sources.filtered(filteredPlatforms),
- visibility = visibility.filtered(filteredPlatforms),
- companion = companion,
- generics = generics,
- supertypes = supertypes.filtered(filteredPlatforms),
- documentation = documentation.filtered(filteredPlatforms),
- expectPresentInSet = expectPresentInSet.filtered(filteredPlatforms),
- sourceSets = filteredPlatforms
- )
- this is DAnnotation -> copy(
- documentation = documentation.filtered(filteredPlatforms),
- expectPresentInSet = expectPresentInSet.filtered(filteredPlatforms),
- sources = sources.filtered(filteredPlatforms),
- functions = functions,
- properties = properties,
- classlikes = classlikes,
- visibility = visibility.filtered(filteredPlatforms),
- companion = companion,
- constructors = constructors,
- generics = generics,
- sourceSets = filteredPlatforms
- )
- this is DEnum -> copy(
- entries = enumEntries,
- documentation = documentation.filtered(filteredPlatforms),
- expectPresentInSet = expectPresentInSet.filtered(filteredPlatforms),
- sources = sources.filtered(filteredPlatforms),
- functions = functions,
- properties = properties,
- classlikes = classlikes,
- visibility = visibility.filtered(filteredPlatforms),
- companion = companion,
- constructors = constructors,
- supertypes = supertypes.filtered(filteredPlatforms),
- sourceSets = filteredPlatforms
- )
- this is DInterface -> copy(
- documentation = documentation.filtered(filteredPlatforms),
- expectPresentInSet = expectPresentInSet.filtered(filteredPlatforms),
- sources = sources.filtered(filteredPlatforms),
- functions = functions,
- properties = properties,
- classlikes = classlikes,
- visibility = visibility.filtered(filteredPlatforms),
- companion = companion,
- generics = generics,
- supertypes = supertypes.filtered(filteredPlatforms),
- sourceSets = filteredPlatforms
- )
- this is DObject -> copy(
- documentation = documentation.filtered(filteredPlatforms),
- expectPresentInSet = expectPresentInSet.filtered(filteredPlatforms),
- sources = sources.filtered(filteredPlatforms),
- functions = functions,
- properties = properties,
- classlikes = classlikes,
- supertypes = supertypes.filtered(filteredPlatforms),
- sourceSets = filteredPlatforms
- )
- else -> null
- }
- }
- }
- }
- return Pair(classlikesListChanged, filteredClasslikes)
- }
-
- private fun filterTypeAliases(
- typeAliases: List<DTypeAlias>,
- additionalCondition: (DTypeAlias, DokkaSourceSet) -> Boolean = ::alwaysTrue
- ) =
- typeAliases.transform(additionalCondition) { original, filteredPlatforms ->
- with(original) {
- copy(
- documentation = documentation.filtered(filteredPlatforms),
- expectPresentInSet = expectPresentInSet.filtered(filteredPlatforms),
- underlyingType = underlyingType.filtered(filteredPlatforms),
- visibility = visibility.filtered(filteredPlatforms),
- generics = generics.mapNotNull { it.filter(filteredPlatforms) },
- sourceSets = filteredPlatforms,
- )
- }
- }
- }
-}
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/EmptyModulesFilterTransformer.kt b/plugins/base/src/main/kotlin/transformers/documentables/EmptyModulesFilterTransformer.kt
deleted file mode 100644
index 7a2387dc..00000000
--- a/plugins/base/src/main/kotlin/transformers/documentables/EmptyModulesFilterTransformer.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.transformers.documentables
-
-import org.jetbrains.dokka.model.DModule
-import org.jetbrains.dokka.transformers.documentation.PreMergeDocumentableTransformer
-
-public class EmptyModulesFilterTransformer : PreMergeDocumentableTransformer {
- override fun invoke(modules: List<DModule>): List<DModule> {
- return modules.filter { it.children.isNotEmpty() }
- }
-}
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/EmptyPackagesFilterTransformer.kt b/plugins/base/src/main/kotlin/transformers/documentables/EmptyPackagesFilterTransformer.kt
deleted file mode 100644
index 30ac8f70..00000000
--- a/plugins/base/src/main/kotlin/transformers/documentables/EmptyPackagesFilterTransformer.kt
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.transformers.documentables
-
-import org.jetbrains.dokka.model.DModule
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.transformers.documentation.PreMergeDocumentableTransformer
-import org.jetbrains.dokka.transformers.documentation.sourceSet
-
-public class EmptyPackagesFilterTransformer(
- public val context: DokkaContext
-) : PreMergeDocumentableTransformer {
- override fun invoke(modules: List<DModule>): List<DModule> {
- return modules.mapNotNull(::filterModule)
- }
-
- private fun filterModule(module: DModule): DModule? {
- val nonEmptyPackages = module.packages.filterNot { pkg ->
- sourceSet(pkg).skipEmptyPackages && pkg.children.isEmpty()
- }
-
- return when {
- nonEmptyPackages == module.packages -> module
- nonEmptyPackages.isEmpty() -> null
- else -> module.copy(packages = nonEmptyPackages)
- }
- }
-}
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/ExtensionExtractorTransformer.kt b/plugins/base/src/main/kotlin/transformers/documentables/ExtensionExtractorTransformer.kt
deleted file mode 100644
index e6102622..00000000
--- a/plugins/base/src/main/kotlin/transformers/documentables/ExtensionExtractorTransformer.kt
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.transformers.documentables
-
-import kotlinx.coroutines.*
-import kotlinx.coroutines.channels.*
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.links.DriOfAny
-import org.jetbrains.dokka.model.*
-import org.jetbrains.dokka.model.properties.ExtraProperty
-import org.jetbrains.dokka.model.properties.MergeStrategy
-import org.jetbrains.dokka.model.properties.plus
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.plugability.plugin
-import org.jetbrains.dokka.plugability.querySingle
-import org.jetbrains.dokka.transformers.documentation.DocumentableTransformer
-import org.jetbrains.dokka.utilities.parallelForEach
-import org.jetbrains.dokka.utilities.parallelMap
-import org.jetbrains.dokka.analysis.kotlin.internal.InternalKotlinAnalysisPlugin
-
-public class ExtensionExtractorTransformer : DocumentableTransformer {
- override fun invoke(original: DModule, context: DokkaContext): DModule = runBlocking(Dispatchers.Default) {
- val classGraph = async {
- if (!context.configuration.suppressInheritedMembers)
- context.plugin<InternalKotlinAnalysisPlugin>().querySingle { fullClassHierarchyBuilder }.build(original)
- else
- emptyMap()
- }
-
- val channel = Channel<Pair<DRI, Callable>>(10)
- launch {
- original.packages.parallelForEach { collectExtensions(it, channel) }
- channel.close()
- }
- val extensionMap = channel.toList().toMultiMap()
-
- val newPackages = original.packages.parallelMap { it.addExtensionInformation(classGraph.await(), extensionMap) }
- original.copy(packages = newPackages)
- }
-
- private suspend fun <T : Documentable> T.addExtensionInformation(
- classGraph: SourceSetDependent<Map<DRI, List<DRI>>>,
- extensionMap: Map<DRI, List<Callable>>
- ): T = coroutineScope {
- val newClasslikes = (this@addExtensionInformation as? WithScope)
- ?.classlikes
- ?.map { async { it.addExtensionInformation(classGraph, extensionMap) } }
- .orEmpty()
-
- @Suppress("UNCHECKED_CAST")
- when (this@addExtensionInformation) {
- is DPackage -> {
- val newTypealiases = typealiases.map { async { it.addExtensionInformation(classGraph, extensionMap) } }
- copy(classlikes = newClasslikes.awaitAll(), typealiases = newTypealiases.awaitAll())
- }
-
- is DClass -> copy(
- classlikes = newClasslikes.awaitAll(),
- extra = extra + findExtensions(classGraph, extensionMap)
- )
-
- is DEnum -> copy(
- classlikes = newClasslikes.awaitAll(),
- extra = extra + findExtensions(classGraph, extensionMap)
- )
-
- is DInterface -> copy(
- classlikes = newClasslikes.awaitAll(),
- extra = extra + findExtensions(classGraph, extensionMap)
- )
-
- is DObject -> copy(
- classlikes = newClasslikes.awaitAll(),
- extra = extra + findExtensions(classGraph, extensionMap)
- )
-
- is DAnnotation -> copy(
- classlikes = newClasslikes.awaitAll(),
- extra = extra + findExtensions(classGraph, extensionMap)
- )
-
- is DTypeAlias -> copy(extra = extra + findExtensions(classGraph, extensionMap))
- else -> throw IllegalStateException(
- "${this@addExtensionInformation::class.simpleName} is not expected to have extensions"
- )
- } as T
- }
-
- private suspend fun collectExtensions(
- documentable: Documentable,
- channel: SendChannel<Pair<DRI, Callable>>
- ): Unit = coroutineScope {
- if (documentable is WithScope) {
- documentable.classlikes.forEach {
- launch { collectExtensions(it, channel) }
- }
-
- if (documentable is DObject || documentable is DPackage) {
- (documentable.properties.asSequence() + documentable.functions.asSequence())
- .flatMap { it.asPairsWithReceiverDRIs() }
- .forEach { channel.send(it) }
- }
- }
- }
-
- private fun <T : Documentable> T.findExtensions(
- classGraph: SourceSetDependent<Map<DRI, List<DRI>>>,
- extensionMap: Map<DRI, List<Callable>>
- ): CallableExtensions? {
- val resultSet = mutableSetOf<Callable>()
-
- fun collectFrom(element: DRI) {
- extensionMap[element]?.let { resultSet.addAll(it) }
- sourceSets.forEach { sourceSet -> classGraph[sourceSet]?.get(element)?.forEach { collectFrom(it) } }
- }
- collectFrom(dri)
-
- return if (resultSet.isEmpty()) null else CallableExtensions(resultSet)
- }
-
- private fun Callable.asPairsWithReceiverDRIs(): Sequence<Pair<DRI, Callable>> =
- receiver?.type?.let { findReceiverDRIs(it) }.orEmpty().map { it to this }
-
- // In normal cases we return at max one DRI, but sometimes receiver type can be bound by more than one type constructor
- // for example `fun <T> T.example() where T: A, T: B` is extension of both types A and B
- // another one `typealias A = B`
- // Note: in some cases returning empty sequence doesn't mean that we cannot determine the DRI but only that we don't
- // care about it since there is nowhere to put documentation of given extension.
- private fun Callable.findReceiverDRIs(bound: Bound): Sequence<DRI> = when (bound) {
- is Nullable -> findReceiverDRIs(bound.inner)
- is DefinitelyNonNullable -> findReceiverDRIs(bound.inner)
- is TypeParameter ->
- if (this is DFunction && bound.dri == this.dri)
- generics.find { it.name == bound.name }?.bounds?.asSequence()?.flatMap { findReceiverDRIs(it) }.orEmpty()
- else
- emptySequence()
-
- is TypeConstructor -> sequenceOf(bound.dri)
- is PrimitiveJavaType -> emptySequence()
- is Void -> emptySequence()
- is JavaObject -> sequenceOf(DriOfAny)
- is Dynamic -> sequenceOf(DriOfAny)
- is UnresolvedBound -> emptySequence()
- is TypeAliased -> findReceiverDRIs(bound.typeAlias) + findReceiverDRIs(bound.inner)
- }
-
- private fun <T, U> Iterable<Pair<T, U>>.toMultiMap(): Map<T, List<U>> =
- groupBy(Pair<T, *>::first, Pair<*, U>::second)
-}
-
-public data class CallableExtensions(val extensions: Set<Callable>) : ExtraProperty<Documentable> {
- public companion object Key : ExtraProperty.Key<Documentable, CallableExtensions> {
- override fun mergeStrategyFor(left: CallableExtensions, right: CallableExtensions): MergeStrategy<Documentable> =
- MergeStrategy.Replace(CallableExtensions(left.extensions + right.extensions))
- }
-
- override val key: Key = Key
-}
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/InheritedEntriesDocumentableFilterTransformer.kt b/plugins/base/src/main/kotlin/transformers/documentables/InheritedEntriesDocumentableFilterTransformer.kt
deleted file mode 100644
index d9b7053a..00000000
--- a/plugins/base/src/main/kotlin/transformers/documentables/InheritedEntriesDocumentableFilterTransformer.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.transformers.documentables
-
-import org.jetbrains.dokka.model.Documentable
-import org.jetbrains.dokka.model.InheritedMember
-import org.jetbrains.dokka.model.properties.WithExtraProperties
-import org.jetbrains.dokka.plugability.DokkaContext
-
-public class InheritedEntriesDocumentableFilterTransformer(
- context: DokkaContext
-) : SuppressedByConditionDocumentableFilterTransformer(context) {
-
- override fun shouldBeSuppressed(d: Documentable): Boolean {
- @Suppress("UNCHECKED_CAST")
- val inheritedMember = (d as? WithExtraProperties<Documentable>)?.extra?.get(InheritedMember)
- val containsInheritedFrom = inheritedMember?.inheritedFrom?.any { entry -> entry.value != null } ?: false
-
- return context.configuration.suppressInheritedMembers && containsInheritedFrom
- }
-}
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/InheritorsExtractorTransformer.kt b/plugins/base/src/main/kotlin/transformers/documentables/InheritorsExtractorTransformer.kt
deleted file mode 100644
index 2c7d6b89..00000000
--- a/plugins/base/src/main/kotlin/transformers/documentables/InheritorsExtractorTransformer.kt
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.transformers.documentables
-
-import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.model.*
-import org.jetbrains.dokka.model.properties.ExtraProperty
-import org.jetbrains.dokka.model.properties.MergeStrategy
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.transformers.documentation.DocumentableTransformer
-
-public class InheritorsExtractorTransformer : DocumentableTransformer {
- override fun invoke(original: DModule, context: DokkaContext): DModule =
- original.generateInheritanceMap().let { inheritanceMap -> original.appendInheritors(inheritanceMap) as DModule }
-
- private fun <T : Documentable> T.appendInheritors(inheritanceMap: Map<DokkaSourceSet, Map<DRI, List<DRI>>>): Documentable =
- InheritorsInfo(inheritanceMap.getForDRI(dri)).let { info ->
- when (this) {
- is DModule -> copy(packages = packages.map { it.appendInheritors(inheritanceMap) as DPackage })
- is DPackage -> copy(classlikes = classlikes.map { it.appendInheritors(inheritanceMap) as DClasslike })
- is DClass -> if (info.isNotEmpty()) {
- copy(
- extra = extra + info,
- classlikes = classlikes.map { it.appendInheritors(inheritanceMap) as DClasslike })
- } else {
- copy(classlikes = classlikes.map { it.appendInheritors(inheritanceMap) as DClasslike })
- }
- is DEnum -> if (info.isNotEmpty()) {
- copy(
- extra = extra + info,
- classlikes = classlikes.map { it.appendInheritors(inheritanceMap) as DClasslike })
- } else {
- copy(classlikes = classlikes.map { it.appendInheritors(inheritanceMap) as DClasslike })
- }
- is DInterface -> if (info.isNotEmpty()) {
- copy(
- extra = extra + info,
- classlikes = classlikes.map { it.appendInheritors(inheritanceMap) as DClasslike })
- } else {
- copy(classlikes = classlikes.map { it.appendInheritors(inheritanceMap) as DClasslike })
- }
- is DObject -> copy(classlikes = classlikes.map { it.appendInheritors(inheritanceMap) as DClasslike })
- is DAnnotation -> copy(classlikes = classlikes.map { it.appendInheritors(inheritanceMap) as DClasslike })
- else -> this
- }
- }
-
- private fun InheritorsInfo.isNotEmpty() = this.value.values.fold(0) { acc, list -> acc + list.size } > 0
-
- private fun Map<DokkaSourceSet, Map<DRI, List<DRI>>>.getForDRI(dri: DRI) =
- map { (v, k) ->
- v to k[dri]
- }.associate { (k, v) -> k to v.orEmpty() }
-
- private fun DModule.generateInheritanceMap() =
- getInheritanceEntriesRec().filterNot { it.second.isEmpty() }.groupBy({ it.first }) { it.second }
- .map { (k, v) ->
- k to v.flatMap { p -> p.groupBy({ it.first }) { it.second }.toList() }
- .groupBy({ it.first }) { it.second }.map { (k2, v2) -> k2 to v2.flatten() }.toMap()
- }.filter { it.second.values.isNotEmpty() }.toMap()
-
- private fun <T : Documentable> T.getInheritanceEntriesRec(): List<Pair<DokkaSourceSet, List<Pair<DRI, DRI>>>> =
- this.toInheritanceEntries() + children.flatMap { it.getInheritanceEntriesRec() }
-
- private fun <T : Documentable> T.toInheritanceEntries() =
- (this as? WithSupertypes)?.let {
- it.supertypes.map { (k, v) -> k to v.map { it.typeConstructor.dri to dri } }
- }.orEmpty()
-
-}
-
-public class InheritorsInfo(
- public val value: SourceSetDependent<List<DRI>>
-) : ExtraProperty<Documentable> {
- public companion object : ExtraProperty.Key<Documentable, InheritorsInfo> {
- override fun mergeStrategyFor(left: InheritorsInfo, right: InheritorsInfo): MergeStrategy<Documentable> =
- MergeStrategy.Replace(
- InheritorsInfo(
- (left.value.entries.toList() + right.value.entries.toList())
- .groupBy({ it.key }) { it.value }
- .map { (k, v) -> k to v.flatten() }.toMap()
- )
- )
- }
-
- override val key: ExtraProperty.Key<Documentable, *> = InheritorsInfo
-}
-
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/KotlinArrayDocumentableReplacerTransformer.kt b/plugins/base/src/main/kotlin/transformers/documentables/KotlinArrayDocumentableReplacerTransformer.kt
deleted file mode 100644
index 7a360cb8..00000000
--- a/plugins/base/src/main/kotlin/transformers/documentables/KotlinArrayDocumentableReplacerTransformer.kt
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.transformers.documentables
-
-import org.jetbrains.dokka.Platform
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.model.*
-import org.jetbrains.dokka.plugability.DokkaContext
-
-public class KotlinArrayDocumentableReplacerTransformer(
- context: DokkaContext
-): DocumentableReplacerTransformer(context) {
-
- private fun Documentable.isJVM() =
- sourceSets.any{ it.analysisPlatform == Platform.jvm }
-
- override fun processGenericTypeConstructor(genericTypeConstructor: GenericTypeConstructor): AnyWithChanges<GenericTypeConstructor> =
- genericTypeConstructor.takeIf { genericTypeConstructor.dri == DRI("kotlin", "Array") }
- ?.let {
- with(it.projections.firstOrNull() as? Variance<Bound>) {
- with(this?.inner as? GenericTypeConstructor) {
- when (this?.dri) {
- DRI("kotlin", "Int") ->
- AnyWithChanges(
- GenericTypeConstructor(DRI("kotlin", "IntArray"), emptyList()),
- true)
- DRI("kotlin", "Boolean") ->
- AnyWithChanges(
- GenericTypeConstructor(DRI("kotlin", "BooleanArray"), emptyList()),
- true)
- DRI("kotlin", "Float") ->
- AnyWithChanges(
- GenericTypeConstructor(DRI("kotlin", "FloatArray"), emptyList()),
- true)
- DRI("kotlin", "Double") ->
- AnyWithChanges(
- GenericTypeConstructor(DRI("kotlin", "DoubleArray"), emptyList()),
- true)
- DRI("kotlin", "Long") ->
- AnyWithChanges(
- GenericTypeConstructor(DRI("kotlin", "LongArray"), emptyList()),
- true)
- DRI("kotlin", "Short") ->
- AnyWithChanges(
- GenericTypeConstructor(DRI("kotlin", "ShortArray"), emptyList()),
- true)
- DRI("kotlin", "Char") ->
- AnyWithChanges(
- GenericTypeConstructor(DRI("kotlin", "CharArray"), emptyList()),
- true)
- DRI("kotlin", "Byte") ->
- AnyWithChanges(
- GenericTypeConstructor(DRI("kotlin", "ByteArray"), emptyList()),
- true)
- else -> null
- }
- }
- }
- }
- ?: super.processGenericTypeConstructor(genericTypeConstructor)
-
- override fun processModule(module: DModule): AnyWithChanges<DModule> =
- if(module.isJVM())
- super.processModule(module)
- else AnyWithChanges(module)
-}
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/ModuleAndPackageDocumentationTransformer.kt b/plugins/base/src/main/kotlin/transformers/documentables/ModuleAndPackageDocumentationTransformer.kt
deleted file mode 100644
index c19bc15e..00000000
--- a/plugins/base/src/main/kotlin/transformers/documentables/ModuleAndPackageDocumentationTransformer.kt
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.transformers.documentables
-
-import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
-import org.jetbrains.dokka.model.DModule
-import org.jetbrains.dokka.model.SourceSetDependent
-import org.jetbrains.dokka.model.doc.DocumentationNode
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.plugability.plugin
-import org.jetbrains.dokka.plugability.querySingle
-import org.jetbrains.dokka.transformers.documentation.PreMergeDocumentableTransformer
-import org.jetbrains.dokka.analysis.kotlin.internal.InternalKotlinAnalysisPlugin
-import org.jetbrains.dokka.analysis.kotlin.internal.ModuleAndPackageDocumentationReader
-
-internal class ModuleAndPackageDocumentationTransformer(
- private val moduleAndPackageDocumentationReader: ModuleAndPackageDocumentationReader
-) : PreMergeDocumentableTransformer {
-
- constructor(context: DokkaContext) : this(
- context.plugin<InternalKotlinAnalysisPlugin>().querySingle { moduleAndPackageDocumentationReader }
- )
-
- override fun invoke(modules: List<DModule>): List<DModule> {
- return modules.map { module ->
- module.copy(
- documentation = module.documentation + moduleAndPackageDocumentationReader.read(module),
- packages = module.packages.map { pkg ->
- pkg.copy(
- documentation = pkg.documentation + moduleAndPackageDocumentationReader.read(pkg)
- )
- }
- )
- }
- }
-
- private operator fun SourceSetDependent<DocumentationNode>.plus(
- other: SourceSetDependent<DocumentationNode>
- ): Map<DokkaSourceSet, DocumentationNode> =
- (asSequence() + other.asSequence())
- .distinct()
- .groupBy({ it.key }, { it.value })
- .mapValues { (_, values) -> DocumentationNode(values.flatMap { it.children }) }
-
-}
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/ObviousFunctionsDocumentableFilterTransformer.kt b/plugins/base/src/main/kotlin/transformers/documentables/ObviousFunctionsDocumentableFilterTransformer.kt
deleted file mode 100644
index 09c6ac87..00000000
--- a/plugins/base/src/main/kotlin/transformers/documentables/ObviousFunctionsDocumentableFilterTransformer.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.transformers.documentables
-
-import org.jetbrains.dokka.model.DFunction
-import org.jetbrains.dokka.model.Documentable
-import org.jetbrains.dokka.model.ObviousMember
-import org.jetbrains.dokka.plugability.DokkaContext
-
-public class ObviousFunctionsDocumentableFilterTransformer(
- context: DokkaContext
-) : SuppressedByConditionDocumentableFilterTransformer(context) {
- override fun shouldBeSuppressed(d: Documentable): Boolean =
- context.configuration.suppressObviousFunctions && d is DFunction && d.extra[ObviousMember] != null
-}
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/ReportUndocumentedTransformer.kt b/plugins/base/src/main/kotlin/transformers/documentables/ReportUndocumentedTransformer.kt
deleted file mode 100644
index 2b270f18..00000000
--- a/plugins/base/src/main/kotlin/transformers/documentables/ReportUndocumentedTransformer.kt
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.transformers.documentables
-
-import org.jetbrains.dokka.DokkaConfiguration
-import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
-import org.jetbrains.dokka.model.*
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.plugability.plugin
-import org.jetbrains.dokka.plugability.querySingle
-import org.jetbrains.dokka.transformers.documentation.DocumentableTransformer
-import org.jetbrains.dokka.analysis.kotlin.internal.InternalKotlinAnalysisPlugin
-
-internal class ReportUndocumentedTransformer : DocumentableTransformer {
-
- override fun invoke(original: DModule, context: DokkaContext): DModule = original.apply {
- withDescendants().forEach { documentable -> invoke(documentable, context) }
- }
-
- private fun invoke(documentable: Documentable, context: DokkaContext) {
- documentable.sourceSets.forEach { sourceSet ->
- if (shouldBeReportedIfNotDocumented(documentable, sourceSet, context)) {
- reportIfUndocumented(context, documentable, sourceSet)
- }
- }
- }
-
- private fun shouldBeReportedIfNotDocumented(
- documentable: Documentable, sourceSet: DokkaSourceSet, context: DokkaContext
- ): Boolean {
- val packageOptionsOrNull = packageOptionsOrNull(sourceSet, documentable)
-
- if (!(packageOptionsOrNull?.reportUndocumented ?: sourceSet.reportUndocumented)) {
- return false
- }
-
- if (documentable is DParameter || documentable is DPackage || documentable is DModule) {
- return false
- }
-
- if (isConstructor(documentable)) {
- return false
- }
-
- val syntheticDetector = context.plugin<InternalKotlinAnalysisPlugin>().querySingle { syntheticDocumentableDetector }
- if (syntheticDetector.isSynthetic(documentable, sourceSet)) {
- return false
- }
-
- if (isPrivateOrInternalApi(documentable, sourceSet)) {
- return false
- }
-
- return true
- }
-
- private fun reportIfUndocumented(
- context: DokkaContext,
- documentable: Documentable,
- sourceSet: DokkaSourceSet
- ) {
- if (isUndocumented(documentable, sourceSet)) {
- val documentableDescription = with(documentable) {
- buildString {
- dri.packageName?.run {
- append(this)
- append("/")
- }
-
- dri.classNames?.run {
- append(this)
- append("/")
- }
-
- dri.callable?.run {
- append(name)
- append("/")
- append(signature())
- append("/")
- }
-
- val sourceSetName = sourceSet.displayName
- if (sourceSetName != null.toString()) {
- append(" ($sourceSetName)")
- }
- }
- }
-
- context.logger.warn("Undocumented: $documentableDescription")
- }
- }
-
- private fun isUndocumented(documentable: Documentable, sourceSet: DokkaSourceSet): Boolean {
- fun resolveDependentSourceSets(sourceSet: DokkaSourceSet): List<DokkaSourceSet> {
- return sourceSet.dependentSourceSets.mapNotNull { sourceSetID ->
- documentable.sourceSets.singleOrNull { it.sourceSetID == sourceSetID }
- }
- }
-
- fun withAllDependentSourceSets(sourceSet: DokkaSourceSet): Sequence<DokkaSourceSet> = sequence {
- yield(sourceSet)
- for (dependentSourceSet in resolveDependentSourceSets(sourceSet)) {
- yieldAll(withAllDependentSourceSets(dependentSourceSet))
- }
- }
-
-
- return withAllDependentSourceSets(sourceSet).all { sourceSetOrDependentSourceSet ->
- documentable.documentation[sourceSetOrDependentSourceSet]?.children?.isEmpty() ?: true
- }
- }
-
- private fun isConstructor(documentable: Documentable): Boolean {
- if (documentable !is DFunction) return false
- return documentable.isConstructor
- }
-
- private fun isPrivateOrInternalApi(documentable: Documentable, sourceSet: DokkaSourceSet): Boolean {
- return when ((documentable as? WithVisibility)?.visibility?.get(sourceSet)) {
- KotlinVisibility.Public -> false
- KotlinVisibility.Private -> true
- KotlinVisibility.Protected -> true
- KotlinVisibility.Internal -> true
- JavaVisibility.Public -> false
- JavaVisibility.Private -> true
- JavaVisibility.Protected -> true
- JavaVisibility.Default -> true
- null -> false
- }
- }
-
- private fun packageOptionsOrNull(
- dokkaSourceSet: DokkaSourceSet,
- documentable: Documentable
- ): DokkaConfiguration.PackageOptions? {
- val packageName = documentable.dri.packageName ?: return null
- return dokkaSourceSet.perPackageOptions
- .filter { packageOptions -> Regex(packageOptions.matchingRegex).matches(packageName) }
- .maxByOrNull { packageOptions -> packageOptions.matchingRegex.length }
- }
-}
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/SuppressTagDocumentableFilter.kt b/plugins/base/src/main/kotlin/transformers/documentables/SuppressTagDocumentableFilter.kt
deleted file mode 100644
index 1dbf1262..00000000
--- a/plugins/base/src/main/kotlin/transformers/documentables/SuppressTagDocumentableFilter.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.transformers.documentables
-
-import org.jetbrains.dokka.model.Documentable
-import org.jetbrains.dokka.model.dfs
-import org.jetbrains.dokka.model.doc.Suppress
-import org.jetbrains.dokka.plugability.DokkaContext
-
-public class SuppressTagDocumentableFilter(
- public val dokkaContext: DokkaContext
-) : SuppressedByConditionDocumentableFilterTransformer(dokkaContext) {
- override fun shouldBeSuppressed(d: Documentable): Boolean =
- d.documentation.any { (_, docs) -> docs.dfs { it is Suppress } != null }
-}
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/SuppressedByConditionDocumentableFilterTransformer.kt b/plugins/base/src/main/kotlin/transformers/documentables/SuppressedByConditionDocumentableFilterTransformer.kt
deleted file mode 100644
index 4631cece..00000000
--- a/plugins/base/src/main/kotlin/transformers/documentables/SuppressedByConditionDocumentableFilterTransformer.kt
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.transformers.documentables
-
-import org.jetbrains.dokka.model.*
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.transformers.documentation.PreMergeDocumentableTransformer
-
-public abstract class SuppressedByConditionDocumentableFilterTransformer(
- public val context: DokkaContext
-) : PreMergeDocumentableTransformer {
- override fun invoke(modules: List<DModule>): List<DModule> =
- modules.map { module ->
- val (documentable, wasChanged) = processModule(module)
- documentable.takeIf { wasChanged } ?: module
- }
-
- public abstract fun shouldBeSuppressed(d: Documentable): Boolean
-
- private fun processModule(module: DModule): DocumentableWithChanges<DModule> {
- val afterProcessing = module.packages.map { processPackage(it) }
- val processedModule = module.takeIf { afterProcessing.none { it.changed } }
- ?: module.copy(packages = afterProcessing.mapNotNull { it.documentable })
- return DocumentableWithChanges(processedModule, afterProcessing.any { it.changed })
- }
-
- private fun processPackage(dPackage: DPackage): DocumentableWithChanges<DPackage> {
- if (shouldBeSuppressed(dPackage)) return DocumentableWithChanges.filteredDocumentable()
-
- val classlikes = dPackage.classlikes.map { processClassLike(it) }
- val typeAliases = dPackage.typealiases.map { processMember(it) }
- val functions = dPackage.functions.map { processMember(it) }
- val properies = dPackage.properties.map { processProperty(it) }
-
- val wasChanged = (classlikes + typeAliases + functions + properies).any { it.changed }
- return (dPackage.takeIf { !wasChanged } ?: dPackage.copy(
- classlikes = classlikes.mapNotNull { it.documentable },
- typealiases = typeAliases.mapNotNull { it.documentable },
- functions = functions.mapNotNull { it.documentable },
- properties = properies.mapNotNull { it.documentable }
- )).let { processedPackage -> DocumentableWithChanges(processedPackage, wasChanged) }
- }
-
- private fun processClassLike(classlike: DClasslike): DocumentableWithChanges<DClasslike> {
- if (shouldBeSuppressed(classlike)) return DocumentableWithChanges.filteredDocumentable()
-
- val functions = classlike.functions.map { processMember(it) }
- val classlikes = classlike.classlikes.map { processClassLike(it) }
- val properties = classlike.properties.map { processProperty(it) }
- val companion = (classlike as? WithCompanion)?.companion?.let { processClassLike(it) }
-
- val wasClasslikeChanged = (functions + classlikes + properties).any { it.changed } || companion?.changed == true
- return when (classlike) {
- is DClass -> {
- val constructors = classlike.constructors.map { processMember(it) }
- val wasClassChange =
- wasClasslikeChanged || constructors.any { it.changed }
- (classlike.takeIf { !wasClassChange } ?: classlike.copy(
- functions = functions.mapNotNull { it.documentable },
- classlikes = classlikes.mapNotNull { it.documentable },
- properties = properties.mapNotNull { it.documentable },
- constructors = constructors.mapNotNull { it.documentable },
- companion = companion?.documentable as? DObject
- )).let { DocumentableWithChanges(it, wasClassChange) }
- }
- is DInterface -> (classlike.takeIf { !wasClasslikeChanged } ?: classlike.copy(
- functions = functions.mapNotNull { it.documentable },
- classlikes = classlikes.mapNotNull { it.documentable },
- properties = properties.mapNotNull { it.documentable },
- companion = companion?.documentable as? DObject
- )).let { DocumentableWithChanges(it, wasClasslikeChanged) }
- is DObject -> (classlike.takeIf { !wasClasslikeChanged } ?: classlike.copy(
- functions = functions.mapNotNull { it.documentable },
- classlikes = classlikes.mapNotNull { it.documentable },
- properties = properties.mapNotNull { it.documentable },
- )).let { DocumentableWithChanges(it, wasClasslikeChanged) }
- is DAnnotation -> {
- val constructors = classlike.constructors.map { processMember(it) }
- val wasClassChange =
- wasClasslikeChanged || constructors.any { it.changed }
- (classlike.takeIf { !wasClassChange } ?: classlike.copy(
- functions = functions.mapNotNull { it.documentable },
- classlikes = classlikes.mapNotNull { it.documentable },
- properties = properties.mapNotNull { it.documentable },
- constructors = constructors.mapNotNull { it.documentable },
- companion = companion?.documentable as? DObject
- )).let { DocumentableWithChanges(it, wasClassChange) }
- }
- is DEnum -> {
- val constructors = classlike.constructors.map { processMember(it) }
- val entries = classlike.entries.map { processEnumEntry(it) }
- val wasClassChange =
- wasClasslikeChanged || (constructors + entries).any { it.changed }
- (classlike.takeIf { !wasClassChange } ?: classlike.copy(
- functions = functions.mapNotNull { it.documentable },
- classlikes = classlikes.mapNotNull { it.documentable },
- properties = properties.mapNotNull { it.documentable },
- constructors = constructors.mapNotNull { it.documentable },
- companion = companion?.documentable as? DObject,
- entries = entries.mapNotNull { it.documentable }
- )).let { DocumentableWithChanges(it, wasClassChange) }
- }
- }
- }
-
- private fun processEnumEntry(dEnumEntry: DEnumEntry): DocumentableWithChanges<DEnumEntry> {
- if (shouldBeSuppressed(dEnumEntry)) return DocumentableWithChanges.filteredDocumentable()
-
- val functions = dEnumEntry.functions.map { processMember(it) }
- val properties = dEnumEntry.properties.map { processProperty(it) }
- val classlikes = dEnumEntry.classlikes.map { processClassLike(it) }
-
- val wasChanged = (functions + properties + classlikes).any { it.changed }
- return (dEnumEntry.takeIf { !wasChanged } ?: dEnumEntry.copy(
- functions = functions.mapNotNull { it.documentable },
- classlikes = classlikes.mapNotNull { it.documentable },
- properties = properties.mapNotNull { it.documentable },
- )).let { DocumentableWithChanges(it, wasChanged) }
- }
-
- private fun processProperty(dProperty: DProperty): DocumentableWithChanges<DProperty> {
- if (shouldBeSuppressed(dProperty)) return DocumentableWithChanges.filteredDocumentable()
-
- val getter = dProperty.getter?.let { processMember(it) } ?: DocumentableWithChanges(null, false)
- val setter = dProperty.setter?.let { processMember(it) } ?: DocumentableWithChanges(null, false)
-
- val wasChanged = getter.changed || setter.changed
- return (dProperty.takeIf { !wasChanged } ?: dProperty.copy(
- getter = getter.documentable,
- setter = setter.documentable
- )).let { DocumentableWithChanges(it, wasChanged) }
- }
-
- private fun <T : Documentable> processMember(member: T): DocumentableWithChanges<T> =
- if (shouldBeSuppressed(member)) DocumentableWithChanges.filteredDocumentable()
- else DocumentableWithChanges(member, false)
-
- private data class DocumentableWithChanges<T : Documentable>(val documentable: T?, val changed: Boolean = false) {
- companion object {
- fun <T : Documentable> filteredDocumentable(): DocumentableWithChanges<T> =
- DocumentableWithChanges(null, true)
- }
- }
-}
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/SuppressedByConfigurationDocumentableFilterTransformer.kt b/plugins/base/src/main/kotlin/transformers/documentables/SuppressedByConfigurationDocumentableFilterTransformer.kt
deleted file mode 100644
index 3195f88d..00000000
--- a/plugins/base/src/main/kotlin/transformers/documentables/SuppressedByConfigurationDocumentableFilterTransformer.kt
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.transformers.documentables
-
-import org.jetbrains.dokka.model.*
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.transformers.documentation.PreMergeDocumentableTransformer
-import org.jetbrains.dokka.transformers.documentation.perPackageOptions
-import org.jetbrains.dokka.transformers.documentation.source
-import org.jetbrains.dokka.transformers.documentation.sourceSet
-import java.io.File
-
-public class SuppressedByConfigurationDocumentableFilterTransformer(
- public val context: DokkaContext
-) : PreMergeDocumentableTransformer {
- override fun invoke(modules: List<DModule>): List<DModule> {
- return modules.mapNotNull(::filterModule)
- }
-
- private fun filterModule(module: DModule): DModule? {
- val packages = module.packages.mapNotNull { pkg -> filterPackage(pkg) }
- return when {
- packages == module.packages -> module
- packages.isEmpty() -> null
- else -> module.copy(packages = packages)
- }
- }
-
- private fun filterPackage(pkg: DPackage): DPackage? {
- val options = perPackageOptions(pkg)
- if (options?.suppress == true) {
- return null
- }
-
- val filteredChildren = pkg.children.filterNot(::isSuppressed)
- return when {
- filteredChildren == pkg.children -> pkg
- filteredChildren.isEmpty() -> null
- else -> pkg.copy(
- functions = filteredChildren.filterIsInstance<DFunction>(),
- classlikes = filteredChildren.filterIsInstance<DClasslike>(),
- typealiases = filteredChildren.filterIsInstance<DTypeAlias>(),
- properties = filteredChildren.filterIsInstance<DProperty>()
- )
- }
- }
-
- private fun isSuppressed(documentable: Documentable): Boolean {
- if (documentable !is WithSources) return false
- val sourceFile = File(source(documentable).path).absoluteFile
- return sourceSet(documentable).suppressedFiles.any { suppressedFile ->
- sourceFile.startsWith(suppressedFile.absoluteFile)
- }
- }
-}
diff --git a/plugins/base/src/main/kotlin/transformers/documentables/utils.kt b/plugins/base/src/main/kotlin/transformers/documentables/utils.kt
deleted file mode 100644
index 60a6396a..00000000
--- a/plugins/base/src/main/kotlin/transformers/documentables/utils.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.transformers.documentables
-
-import org.jetbrains.dokka.model.Annotations
-import org.jetbrains.dokka.model.Documentable
-import org.jetbrains.dokka.model.ExceptionInSupertypes
-import org.jetbrains.dokka.model.properties.WithExtraProperties
-
-public val <T : Documentable> WithExtraProperties<T>.isException: Boolean
- get() = extra[ExceptionInSupertypes] != null
-
-
-public val <T : Documentable> WithExtraProperties<T>.deprecatedAnnotation: Annotations.Annotation?
- get() = extra[Annotations]?.let { annotations ->
- annotations.directAnnotations.values.flatten().firstOrNull {
- it.isDeprecated()
- }
- }
-
-/**
- * @return true if [T] has [kotlin.Deprecated] or [java.lang.Deprecated]
- * annotation for **any** source set
- */
-public fun <T : Documentable> WithExtraProperties<T>.isDeprecated(): Boolean = deprecatedAnnotation != null
-
-/**
- * @return true for [kotlin.Deprecated] and [java.lang.Deprecated]
- */
-public fun Annotations.Annotation.isDeprecated(): Boolean {
- return (this.dri.packageName == "kotlin" && this.dri.classNames == "Deprecated") ||
- (this.dri.packageName == "java.lang" && this.dri.classNames == "Deprecated")
-}
diff --git a/plugins/base/src/main/kotlin/transformers/pages/DefaultSamplesTransformer.kt b/plugins/base/src/main/kotlin/transformers/pages/DefaultSamplesTransformer.kt
deleted file mode 100644
index 1ba049c8..00000000
--- a/plugins/base/src/main/kotlin/transformers/pages/DefaultSamplesTransformer.kt
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.transformers.pages
-
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.model.DisplaySourceSet
-import org.jetbrains.dokka.model.doc.Sample
-import org.jetbrains.dokka.model.properties.PropertyContainer
-import org.jetbrains.dokka.pages.*
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.plugability.plugin
-import org.jetbrains.dokka.plugability.querySingle
-import org.jetbrains.dokka.transformers.pages.PageTransformer
-import org.jetbrains.dokka.analysis.kotlin.internal.InternalKotlinAnalysisPlugin
-import org.jetbrains.dokka.analysis.kotlin.internal.SampleProvider
-import org.jetbrains.dokka.analysis.kotlin.internal.SampleProviderFactory
-
-internal const val KOTLIN_PLAYGROUND_SCRIPT = "https://unpkg.com/kotlin-playground@1/dist/playground.min.js"
-
-internal class DefaultSamplesTransformer(val context: DokkaContext) : PageTransformer {
-
- private val sampleProviderFactory: SampleProviderFactory = context.plugin<InternalKotlinAnalysisPlugin>().querySingle { sampleProviderFactory }
-
- override fun invoke(input: RootPageNode): RootPageNode {
- return sampleProviderFactory.build().use { sampleProvider ->
- input.transformContentPagesTree { page ->
- val samples = (page as? WithDocumentables)?.documentables?.flatMap {
- it.documentation.entries.flatMap { entry ->
- entry.value.children.filterIsInstance<Sample>().map { entry.key to it }
- }
- } ?: return@transformContentPagesTree page
-
- val newContent = samples.fold(page.content) { acc, (sampleSourceSet, sample) ->
- sampleProvider.getSample(sampleSourceSet, sample.name)
- ?.let {
- acc.addSample(page, sample.name, it)
- } ?: acc
- }
-
- page.modified(
- content = newContent,
- embeddedResources = page.embeddedResources + KOTLIN_PLAYGROUND_SCRIPT
- )
- }
- }
- }
-
-
- private fun ContentNode.addSample(
- contentPage: ContentPage,
- fqLink: String,
- sample: SampleProvider.SampleSnippet,
- ): ContentNode {
- val node = contentCode(contentPage.content.sourceSets, contentPage.dri, createSampleBody(sample.imports, sample.body), "kotlin")
- return dfs(fqLink, node)
- }
-
- fun createSampleBody(imports: String, body: String) =
- """ |$imports
- |fun main() {
- | //sampleStart
- | $body
- | //sampleEnd
- |}""".trimMargin()
-
- private fun ContentNode.dfs(fqName: String, node: ContentCodeBlock): ContentNode {
- return when (this) {
- is ContentHeader -> copy(children.map { it.dfs(fqName, node) })
- is ContentDivergentGroup -> @Suppress("UNCHECKED_CAST") copy(children.map {
- it.dfs(fqName, node)
- } as List<ContentDivergentInstance>)
- is ContentDivergentInstance -> copy(
- before.let { it?.dfs(fqName, node) },
- divergent.dfs(fqName, node),
- after.let { it?.dfs(fqName, node) })
- is ContentCodeBlock -> copy(children.map { it.dfs(fqName, node) })
- is ContentCodeInline -> copy(children.map { it.dfs(fqName, node) })
- is ContentDRILink -> copy(children.map { it.dfs(fqName, node) })
- is ContentResolvedLink -> copy(children.map { it.dfs(fqName, node) })
- is ContentEmbeddedResource -> copy(children.map { it.dfs(fqName, node) })
- is ContentTable -> copy(children = children.map { it.dfs(fqName, node) as ContentGroup })
- is ContentList -> copy(children.map { it.dfs(fqName, node) })
- is ContentGroup -> copy(children.map { it.dfs(fqName, node) })
- is PlatformHintedContent -> copy(inner.dfs(fqName, node))
- is ContentText -> if (text == fqName) node else this
- is ContentBreakLine -> this
- else -> this.also { context.logger.error("Could not recognize $this ContentNode in SamplesTransformer") }
- }
- }
-
- private fun contentCode(
- sourceSets: Set<DisplaySourceSet>,
- dri: Set<DRI>,
- content: String,
- language: String,
- styles: Set<Style> = emptySet(),
- extra: PropertyContainer<ContentNode> = PropertyContainer.empty()
- ) =
- ContentCodeBlock(
- children = listOf(
- ContentText(
- text = content,
- dci = DCI(dri, ContentKind.Sample),
- sourceSets = sourceSets,
- style = emptySet(),
- extra = PropertyContainer.empty()
- )
- ),
- language = language,
- dci = DCI(dri, ContentKind.Sample),
- sourceSets = sourceSets,
- style = styles + ContentStyle.RunnableSample + TextStyle.Monospace,
- extra = extra
- )
-}
diff --git a/plugins/base/src/main/kotlin/transformers/pages/annotations/SinceKotlinTransformer.kt b/plugins/base/src/main/kotlin/transformers/pages/annotations/SinceKotlinTransformer.kt
deleted file mode 100644
index 9ff5960d..00000000
--- a/plugins/base/src/main/kotlin/transformers/pages/annotations/SinceKotlinTransformer.kt
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.transformers.pages.annotations
-
-
-import org.jetbrains.dokka.DokkaConfiguration
-import org.jetbrains.dokka.Platform
-import org.jetbrains.dokka.analysis.markdown.jb.MARKDOWN_ELEMENT_FILE_NAME
-import org.jetbrains.dokka.base.signatures.KotlinSignatureUtils.annotations
-import org.jetbrains.dokka.model.*
-import org.jetbrains.dokka.model.doc.CustomDocTag
-import org.jetbrains.dokka.model.doc.CustomTagWrapper
-import org.jetbrains.dokka.model.doc.DocumentationNode
-import org.jetbrains.dokka.model.doc.Text
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.transformers.documentation.DocumentableTransformer
-import org.jetbrains.dokka.utilities.associateWithNotNull
-
-public class SinceKotlinVersion(str: String) : Comparable<SinceKotlinVersion> {
- private val parts: List<Int> = str.split(".").map { it.toInt() }
-
- /**
- * Corner case: 1.0 == 1.0.0
- */
- override fun compareTo(other: SinceKotlinVersion): Int {
- val i1 = parts.listIterator()
- val i2 = other.parts.listIterator()
-
- while (i1.hasNext() || i2.hasNext()) {
- val diff = (if (i1.hasNext()) i1.next() else 0) - (if (i2.hasNext()) i2.next() else 0)
- if (diff != 0) return diff
- }
-
- return 0
- }
-
- override fun toString(): String = parts.joinToString(".")
-}
-
-public class SinceKotlinTransformer(
- public val context: DokkaContext
-) : DocumentableTransformer {
-
- private val minSinceKotlinVersionOfPlatform = mapOf(
- Platform.common to SinceKotlinVersion("1.0"),
- Platform.jvm to SinceKotlinVersion("1.0"),
- Platform.js to SinceKotlinVersion("1.1"),
- Platform.native to SinceKotlinVersion("1.3"),
- Platform.wasm to SinceKotlinVersion("1.8"),
- )
-
- override fun invoke(original: DModule, context: DokkaContext): DModule = original.transform() as DModule
-
- private fun <T : Documentable> T.transform(parent: SourceSetDependent<SinceKotlinVersion>? = null): Documentable {
- val versions = calculateVersions(parent)
- return when (this) {
- is DModule -> copy(
- packages = packages.map { it.transform() as DPackage }
- )
-
- is DPackage -> copy(
- classlikes = classlikes.map { it.transform() as DClasslike },
- functions = functions.map { it.transform() as DFunction },
- properties = properties.map { it.transform() as DProperty },
- typealiases = typealiases.map { it.transform() as DTypeAlias }
- )
-
- is DClass -> copy(
- documentation = appendSinceKotlin(versions),
- classlikes = classlikes.map { it.transform(versions) as DClasslike },
- functions = functions.map { it.transform(versions) as DFunction },
- properties = properties.map { it.transform(versions) as DProperty }
- )
-
- is DEnum -> copy(
- documentation = appendSinceKotlin(versions),
- classlikes = classlikes.map { it.transform(versions) as DClasslike },
- functions = functions.map { it.transform(versions) as DFunction },
- properties = properties.map { it.transform(versions) as DProperty }
- )
-
- is DInterface -> copy(
- documentation = appendSinceKotlin(versions),
- classlikes = classlikes.map { it.transform(versions) as DClasslike },
- functions = functions.map { it.transform(versions) as DFunction },
- properties = properties.map { it.transform(versions) as DProperty }
- )
-
- is DObject -> copy(
- documentation = appendSinceKotlin(versions),
- classlikes = classlikes.map { it.transform(versions) as DClasslike },
- functions = functions.map { it.transform(versions) as DFunction },
- properties = properties.map { it.transform(versions) as DProperty }
- )
-
- is DTypeAlias -> copy(
- documentation = appendSinceKotlin(versions)
- )
-
- is DAnnotation -> copy(
- documentation = appendSinceKotlin(versions),
- classlikes = classlikes.map { it.transform(versions) as DClasslike },
- functions = functions.map { it.transform(versions) as DFunction },
- properties = properties.map { it.transform(versions) as DProperty }
- )
-
- is DFunction -> copy(
- documentation = appendSinceKotlin(versions)
- )
-
- is DProperty -> copy(
- documentation = appendSinceKotlin(versions)
- )
-
- is DParameter -> copy(
- documentation = appendSinceKotlin(versions)
- )
-
- else -> this.also { context.logger.warn("Unrecognized documentable $this while SinceKotlin transformation") }
- }
- }
-
- private fun List<Annotations.Annotation>.findSinceKotlinAnnotation(): Annotations.Annotation? =
- this.find { it.dri.packageName == "kotlin" && it.dri.classNames == "SinceKotlin" }
-
- private fun Documentable.getVersion(sourceSet: DokkaConfiguration.DokkaSourceSet): SinceKotlinVersion {
- val annotatedVersion =
- annotations()[sourceSet]
- ?.findSinceKotlinAnnotation()
- ?.params?.let { it["version"] as? StringValue }?.value
- ?.let { SinceKotlinVersion(it) }
-
- val minSinceKotlin = minSinceKotlinVersionOfPlatform[sourceSet.analysisPlatform]
- ?: throw IllegalStateException("No value for platform: ${sourceSet.analysisPlatform}")
-
- return annotatedVersion?.takeIf { version -> version >= minSinceKotlin } ?: minSinceKotlin
- }
-
-
- private fun Documentable.calculateVersions(parent: SourceSetDependent<SinceKotlinVersion>?): SourceSetDependent<SinceKotlinVersion> {
- return sourceSets.associateWithNotNull { sourceSet ->
- val version = getVersion(sourceSet)
- val parentVersion = parent?.get(sourceSet)
- if (parentVersion != null)
- maxOf(version, parentVersion)
- else
- version
- }
- }
-
- private fun Documentable.appendSinceKotlin(versions: SourceSetDependent<SinceKotlinVersion>) =
- sourceSets.fold(documentation) { acc, sourceSet ->
-
- val version = versions[sourceSet]
-
- val sinceKotlinCustomTag = CustomTagWrapper(
- CustomDocTag(
- listOf(
- Text(
- version.toString()
- )
- ),
- name = MARKDOWN_ELEMENT_FILE_NAME
- ),
- "Since Kotlin"
- )
- if (acc[sourceSet] == null)
- acc + (sourceSet to DocumentationNode(listOf(sinceKotlinCustomTag)))
- else
- acc.mapValues {
- if (it.key == sourceSet) it.value.copy(
- it.value.children + listOf(
- sinceKotlinCustomTag
- )
- ) else it.value
- }
- }
-
- internal companion object {
- internal const val SHOULD_DISPLAY_SINCE_KOTLIN_SYS_PROP = "dokka.shouldDisplaySinceKotlin"
- internal fun shouldDisplaySinceKotlin() =
- System.getProperty(SHOULD_DISPLAY_SINCE_KOTLIN_SYS_PROP) in listOf("true", "1")
- }
-}
diff --git a/plugins/base/src/main/kotlin/transformers/pages/comments/CommentsToContentConverter.kt b/plugins/base/src/main/kotlin/transformers/pages/comments/CommentsToContentConverter.kt
deleted file mode 100644
index 6ca3f8d0..00000000
--- a/plugins/base/src/main/kotlin/transformers/pages/comments/CommentsToContentConverter.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.transformers.pages.comments
-
-import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
-import org.jetbrains.dokka.model.doc.DocTag
-import org.jetbrains.dokka.model.properties.PropertyContainer
-import org.jetbrains.dokka.pages.ContentNode
-import org.jetbrains.dokka.pages.DCI
-import org.jetbrains.dokka.pages.Style
-
-public interface CommentsToContentConverter {
- public fun buildContent(
- docTag: DocTag,
- dci: DCI,
- sourceSets: Set<DokkaSourceSet>,
- styles: Set<Style> = emptySet(),
- extras: PropertyContainer<ContentNode> = PropertyContainer.empty()
- ): List<ContentNode>
-}
diff --git a/plugins/base/src/main/kotlin/transformers/pages/comments/DocTagToContentConverter.kt b/plugins/base/src/main/kotlin/transformers/pages/comments/DocTagToContentConverter.kt
deleted file mode 100644
index e4e0f53f..00000000
--- a/plugins/base/src/main/kotlin/transformers/pages/comments/DocTagToContentConverter.kt
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.transformers.pages.comments
-
-
-import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
-import org.jetbrains.dokka.analysis.markdown.jb.MARKDOWN_ELEMENT_FILE_NAME
-import org.jetbrains.dokka.model.doc.*
-import org.jetbrains.dokka.model.properties.PropertyContainer
-import org.jetbrains.dokka.model.properties.plus
-import org.jetbrains.dokka.model.toDisplaySourceSets
-import org.jetbrains.dokka.pages.*
-import org.jetbrains.dokka.utilities.firstIsInstanceOrNull
-
-public open class DocTagToContentConverter : CommentsToContentConverter {
- override fun buildContent(
- docTag: DocTag,
- dci: DCI,
- sourceSets: Set<DokkaSourceSet>,
- styles: Set<Style>,
- extras: PropertyContainer<ContentNode>
- ): List<ContentNode> {
-
- fun buildChildren(docTag: DocTag, newStyles: Set<Style> = emptySet(), newExtras: SimpleAttr? = null) =
- docTag.children.flatMap {
- buildContent(it, dci, sourceSets, styles + newStyles, newExtras?.let { extras + it } ?: extras)
- }
-
- fun buildTableRows(rows: List<DocTag>, newStyle: Style): List<ContentGroup> =
- rows.flatMap {
- @Suppress("UNCHECKED_CAST")
- buildContent(it, dci, sourceSets, styles + newStyle, extras) as List<ContentGroup>
- }
-
- fun buildHeader(level: Int) =
- listOf(
- ContentHeader(
- buildChildren(docTag),
- level,
- dci,
- sourceSets.toDisplaySourceSets(),
- styles
- )
- )
-
- fun buildList(ordered: Boolean, newStyles: Set<Style> = emptySet(), start: Int = 1) =
- listOf(
- ContentList(
- buildChildren(docTag),
- ordered,
- dci,
- sourceSets.toDisplaySourceSets(),
- styles + newStyles,
- ((PropertyContainer.empty<ContentNode>()) + SimpleAttr("start", start.toString()))
- )
- )
-
- fun buildNewLine() = listOf(
- ContentBreakLine(
- sourceSets.toDisplaySourceSets()
- )
- )
-
- fun P.collapseParagraphs(): P =
- if (children.size == 1 && children.first() is P) (children.first() as P).collapseParagraphs() else this
-
- return when (docTag) {
- is H1 -> buildHeader(1)
- is H2 -> buildHeader(2)
- is H3 -> buildHeader(3)
- is H4 -> buildHeader(4)
- is H5 -> buildHeader(5)
- is H6 -> buildHeader(6)
- is Ul -> buildList(false)
- is Ol -> buildList(true, start = docTag.params["start"]?.toInt() ?: 1)
- is Li -> listOf(
- ContentGroup(buildChildren(docTag), dci, sourceSets.toDisplaySourceSets(), styles, extras)
- )
- is Dl -> buildList(false, newStyles = setOf(ListStyle.DescriptionList))
- is Dt -> listOf(
- ContentGroup(
- buildChildren(docTag),
- dci,
- sourceSets.toDisplaySourceSets(),
- styles + ListStyle.DescriptionTerm
- )
- )
- is Dd -> listOf(
- ContentGroup(
- buildChildren(docTag),
- dci,
- sourceSets.toDisplaySourceSets(),
- styles + ListStyle.DescriptionDetails
- )
- )
- is Br -> buildNewLine()
- is B -> buildChildren(docTag, setOf(TextStyle.Strong))
- is I -> buildChildren(docTag, setOf(TextStyle.Italic))
- is P -> listOf(
- ContentGroup(
- buildChildren(docTag.collapseParagraphs()),
- dci,
- sourceSets.toDisplaySourceSets(),
- styles + setOf(TextStyle.Paragraph),
- extras
- )
- )
- is A -> listOf(
- ContentResolvedLink(
- buildChildren(docTag),
- docTag.params.getValue("href"),
- dci,
- sourceSets.toDisplaySourceSets(),
- styles
- )
- )
- is DocumentationLink -> listOf(
- ContentDRILink(
- buildChildren(docTag),
- docTag.dri,
- DCI(
- setOf(docTag.dri),
- ContentKind.Main
- ),
- sourceSets.toDisplaySourceSets(),
- styles
- )
- )
- is BlockQuote -> listOf(
- ContentGroup(
- buildChildren(docTag),
- dci,
- sourceSets.toDisplaySourceSets(),
- styles + TextStyle.Quotation,
- )
- )
- is Pre, is CodeBlock -> listOf(
- ContentCodeBlock(
- buildChildren(docTag),
- docTag.params.getOrDefault("lang", ""),
- dci,
- sourceSets.toDisplaySourceSets(),
- styles
- )
- )
- is CodeInline -> listOf(
- ContentCodeInline(
- buildChildren(docTag),
- "",
- dci,
- sourceSets.toDisplaySourceSets(),
- styles
- )
- )
- is Img -> listOf(
- ContentEmbeddedResource(
- address = docTag.params["href"]!!,
- altText = docTag.params["alt"],
- dci = dci,
- sourceSets = sourceSets.toDisplaySourceSets(),
- style = styles,
- extra = extras
- )
- )
- is HorizontalRule -> listOf(
- ContentText(
- "",
- dci,
- sourceSets.toDisplaySourceSets(),
- setOf()
- )
- )
- is Text -> listOf(
- ContentText(
- docTag.body,
- dci,
- sourceSets.toDisplaySourceSets(),
- styles,
- extras + HtmlContent.takeIf { docTag.params["content-type"] == "html" }
- )
- )
- is Strikethrough -> buildChildren(docTag, setOf(TextStyle.Strikethrough))
- is Table -> {
- //https://html.spec.whatwg.org/multipage/tables.html#the-caption-element
- if (docTag.children.any { it is TBody }) {
- val head = docTag.children.filterIsInstance<THead>().flatMap { it.children }
- val body = docTag.children.filterIsInstance<TBody>().flatMap { it.children }
- listOf(
- ContentTable(
- header = buildTableRows(head.filterIsInstance<Th>(), CommentTable),
- caption = docTag.children.firstIsInstanceOrNull<Caption>()?.let {
- ContentGroup(
- buildContent(it, dci, sourceSets),
- dci,
- sourceSets.toDisplaySourceSets(),
- styles,
- extras
- )
- },
- buildTableRows(body.filterIsInstance<Tr>(), CommentTable),
- dci,
- sourceSets.toDisplaySourceSets(),
- styles + CommentTable
- )
- )
- } else {
- listOf(
- ContentTable(
- header = buildTableRows(docTag.children.filterIsInstance<Th>(), CommentTable),
- caption = null,
- buildTableRows(docTag.children.filterIsInstance<Tr>(), CommentTable),
- dci,
- sourceSets.toDisplaySourceSets(),
- styles + CommentTable
- )
- )
- }
- }
- is Th,
- is Tr -> listOf(
- ContentGroup(
- docTag.children.map {
- ContentGroup(buildChildren(it), dci, sourceSets.toDisplaySourceSets(), styles, extras)
- },
- dci,
- sourceSets.toDisplaySourceSets(),
- styles
- )
- )
- is Index -> listOf(
- ContentGroup(
- buildChildren(docTag, newStyles = styles + ContentStyle.InDocumentationAnchor),
- dci,
- sourceSets.toDisplaySourceSets(),
- styles
- )
- )
- is CustomDocTag -> if (docTag.isNonemptyFile()) {
- listOf(
- ContentGroup(
- buildChildren(docTag),
- dci,
- sourceSets.toDisplaySourceSets(),
- styles,
- extra = extras
- )
- )
- } else {
- buildChildren(docTag)
- }
- is Caption -> listOf(
- ContentGroup(
- buildChildren(docTag),
- dci,
- sourceSets.toDisplaySourceSets(),
- styles + ContentStyle.Caption,
- extra = extras
- )
- )
- is Var -> buildChildren(docTag, setOf(TextStyle.Var))
- is U -> buildChildren(docTag, setOf(TextStyle.Underlined))
-
- else -> buildChildren(docTag)
- }
- }
-
- private fun CustomDocTag.isNonemptyFile() = name == MARKDOWN_ELEMENT_FILE_NAME && children.size > 1
-}
diff --git a/plugins/base/src/main/kotlin/transformers/pages/merger/FallbackPageMergerStrategy.kt b/plugins/base/src/main/kotlin/transformers/pages/merger/FallbackPageMergerStrategy.kt
deleted file mode 100644
index 80886cc5..00000000
--- a/plugins/base/src/main/kotlin/transformers/pages/merger/FallbackPageMergerStrategy.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.transformers.pages.merger
-
-import org.jetbrains.dokka.pages.ContentPage
-import org.jetbrains.dokka.pages.PageNode
-import org.jetbrains.dokka.utilities.DokkaLogger
-
-public class FallbackPageMergerStrategy(
- private val logger: DokkaLogger
-) : PageMergerStrategy {
- override fun tryMerge(pages: List<PageNode>, path: List<String>): List<PageNode> {
- pages.map {
- (it as? ContentPage)
- }
- val renderedPath = path.joinToString(separator = "/")
- if (pages.size != 1) logger.warn("For $renderedPath: expected 1 page, but got ${pages.size}")
- return listOf(pages.first())
- }
-}
diff --git a/plugins/base/src/main/kotlin/transformers/pages/merger/PageMerger.kt b/plugins/base/src/main/kotlin/transformers/pages/merger/PageMerger.kt
deleted file mode 100644
index e52c233c..00000000
--- a/plugins/base/src/main/kotlin/transformers/pages/merger/PageMerger.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.transformers.pages.merger
-
-import org.jetbrains.dokka.base.DokkaBase
-import org.jetbrains.dokka.pages.PageNode
-import org.jetbrains.dokka.pages.RootPageNode
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.plugability.plugin
-import org.jetbrains.dokka.plugability.query
-import org.jetbrains.dokka.transformers.pages.PageTransformer
-
-public class PageMerger(context: DokkaContext) : PageTransformer {
-
- private val strategies: Iterable<PageMergerStrategy> = context.plugin<DokkaBase>().query { pageMergerStrategy }
-
- override fun invoke(input: RootPageNode): RootPageNode =
- input.modified(children = input.children.map { it.mergeChildren(emptyList()) })
-
- private fun PageNode.mergeChildren(path: List<String>): PageNode = children.groupBy { it::class }.map {
- it.value.groupBy { it.name }.map { (n, v) -> mergePageNodes(v, path + n) }.map { it.assertSingle(path) }
- }.let { pages ->
- modified(children = pages.flatten().map { it.mergeChildren(path + it.name) })
- }
-
- private fun mergePageNodes(pages: List<PageNode>, path: List<String>): List<PageNode> =
- strategies.fold(pages) { acc, strategy -> tryMerge(strategy, acc, path) }
-
- private fun tryMerge(strategy: PageMergerStrategy, pages: List<PageNode>, path: List<String>) =
- if (pages.size > 1) strategy.tryMerge(pages, path) else pages
-}
-
-private fun <T> Iterable<T>.assertSingle(path: List<String>): T = try {
- single()
- } catch (e: Exception) {
- val renderedPath = path.joinToString(separator = "/")
- throw IllegalStateException("Page merger is misconfigured. Error for $renderedPath: ${e.message}")
- }
diff --git a/plugins/base/src/main/kotlin/transformers/pages/merger/PageMergerStrategy.kt b/plugins/base/src/main/kotlin/transformers/pages/merger/PageMergerStrategy.kt
deleted file mode 100644
index ea1b1f03..00000000
--- a/plugins/base/src/main/kotlin/transformers/pages/merger/PageMergerStrategy.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.transformers.pages.merger
-
-import org.jetbrains.dokka.pages.PageNode
-
-public fun interface PageMergerStrategy {
-
- public fun tryMerge(pages: List<PageNode>, path: List<String>): List<PageNode>
-
-}
diff --git a/plugins/base/src/main/kotlin/transformers/pages/merger/SameMethodNamePageMergerStrategy.kt b/plugins/base/src/main/kotlin/transformers/pages/merger/SameMethodNamePageMergerStrategy.kt
deleted file mode 100644
index 864545e6..00000000
--- a/plugins/base/src/main/kotlin/transformers/pages/merger/SameMethodNamePageMergerStrategy.kt
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.transformers.pages.merger
-
-import org.jetbrains.dokka.base.renderers.sourceSets
-import org.jetbrains.dokka.base.transformers.documentables.isDeprecated
-import org.jetbrains.dokka.model.DisplaySourceSet
-import org.jetbrains.dokka.model.Documentable
-import org.jetbrains.dokka.model.dfs
-import org.jetbrains.dokka.model.properties.WithExtraProperties
-import org.jetbrains.dokka.pages.*
-import org.jetbrains.dokka.utilities.DokkaLogger
-
-/**
- * Merges [MemberPage] elements that have the same name.
- * That includes **both** properties and functions.
- */
-public class SameMethodNamePageMergerStrategy(
- public val logger: DokkaLogger
-) : PageMergerStrategy {
- override fun tryMerge(pages: List<PageNode>, path: List<String>): List<PageNode> {
- val members = pages
- .filterIsInstance<MemberPageNode>()
- .takeIf { it.isNotEmpty() }
- ?.sortedBy { it.containsDeprecatedDocumentables() } // non-deprecated first
- ?: return pages
-
- val name = pages.first().name.also {
- if (pages.any { page -> page.name != it }) { // Is this even possible?
- logger.error("Page names for $it do not match!")
- }
- }
- val dri = members.flatMap { it.dri }.toSet()
-
-
- val merged = MemberPageNode(
- dri = dri,
- name = name,
- children = members.flatMap { it.children }.distinct(),
- content = squashDivergentInstances(members).withSourceSets(members.allSourceSets()),
- embeddedResources = members.flatMap { it.embeddedResources }.distinct(),
- documentables = members.flatMap { it.documentables }
- )
-
- return (pages - members) + listOf(merged)
- }
-
- @Suppress("UNCHECKED_CAST")
- private fun MemberPageNode.containsDeprecatedDocumentables() =
- this.documentables.any { (it as? WithExtraProperties<Documentable>)?.isDeprecated() == true }
-
- private fun List<MemberPageNode>.allSourceSets(): Set<DisplaySourceSet> =
- fold(emptySet()) { acc, e -> acc + e.sourceSets() }
-
- private fun squashDivergentInstances(nodes: List<MemberPageNode>): ContentNode =
- nodes.map { it.content }
- .reduce { acc, node ->
- acc.mapTransform<ContentDivergentGroup, ContentNode> { g ->
- g.copy(children = (g.children +
- ((node.dfs { it is ContentDivergentGroup && it.groupID == g.groupID } as? ContentDivergentGroup)
- ?.children ?: emptyList())
- )
- )
- }
- }
-}
diff --git a/plugins/base/src/main/kotlin/transformers/pages/merger/SourceSetMergingPageTransformer.kt b/plugins/base/src/main/kotlin/transformers/pages/merger/SourceSetMergingPageTransformer.kt
deleted file mode 100644
index 8d52a39d..00000000
--- a/plugins/base/src/main/kotlin/transformers/pages/merger/SourceSetMergingPageTransformer.kt
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.transformers.pages.merger
-
-import org.jetbrains.dokka.Platform
-import org.jetbrains.dokka.model.DisplaySourceSet
-import org.jetbrains.dokka.model.toDisplaySourceSets
-import org.jetbrains.dokka.pages.ContentComposite
-import org.jetbrains.dokka.pages.ContentNode
-import org.jetbrains.dokka.pages.RootPageNode
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.transformers.pages.PageTransformer
-
-public class SourceSetMergingPageTransformer(context: DokkaContext) : PageTransformer {
-
- private val mergedSourceSets = context.configuration.sourceSets.toDisplaySourceSets()
- .associateBy { sourceSet -> sourceSet.key }
-
- override fun invoke(input: RootPageNode): RootPageNode {
- return input.transformContentPagesTree { contentPage ->
- val content: ContentNode = contentPage.content
- contentPage.modified(content = transformWithMergedSourceSets(content))
- }
- }
-
- private fun transformWithMergedSourceSets(
- contentNode: ContentNode
- ): ContentNode {
- val mergedSourceSets = contentNode.sourceSets.map { mergedSourceSets.getValue(it.key) }.toSet()
- return when (contentNode) {
- is ContentComposite -> contentNode
- .transformChildren(::transformWithMergedSourceSets)
- .withSourceSets(mergedSourceSets)
- else -> contentNode.withSourceSets(mergedSourceSets.toSet())
- }
- }
-}
-
-private val DisplaySourceSet.key get() = SourceSetMergingKey(name, platform)
-
-private data class SourceSetMergingKey(private val displayName: String, private val platform: Platform)
diff --git a/plugins/base/src/main/kotlin/transformers/pages/sourcelinks/SourceLinksTransformer.kt b/plugins/base/src/main/kotlin/transformers/pages/sourcelinks/SourceLinksTransformer.kt
deleted file mode 100644
index 80eeca7e..00000000
--- a/plugins/base/src/main/kotlin/transformers/pages/sourcelinks/SourceLinksTransformer.kt
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.transformers.pages.sourcelinks
-
-import org.jetbrains.dokka.DokkaConfiguration
-import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
-import org.jetbrains.dokka.base.DokkaBase
-import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.model.*
-import org.jetbrains.dokka.pages.*
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.plugability.plugin
-import org.jetbrains.dokka.plugability.querySingle
-import org.jetbrains.dokka.transformers.pages.PageTransformer
-import java.io.File
-
-public class SourceLinksTransformer(
- public val context: DokkaContext
-) : PageTransformer {
-
- private val builder : PageContentBuilder = PageContentBuilder(
- context.plugin<DokkaBase>().querySingle { commentsToContentConverter },
- context.plugin<DokkaBase>().querySingle { signatureProvider },
- context.logger
- )
-
- override fun invoke(input: RootPageNode): RootPageNode {
- val sourceLinks = getSourceLinksFromConfiguration()
- if (sourceLinks.isEmpty()) {
- return input
- }
- return input.transformContentPagesTree { node ->
- when (node) {
- is WithDocumentables -> {
- val sources = node.documentables
- .filterIsInstance<WithSources>()
- .fold(mutableMapOf<DRI, List<Pair<DokkaSourceSet, String>>>()) { acc, documentable ->
- val dri = (documentable as Documentable).dri
- acc.compute(dri) { _, v ->
- val sources = resolveSources(sourceLinks, documentable)
- v?.plus(sources) ?: sources
- }
- acc
- }
- if (sources.isNotEmpty())
- node.modified(content = transformContent(node.content, sources))
- else
- node
- }
- else -> node
- }
- }
- }
-
- private fun getSourceLinksFromConfiguration(): List<SourceLink> {
- return context.configuration.sourceSets
- .flatMap { it.sourceLinks.map { sl -> SourceLink(sl, it) } }
- }
-
- private fun resolveSources(
- sourceLinks: List<SourceLink>, documentable: WithSources
- ): List<Pair<DokkaSourceSet, String>> {
- return documentable.sources.mapNotNull { (sourceSet, documentableSource) ->
- val sourceLink = sourceLinks.find { sourceLink ->
- File(documentableSource.path).startsWith(sourceLink.path) && sourceLink.sourceSetData == sourceSet
- } ?: return@mapNotNull null
-
- sourceSet to documentableSource.toLink(sourceLink)
- }
- }
-
- private fun DocumentableSource.toLink(sourceLink: SourceLink): String {
- val sourcePath = File(this.path).invariantSeparatorsPath
- val sourceLinkPath = File(sourceLink.path).invariantSeparatorsPath
-
- val lineNumber = this.computeLineNumber()
- return sourceLink.url +
- sourcePath.split(sourceLinkPath)[1] +
- sourceLink.lineSuffix +
- "${lineNumber ?: 1}"
- }
-
- private fun ContentNode.signatureGroupOrNull() =
- (this as? ContentGroup)?.takeIf { it.dci.kind == ContentKind.Symbol }
-
- private fun transformContent(
- contentNode: ContentNode, sources: Map<DRI, List<Pair<DokkaSourceSet, String>>>
- ): ContentNode =
- contentNode.signatureGroupOrNull()?.let { sg ->
- val sgIds = sg.sourceSets.computeSourceSetIds()
- sources[sg.dci.dri.singleOrNull()]?.let { sourceLinks ->
- sourceLinks
- .filter { it.first.sourceSetID in sgIds }
- .takeIf { it.isNotEmpty() }
- ?.let { filteredSourcesLinks ->
- sg.copy(children = sg.children + filteredSourcesLinks.map {
- buildContentLink(
- sg.dci.dri.first(),
- it.first,
- it.second
- )
- })
- }
- }
- } ?: when (contentNode) {
- is ContentComposite -> contentNode.transformChildren { transformContent(it, sources) }
- else -> contentNode
- }
-
- private fun buildContentLink(dri: DRI, sourceSet: DokkaSourceSet, link: String) = builder.contentFor(
- dri,
- setOf(sourceSet),
- ContentKind.Source,
- setOf(TextStyle.FloatingRight)
- ) {
- text("(")
- link("source", link)
- text(")")
- }
-}
-
-public data class SourceLink(
- val path: String,
- val url: String,
- val lineSuffix: String?,
- val sourceSetData: DokkaSourceSet
-) {
- public constructor(
- sourceLinkDefinition: DokkaConfiguration.SourceLinkDefinition,
- sourceSetData: DokkaSourceSet
- ) : this(
- sourceLinkDefinition.localDirectory,
- sourceLinkDefinition.remoteUrl.toExternalForm(),
- sourceLinkDefinition.remoteLineSuffix,
- sourceSetData
- )
-}
diff --git a/plugins/base/src/main/kotlin/transformers/pages/tags/CustomTagContentProvider.kt b/plugins/base/src/main/kotlin/transformers/pages/tags/CustomTagContentProvider.kt
deleted file mode 100644
index fcec234f..00000000
--- a/plugins/base/src/main/kotlin/transformers/pages/tags/CustomTagContentProvider.kt
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-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.
- */
-public interface CustomTagContentProvider {
-
- /**
- * Whether this content provider supports given [CustomTagWrapper].
- *
- * Tags can be filtered out either by name or by nested [DocTag] type
- */
- public 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.
- */
- public 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.
- */
- public fun DocumentableContentBuilder.contentForBrief(
- sourceSet: DokkaSourceSet,
- customTag: CustomTagWrapper
- ) {}
-}
diff --git a/plugins/base/src/main/kotlin/transformers/pages/tags/SinceKotlinTagContentProvider.kt b/plugins/base/src/main/kotlin/transformers/pages/tags/SinceKotlinTagContentProvider.kt
deleted file mode 100644
index 7c35f719..00000000
--- a/plugins/base/src/main/kotlin/transformers/pages/tags/SinceKotlinTagContentProvider.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.transformers.pages.tags
-
-import org.jetbrains.dokka.DokkaConfiguration
-import org.jetbrains.dokka.base.translators.documentables.KDOC_TAG_HEADER_LEVEL
-import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder.DocumentableContentBuilder
-import org.jetbrains.dokka.model.doc.CustomTagWrapper
-import org.jetbrains.dokka.pages.TextStyle
-
-public object SinceKotlinTagContentProvider : CustomTagContentProvider {
-
- private const val SINCE_KOTLIN_TAG_NAME = "Since Kotlin"
-
- override fun isApplicable(customTag: CustomTagWrapper): Boolean = customTag.name == SINCE_KOTLIN_TAG_NAME
-
- override fun DocumentableContentBuilder.contentForDescription(
- sourceSet: DokkaConfiguration.DokkaSourceSet,
- customTag: CustomTagWrapper
- ) {
- group(sourceSets = setOf(sourceSet), styles = emptySet()) {
- header(KDOC_TAG_HEADER_LEVEL, 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())
- }
- }
-}
diff --git a/plugins/base/src/main/kotlin/translators/documentables/DefaultDocumentableToPageTranslator.kt b/plugins/base/src/main/kotlin/translators/documentables/DefaultDocumentableToPageTranslator.kt
deleted file mode 100644
index 0b2597d5..00000000
--- a/plugins/base/src/main/kotlin/translators/documentables/DefaultDocumentableToPageTranslator.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.translators.documentables
-
-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.*
-import org.jetbrains.dokka.transformers.documentation.DocumentableToPageTranslator
-import org.jetbrains.dokka.analysis.kotlin.internal.InternalKotlinAnalysisPlugin
-
-public class DefaultDocumentableToPageTranslator(
- context: DokkaContext
-) : DocumentableToPageTranslator {
- 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 documentableSourceLanguageParser = context.plugin<InternalKotlinAnalysisPlugin>().querySingle { documentableSourceLanguageParser }
- private val logger = context.logger
-
- override fun invoke(module: DModule): ModulePageNode =
- DefaultPageCreator(
- configuration,
- commentsToContentConverter,
- signatureProvider,
- logger,
- customTagContentProviders,
- documentableSourceLanguageParser
- ).pageForModule(module)
-}
diff --git a/plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt b/plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt
deleted file mode 100644
index 5c8ac512..00000000
--- a/plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt
+++ /dev/null
@@ -1,779 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.translators.documentables
-
-import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
-import org.jetbrains.dokka.base.DokkaBaseConfiguration
-import org.jetbrains.dokka.base.resolvers.anchors.SymbolAnchorHint
-import org.jetbrains.dokka.base.signatures.SignatureProvider
-import org.jetbrains.dokka.base.transformers.documentables.CallableExtensions
-import org.jetbrains.dokka.transformers.documentation.ClashingDriIdentifier
-import org.jetbrains.dokka.base.transformers.pages.comments.CommentsToContentConverter
-import org.jetbrains.dokka.base.transformers.pages.tags.CustomTagContentProvider
-import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder.DocumentableContentBuilder
-import org.jetbrains.dokka.base.utils.canonicalAlphabeticalOrder
-import org.jetbrains.dokka.links.Callable
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.model.*
-import org.jetbrains.dokka.model.doc.*
-import org.jetbrains.dokka.model.properties.PropertyContainer
-import org.jetbrains.dokka.model.properties.WithExtraProperties
-import org.jetbrains.dokka.pages.*
-import org.jetbrains.dokka.utilities.DokkaLogger
-import org.jetbrains.dokka.analysis.kotlin.internal.DocumentableSourceLanguageParser
-import org.jetbrains.dokka.analysis.kotlin.internal.DocumentableLanguage
-import kotlin.reflect.KClass
-
-internal typealias GroupedTags = Map<KClass<out TagWrapper>, List<Pair<DokkaSourceSet?, TagWrapper>>>
-
-public open class DefaultPageCreator(
- configuration: DokkaBaseConfiguration?,
- commentsToContentConverter: CommentsToContentConverter,
- signatureProvider: SignatureProvider,
- public val logger: DokkaLogger,
- public val customTagContentProviders: List<CustomTagContentProvider> = emptyList(),
- public val documentableAnalyzer: DocumentableSourceLanguageParser
-) {
- protected open val contentBuilder: PageContentBuilder = PageContentBuilder(
- commentsToContentConverter, signatureProvider, logger
- )
-
- protected val mergeImplicitExpectActualDeclarations: Boolean =
- configuration?.mergeImplicitExpectActualDeclarations
- ?: DokkaBaseConfiguration.mergeImplicitExpectActualDeclarationsDefault
-
- protected val separateInheritedMembers: Boolean =
- configuration?.separateInheritedMembers ?: DokkaBaseConfiguration.separateInheritedMembersDefault
-
- public open fun pageForModule(m: DModule): ModulePageNode =
- ModulePageNode(m.name.ifEmpty { "<root>" }, contentForModule(m), listOf(m), m.packages.map(::pageForPackage))
-
- /**
- * We want to generate separated pages for no-actual typealias.
- * Actual typealias are displayed on pages for their expect class (trough [ActualTypealias] extra).
- *
- * @see ActualTypealias
- */
- private fun List<Documentable>.filterOutActualTypeAlias(): List<Documentable> {
- fun List<Documentable>.hasExpectClass(dri: DRI) = find { it is DClasslike && it.dri == dri && it.expectPresentInSet != null } != null
- return this.filterNot { it is DTypeAlias && this.hasExpectClass(it.dri) }
- }
-
- public open fun pageForPackage(p: DPackage): PackagePageNode {
- val children = if (mergeImplicitExpectActualDeclarations) {
- (p.classlikes + p.typealiases).filterOutActualTypeAlias()
- .mergeClashingDocumentable().map(::pageForClasslikes) +
- p.functions.mergeClashingDocumentable().map(::pageForFunctions) +
- p.properties.mergeClashingDocumentable().map(::pageForProperties)
- } else {
- (p.classlikes + p.typealiases).filterOutActualTypeAlias()
- .renameClashingDocumentable().map(::pageForClasslike) +
- p.functions.renameClashingDocumentable().map(::pageForFunction) +
- p.properties.mapNotNull(::pageForProperty)
- }
- return PackagePageNode(
- name = p.name,
- content = contentForPackage(p),
- dri = setOf(p.dri),
- documentables = listOf(p),
- children = children
- )
- }
-
- public open fun pageForEnumEntry(e: DEnumEntry): ClasslikePageNode = pageForEnumEntries(listOf(e))
-
- public open fun pageForClasslike(c: Documentable): ClasslikePageNode = pageForClasslikes(listOf(c))
-
- public open fun pageForEnumEntries(documentables: List<DEnumEntry>): ClasslikePageNode {
- val dri = documentables.dri.also {
- if (it.size != 1) {
- logger.error("Documentable dri should have the same one ${it.first()} inside the one page!")
- }
- }
-
- val classlikes = documentables.flatMap { it.classlikes }
- val functions = documentables.flatMap { it.filteredFunctions }
- val props = documentables.flatMap { it.filteredProperties }
-
- val childrenPages = if (mergeImplicitExpectActualDeclarations)
- functions.mergeClashingDocumentable().map(::pageForFunctions) +
- props.mergeClashingDocumentable().map(::pageForProperties)
- else
- classlikes.renameClashingDocumentable().map(::pageForClasslike) +
- functions.renameClashingDocumentable().map(::pageForFunction) +
- props.renameClashingDocumentable().mapNotNull(::pageForProperty)
-
- return ClasslikePageNode(
- documentables.first().nameAfterClash(), contentForClasslikesAndEntries(documentables), dri, documentables,
- childrenPages
- )
- }
-
- /**
- * @param documentables a list of [DClasslike] and [DTypeAlias] with the same dri in different sourceSets
- */
- public open fun pageForClasslikes(documentables: List<Documentable>): ClasslikePageNode {
- val dri = documentables.dri.also {
- if (it.size != 1) {
- logger.error("Documentable dri should have the same one ${it.first()} inside the one page!")
- }
- }
-
- val classlikes = documentables.filterIsInstance<DClasslike>()
-
- val constructors =
- if (classlikes.shouldDocumentConstructors()) {
- classlikes.flatMap { (it as? WithConstructors)?.constructors ?: emptyList() }
- } else {
- emptyList()
- }
-
- val nestedClasslikes = classlikes.flatMap { it.classlikes }
- val functions = classlikes.flatMap { it.filteredFunctions }
- val props = classlikes.flatMap { it.filteredProperties }
- val entries = classlikes.flatMap { if (it is DEnum) it.entries else emptyList() }
-
- val childrenPages = constructors.map(::pageForFunction) +
- if (mergeImplicitExpectActualDeclarations)
- nestedClasslikes.mergeClashingDocumentable().map(::pageForClasslikes) +
- functions.mergeClashingDocumentable().map(::pageForFunctions) +
- props.mergeClashingDocumentable().map(::pageForProperties) +
- entries.mergeClashingDocumentable().map(::pageForEnumEntries)
- else
- nestedClasslikes.renameClashingDocumentable().map(::pageForClasslike) +
- functions.renameClashingDocumentable().map(::pageForFunction) +
- props.renameClashingDocumentable().mapNotNull(::pageForProperty) +
- entries.renameClashingDocumentable().map(::pageForEnumEntry)
-
-
- return ClasslikePageNode(
- documentables.first().nameAfterClash(), contentForClasslikesAndEntries(documentables), dri, documentables,
- childrenPages
- )
- }
-
- private fun <T> T.toClashedName() where T : Documentable, T : WithExtraProperties<T> =
- (extra[ClashingDriIdentifier]?.value?.joinToString(", ", "[", "]") { it.displayName } ?: "") + name.orEmpty()
-
- private fun <T : Documentable> List<T>.renameClashingDocumentable(): List<T> =
- groupBy { it.dri }.values.flatMap { elements ->
- if (elements.size == 1) elements else elements.mapNotNull { element ->
- element.renameClashingDocumentable()
- }
- }
-
- @Suppress("UNCHECKED_CAST")
- private fun <T : Documentable> T.renameClashingDocumentable(): T? = when (this) {
- is DClass -> copy(extra = this.extra + DriClashAwareName(this.toClashedName()))
- is DObject -> copy(extra = this.extra + DriClashAwareName(this.toClashedName()))
- is DAnnotation -> copy(extra = this.extra + DriClashAwareName(this.toClashedName()))
- is DInterface -> copy(extra = this.extra + DriClashAwareName(this.toClashedName()))
- is DEnum -> copy(extra = this.extra + DriClashAwareName(this.toClashedName()))
- is DFunction -> copy(extra = this.extra + DriClashAwareName(this.toClashedName()))
- is DProperty -> copy(extra = this.extra + DriClashAwareName(this.toClashedName()))
- is DTypeAlias -> copy(extra = this.extra + DriClashAwareName(this.toClashedName()))
- else -> null
- } as? T?
-
- private fun <T : Documentable> List<T>.mergeClashingDocumentable(): List<List<T>> =
- groupBy { it.dri }.values.toList()
-
- public open fun pageForFunction(f: DFunction): MemberPageNode =
- MemberPageNode(f.nameAfterClash(), contentForFunction(f), setOf(f.dri), listOf(f))
-
- public open fun pageForFunctions(fs: List<DFunction>): MemberPageNode {
- val dri = fs.dri.also {
- if (it.size != 1) {
- logger.error("Function dri should have the same one ${it.first()} inside the one page!")
- }
- }
- return MemberPageNode(fs.first().nameAfterClash(), contentForMembers(fs), dri, fs)
- }
-
- public open fun pageForProperty(p: DProperty): MemberPageNode? =
- MemberPageNode(p.nameAfterClash(), contentForProperty(p), setOf(p.dri), listOf(p))
-
- public open fun pageForProperties(ps: List<DProperty>): MemberPageNode {
- val dri = ps.dri.also {
- if (it.size != 1) {
- logger.error("Property dri should have the same one ${it.first()} inside the one page!")
- }
- }
- return MemberPageNode(ps.first().nameAfterClash(), contentForMembers(ps), dri, ps)
- }
-
- private fun <T> T.isInherited(): Boolean where T : Documentable, T : WithExtraProperties<T> =
- sourceSets.all { sourceSet -> extra[InheritedMember]?.isInherited(sourceSet) == true }
-
- private val WithScope.filteredFunctions: List<DFunction>
- get() = functions.filterNot { it.isInherited() }
-
- private val WithScope.filteredProperties: List<DProperty>
- get() = properties.filterNot { it.isInherited() }
-
- private fun Collection<Documentable>.splitPropsAndFuns(): Pair<List<DProperty>, List<DFunction>> {
- val first = ArrayList<DProperty>()
- val second = ArrayList<DFunction>()
- for (element in this) {
- when (element) {
- is DProperty -> first.add(element)
- is DFunction -> second.add(element)
- else -> throw IllegalStateException("Expected only properties or functions")
- }
- }
- return Pair(first, second)
- }
-
- private fun <T> Collection<T>.splitInheritedExtension(dri: Set<DRI>): Pair<List<T>, List<T>> where T : org.jetbrains.dokka.model.Callable =
- partition { it.receiver?.dri !in dri }
-
- private fun <T> Collection<T>.splitInherited(): Pair<List<T>, List<T>> where T : Documentable, T : WithExtraProperties<T> =
- partition { it.isInherited() }
-
- protected open fun contentForModule(m: DModule): ContentGroup {
- return contentBuilder.contentFor(m) {
- group(kind = ContentKind.Cover) {
- cover(m.name)
- if (contentForDescription(m).isNotEmpty()) {
- sourceSetDependentHint(
- m.dri,
- m.sourceSets.toSet(),
- kind = ContentKind.SourceSetDependentHint,
- styles = setOf(TextStyle.UnderCoverText)
- ) {
- +contentForDescription(m)
- }
- }
- }
-
- block(
- name = "Packages",
- level = 2,
- kind = ContentKind.Packages,
- elements = m.packages,
- sourceSets = m.sourceSets.toSet(),
- needsAnchors = true,
- headers = listOf(
- headers("Name")
- )
- ) {
- val documentations = it.sourceSets.map { platform ->
- it.descriptions[platform]?.also { it.root }
- }
- val haveSameContent =
- documentations.all { it?.root == documentations.firstOrNull()?.root && it?.root != null }
-
- link(it.name, it.dri)
- if (it.sourceSets.size == 1 || (documentations.isNotEmpty() && haveSameContent)) {
- documentations.first()?.let { firstParagraphComment(kind = ContentKind.Comment, content = it.root) }
- }
- }
- }
- }
-
- protected open fun contentForPackage(p: DPackage): ContentGroup {
- return contentBuilder.contentFor(p) {
- group(kind = ContentKind.Cover) {
- cover("Package-level declarations")
- if (contentForDescription(p).isNotEmpty()) {
- sourceSetDependentHint(
- dri = p.dri,
- sourcesetData = p.sourceSets.toSet(),
- kind = ContentKind.SourceSetDependentHint,
- styles = setOf(TextStyle.UnderCoverText)
- ) {
- +contentForDescription(p)
- }
- }
- }
- group(styles = setOf(ContentStyle.TabbedContent), extra = mainExtra) {
- +contentForScope(p, p.dri, p.sourceSets)
- }
- }
- }
-
- protected open fun contentForScopes(
- scopes: List<WithScope>,
- sourceSets: Set<DokkaSourceSet>,
- extensions: List<Documentable> = emptyList()
- ): ContentGroup {
- val types = scopes.flatMap { it.classlikes } + scopes.filterIsInstance<DPackage>().flatMap { it.typealiases }
- return contentForScope(
- @Suppress("UNCHECKED_CAST")
- (scopes as List<Documentable>).dri,
- sourceSets,
- types,
- scopes.flatMap { it.functions },
- scopes.flatMap { it.properties },
- extensions
- )
- }
-
- protected open fun contentForScope(
- s: WithScope,
- dri: DRI,
- sourceSets: Set<DokkaSourceSet>,
- extensions: List<Documentable> = emptyList()
- ): ContentGroup {
- val types = listOf(
- s.classlikes,
- (s as? DPackage)?.typealiases ?: emptyList()
- ).flatten()
- return contentForScope(setOf(dri), sourceSets, types, s.functions, s.properties, extensions)
- }
-
- private fun contentForScope(
- dri: Set<DRI>,
- sourceSets: Set<DokkaSourceSet>,
- types: List<Documentable>,
- functions: List<DFunction>,
- properties: List<DProperty>,
- extensions: List<Documentable>
- ) = contentBuilder.contentFor(dri, sourceSets) {
- divergentBlock(
- "Types",
- types,
- ContentKind.Classlikes
- )
- val (extensionProps, extensionFuns) = extensions.splitPropsAndFuns()
- if (separateInheritedMembers) {
- val (inheritedFunctions, memberFunctions) = functions.splitInherited()
- val (inheritedProperties, memberProperties) = properties.splitInherited()
-
- val (inheritedExtensionFunctions, extensionFunctions) = extensionFuns.splitInheritedExtension(dri)
- val (inheritedExtensionProperties, extensionProperties) = extensionProps.splitInheritedExtension(dri)
- propertiesBlock(
- "Properties", memberProperties + extensionProperties
- )
- propertiesBlock(
- "Inherited properties", inheritedProperties + inheritedExtensionProperties
- )
- functionsBlock("Functions", memberFunctions + extensionFunctions)
- functionsBlock(
- "Inherited functions", inheritedFunctions + inheritedExtensionFunctions
- )
- } else {
- propertiesBlock(
- "Properties", properties + extensionProps
- )
- functionsBlock("Functions", functions + extensionFuns)
- }
- }
-
- private fun Iterable<DFunction>.sorted() =
- sortedWith(compareBy({ it.name }, { it.parameters.size }, { it.dri.toString() }))
-
- /**
- * @param documentables a list of [DClasslike] and [DEnumEntry] and [DTypeAlias] with the same dri in different sourceSets
- */
- protected open fun contentForClasslikesAndEntries(documentables: List<Documentable>): ContentGroup =
- contentBuilder.contentFor(documentables.dri, documentables.sourceSets) {
- val classlikes = documentables.filterIsInstance<DClasslike>()
-
- @Suppress("UNCHECKED_CAST")
- val extensions = (classlikes as List<WithExtraProperties<DClasslike>>).flatMap {
- it.extra[CallableExtensions]?.extensions
- ?.filterIsInstance<Documentable>().orEmpty()
- }
- .distinctBy { it.sourceSets to it.dri } // [Documentable] has expensive equals/hashCode at the moment, see #2620
-
- // Extensions are added to sourceSets since they can be placed outside the sourceSets from classlike
- // Example would be an Interface in common and extension function in jvm
- group(kind = ContentKind.Cover, sourceSets = mainSourcesetData + extensions.sourceSets) {
- cover(documentables.first().name.orEmpty())
- sourceSetDependentHint(documentables.dri, documentables.sourceSets) {
- documentables.forEach {
- +buildSignature(it)
- +contentForDescription(it)
- }
- }
- }
- val csEnum = classlikes.filterIsInstance<DEnum>()
- val csWithConstructor = classlikes.filterIsInstance<WithConstructors>()
- val scopes = documentables.filterIsInstance<WithScope>()
- val constructorsToDocumented = csWithConstructor.flatMap { it.constructors }
-
- group(
- styles = setOf(ContentStyle.TabbedContent),
- sourceSets = mainSourcesetData + extensions.sourceSets,
- extra = mainExtra
- ) {
- if (constructorsToDocumented.isNotEmpty() && documentables.shouldDocumentConstructors()) {
- +contentForConstructors(constructorsToDocumented, classlikes.dri, classlikes.sourceSets)
- }
- if (csEnum.isNotEmpty()) {
- +contentForEntries(csEnum.flatMap { it.entries }, csEnum.dri, csEnum.sourceSets)
- }
- +contentForScopes(scopes, documentables.sourceSets, extensions)
- }
- }
- protected open fun contentForConstructors(
- constructorsToDocumented: List<DFunction>,
- dri: Set<DRI>,
- sourceSets: Set<DokkaSourceSet>
- ): ContentGroup {
- return contentBuilder.contentFor(dri, sourceSets) {
- multiBlock(
- name = "Constructors",
- level = 2,
- kind = ContentKind.Constructors,
- groupedElements = constructorsToDocumented.groupBy { it.name }
- .map { (_, v) -> v.first().name to v },
- sourceSets = (constructorsToDocumented as List<Documentable>).sourceSets,
- needsAnchors = true,
- extra = PropertyContainer.empty<ContentNode>() + TabbedContentTypeExtra(
- BasicTabbedContentType.CONSTRUCTOR
- ),
- ) { key, ds ->
- link(key, ds.first().dri, kind = ContentKind.Main, styles = setOf(ContentStyle.RowTitle))
- sourceSetDependentHint(
- dri = ds.dri,
- sourceSets = ds.sourceSets,
- kind = ContentKind.SourceSetDependentHint,
- styles = emptySet(),
- extra = PropertyContainer.empty()
- ) {
- ds.forEach {
- +buildSignature(it)
- contentForBrief(it)
- }
- }
- }
- }
- }
-
- protected open fun contentForEntries(
- entries: List<DEnumEntry>,
- dri: Set<DRI>,
- sourceSets: Set<DokkaSourceSet>
- ): ContentGroup {
- return contentBuilder.contentFor(dri, sourceSets) {
- multiBlock(
- name = "Entries",
- level = 2,
- kind = ContentKind.Classlikes,
- groupedElements = entries.groupBy { it.name }.toList(),
- sourceSets = entries.sourceSets,
- needsSorting = false,
- needsAnchors = true,
- extra = mainExtra + TabbedContentTypeExtra(BasicTabbedContentType.ENTRY),
- styles = emptySet()
- ) { key, ds ->
- link(key, ds.first().dri)
- sourceSetDependentHint(
- dri = ds.dri,
- sourceSets = ds.sourceSets,
- kind = ContentKind.SourceSetDependentHint,
- extra = PropertyContainer.empty<ContentNode>()
- ) {
- ds.forEach {
- +buildSignature(it)
- contentForBrief(it)
- }
- }
- }
- }
- }
-
-
-
- protected open fun contentForDescription(
- d: Documentable
- ): List<ContentNode> {
- val sourceSets = d.sourceSets.toSet()
- val tags = d.groupedTags
-
- return contentBuilder.contentFor(d) {
- deprecatedSectionContent(d, sourceSets)
-
- descriptionSectionContent(d, sourceSets)
- customTagSectionContent(d, sourceSets, customTagContentProviders)
- unnamedTagSectionContent(d, sourceSets) { toHeaderString() }
-
- paramsSectionContent(tags)
- seeAlsoSectionContent(tags)
- throwsSectionContent(tags)
- samplesSectionContent(tags)
-
- inheritorsSectionContent(d, logger)
- }.children
- }
-
- protected open fun DocumentableContentBuilder.contentForBrief(
- documentable: Documentable
- ) {
- documentable.sourceSets.forEach { sourceSet ->
- documentable.documentation[sourceSet]?.let {
- /*
- Get description or a tag that holds documentation.
- This tag can be either property or constructor but constructor tags are handled already in analysis so we
- only need to keep an eye on property
-
- We purposefully ignore all other tags as they should not be visible in brief
- */
- it.firstMemberOfTypeOrNull<Description>() ?: it.firstMemberOfTypeOrNull<Property>()
- .takeIf { documentable is DProperty }
- }?.let {
- group(sourceSets = setOf(sourceSet), kind = ContentKind.BriefComment) {
- createBriefComment(documentable, sourceSet, it)
- }
- }
- }
- }
-
- private fun DocumentableContentBuilder.createBriefComment(
- documentable: Documentable,
- sourceSet: DokkaSourceSet,
- tag: TagWrapper
- ) {
- val language = documentableAnalyzer.getLanguage(documentable, sourceSet)
- when(language) {
- DocumentableLanguage.JAVA -> firstSentenceComment(tag.root)
- DocumentableLanguage.KOTLIN -> firstParagraphComment(tag.root)
- else -> firstParagraphComment(tag.root)
- }
- }
-
- protected open fun contentForFunction(f: DFunction): ContentGroup = contentForMember(f)
-
- protected open fun contentForProperty(p: DProperty): ContentGroup = contentForMember(p)
-
- protected open fun contentForMember(d: Documentable): ContentGroup = contentForMembers(listOf(d))
-
- protected open fun contentForMembers(doumentables: List<Documentable>): ContentGroup =
- contentBuilder.contentFor(doumentables.dri, doumentables.sourceSets) {
- group(kind = ContentKind.Cover) {
- cover(doumentables.first().name.orEmpty())
- }
- divergentGroup(ContentDivergentGroup.GroupID("member")) {
- doumentables.forEach { d ->
- instance(setOf(d.dri), d.sourceSets) {
- divergent {
- +buildSignature(d)
- }
- after {
- +contentForDescription(d)
- }
- }
- }
- }
- }
-
- private fun DocumentableContentBuilder.functionsBlock(
- name: String,
- list: Collection<DFunction>
- ) {
- divergentBlock(
- name,
- list.sorted(),
- ContentKind.Functions,
- extra = mainExtra
- )
- }
-
- private fun DocumentableContentBuilder.propertiesBlock(
- name: String,
- list: Collection<DProperty>
- ) {
- divergentBlock(
- name,
- list,
- ContentKind.Properties,
- extra = mainExtra
- )
-
- }
- private data class NameAndIsExtension(val name:String?, val isExtension: Boolean)
-
- private fun groupAndSortDivergentCollection(collection: Collection<Documentable>): List<Map.Entry<NameAndIsExtension, List<Documentable>>> {
- val groupKeyComparator: Comparator<Map.Entry<NameAndIsExtension, List<Documentable>>> =
- compareBy<Map.Entry<NameAndIsExtension, List<Documentable>>, String?>(
- nullsFirst(canonicalAlphabeticalOrder)
- ) { it.key.name }
- .thenBy { it.key.isExtension }
-
- return collection
- .groupBy {
- NameAndIsExtension(
- it.name,
- it.isExtension()
- )
- } // This groupBy should probably use LocationProvider
- // This hacks displaying actual typealias signatures along classlike ones
- .mapValues { if (it.value.any { it is DClasslike }) it.value.filter { it !is DTypeAlias } else it.value }
- .entries.sortedWith(groupKeyComparator)
- }
-
- protected open fun DocumentableContentBuilder.divergentBlock(
- name: String,
- collection: Collection<Documentable>,
- kind: ContentKind,
- extra: PropertyContainer<ContentNode> = mainExtra
- ) {
- if (collection.any()) {
- val onlyExtensions = collection.all { it.isExtension() }
- val groupExtra = when(kind) {
- ContentKind.Functions -> extra + TabbedContentTypeExtra(if (onlyExtensions) BasicTabbedContentType.EXTENSION_FUNCTION else BasicTabbedContentType.FUNCTION)
- ContentKind.Properties -> extra + TabbedContentTypeExtra(if (onlyExtensions) BasicTabbedContentType.EXTENSION_PROPERTY else BasicTabbedContentType.PROPERTY)
- ContentKind.Classlikes -> extra + TabbedContentTypeExtra(BasicTabbedContentType.TYPE)
- else -> extra
- }
-
- group(extra = groupExtra) {
- // be careful: groupExtra will be applied for children by default
- header(2, name, kind = kind, extra = extra) { }
- val isFunctions = collection.any { it is DFunction }
- table(kind, extra = extra, styles = emptySet()) {
- header {
- group { text("Name") }
- group { text("Summary") }
- }
- groupAndSortDivergentCollection(collection)
- .forEach { (elementNameAndIsExtension, elements) -> // This groupBy should probably use LocationProvider
- val elementName = elementNameAndIsExtension.name
- val isExtension = elementNameAndIsExtension.isExtension
- val rowExtra =
- if (isExtension) extra + TabbedContentTypeExtra(if(isFunctions) BasicTabbedContentType.EXTENSION_FUNCTION else BasicTabbedContentType.EXTENSION_PROPERTY) else extra
- val rowKind = if (isExtension) ContentKind.Extensions else kind
- val sortedElements = sortDivergentElementsDeterministically(elements)
- row(
- dri = sortedElements.map { it.dri }.toSet(),
- sourceSets = sortedElements.flatMap { it.sourceSets }.toSet(),
- kind = rowKind,
- styles = emptySet(),
- extra = elementName?.let { name -> rowExtra + SymbolAnchorHint(name, kind) } ?: rowExtra
- ) {
- link(
- text = elementName.orEmpty(),
- address = sortedElements.first().dri,
- kind = rowKind,
- styles = setOf(ContentStyle.RowTitle),
- sourceSets = sortedElements.sourceSets.toSet(),
- extra = extra
- )
- divergentGroup(
- ContentDivergentGroup.GroupID(name),
- sortedElements.map { it.dri }.toSet(),
- kind = rowKind,
- extra = extra
- ) {
- sortedElements.map { element ->
- instance(
- setOf(element.dri),
- element.sourceSets.toSet(),
- extra = PropertyContainer.withAll(
- SymbolAnchorHint(element.name ?: "", rowKind)
- )
- ) {
- divergent(extra = PropertyContainer.empty()) {
- group {
- +buildSignature(element)
- }
- }
- after(
- extra = PropertyContainer.empty()
- ) {
- contentForBrief(element)
- contentForCustomTagsBrief(element)
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
-
- /**
- * Divergent elements, such as extensions for the same receiver, can have identical signatures
- * if they are declared in different places. If such elements are shown on the same page together,
- * they need to be rendered deterministically to have reproducible builds.
- *
- * For example, you can have three identical extensions, if they are declared as:
- * 1) top-level in package A
- * 2) top-level in package B
- * 3) inside a companion object in package A/B
- *
- * @see divergentBlock
- *
- * @param elements can contain types (annotation/class/interface/object/typealias), functions and properties
- * @return the original list if it has one or zero elements
- */
- private fun sortDivergentElementsDeterministically(elements: List<Documentable>): List<Documentable> =
- elements.takeIf { it.size > 1 } // the majority are single-element lists, but no real benchmarks done
- ?.sortedWith(divergentDocumentableComparator)
- ?: elements
-
- private fun DocumentableContentBuilder.contentForCustomTagsBrief(documentable: Documentable) {
- val customTags = documentable.customTags
- if (customTags.isEmpty()) return
-
- documentable.sourceSets.forEach { sourceSet ->
- customTags.forEach { (_, sourceSetTag) ->
- sourceSetTag[sourceSet]?.let { tag ->
- customTagContentProviders.filter { it.isApplicable(tag) }.forEach { provider ->
- with(provider) {
- contentForBrief(sourceSet, tag)
- }
- }
- }
- }
- }
- }
-
- protected open fun TagWrapper.toHeaderString(): String = this.javaClass.toGenericString().split('.').last()
-}
-
-internal val List<Documentable>.sourceSets: Set<DokkaSourceSet>
- get() = flatMap { it.sourceSets }.toSet()
-
-internal val List<Documentable>.dri: Set<DRI>
- get() = map { it.dri }.toSet()
-
-internal val Documentable.groupedTags: GroupedTags
- get() = documentation.flatMap { (pd, doc) ->
- doc.children.map { pd to it }.toList()
- }.groupBy { it.second::class }
-
-internal val Documentable.descriptions: SourceSetDependent<Description>
- get() = groupedTags.withTypeUnnamed()
-
-internal val Documentable.customTags: Map<String, SourceSetDependent<CustomTagWrapper>>
- get() = groupedTags.withTypeNamed()
-
-/**
- * @see DefaultPageCreator.sortDivergentElementsDeterministically for usage
- */
-private val divergentDocumentableComparator =
- compareBy<Documentable, String?>(nullsLast()) { it.dri.packageName }
- .thenBy(nullsFirst()) { it.dri.classNames } // nullsFirst for top level to be first
- .thenBy(
- nullsLast(
- compareBy<Callable> { it.params.size }
- .thenBy { it.signature() }
- )
- ) { it.dri.callable }
-
-@Suppress("UNCHECKED_CAST")
-private fun <T : Documentable> T.nameAfterClash(): String =
- ((this as? WithExtraProperties<Documentable>)?.extra?.get(DriClashAwareName)?.value ?: name).orEmpty()
-
-@Suppress("UNCHECKED_CAST")
-internal inline fun <reified T : TagWrapper> GroupedTags.withTypeUnnamed(): SourceSetDependent<T> =
- (this[T::class] as List<Pair<DokkaSourceSet, T>>?)?.toMap().orEmpty()
-
-@Suppress("UNCHECKED_CAST")
-internal inline fun <reified T : NamedTagWrapper> GroupedTags.withTypeNamed(): Map<String, SourceSetDependent<T>> =
- (this[T::class] as List<Pair<DokkaSourceSet, T>>?)
- ?.groupByTo(linkedMapOf()) { it.second.name }
- ?.mapValues { (_, v) -> v.toMap() }
- .orEmpty()
-
-// Annotations might have constructors to substitute reflection invocations
-// and for internal/compiler purposes, but they are not expected to be documented
-// and instantiated directly under normal circumstances, so constructors should not be rendered.
-internal fun List<Documentable>.shouldDocumentConstructors() = !this.any { it is DAnnotation }
diff --git a/plugins/base/src/main/kotlin/translators/documentables/DeprecationSectionCreator.kt b/plugins/base/src/main/kotlin/translators/documentables/DeprecationSectionCreator.kt
deleted file mode 100644
index 0f51578f..00000000
--- a/plugins/base/src/main/kotlin/translators/documentables/DeprecationSectionCreator.kt
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.translators.documentables
-
-import org.jetbrains.dokka.DokkaConfiguration
-import org.jetbrains.dokka.base.signatures.KotlinSignatureUtils.annotations
-import org.jetbrains.dokka.base.transformers.documentables.isDeprecated
-import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder.DocumentableContentBuilder
-import org.jetbrains.dokka.model.*
-import org.jetbrains.dokka.pages.ContentKind
-import org.jetbrains.dokka.pages.ContentStyle
-import org.jetbrains.dokka.pages.TextStyle
-
-/**
- * Main header for [Deprecated] section
- */
-private const val DEPRECATED_HEADER_LEVEL = 3
-
-/**
- * Header for a direct parameter of [Deprecated] annotation,
- * such as [Deprecated.message] and [Deprecated.replaceWith]
- */
-private const val DIRECT_PARAM_HEADER_LEVEL = 4
-
-internal fun PageContentBuilder.DocumentableContentBuilder.deprecatedSectionContent(
- documentable: Documentable,
- platforms: Set<DokkaConfiguration.DokkaSourceSet>
-) {
- val allAnnotations = documentable.annotations()
- if (allAnnotations.isEmpty()) {
- return
- }
-
- platforms.forEach { platform ->
- val platformAnnotations = allAnnotations[platform] ?: emptyList()
- val deprecatedPlatformAnnotations = platformAnnotations.filter { it.isDeprecated() }
-
- if (deprecatedPlatformAnnotations.isNotEmpty()) {
- group(kind = ContentKind.Deprecation, sourceSets = setOf(platform), styles = emptySet()) {
- val kotlinAnnotation = deprecatedPlatformAnnotations.find { it.dri.packageName == "kotlin" }
- val javaAnnotation = deprecatedPlatformAnnotations.find { it.dri.packageName == "java.lang" }
-
- // If both annotations are present, priority is given to Kotlin's annotation since it
- // contains more useful information, and Java's annotation is probably there
- // for interop with Java callers, so it should be OK to ignore it
- if (kotlinAnnotation != null) {
- createKotlinDeprecatedSectionContent(kotlinAnnotation, platformAnnotations)
- } else if (javaAnnotation != null) {
- createJavaDeprecatedSectionContent(javaAnnotation)
- }
- }
- }
- }
-}
-
-/**
- * @see [DeprecatedSinceKotlin]
- */
-private fun findDeprecatedSinceKotlinAnnotation(annotations: List<Annotations.Annotation>): Annotations.Annotation? {
- return annotations.firstOrNull {
- it.dri.packageName == "kotlin" && it.dri.classNames == "DeprecatedSinceKotlin"
- }
-}
-
-/**
- * Section with details for Kotlin's [kotlin.Deprecated] annotation
- */
-private fun DocumentableContentBuilder.createKotlinDeprecatedSectionContent(
- deprecatedAnnotation: Annotations.Annotation,
- allAnnotations: List<Annotations.Annotation>
-) {
- val deprecatedSinceKotlinAnnotation = findDeprecatedSinceKotlinAnnotation(allAnnotations)
- header(
- level = DEPRECATED_HEADER_LEVEL,
- text = createKotlinDeprecatedHeaderText(deprecatedAnnotation, deprecatedSinceKotlinAnnotation)
- )
-
- deprecatedSinceKotlinAnnotation?.let {
- createDeprecatedSinceKotlinFootnoteContent(it)
- }
-
- deprecatedAnnotation.takeStringParam("message")?.let {
- group(styles = setOf(TextStyle.Paragraph)) {
- text(it)
- }
- }
-
- createReplaceWithSectionContent(deprecatedAnnotation)
-}
-
-private fun createKotlinDeprecatedHeaderText(
- kotlinDeprecatedAnnotation: Annotations.Annotation,
- deprecatedSinceKotlinAnnotation: Annotations.Annotation?
-): String {
- if (deprecatedSinceKotlinAnnotation != null) {
- // In this case there's no single level, it's dynamic based on api version,
- // so there should be a footnote with levels and their respective versions
- return "Deprecated"
- }
-
- val deprecationLevel = kotlinDeprecatedAnnotation.params["level"]?.let { (it as? EnumValue)?.enumName }
- return when (deprecationLevel) {
- "DeprecationLevel.ERROR" -> "Deprecated (with error)"
- "DeprecationLevel.HIDDEN" -> "Deprecated (hidden)"
- else -> "Deprecated"
- }
-}
-
-/**
- * Footnote for [DeprecatedSinceKotlin] annotation used in stdlib
- *
- * Notice that values are empty by default, so it's not guaranteed that all three will be set
- */
-private fun DocumentableContentBuilder.createDeprecatedSinceKotlinFootnoteContent(
- deprecatedSinceKotlinAnnotation: Annotations.Annotation
-) {
- group(styles = setOf(ContentStyle.Footnote)) {
- deprecatedSinceKotlinAnnotation.takeStringParam("warningSince")?.let {
- group(styles = setOf(TextStyle.Paragraph)) {
- text("Warning since $it")
- }
- }
- deprecatedSinceKotlinAnnotation.takeStringParam("errorSince")?.let {
- group(styles = setOf(TextStyle.Paragraph)) {
- text("Error since $it")
- }
- }
- deprecatedSinceKotlinAnnotation.takeStringParam("hiddenSince")?.let {
- group(styles = setOf(TextStyle.Paragraph)) {
- text("Hidden since $it")
- }
- }
- }
-}
-
-/**
- * Section for [ReplaceWith] parameter of [kotlin.Deprecated] annotation
- */
-private fun DocumentableContentBuilder.createReplaceWithSectionContent(kotlinDeprecatedAnnotation: Annotations.Annotation) {
- val replaceWithAnnotation = (kotlinDeprecatedAnnotation.params["replaceWith"] as? AnnotationValue)?.annotation
- ?: return
-
- header(
- level = DIRECT_PARAM_HEADER_LEVEL,
- text = "Replace with"
- )
-
- // Signature: vararg val imports: String
- val imports = (replaceWithAnnotation.params["imports"] as? ArrayValue)
- ?.value
- ?.mapNotNull { (it as? StringValue)?.value }
- ?: emptyList()
-
- if (imports.isNotEmpty()) {
- codeBlock(language = "kotlin", styles = setOf(TextStyle.Monospace)) {
- imports.forEach {
- text("import $it")
- breakLine()
- }
- }
- }
-
- replaceWithAnnotation.takeStringParam("expression")?.removeSurrounding("`")?.let {
- codeBlock(language = "kotlin", styles = setOf(TextStyle.Monospace)) {
- text(it)
- }
- }
-}
-
-/**
- * Section with details for Java's [java.lang.Deprecated] annotation
- */
-private fun DocumentableContentBuilder.createJavaDeprecatedSectionContent(
- deprecatedAnnotation: Annotations.Annotation,
-) {
- val isForRemoval = deprecatedAnnotation.takeBooleanParam("forRemoval", default = false)
- header(
- level = DEPRECATED_HEADER_LEVEL,
- text = if (isForRemoval) "Deprecated (for removal)" else "Deprecated"
- )
- deprecatedAnnotation.takeStringParam("since")?.let {
- group(styles = setOf(ContentStyle.Footnote)) {
- text("Since version $it")
- }
- }
-}
-
-private fun Annotations.Annotation.takeBooleanParam(name: String, default: Boolean): Boolean =
- (this.params[name] as? BooleanValue)?.value ?: default
-
-private fun Annotations.Annotation.takeStringParam(name: String): String? =
- (this.params[name] as? StringValue)?.takeIf { it.value.isNotEmpty() }?.value
diff --git a/plugins/base/src/main/kotlin/translators/documentables/DescriptionSections.kt b/plugins/base/src/main/kotlin/translators/documentables/DescriptionSections.kt
deleted file mode 100644
index e2489260..00000000
--- a/plugins/base/src/main/kotlin/translators/documentables/DescriptionSections.kt
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.translators.documentables
-
-import org.jetbrains.dokka.DokkaConfiguration
-import org.jetbrains.dokka.Platform
-import org.jetbrains.dokka.base.transformers.documentables.InheritorsInfo
-import org.jetbrains.dokka.base.transformers.pages.tags.CustomTagContentProvider
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.links.PointingToDeclaration
-import org.jetbrains.dokka.model.Documentable
-import org.jetbrains.dokka.model.SourceSetDependent
-import org.jetbrains.dokka.model.WithScope
-import org.jetbrains.dokka.model.doc.*
-import org.jetbrains.dokka.model.orEmpty
-import org.jetbrains.dokka.model.properties.WithExtraProperties
-import org.jetbrains.dokka.pages.ContentKind
-import org.jetbrains.dokka.pages.ContentStyle
-import org.jetbrains.dokka.pages.TextStyle
-import org.jetbrains.dokka.utilities.DokkaLogger
-import kotlin.reflect.KClass
-import kotlin.reflect.full.isSubclassOf
-
-internal const val KDOC_TAG_HEADER_LEVEL = 4
-
-private val unnamedTagsExceptions: Set<KClass<out TagWrapper>> =
- setOf(Property::class, Description::class, Constructor::class, Param::class, See::class)
-
-internal fun PageContentBuilder.DocumentableContentBuilder.descriptionSectionContent(
- documentable: Documentable,
- sourceSets: Set<DokkaConfiguration.DokkaSourceSet>,
-) {
- val descriptions = documentable.descriptions
- if (descriptions.any { it.value.root.children.isNotEmpty() }) {
- sourceSets.forEach { sourceSet ->
- descriptions[sourceSet]?.also {
- group(sourceSets = setOf(sourceSet), styles = emptySet()) {
- comment(it.root)
- }
- }
- }
- }
-}
-
-/**
- * Custom tags are tags which are not part of the [KDoc specification](https://kotlinlang.org/docs/kotlin-doc.html). For instance, a user-defined tag
- * which is specific to the user's code base would be considered a custom tag.
- *
- * For details, see [CustomTagContentProvider]
- */
-internal fun PageContentBuilder.DocumentableContentBuilder.customTagSectionContent(
- documentable: Documentable,
- sourceSets: Set<DokkaConfiguration.DokkaSourceSet>,
- customTagContentProviders: List<CustomTagContentProvider>,
-) {
- val customTags = documentable.customTags
- if (customTags.isEmpty()) return
-
- sourceSets.forEach { sourceSet ->
- customTags.forEach { (_, sourceSetTag) ->
- sourceSetTag[sourceSet]?.let { tag ->
- customTagContentProviders.filter { it.isApplicable(tag) }.forEach { provider ->
- group(sourceSets = setOf(sourceSet), styles = setOf(ContentStyle.KDocTag)) {
- with(provider) {
- contentForDescription(sourceSet, tag)
- }
- }
- }
- }
- }
- }
-}
-
-/**
- * Tags in KDoc are used in form of "@tag name value".
- * This function handles tags that have only value parameter without name.
- * List of such tags: `@return`, `@author`, `@since`, `@receiver`
- */
-internal fun PageContentBuilder.DocumentableContentBuilder.unnamedTagSectionContent(
- documentable: Documentable,
- sourceSets: Set<DokkaConfiguration.DokkaSourceSet>,
- toHeaderString: TagWrapper.() -> String,
-) {
- val unnamedTags = documentable.groupedTags
- .filterNot { (k, _) -> k.isSubclassOf(NamedTagWrapper::class) || k in unnamedTagsExceptions }
- .values.flatten().groupBy { it.first }
- .mapValues { it.value.map { it.second } }
- .takeIf { it.isNotEmpty() } ?: return
-
- sourceSets.forEach { sourceSet ->
- unnamedTags[sourceSet]?.let { tags ->
- if (tags.isNotEmpty()) {
- tags.groupBy { it::class }.forEach { (_, sameCategoryTags) ->
- group(sourceSets = setOf(sourceSet), styles = setOf(ContentStyle.KDocTag)) {
- header(
- level = KDOC_TAG_HEADER_LEVEL,
- text = sameCategoryTags.first().toHeaderString(),
- styles = setOf()
- )
- sameCategoryTags.forEach { comment(it.root, styles = setOf()) }
- }
- }
- }
- }
- }
-}
-
-
-internal fun PageContentBuilder.DocumentableContentBuilder.paramsSectionContent(tags: GroupedTags) {
- val params = tags.withTypeNamed<Param>()
- if (params.isEmpty()) return
-
- val availableSourceSets = params.availableSourceSets()
- tableSectionContentBlock(
- blockName = "Parameters",
- kind = ContentKind.Parameters,
- sourceSets = availableSourceSets
- ) {
- availableSourceSets.forEach { sourceSet ->
- val possibleFallbacks = availableSourceSets.getPossibleFallback(sourceSet)
- params.mapNotNull { (_, param) ->
- (param[sourceSet] ?: param.fallback(possibleFallbacks))?.let {
- row(sourceSets = setOf(sourceSet), kind = ContentKind.Parameters) {
- text(
- it.name,
- kind = ContentKind.Parameters,
- styles = mainStyles + setOf(ContentStyle.RowTitle, TextStyle.Underlined)
- )
- if (it.isNotEmpty()) {
- comment(it.root)
- }
- }
- }
- }
- }
- }
-}
-
-internal fun PageContentBuilder.DocumentableContentBuilder.seeAlsoSectionContent(tags: GroupedTags) {
- val seeAlsoTags = tags.withTypeNamed<See>()
- if (seeAlsoTags.isEmpty()) return
-
- val availableSourceSets = seeAlsoTags.availableSourceSets()
- tableSectionContentBlock(
- blockName = "See also",
- kind = ContentKind.Comment,
- sourceSets = availableSourceSets
- ) {
- availableSourceSets.forEach { sourceSet ->
- val possibleFallbacks = availableSourceSets.getPossibleFallback(sourceSet)
- seeAlsoTags.forEach { (_, see) ->
- (see[sourceSet] ?: see.fallback(possibleFallbacks))?.let { seeTag ->
- row(
- sourceSets = setOf(sourceSet),
- kind = ContentKind.Comment
- ) {
- seeTag.address?.let { dri ->
- link(
- text = seeTag.name.removePrefix("${dri.packageName}."),
- address = dri,
- kind = ContentKind.Comment,
- styles = mainStyles + ContentStyle.RowTitle
- )
- } ?: text(
- text = seeTag.name,
- kind = ContentKind.Comment,
- styles = mainStyles + ContentStyle.RowTitle
- )
- if (seeTag.isNotEmpty()) {
- comment(seeTag.root)
- }
- }
- }
- }
- }
- }
-}
-
-/**
- * Used for multi-value tags (e.g. params) when values are missed on some platforms.
- * It this case description is inherited from parent platform.
- * E.g. if param hasn't description in JVM, the description is taken from common.
- */
-private fun Set<DokkaConfiguration.DokkaSourceSet>.getPossibleFallback(sourceSet: DokkaConfiguration.DokkaSourceSet) =
- this.filter { it.sourceSetID in sourceSet.dependentSourceSets }
-
-private fun <V> Map<DokkaConfiguration.DokkaSourceSet, V>.fallback(sourceSets: List<DokkaConfiguration.DokkaSourceSet>): V? =
- sourceSets.firstOrNull { it in this.keys }.let { this[it] }
-
-internal fun PageContentBuilder.DocumentableContentBuilder.throwsSectionContent(tags: GroupedTags) {
- val throwsTags = tags.withTypeNamed<Throws>()
- if (throwsTags.isEmpty()) return
-
- val availableSourceSets = throwsTags.availableSourceSets()
- tableSectionContentBlock(
- blockName = "Throws",
- kind = ContentKind.Main,
- sourceSets = availableSourceSets
- ) {
- throwsTags.forEach { (throwsName, throwsPerSourceSet) ->
- throwsPerSourceSet.forEach { (sourceSet, throws) ->
- row(sourceSets = setOf(sourceSet)) {
- group(styles = mainStyles + ContentStyle.RowTitle) {
- throws.exceptionAddress?.let {
- val className = it.takeIf { it.target is PointingToDeclaration }?.classNames
- link(text = className ?: throwsName, address = it)
- } ?: text(throwsName)
- }
- if (throws.isNotEmpty()) {
- comment(throws.root)
- }
- }
- }
- }
- }
-}
-
-private fun TagWrapper.isNotEmpty() = this.children.isNotEmpty()
-
-internal fun PageContentBuilder.DocumentableContentBuilder.samplesSectionContent(tags: GroupedTags) {
- val samples = tags.withTypeNamed<Sample>()
- if (samples.isEmpty()) return
-
- val availableSourceSets = samples.availableSourceSets()
-
- header(KDOC_TAG_HEADER_LEVEL, "Samples", kind = ContentKind.Sample, sourceSets = availableSourceSets)
- availableSourceSets.forEach { sourceSet ->
- group(
- sourceSets = setOf(sourceSet),
- kind = ContentKind.Sample,
- styles = setOf(TextStyle.Monospace, ContentStyle.RunnableSample),
- ) {
- samples.filter { it.value.isEmpty() || sourceSet in it.value }
- .forEach { text(text = it.key, sourceSets = setOf(sourceSet)) }
- }
- }
-}
-
-internal fun PageContentBuilder.DocumentableContentBuilder.inheritorsSectionContent(
- documentable: Documentable,
- logger: DokkaLogger,
-) {
- val inheritors = if (documentable is WithScope) documentable.inheritors() else return
- if (inheritors.values.none()) return
-
- // split content section for the case:
- // parent is in the shared source set (without expect-actual) and inheritor is in the platform code
- if (documentable.isDefinedInSharedSourceSetOnly(inheritors.keys.toSet()))
- sharedSourceSetOnlyInheritorsSectionContent(inheritors, logger)
- else
- multiplatformInheritorsSectionContent(documentable, inheritors, logger)
-}
-
-private fun WithScope.inheritors(): SourceSetDependent<List<DRI>> {
- @Suppress("UNCHECKED_CAST")
- val withExtra = this as? WithExtraProperties<Documentable>
-
- return withExtra
- ?.let { it.extra[InheritorsInfo] }
- ?.let { inheritors -> inheritors.value.filter { it.value.isNotEmpty() } }
- .orEmpty()
-}
-
-/**
- * Detect that documentable is located only in the shared code without expect-actuals
- * Value of `analysisPlatform` will be [Platform.common] in cases if a source set shared between 2 different platforms.
- * But if it shared between 2 same platforms (e.g. jvm("awt") and jvm("android"))
- * then the source set will be still marked as jvm platform.
- *
- * So, we also try to check if any of inheritors source sets depends on current documentable source set.
- * that will mean that the source set is shared.
- */
-private fun Documentable.isDefinedInSharedSourceSetOnly(inheritorsSourceSets: Set<DokkaConfiguration.DokkaSourceSet>) =
- sourceSets.size == 1 &&
- (sourceSets.first().analysisPlatform == Platform.common
- || sourceSets.first().hasDependentSourceSet(inheritorsSourceSets))
-
-private fun DokkaConfiguration.DokkaSourceSet.hasDependentSourceSet(
- sourceSets: Set<DokkaConfiguration.DokkaSourceSet>,
-) =
- sourceSets.any { sourceSet -> sourceSet.dependentSourceSets.any { it == this.sourceSetID } }
-
-private fun PageContentBuilder.DocumentableContentBuilder.multiplatformInheritorsSectionContent(
- documentable: Documentable,
- inheritors: Map<DokkaConfiguration.DokkaSourceSet, List<DRI>>,
- logger: DokkaLogger,
-) {
- // intersect is used for removing duplication in case of merged classlikes from different platforms
- val availableSourceSets = inheritors.keys.toSet().intersect(documentable.sourceSets)
-
- tableSectionContentBlock(
- blockName = "Inheritors",
- kind = ContentKind.Inheritors,
- sourceSets = availableSourceSets
- ) {
- availableSourceSets.forEach { sourceSet ->
- inheritors[sourceSet]?.forEach { classlike: DRI ->
- inheritorRow(classlike, logger, sourceSet)
- }
- }
- }
-}
-
-private fun PageContentBuilder.DocumentableContentBuilder.sharedSourceSetOnlyInheritorsSectionContent(
- inheritors: Map<DokkaConfiguration.DokkaSourceSet, List<DRI>>,
- logger: DokkaLogger,
-) {
- val uniqueInheritors = inheritors.values.flatten().toSet()
- tableSectionContentBlock(
- blockName = "Inheritors",
- kind = ContentKind.Inheritors,
- ) {
- uniqueInheritors.forEach { classlike ->
- inheritorRow(classlike, logger)
- }
- }
-}
-
-private fun PageContentBuilder.TableBuilder.inheritorRow(
- classlike: DRI, logger: DokkaLogger, sourceSet: DokkaConfiguration.DokkaSourceSet? = null,
-) = row {
- link(
- text = classlike.friendlyClassName()
- ?: classlike.toString().also { logger.warn("No class name found for DRI $classlike") },
- address = classlike,
- sourceSets = sourceSet?.let { setOf(it) } ?: mainSourcesetData
- )
-}
-
-private fun PageContentBuilder.DocumentableContentBuilder.tableSectionContentBlock(
- blockName: String,
- kind: ContentKind,
- sourceSets: Set<DokkaConfiguration.DokkaSourceSet> = mainSourcesetData,
- body: PageContentBuilder.TableBuilder.() -> Unit,
-) {
- header(KDOC_TAG_HEADER_LEVEL, text = blockName, kind = kind, sourceSets = sourceSets)
- table(
- kind = kind,
- sourceSets = sourceSets,
- ) {
- body()
- }
-}
-
-private fun DRI.friendlyClassName() = classNames?.substringAfterLast(".")
-
-private fun <T> Map<String, SourceSetDependent<T>>.availableSourceSets() = values.flatMap { it.keys }.toSet()
diff --git a/plugins/base/src/main/kotlin/translators/documentables/DriClashAwareName.kt b/plugins/base/src/main/kotlin/translators/documentables/DriClashAwareName.kt
deleted file mode 100644
index 362bb9b9..00000000
--- a/plugins/base/src/main/kotlin/translators/documentables/DriClashAwareName.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.translators.documentables
-
-import org.jetbrains.dokka.model.Documentable
-import org.jetbrains.dokka.model.properties.ExtraProperty
-
-public data class DriClashAwareName(val value: String?): ExtraProperty<Documentable> {
- public companion object : ExtraProperty.Key<Documentable, DriClashAwareName>
- override val key: ExtraProperty.Key<Documentable, *> = Companion
-}
diff --git a/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt b/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt
deleted file mode 100644
index 4ddda674..00000000
--- a/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt
+++ /dev/null
@@ -1,781 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.translators.documentables
-
-import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
-import org.jetbrains.dokka.base.resolvers.anchors.SymbolAnchorHint
-import org.jetbrains.dokka.base.signatures.SignatureProvider
-import org.jetbrains.dokka.base.transformers.pages.comments.CommentsToContentConverter
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.model.Documentable
-import org.jetbrains.dokka.model.SourceSetDependent
-import org.jetbrains.dokka.model.doc.DocTag
-import org.jetbrains.dokka.model.properties.PropertyContainer
-import org.jetbrains.dokka.model.properties.plus
-import org.jetbrains.dokka.model.toDisplaySourceSets
-import org.jetbrains.dokka.pages.*
-import org.jetbrains.dokka.utilities.DokkaLogger
-
-@DslMarker
-public annotation class ContentBuilderMarker
-
-public open class PageContentBuilder(
- public val commentsConverter: CommentsToContentConverter,
- public val signatureProvider: SignatureProvider,
- public val logger: DokkaLogger
-) {
- public fun contentFor(
- dri: DRI,
- sourceSets: Set<DokkaSourceSet>,
- kind: Kind = ContentKind.Main,
- styles: Set<Style> = emptySet(),
- extra: PropertyContainer<ContentNode> = PropertyContainer.empty(),
- block: DocumentableContentBuilder.() -> Unit
- ): ContentGroup =
- DocumentableContentBuilder(setOf(dri), sourceSets, styles, extra)
- .apply(block)
- .build(sourceSets, kind, styles, extra)
-
- public fun contentFor(
- dri: Set<DRI>,
- sourceSets: Set<DokkaSourceSet>,
- kind: Kind = ContentKind.Main,
- styles: Set<Style> = emptySet(),
- extra: PropertyContainer<ContentNode> = PropertyContainer.empty(),
- block: DocumentableContentBuilder.() -> Unit
- ): ContentGroup =
- DocumentableContentBuilder(dri, sourceSets, styles, extra)
- .apply(block)
- .build(sourceSets, kind, styles, extra)
-
- public fun contentFor(
- d: Documentable,
- kind: Kind = ContentKind.Main,
- styles: Set<Style> = emptySet(),
- extra: PropertyContainer<ContentNode> = PropertyContainer.empty(),
- sourceSets: Set<DokkaSourceSet> = d.sourceSets.toSet(),
- block: DocumentableContentBuilder.() -> Unit = {}
- ): ContentGroup =
- DocumentableContentBuilder(setOf(d.dri), sourceSets, styles, extra)
- .apply(block)
- .build(sourceSets, kind, styles, extra)
-
- @ContentBuilderMarker
- public open inner class DocumentableContentBuilder(
- public val mainDRI: Set<DRI>,
- public val mainSourcesetData: Set<DokkaSourceSet>,
- public val mainStyles: Set<Style>,
- public val mainExtra: PropertyContainer<ContentNode>
- ) {
- protected val contents: MutableList<ContentNode> = mutableListOf<ContentNode>()
-
- public fun build(
- sourceSets: Set<DokkaSourceSet>,
- kind: Kind,
- styles: Set<Style>,
- extra: PropertyContainer<ContentNode>
- ): ContentGroup {
- return ContentGroup(
- children = contents.toList(),
- dci = DCI(mainDRI, kind),
- sourceSets = sourceSets.toDisplaySourceSets(),
- style = styles,
- extra = extra
- )
- }
-
- public operator fun ContentNode.unaryPlus() {
- contents += this
- }
-
- public operator fun Collection<ContentNode>.unaryPlus() {
- contents += this
- }
-
- public fun header(
- level: Int,
- text: String,
- kind: Kind = ContentKind.Main,
- sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra,
- block: DocumentableContentBuilder.() -> Unit = {}
- ) {
- contents += ContentHeader(
- level,
- contentFor(
- mainDRI,
- sourceSets,
- kind,
- styles,
- extra + SymbolAnchorHint(text.replace("\\s".toRegex(), "").toLowerCase(), kind)
- ) {
- text(text, kind = kind)
- block()
- }
- )
- }
-
- public fun cover(
- text: String,
- sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
- styles: Set<Style> = mainStyles + TextStyle.Cover,
- extra: PropertyContainer<ContentNode> = mainExtra,
- block: DocumentableContentBuilder.() -> Unit = {}
- ) {
- header(1, text, sourceSets = sourceSets, styles = styles, extra = extra, block = block)
- }
-
- public fun constant(text: String) {
- text(text, styles = mainStyles + TokenStyle.Constant)
- }
-
- public fun keyword(text: String) {
- text(text, styles = mainStyles + TokenStyle.Keyword)
- }
-
- public fun stringLiteral(text: String) {
- text(text, styles = mainStyles + TokenStyle.String)
- }
-
- public fun booleanLiteral(value: Boolean) {
- text(value.toString(), styles = mainStyles + TokenStyle.Boolean)
- }
-
- public fun punctuation(text: String) {
- text(text, styles = mainStyles + TokenStyle.Punctuation)
- }
-
- public fun operator(text: String) {
- text(text, styles = mainStyles + TokenStyle.Operator)
- }
-
- public fun text(
- text: String,
- kind: Kind = ContentKind.Main,
- sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra
- ) {
- contents += createText(text, kind, sourceSets, styles, extra)
- }
-
- public fun breakLine(sourceSets: Set<DokkaSourceSet> = mainSourcesetData) {
- contents += ContentBreakLine(sourceSets.toDisplaySourceSets())
- }
-
- public fun buildSignature(d: Documentable): List<ContentNode> = signatureProvider.signature(d)
-
- public fun table(
- kind: Kind = ContentKind.Main,
- sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra,
- operation: TableBuilder.() -> Unit = {}
- ) {
- contents += TableBuilder(mainDRI, sourceSets, kind, styles, extra).apply {
- operation()
- }.build()
- }
-
- public fun unorderedList(
- kind: Kind = ContentKind.Main,
- sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra,
- operation: ListBuilder.() -> Unit = {}
- ) {
- contents += ListBuilder(false, mainDRI, sourceSets, kind, styles, extra).apply(operation).build()
- }
-
- public fun orderedList(
- kind: Kind = ContentKind.Main,
- sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra,
- operation: ListBuilder.() -> Unit = {}
- ) {
- contents += ListBuilder(true, mainDRI, sourceSets, kind, styles, extra).apply(operation).build()
- }
-
- public fun descriptionList(
- kind: Kind = ContentKind.Main,
- sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra,
- operation: ListBuilder.() -> Unit = {}
- ) {
- contents += ListBuilder(false, mainDRI, sourceSets, kind, styles + ListStyle.DescriptionList, extra)
- .apply(operation)
- .build()
- }
-
- internal fun headers(vararg label: String) = contentFor(mainDRI, mainSourcesetData) {
- label.forEach { text(it) }
- }
-
- public fun <T : Documentable> block(
- name: String,
- level: Int,
- kind: Kind = ContentKind.Main,
- elements: Iterable<T>,
- sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra,
- renderWhenEmpty: Boolean = false,
- needsSorting: Boolean = true,
- headers: List<ContentGroup> = emptyList(),
- needsAnchors: Boolean = false,
- operation: DocumentableContentBuilder.(T) -> Unit
- ) {
- if (renderWhenEmpty || elements.any()) {
- header(level, name, kind = kind) { }
- contents += ContentTable(
- header = headers,
- children = elements
- .let {
- if (needsSorting)
- it.sortedWith(compareBy(nullsLast(String.CASE_INSENSITIVE_ORDER)) { it.name })
- else it
- }
- .map {
- val newExtra = if (needsAnchors) extra + SymbolAnchorHint.from(it, kind) else extra
- buildGroup(setOf(it.dri), it.sourceSets.toSet(), kind, styles, newExtra) {
- operation(it)
- }
- },
- dci = DCI(mainDRI, kind),
- sourceSets = sourceSets.toDisplaySourceSets(),
- style = styles,
- extra = extra
- )
- }
- }
-
- public fun <T : Pair<String, List<Documentable>>> multiBlock(
- name: String,
- level: Int,
- kind: Kind = ContentKind.Main,
- groupedElements: Iterable<T>,
- sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra,
- renderWhenEmpty: Boolean = false,
- needsSorting: Boolean = true,
- headers: List<ContentGroup> = emptyList(),
- needsAnchors: Boolean = false,
- operation: DocumentableContentBuilder.(String, List<Documentable>) -> Unit
- ) {
-
- if (renderWhenEmpty || groupedElements.any()) {
- group(extra = extra) {
- header(level, name, kind = kind) { }
- contents += ContentTable(
- header = headers,
- children = groupedElements
- .let {
- if (needsSorting)
- it.sortedWith(compareBy(nullsLast(String.CASE_INSENSITIVE_ORDER)) { it.first })
- else it
- }
- .map {
- val documentables = it.second
- val newExtra = if (needsAnchors) extra + SymbolAnchorHint(
- it.first,
- kind
- ) else extra
- buildGroup(
- documentables.map { it.dri }.toSet(),
- documentables.flatMap { it.sourceSets }.toSet(),
- kind,
- styles,
- newExtra
- ) {
- operation(it.first, documentables)
- }
- },
- dci = DCI(mainDRI, kind),
- sourceSets = sourceSets.toDisplaySourceSets(),
- style = styles,
- extra = extra
- )
- }
- }
- }
-
- public fun <T> list(
- elements: List<T>,
- prefix: String = "",
- suffix: String = "",
- separator: String = ", ",
- sourceSets: Set<DokkaSourceSet> = mainSourcesetData, // TODO: children should be aware of this platform data
- surroundingCharactersStyle: Set<Style> = mainStyles,
- separatorStyles: Set<Style> = mainStyles,
- operation: DocumentableContentBuilder.(T) -> Unit
- ) {
- if (elements.isNotEmpty()) {
- if (prefix.isNotEmpty()) text(prefix, sourceSets = sourceSets, styles = surroundingCharactersStyle)
- elements.dropLast(1).forEach {
- operation(it)
- text(separator, sourceSets = sourceSets, styles = separatorStyles)
- }
- operation(elements.last())
- if (suffix.isNotEmpty()) text(suffix, sourceSets = sourceSets, styles = surroundingCharactersStyle)
- }
- }
-
- public fun link(
- text: String,
- address: DRI,
- kind: Kind = ContentKind.Main,
- sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra
- ) {
- contents += linkNode(text, address, DCI(mainDRI, kind), sourceSets, styles, extra)
- }
-
- public fun linkNode(
- text: String,
- address: DRI,
- dci: DCI = DCI(mainDRI, ContentKind.Main),
- sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra
- ): ContentLink {
- return ContentDRILink(
- listOf(createText(text, dci.kind, sourceSets, styles, extra)),
- address,
- dci,
- sourceSets.toDisplaySourceSets(),
- extra = extra
- )
- }
-
- public fun link(
- text: String,
- address: String,
- kind: Kind = ContentKind.Main,
- sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra
- ) {
- contents += ContentResolvedLink(
- children = listOf(createText(text, kind, sourceSets, styles, extra)),
- address = address,
- extra = PropertyContainer.empty(),
- dci = DCI(mainDRI, kind),
- sourceSets = sourceSets.toDisplaySourceSets(),
- style = emptySet()
- )
- }
-
- public fun link(
- address: DRI,
- kind: Kind = ContentKind.Main,
- sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra,
- block: DocumentableContentBuilder.() -> Unit
- ) {
- contents += ContentDRILink(
- contentFor(mainDRI, sourceSets, kind, styles, extra, block).children,
- address,
- DCI(mainDRI, kind),
- sourceSets.toDisplaySourceSets(),
- extra = extra
- )
- }
-
- public fun comment(
- docTag: DocTag,
- kind: Kind = ContentKind.Comment,
- sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra
- ) {
- val content = commentsConverter.buildContent(
- docTag,
- DCI(mainDRI, kind),
- sourceSets
- )
- contents += ContentGroup(content, DCI(mainDRI, kind), sourceSets.toDisplaySourceSets(), styles, extra)
- }
-
- public fun codeBlock(
- language: String = "",
- kind: Kind = ContentKind.Main,
- sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra,
- block: DocumentableContentBuilder.() -> Unit
- ) {
- contents += ContentCodeBlock(
- contentFor(mainDRI, sourceSets, kind, styles, extra, block).children,
- language,
- DCI(mainDRI, kind),
- sourceSets.toDisplaySourceSets(),
- styles,
- extra
- )
- }
-
- public fun codeInline(
- language: String = "",
- kind: Kind = ContentKind.Main,
- sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra,
- block: DocumentableContentBuilder.() -> Unit
- ) {
- contents += ContentCodeInline(
- contentFor(mainDRI, sourceSets, kind, styles, extra, block).children,
- language,
- DCI(mainDRI, kind),
- sourceSets.toDisplaySourceSets(),
- styles,
- extra
- )
- }
-
- public fun firstParagraphComment(
- content: DocTag,
- kind: Kind = ContentKind.Comment,
- sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra
- ) {
- firstParagraphBrief(content)?.let { brief ->
- val builtDescription = commentsConverter.buildContent(
- brief,
- DCI(mainDRI, kind),
- sourceSets
- )
-
- contents += ContentGroup(
- builtDescription,
- DCI(mainDRI, kind),
- sourceSets.toDisplaySourceSets(),
- styles,
- extra
- )
- }
- }
-
- public fun firstSentenceComment(
- content: DocTag,
- kind: Kind = ContentKind.Comment,
- sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra
- ){
- val builtDescription = commentsConverter.buildContent(
- content,
- DCI(mainDRI, kind),
- sourceSets
- )
-
- contents += ContentGroup(
- firstSentenceBriefFromContentNodes(builtDescription),
- DCI(mainDRI, kind),
- sourceSets.toDisplaySourceSets(),
- styles,
- extra
- )
- }
-
- public fun group(
- dri: Set<DRI> = mainDRI,
- sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
- kind: Kind = ContentKind.Main,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra,
- block: DocumentableContentBuilder.() -> Unit
- ) {
- contents += buildGroup(dri, sourceSets, kind, styles, extra, block)
- }
-
- public fun divergentGroup(
- groupID: ContentDivergentGroup.GroupID,
- dri: Set<DRI> = mainDRI,
- kind: Kind = ContentKind.Main,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra,
- implicitlySourceSetHinted: Boolean = true,
- block: DivergentBuilder.() -> Unit
- ) {
- contents +=
- DivergentBuilder(dri, kind, styles, extra)
- .apply(block)
- .build(groupID = groupID, implicitlySourceSetHinted = implicitlySourceSetHinted)
- }
-
- public fun buildGroup(
- dri: Set<DRI> = mainDRI,
- sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
- kind: Kind = ContentKind.Main,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra,
- block: DocumentableContentBuilder.() -> Unit
- ): ContentGroup = contentFor(dri, sourceSets, kind, styles, extra, block)
-
- public fun sourceSetDependentHint(
- dri: Set<DRI> = mainDRI,
- sourceSets: Set<DokkaSourceSet> = mainSourcesetData,
- kind: Kind = ContentKind.Main,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra,
- block: DocumentableContentBuilder.() -> Unit
- ) {
- contents += PlatformHintedContent(
- buildGroup(dri, sourceSets, kind, styles, extra, block),
- sourceSets.toDisplaySourceSets()
- )
- }
-
- public fun sourceSetDependentHint(
- dri: DRI,
- sourcesetData: Set<DokkaSourceSet> = mainSourcesetData,
- kind: Kind = ContentKind.Main,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra,
- block: DocumentableContentBuilder.() -> Unit
- ) {
- contents += PlatformHintedContent(
- buildGroup(setOf(dri), sourcesetData, kind, styles, extra, block),
- sourcesetData.toDisplaySourceSets()
- )
- }
-
- protected fun createText(
- text: String,
- kind: Kind,
- sourceSets: Set<DokkaSourceSet>,
- styles: Set<Style>,
- extra: PropertyContainer<ContentNode>
- ): ContentText {
- return ContentText(text, DCI(mainDRI, kind), sourceSets.toDisplaySourceSets(), styles, extra)
- }
-
- public fun <T> sourceSetDependentText(
- value: SourceSetDependent<T>,
- sourceSets: Set<DokkaSourceSet> = value.keys,
- styles: Set<Style> = mainStyles,
- transform: (T) -> String
- ) {
- value.entries
- .filter { it.key in sourceSets }
- .mapNotNull { (p, v) -> transform(v).takeIf { it.isNotBlank() }?.let { it to p } }
- .groupBy({ it.first }) { it.second }
- .forEach { text(it.key, sourceSets = it.value.toSet(), styles = styles) }
- }
- }
-
- @ContentBuilderMarker
- public open inner class TableBuilder(
- private val mainDRI: Set<DRI>,
- private val mainSourceSets: Set<DokkaSourceSet>,
- private val mainKind: Kind,
- private val mainStyles: Set<Style>,
- private val mainExtra: PropertyContainer<ContentNode>
- ) {
- private val headerRows: MutableList<ContentGroup> = mutableListOf()
- private val rows: MutableList<ContentGroup> = mutableListOf()
- private var caption: ContentGroup? = null
-
- public fun header(
- dri: Set<DRI> = mainDRI,
- sourceSets: Set<DokkaSourceSet> = mainSourceSets,
- kind: Kind = mainKind,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra,
- block: DocumentableContentBuilder.() -> Unit
- ) {
- headerRows += contentFor(dri, sourceSets, kind, styles, extra, block)
- }
-
- public fun row(
- dri: Set<DRI> = mainDRI,
- sourceSets: Set<DokkaSourceSet> = mainSourceSets,
- kind: Kind = mainKind,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra,
- block: DocumentableContentBuilder.() -> Unit
- ) {
- rows += contentFor(dri, sourceSets, kind, styles, extra, block)
- }
-
- public fun caption(
- dri: Set<DRI> = mainDRI,
- sourceSets: Set<DokkaSourceSet> = mainSourceSets,
- kind: Kind = mainKind,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra,
- block: DocumentableContentBuilder.() -> Unit
- ) {
- caption = contentFor(dri, sourceSets, kind, styles, extra, block)
- }
-
- public fun build(
- sourceSets: Set<DokkaSourceSet> = mainSourceSets,
- kind: Kind = mainKind,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra
- ): ContentTable {
- return ContentTable(
- headerRows,
- caption,
- rows,
- DCI(mainDRI, kind),
- sourceSets.toDisplaySourceSets(),
- styles, extra
- )
- }
- }
-
- @ContentBuilderMarker
- public open inner class DivergentBuilder(
- private val mainDRI: Set<DRI>,
- private val mainKind: Kind,
- private val mainStyles: Set<Style>,
- private val mainExtra: PropertyContainer<ContentNode>
- ) {
- private val instances: MutableList<ContentDivergentInstance> = mutableListOf()
-
- public fun instance(
- dri: Set<DRI>,
- sourceSets: Set<DokkaSourceSet>, // Having correct sourcesetData is crucial here, that's why there's no default
- kind: Kind = mainKind,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra,
- block: DivergentInstanceBuilder.() -> Unit
- ) {
- instances += DivergentInstanceBuilder(dri, sourceSets, styles, extra)
- .apply(block)
- .build(kind)
- }
-
- public fun build(
- groupID: ContentDivergentGroup.GroupID,
- implicitlySourceSetHinted: Boolean,
- kind: Kind = mainKind,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra
- ): ContentDivergentGroup {
- return ContentDivergentGroup(
- children = instances.toList(),
- dci = DCI(mainDRI, kind),
- style = styles,
- extra = extra,
- groupID = groupID,
- implicitlySourceSetHinted = implicitlySourceSetHinted
- )
- }
- }
-
- @ContentBuilderMarker
- public open inner class DivergentInstanceBuilder(
- private val mainDRI: Set<DRI>,
- private val mainSourceSets: Set<DokkaSourceSet>,
- private val mainStyles: Set<Style>,
- private val mainExtra: PropertyContainer<ContentNode>
- ) {
- private var before: ContentNode? = null
- private var divergent: ContentNode? = null
- private var after: ContentNode? = null
-
- public fun before(
- dri: Set<DRI> = mainDRI,
- sourceSets: Set<DokkaSourceSet> = mainSourceSets,
- kind: Kind = ContentKind.Main,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra,
- block: DocumentableContentBuilder.() -> Unit
- ) {
- contentFor(dri, sourceSets, kind, styles, extra, block)
- .takeIf { it.hasAnyContent() }
- .also { before = it }
- }
-
- public fun divergent(
- dri: Set<DRI> = mainDRI,
- sourceSets: Set<DokkaSourceSet> = mainSourceSets,
- kind: Kind = ContentKind.Main,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra,
- block: DocumentableContentBuilder.() -> Unit
- ) {
- divergent = contentFor(dri, sourceSets, kind, styles, extra, block)
- }
-
- public fun after(
- dri: Set<DRI> = mainDRI,
- sourceSets: Set<DokkaSourceSet> = mainSourceSets,
- kind: Kind = ContentKind.Main,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra,
- block: DocumentableContentBuilder.() -> Unit
- ) {
- contentFor(dri, sourceSets, kind, styles, extra, block)
- .takeIf { it.hasAnyContent() }
- .also { after = it }
- }
-
- public fun build(
- kind: Kind,
- sourceSets: Set<DokkaSourceSet> = mainSourceSets,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra
- ): ContentDivergentInstance {
- return ContentDivergentInstance(
- before,
- divergent ?: throw IllegalStateException("Divergent block needs divergent part"),
- after,
- DCI(mainDRI, kind),
- sourceSets.toDisplaySourceSets(),
- styles,
- extra
- )
- }
- }
-
- @ContentBuilderMarker
- public open inner class ListBuilder(
- public val ordered: Boolean,
- private val mainDRI: Set<DRI>,
- private val mainSourceSets: Set<DokkaSourceSet>,
- private val mainKind: Kind,
- private val mainStyles: Set<Style>,
- private val mainExtra: PropertyContainer<ContentNode>
- ) {
- private val contentNodes: MutableList<ContentNode> = mutableListOf()
-
- public fun item(
- dri: Set<DRI> = mainDRI,
- sourceSets: Set<DokkaSourceSet> = mainSourceSets,
- kind: Kind = mainKind,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra,
- block: DocumentableContentBuilder.() -> Unit
- ) {
- contentNodes += contentFor(dri, sourceSets, kind, styles, extra, block)
- }
-
- public fun build(
- sourceSets: Set<DokkaSourceSet> = mainSourceSets,
- kind: Kind = mainKind,
- styles: Set<Style> = mainStyles,
- extra: PropertyContainer<ContentNode> = mainExtra
- ): ContentList {
- return ContentList(
- contentNodes,
- ordered,
- DCI(mainDRI, kind),
- sourceSets.toDisplaySourceSets(),
- styles, extra
- )
- }
- }
-}
diff --git a/plugins/base/src/main/kotlin/translators/documentables/briefFromContentNodes.kt b/plugins/base/src/main/kotlin/translators/documentables/briefFromContentNodes.kt
deleted file mode 100644
index a073f73a..00000000
--- a/plugins/base/src/main/kotlin/translators/documentables/briefFromContentNodes.kt
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.translators.documentables
-
-import org.jetbrains.dokka.base.utils.firstNotNullOfOrNull
-import org.jetbrains.dokka.model.doc.CustomDocTag
-import org.jetbrains.dokka.model.doc.DocTag
-import org.jetbrains.dokka.model.doc.P
-import org.jetbrains.dokka.model.doc.Text
-import org.jetbrains.dokka.model.withDescendants
-import org.jetbrains.dokka.pages.*
-
-public fun firstParagraphBrief(docTag: DocTag): DocTag? =
- when(docTag){
- is P -> docTag
- is CustomDocTag -> docTag.children.firstNotNullOfOrNull { firstParagraphBrief(it) }
- is Text -> docTag
- else -> null
- }
-
-public fun firstSentenceBriefFromContentNodes(description: List<ContentNode>): List<ContentNode> {
- val firstSentenceRegex = """^((?:[^.?!]|[.!?](?!\s))*[.!?])""".toRegex()
-
- //Description that is entirely based on html content. In html it is hard to define a brief so we render all of it
- if(description.all { it.withDescendants().all { it is ContentGroup || (it as? ContentText)?.isHtml == true } }){
- return description
- }
-
- var sentenceFound = false
- fun lookthrough(node: ContentNode, neighbours: List<ContentNode>, currentIndex: Int): ContentNode =
- if (node.finishesWithSentenceNotFollowedByHtml(firstSentenceRegex, neighbours, currentIndex) || node.containsSentenceFinish(firstSentenceRegex)) {
- node as ContentText
- sentenceFound = true
- node.copy(text = firstSentenceRegex.find(node.text)?.value.orEmpty())
- } else if (node is ContentGroup) {
- node.copy(children = node.children.mapIndexedNotNull { i, element ->
- if (!sentenceFound) lookthrough(element, node.children, i) else null
- }, style = node.style - TextStyle.Paragraph)
- } else {
- node
- }
- return description.mapIndexedNotNull { i, element ->
- if (!sentenceFound) lookthrough(element, description, i) else null
- }
-}
-
-private fun ContentNode.finishesWithSentenceNotFollowedByHtml(firstSentenceRegex: Regex, neighbours: List<ContentNode>, currentIndex: Int): Boolean =
- this is ContentText && !isHtml && matchContainsEnd(this, firstSentenceRegex) && !neighbours.nextElementIsHtml(currentIndex)
-
-private fun ContentNode.containsSentenceFinish(firstSentenceRegex: Regex): Boolean =
- this is ContentText && !isHtml && firstSentenceRegex.containsMatchIn(text) && !matchContainsEnd(this, firstSentenceRegex)
-
-private fun matchContainsEnd(node: ContentText, regex: Regex): Boolean =
- regex.find(node.text)?.let { node.text.endsWith(it.value) } ?: false
-
-private fun List<ContentNode>.nextElementIsHtml(currentElementIndex: Int): Boolean =
- currentElementIndex != lastIndex && get(currentElementIndex + 1).isHtml
-
-private val ContentNode.isHtml
- get() = extra[HtmlContent] != null
diff --git a/plugins/base/src/main/kotlin/utils/CollectionExtensions.kt b/plugins/base/src/main/kotlin/utils/CollectionExtensions.kt
deleted file mode 100644
index 96a0a039..00000000
--- a/plugins/base/src/main/kotlin/utils/CollectionExtensions.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.utils
-
-// TODO [beresnev] remove this copy-paste and use the same method from stdlib instead after updating to 1.5
-internal inline fun <T, R : Any> Iterable<T>.firstNotNullOfOrNull(transform: (T) -> R?): R? {
- for (element in this) {
- val result = transform(element)
- if (result != null) {
- return result
- }
- }
- return null
-}
diff --git a/plugins/base/src/main/kotlin/utils/alphabeticalOrder.kt b/plugins/base/src/main/kotlin/utils/alphabeticalOrder.kt
deleted file mode 100644
index ed620b34..00000000
--- a/plugins/base/src/main/kotlin/utils/alphabeticalOrder.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.base.utils
-
-
-/**
- * Canonical alphabetical order to sort named elements
- */
-internal val canonicalAlphabeticalOrder: Comparator<in String> = String.CASE_INSENSITIVE_ORDER.thenBy { it }