diff options
author | Ignat Beresnev <ignat.beresnev@jetbrains.com> | 2023-11-10 11:46:54 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-10 11:46:54 +0100 |
commit | 8e5c63d035ef44a269b8c43430f43f5c8eebfb63 (patch) | |
tree | 1b915207b2b9f61951ddbf0ff2e687efd053d555 /plugins/base/src | |
parent | a44efd4ba0c2e4ab921ff75e0f53fc9335aa79db (diff) | |
download | dokka-8e5c63d035ef44a269b8c43430f43f5c8eebfb63.tar.gz dokka-8e5c63d035ef44a269b8c43430f43f5c8eebfb63.tar.bz2 dokka-8e5c63d035ef44a269b8c43430f43f5c8eebfb63.zip |
Restructure the project to utilize included builds (#3174)
* Refactor and simplify artifact publishing
* Update Gradle to 8.4
* Refactor and simplify convention plugins and build scripts
Fixes #3132
---------
Co-authored-by: Adam <897017+aSemy@users.noreply.github.com>
Co-authored-by: Oleg Yukhnevich <whyoleg@gmail.com>
Diffstat (limited to 'plugins/base/src')
318 files changed, 0 insertions, 45163 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 } diff --git a/plugins/base/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin b/plugins/base/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin deleted file mode 100644 index a014a209..00000000 --- a/plugins/base/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin +++ /dev/null @@ -1,5 +0,0 @@ -# -# Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. -# - -org.jetbrains.dokka.base.DokkaBase diff --git a/plugins/base/src/main/resources/dokka/docs/javadoc/EnumValueOf.java.template b/plugins/base/src/main/resources/dokka/docs/javadoc/EnumValueOf.java.template deleted file mode 100644 index 233f8819..00000000 --- a/plugins/base/src/main/resources/dokka/docs/javadoc/EnumValueOf.java.template +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Returns the enum constant of this type with the specified - * name. - * The string must match exactly an identifier used to declare - * an enum constant in this type. (Extraneous whitespace - * characters are not permitted.) - * - * @return the enum constant with the specified name - * @throws IllegalArgumentException if this enum type has no - * constant with the specified name - */ -
\ No newline at end of file diff --git a/plugins/base/src/main/resources/dokka/docs/javadoc/EnumValues.java.template b/plugins/base/src/main/resources/dokka/docs/javadoc/EnumValues.java.template deleted file mode 100644 index 4aed38a6..00000000 --- a/plugins/base/src/main/resources/dokka/docs/javadoc/EnumValues.java.template +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Returns an array containing the constants of this enum - * type, in the order they're declared. This method may be - * used to iterate over the constants. - * - * @return an array containing the constants of this enum - * type, in the order they're declared - */ diff --git a/plugins/base/src/main/resources/dokka/docs/kdoc/EnumEntries.kt.template b/plugins/base/src/main/resources/dokka/docs/kdoc/EnumEntries.kt.template deleted file mode 100644 index 20d16421..00000000 --- a/plugins/base/src/main/resources/dokka/docs/kdoc/EnumEntries.kt.template +++ /dev/null @@ -1,3 +0,0 @@ -Returns a representation of an immutable list of all enum entries, in the order they're declared. - -This method may be used to iterate over the enum entries. diff --git a/plugins/base/src/main/resources/dokka/docs/kdoc/EnumValueOf.kt.template b/plugins/base/src/main/resources/dokka/docs/kdoc/EnumValueOf.kt.template deleted file mode 100644 index fbf8fa8d..00000000 --- a/plugins/base/src/main/resources/dokka/docs/kdoc/EnumValueOf.kt.template +++ /dev/null @@ -1,4 +0,0 @@ -Returns the enum constant of this type with the specified name. The string must match exactly an identifier used -to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.) - -@throws kotlin.IllegalArgumentException if this enum type has no constant with the specified name diff --git a/plugins/base/src/main/resources/dokka/docs/kdoc/EnumValues.kt.template b/plugins/base/src/main/resources/dokka/docs/kdoc/EnumValues.kt.template deleted file mode 100644 index c0e3559c..00000000 --- a/plugins/base/src/main/resources/dokka/docs/kdoc/EnumValues.kt.template +++ /dev/null @@ -1,3 +0,0 @@ -Returns an array containing the constants of this enum type, in the order they're declared. - -This method may be used to iterate over the constants. diff --git a/plugins/base/src/main/resources/dokka/format/gfm.properties b/plugins/base/src/main/resources/dokka/format/gfm.properties deleted file mode 100644 index 66b1ea8f..00000000 --- a/plugins/base/src/main/resources/dokka/format/gfm.properties +++ /dev/null @@ -1,6 +0,0 @@ -# -# Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. -# - -class=org.jetbrains.dokka.Formats.GFMFormatDescriptor -description=Produces documentation in GitHub-flavored markdown format diff --git a/plugins/base/src/main/resources/dokka/format/html-as-java.properties b/plugins/base/src/main/resources/dokka/format/html-as-java.properties deleted file mode 100644 index cbb5a399..00000000 --- a/plugins/base/src/main/resources/dokka/format/html-as-java.properties +++ /dev/null @@ -1,6 +0,0 @@ -# -# Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. -# - -class=org.jetbrains.dokka.Formats.HtmlAsJavaFormatDescriptor -description=Produces output in HTML format using Java syntax diff --git a/plugins/base/src/main/resources/dokka/format/html.properties b/plugins/base/src/main/resources/dokka/format/html.properties deleted file mode 100644 index 42438d16..00000000 --- a/plugins/base/src/main/resources/dokka/format/html.properties +++ /dev/null @@ -1,6 +0,0 @@ -# -# Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. -# - -class=org.jetbrains.dokka.Formats.HtmlFormatDescriptor -description=Produces output in HTML format diff --git a/plugins/base/src/main/resources/dokka/format/java-layout-html.properties b/plugins/base/src/main/resources/dokka/format/java-layout-html.properties deleted file mode 100644 index 79925edd..00000000 --- a/plugins/base/src/main/resources/dokka/format/java-layout-html.properties +++ /dev/null @@ -1,6 +0,0 @@ -# -# Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. -# - -class=org.jetbrains.dokka.Formats.JavaLayoutHtmlFormatDescriptor -description=Produces Kotlin Style Docs with Javadoc like layout diff --git a/plugins/base/src/main/resources/dokka/format/jekyll.properties b/plugins/base/src/main/resources/dokka/format/jekyll.properties deleted file mode 100644 index 28f55afc..00000000 --- a/plugins/base/src/main/resources/dokka/format/jekyll.properties +++ /dev/null @@ -1,6 +0,0 @@ -# -# Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. -# - -class=org.jetbrains.dokka.Formats.JekyllFormatDescriptor -description=Produces documentation in Jekyll format diff --git a/plugins/base/src/main/resources/dokka/format/kotlin-website-html.properties b/plugins/base/src/main/resources/dokka/format/kotlin-website-html.properties deleted file mode 100644 index 4e8dea39..00000000 --- a/plugins/base/src/main/resources/dokka/format/kotlin-website-html.properties +++ /dev/null @@ -1,6 +0,0 @@ -# -# Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. -# - -class=org.jetbrains.dokka.Formats.KotlinWebsiteHtmlFormatDescriptor -description=Generates Kotlin website documentation diff --git a/plugins/base/src/main/resources/dokka/format/markdown.properties b/plugins/base/src/main/resources/dokka/format/markdown.properties deleted file mode 100644 index 62a0f2b2..00000000 --- a/plugins/base/src/main/resources/dokka/format/markdown.properties +++ /dev/null @@ -1,6 +0,0 @@ -# -# Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. -# - -class=org.jetbrains.dokka.Formats.MarkdownFormatDescriptor -description=Produces documentation in markdown format diff --git a/plugins/base/src/main/resources/dokka/images/anchor-copy-button.svg b/plugins/base/src/main/resources/dokka/images/anchor-copy-button.svg deleted file mode 100644 index 19c1fa3f..00000000 --- a/plugins/base/src/main/resources/dokka/images/anchor-copy-button.svg +++ /dev/null @@ -1,8 +0,0 @@ -<!-- - - Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - --> - -<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> - <path d="M21.2496 5.3C20.3496 4.5 19.2496 4 18.0496 4C16.8496 4 15.6496 4.5 14.8496 5.3L10.3496 9.8L11.7496 11.2L16.2496 6.7C17.2496 5.7 18.8496 5.7 19.8496 6.7C20.8496 7.7 20.8496 9.3 19.8496 10.3L15.3496 14.8L16.7496 16.2L21.2496 11.7C22.1496 10.8 22.5496 9.7 22.5496 8.5C22.5496 7.3 22.1496 6.2 21.2496 5.3Z" fill="#637282"/> - <path d="M8.35 16.7998C7.35 17.7998 5.75 17.7998 4.75 16.7998C3.75 15.7998 3.75 14.1998 4.75 13.1998L9.25 8.6998L7.85 7.2998L3.35 11.7998C1.55 13.5998 1.55 16.3998 3.35 18.1998C4.25 19.0998 5.35 19.4998 6.55 19.4998C7.75 19.4998 8.85 19.0998 9.75 18.1998L14.25 13.6998L12.85 12.2998L8.35 16.7998Z" fill="#637282"/> -</svg> diff --git a/plugins/base/src/main/resources/dokka/images/arrow_down.svg b/plugins/base/src/main/resources/dokka/images/arrow_down.svg deleted file mode 100755 index 639aaf12..00000000 --- a/plugins/base/src/main/resources/dokka/images/arrow_down.svg +++ /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. - --> - -<svg width="24" height="24" viewBox="-5 -3 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> - <path d="M11 9l-6 5.25V3.75z" fill="currentColor"/> -</svg> diff --git a/plugins/base/src/main/resources/dokka/images/burger.svg b/plugins/base/src/main/resources/dokka/images/burger.svg deleted file mode 100644 index fcca732b..00000000 --- a/plugins/base/src/main/resources/dokka/images/burger.svg +++ /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. - --> - -<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg"> - <path d="M23.3379 5.83331H4.67126V8.16665H23.3379V5.83331Z" fill="white"/> - <path d="M23.3379 12.8333H4.67126V15.1666H23.3379V12.8333Z" fill="white"/> - <path d="M4.67126 19.8333H23.3379V22.1666H4.67126V19.8333Z" fill="white"/> -</svg> diff --git a/plugins/base/src/main/resources/dokka/images/copy-icon.svg b/plugins/base/src/main/resources/dokka/images/copy-icon.svg deleted file mode 100644 index 2cb02ec6..00000000 --- a/plugins/base/src/main/resources/dokka/images/copy-icon.svg +++ /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. - --> - -<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> - <path fill-rule="evenodd" clip-rule="evenodd" d="M5 4H15V16H5V4ZM17 7H19V18V20H17H8V18H17V7Z" fill="black"/> -</svg> diff --git a/plugins/base/src/main/resources/dokka/images/copy-successful-icon.svg b/plugins/base/src/main/resources/dokka/images/copy-successful-icon.svg deleted file mode 100644 index c4b95383..00000000 --- a/plugins/base/src/main/resources/dokka/images/copy-successful-icon.svg +++ /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. - --> - -<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg"> - <path d="M18 9C18 14 14 18 9 18C4 18 0 14 0 9C0 4 4 0 9 0C14 0 18 4 18 9ZM14.2 6.2L12.8 4.8L7.5 10.1L5.3 7.8L3.8 9.2L7.5 13L14.2 6.2Z" fill="#4DBB5F"/> -</svg> diff --git a/plugins/base/src/main/resources/dokka/images/footer-go-to-link.svg b/plugins/base/src/main/resources/dokka/images/footer-go-to-link.svg deleted file mode 100644 index a87add7a..00000000 --- a/plugins/base/src/main/resources/dokka/images/footer-go-to-link.svg +++ /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. - --> - -<svg width="8" height="8" viewBox="0 0 8 8" fill="none" xmlns="http://www.w3.org/2000/svg"> - <path d="M8 0H2.3949L4.84076 2.44586L0 7.28662L0.713376 8L5.55414 3.15924L8 5.6051V0Z" fill="#637282"/> -</svg> diff --git a/plugins/base/src/main/resources/dokka/images/go-to-top-icon.svg b/plugins/base/src/main/resources/dokka/images/go-to-top-icon.svg deleted file mode 100644 index abc3d1ce..00000000 --- a/plugins/base/src/main/resources/dokka/images/go-to-top-icon.svg +++ /dev/null @@ -1,8 +0,0 @@ -<!-- - - Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - --> - -<svg width="12" height="10" viewBox="0 0 12 10" fill="none" xmlns="http://www.w3.org/2000/svg"> - <path d="M11.3337 9.66683H0.666992L6.00033 3.66683L11.3337 9.66683Z" fill="#637282"/> - <path d="M0.666992 0.333496H11.3337V1.66683H0.666992V0.333496Z" fill="#637282"/> -</svg> diff --git a/plugins/base/src/main/resources/dokka/images/homepage.svg b/plugins/base/src/main/resources/dokka/images/homepage.svg deleted file mode 100644 index a3d7602b..00000000 --- a/plugins/base/src/main/resources/dokka/images/homepage.svg +++ /dev/null @@ -1,5 +0,0 @@ -<!-- SOURCE: https://www.svgrepo.com/svg/416627/home-house-ui --> -<svg fill="#ffffff" width="64px" height="64px" viewBox="0 0 512.00 512.00" xmlns="http://www.w3.org/2000/svg"> - <path d="M256,0C114.615,0,0,114.615,0,256s114.615,256,256,256s256-114.615,256-256S397.385,0,256,0z M404.861,263.236 L404.861,263.236c-7.297,7.297-18.066,8.993-26.986,5.104v97.098c0,20.193-16.37,36.562-36.562,36.562H170.688 c-20.193,0-36.562-16.37-36.562-36.562v-97.098c-8.919,3.89-19.689,2.193-26.986-5.104c-9.519-9.519-9.519-24.952,0-34.471 L238.764,97.139h0c9.519-9.519,24.952-9.519,34.471,0l131.625,131.625C414.38,238.283,414.38,253.717,404.861,263.236z"/> - <path d="M286.469,267.938h-60.938c-6.731,0-12.188,5.457-12.188,12.188v73.125c0,6.731,5.457,12.188,12.188,12.188h60.938 c6.731,0,12.188-5.457,12.188-12.188v-73.125C298.656,273.394,293.2,267.938,286.469,267.938z"/> -</svg> diff --git a/plugins/base/src/main/resources/dokka/images/logo-icon.svg b/plugins/base/src/main/resources/dokka/images/logo-icon.svg deleted file mode 100755 index e42f9570..00000000 --- a/plugins/base/src/main/resources/dokka/images/logo-icon.svg +++ /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. - --> - -<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg"> - <path d="M64 64H0V0H64L31.3373 31.5369L64 64Z" fill="url(#paint0_radial)"/> - <defs> - <radialGradient id="paint0_radial" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(61.8732 2.63097) scale(73.3111)"> - <stop offset="0.00343514" stop-color="#EF4857"/> - <stop offset="0.4689" stop-color="#D211EC"/> - <stop offset="1" stop-color="#7F52FF"/> - </radialGradient> - </defs> -</svg> diff --git a/plugins/base/src/main/resources/dokka/images/nav-icons/abstract-class-kotlin.svg b/plugins/base/src/main/resources/dokka/images/nav-icons/abstract-class-kotlin.svg deleted file mode 100644 index 19d6148c..00000000 --- a/plugins/base/src/main/resources/dokka/images/nav-icons/abstract-class-kotlin.svg +++ /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. - --> - -<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> -<g id="abstractClassKotlin"> -<path id="Fill 1" fill-rule="evenodd" clip-rule="evenodd" d="M3 3.1055C1.764 4.3685 1 6.0935 1 8.0005C1 9.9065 1.764 11.6315 3 12.8945V3.1055Z" fill="#9AA7B0" fill-opacity="0.8"/> -<path id="Combined Shape" fill-rule="evenodd" clip-rule="evenodd" d="M13 8V3.1055C14.2359 4.36739 14.9999 6.0932 15 8H13Z" fill="#9AA7B0" fill-opacity="0.8"/> -<g id="idea/community/platform/icons/src/nodes/class"> -<mask id="mask0" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="4" y="1" width="8" height="14"> -<path id="Mask" d="M4 1H12V8H8V15H4V1Z" fill="white"/> -</mask> -<g mask="url(#mask0)"> -<g id="class"> -<path id="Fill 1_2" fill-rule="evenodd" clip-rule="evenodd" d="M15 8C15 11.866 11.866 15 8 15C4.134 15 1 11.866 1 8C1 4.134 4.134 1 8 1C11.866 1 15 4.134 15 8Z" fill="#40B6E0" fill-opacity="0.6"/> -<g id="⌘/alphabet/nodes/c"> -<path id="⌘/alphabet/nodes/c_2" fill-rule="evenodd" clip-rule="evenodd" d="M10 9.28253C9.53001 9.74153 9.02801 9.978 8.10001 10C7.06101 10.022 6.00001 9.2794 6.00001 8.0004C6.00001 6.7124 6.97101 6 8.10001 6C9.37251 6 9.90001 6.55426 9.90001 6.55426L10.5162 5.83673C9.82941 5.27017 9.28828 5.0004 8.09821 5.0004C6.34021 5.0004 5.00021 6.3584 5.00021 8.0004C5.00021 9.6824 6.36421 11.0004 8.00221 11.0004C9.29286 11.0004 10.0232 10.5934 10.6162 9.9814L10 9.28253Z" fill="#231F20" fill-opacity="0.7"/> -</g> -</g> -</g> -</g> -<g id="⌘/modifier/kotlin"> -<path id="⌘/modifier/kotlin_2" d="M16 16H9V9H16L12.4 12.4L16 16Z" fill="#B99BF8"/> -</g> -</g> -</svg> diff --git a/plugins/base/src/main/resources/dokka/images/nav-icons/abstract-class.svg b/plugins/base/src/main/resources/dokka/images/nav-icons/abstract-class.svg deleted file mode 100644 index 60182030..00000000 --- a/plugins/base/src/main/resources/dokka/images/nav-icons/abstract-class.svg +++ /dev/null @@ -1,20 +0,0 @@ -<!-- Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. --> -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16"> - <defs> - <rect id="abstractclass-a" width="8" height="14"/> - </defs> - <g fill="none" fill-rule="evenodd"> - <path fill="#9AA7B0" fill-opacity=".8" d="M3 3.1055C1.764 4.3685 1 6.0935 1 8.0005 1 9.9065 1.764 11.6315 3 12.8945L3 3.1055zM13 3.1055L13 12.8945C14.236 11.6315 15 9.9065 15 8.0005 15 6.0935 14.236 4.3675 13 3.1055"/> - <g transform="translate(4 1)"> - <mask id="abstractclass-b" fill="#fff"> - <use xlink:href="#abstractclass-a"/> - </mask> - <g mask="url(#abstractclass-b)"> - <g transform="translate(-4 -1)"> - <path fill="#40B6E0" fill-opacity=".6" d="M15,8 C15,11.866 11.866,15 8,15 C4.134,15 1,11.866 1,8 C1,4.134 4.134,1 8,1 C11.866,1 15,4.134 15,8"/> - <path fill="#231F20" fill-opacity=".7" d="M5,4.28253174 C4.53,4.74153174 4.028,4.978 3.1,5 C2.061,5.022 1,4.2794 1,3.0004 C1,1.7124 1.971,1 3.1,1 C3.94833171,1 4.54833171,1.18475342 4.9,1.55426025 L5.5162,0.836730957 C4.8293999,0.270175195 4.28826904,0.0004 3.0982,0.0004 C1.3402,0.0004 0.0002,1.3584 0.0002,3.0004 C0.0002,4.6824 1.3642,6.0004 3.0022,6.0004 C4.29284668,6.0004 5.0232,5.5934 5.6162,4.9814 C5.2054,4.51548783 5,4.28253174 5,4.28253174 Z" transform="translate(5 5)"/> - </g> - </g> - </g> - </g> -</svg> diff --git a/plugins/base/src/main/resources/dokka/images/nav-icons/annotation-kotlin.svg b/plugins/base/src/main/resources/dokka/images/nav-icons/annotation-kotlin.svg deleted file mode 100644 index b90f508c..00000000 --- a/plugins/base/src/main/resources/dokka/images/nav-icons/annotation-kotlin.svg +++ /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. - --> - -<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> -<g id="annotationKotlin"> -<g id="⌘/modifier/kotlin"> -<path id="⌘/modifier/kotlin_2" d="M16 16H9V9H16L12.4 12.4L16 16Z" fill="#B99BF8"/> -</g> -<path id="Vector" fill-rule="evenodd" clip-rule="evenodd" d="M8 15C4.134 15 1 11.866 1 8C1 4.134 4.134 1 8 1C11.866 1 15 4.134 15 8H8V15Z" fill="#62B543" fill-opacity="0.6"/> -<path id="Vector_2" fill-rule="evenodd" clip-rule="evenodd" d="M8.00001 9.32546V9.99479C7.96296 9.99826 7.92599 10 7.88911 10C7.07966 10 6.00011 9.9211 6.00011 8.0001C6.00011 6.32043 7.45594 6.0001 8.00011 6.0001C8.15311 6.0001 9.74511 6.0551 9.82411 6.0791L9.75124 8H8.76699C8.7695 7.96484 8.77154 7.9292 8.77311 7.8931L8.84211 6.6991L8.80011 6.6891C8.68511 6.6621 8.59811 6.6481 8.50011 6.6371C8.40211 6.6271 8.30411 6.6221 8.20211 6.6221C7.97811 6.6221 7.78611 6.6681 7.62811 6.7611C7.47311 6.8511 7.34511 6.9741 7.24611 7.1241C7.15111 7.2721 7.08111 7.4411 7.03911 7.6261C6.99711 7.8091 6.97611 7.9961 6.97611 8.1841C6.97611 8.5861 7.04911 8.8721 7.19711 9.0581C7.34911 9.2481 7.55411 9.3451 7.80511 9.3451C7.87359 9.3451 7.93863 9.33855 8.00001 9.32546ZM11.9819 8H11.0207C11.0512 7.78917 11.0601 7.61595 11.0601 7.5471C11.0601 4.90741 8.70811 4.7451 8.31611 4.7451C7.77111 4.7451 4.94355 4.85089 4.94355 8.0006C4.94355 8.58402 4.94355 11.2461 7.88911 11.2461C7.91058 11.2461 7.94864 11.2438 8.00001 11.2394V11.9994C7.9664 11.9999 7.93243 12.0001 7.89811 12.0001C7.15577 12.0001 4.00211 12.0001 4.00211 8.0006C4.00211 4.0011 7.66743 4.0011 8.31611 4.0011C8.65106 4.0011 12.0001 4.08643 12.0001 7.5571C12.0001 7.71468 11.9938 7.86209 11.9819 8Z" fill="#231F20" fill-opacity="0.7"/> -</g> -</svg> diff --git a/plugins/base/src/main/resources/dokka/images/nav-icons/annotation.svg b/plugins/base/src/main/resources/dokka/images/nav-icons/annotation.svg deleted file mode 100644 index b80c54b4..00000000 --- a/plugins/base/src/main/resources/dokka/images/nav-icons/annotation.svg +++ /dev/null @@ -1,7 +0,0 @@ -<!-- Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. --> -<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"> - <g fill="none" fill-rule="evenodd"> - <path fill="#62B543" fill-opacity=".6" d="M15,8 C15,11.866 11.866,15 8,15 C4.134,15 1,11.866 1,8 C1,4.134 4.134,1 8,1 C11.866,1 15,4.134 15,8"/> - <path fill="#231F20" fill-opacity=".7" d="M3.6281,2.7611 C3.4731,2.8511 3.3451,2.9741 3.2461,3.1241 C3.1511,3.2721 3.0811,3.4411 3.0391,3.6261 C2.9971,3.8091 2.9761,3.9961 2.9761,4.1841 C2.9761,4.5861 3.0491,4.8721 3.1971,5.0581 C3.3491,5.2481 3.5541,5.3451 3.8051,5.3451 C3.9701,5.3451 4.1151,5.3071 4.2371,5.2311 C4.3571,5.1581 4.4571,5.0531 4.5331,4.9201 C4.6061,4.7931 4.6631,4.6401 4.7011,4.4641 C4.7391,4.2941 4.7641,4.1011 4.7731,3.8931 L4.8421,2.6991 L4.8001,2.6891 C4.6851,2.6621 4.5981,2.6481 4.5001,2.6371 C4.4021,2.6271 4.3041,2.6221 4.2021,2.6221 C3.9781,2.6221 3.7861,2.6681 3.6281,2.7611 Z M0.0021,4.0006 C0.0021,0.0011 3.66741943,0.0011 4.3161,0.0011 C4.65105644,0.0011 8.0001,0.0864290039 8.0001,3.5571 C8.0001,6.0091 6.4751,6 6.1701,6 C5.67331784,5.97 5.31431784,5.7737 5.0931,5.4111 C4.68260397,5.8037 4.28127064,6 3.8891,6 C3.0796519,6 2.0001,5.9211 2.0001,4.0001 C2.0001,2.32043457 3.45593262,2.0001 4.0001,2.0001 C4.1531,2.0001 5.7451,2.0551 5.8241,2.0791 L5.7441,4.1881 C5.6361,4.89276667 5.7991,5.2451 6.2331,5.2451 C6.95605469,5.2451 7.0601,3.7831 7.0601,3.5471 C7.0601,0.907409668 4.7081,0.7451 4.3161,0.7451 C3.7711,0.7451 0.94354248,0.850891113 0.94354248,4.0006 C0.94354248,4.58402311 0.94354248,7.2461 3.8891,7.2461 C4.0901,7.2461 5.7441,7.04302979 6.1621,6.8281 L6.1621,7.5781 C5.8551,7.7031 5.0931,8.0001 3.8981,8.0001 C3.15576172,8.0001 0.0021,8.0001 0.0021,4.0006 Z" transform="translate(4 4)"/> - </g> -</svg> diff --git a/plugins/base/src/main/resources/dokka/images/nav-icons/class-kotlin.svg b/plugins/base/src/main/resources/dokka/images/nav-icons/class-kotlin.svg deleted file mode 100644 index 797a2423..00000000 --- a/plugins/base/src/main/resources/dokka/images/nav-icons/class-kotlin.svg +++ /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. - --> - -<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> -<g id="classKotlin"> -<g id="⌘/modifier/kotlin"> -<path id="⌘/modifier/kotlin_2" d="M16 16H9V9H16L12.4 12.4L16 16Z" fill="#B99BF8"/> -</g> -<path id="Vector" fill-rule="evenodd" clip-rule="evenodd" d="M8 15C4.134 15 1 11.866 1 8C1 4.134 4.134 1 8 1C11.866 1 15 4.134 15 8H8V15Z" fill="#40B6E0" fill-opacity="0.6"/> -<path id="Vector_2" fill-rule="evenodd" clip-rule="evenodd" d="M8.00001 11.0004C6.36299 10.9992 5.00021 9.68165 5.00021 8.0004C5.00021 6.3584 6.34021 5.0004 8.09821 5.0004C9.28828 5.0004 9.82941 5.27018 10.5162 5.83673L9.90001 6.55426C9.54835 6.18475 8.94835 6 8.10001 6C6.97101 6 6.00001 6.7124 6.00001 8.0004C6.00001 9.23838 6.99405 9.97382 8.00001 9.99976V11.0004V11.0004Z" fill="#231F20" fill-opacity="0.7"/> -</g> -</svg> diff --git a/plugins/base/src/main/resources/dokka/images/nav-icons/class.svg b/plugins/base/src/main/resources/dokka/images/nav-icons/class.svg deleted file mode 100644 index 3f1ad167..00000000 --- a/plugins/base/src/main/resources/dokka/images/nav-icons/class.svg +++ /dev/null @@ -1,7 +0,0 @@ -<!-- Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. --> -<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"> - <g fill="none" fill-rule="evenodd"> - <path fill="#40B6E0" fill-opacity=".6" d="M15,8 C15,11.866 11.866,15 8,15 C4.134,15 1,11.866 1,8 C1,4.134 4.134,1 8,1 C11.866,1 15,4.134 15,8"/> - <path fill="#231F20" fill-opacity=".7" d="M5,4.28253174 C4.53,4.74153174 4.028,4.978 3.1,5 C2.061,5.022 1,4.2794 1,3.0004 C1,1.7124 1.971,1 3.1,1 C3.94833171,1 4.54833171,1.18475342 4.9,1.55426025 L5.5162,0.836730957 C4.8293999,0.270175195 4.28826904,0.0004 3.0982,0.0004 C1.3402,0.0004 0.0002,1.3584 0.0002,3.0004 C0.0002,4.6824 1.3642,6.0004 3.0022,6.0004 C4.29284668,6.0004 5.0232,5.5934 5.6162,4.9814 C5.2054,4.51548783 5,4.28253174 5,4.28253174 Z" transform="translate(5 5)"/> - </g> -</svg> diff --git a/plugins/base/src/main/resources/dokka/images/nav-icons/enum-kotlin.svg b/plugins/base/src/main/resources/dokka/images/nav-icons/enum-kotlin.svg deleted file mode 100644 index 775a7cc9..00000000 --- a/plugins/base/src/main/resources/dokka/images/nav-icons/enum-kotlin.svg +++ /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. - --> - -<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> -<g id="enumKotlin"> -<g id="⌘/modifier/kotlin"> -<path id="⌘/modifier/kotlin_2" d="M16 16H9V9H16L12.4 12.4L16 16Z" fill="#B99BF8"/> -</g> -<path id="Vector" fill-rule="evenodd" clip-rule="evenodd" d="M8 15C4.134 15 1 11.866 1 8C1 4.134 4.134 1 8 1C11.866 1 15 4.134 15 8H8V15Z" fill="#40B6E0" fill-opacity="0.6"/> -<path id="Vector_2" fill-rule="evenodd" clip-rule="evenodd" d="M8 11H6V5H10V6H7V7H9V8H7V10H8V11Z" fill="#231F20" fill-opacity="0.7"/> -</g> -</svg> diff --git a/plugins/base/src/main/resources/dokka/images/nav-icons/enum.svg b/plugins/base/src/main/resources/dokka/images/nav-icons/enum.svg deleted file mode 100644 index fa7f2476..00000000 --- a/plugins/base/src/main/resources/dokka/images/nav-icons/enum.svg +++ /dev/null @@ -1,7 +0,0 @@ -<!-- Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. --> -<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"> - <g fill="none" fill-rule="evenodd"> - <path fill="#40B6E0" fill-opacity=".6" d="M15,8 C15,11.866 11.866,15 8,15 C4.134,15 1,11.866 1,8 C1,4.134 4.134,1 8,1 C11.866,1 15,4.134 15,8"/> - <polygon fill="#231F20" fill-opacity=".7" points="4 6 0 6 0 0 4 0 4 1 1 1 1 2 3.5 2 3.5 3 1 3 1 5 4 5" transform="translate(6 5)"/> - </g> -</svg> diff --git a/plugins/base/src/main/resources/dokka/images/nav-icons/exception-class.svg b/plugins/base/src/main/resources/dokka/images/nav-icons/exception-class.svg deleted file mode 100644 index c0b2bdeb..00000000 --- a/plugins/base/src/main/resources/dokka/images/nav-icons/exception-class.svg +++ /dev/null @@ -1,7 +0,0 @@ -<!-- Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. --> -<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"> - <g fill="none" fill-rule="evenodd"> - <path fill="#40B6E0" fill-opacity=".6" d="M15,8 C15,11.866 11.866,15 8,15 C4.134,15 1,11.866 1,8 C1,4.134 4.134,1 8,1 C11.866,1 15,4.134 15,8"/> - <polygon fill="#231F20" fill-opacity=".7" points="7 13 9 9 4 9 9 3 8 7 12 7"/> - </g> -</svg> diff --git a/plugins/base/src/main/resources/dokka/images/nav-icons/field-value.svg b/plugins/base/src/main/resources/dokka/images/nav-icons/field-value.svg deleted file mode 100644 index 2771ee56..00000000 --- a/plugins/base/src/main/resources/dokka/images/nav-icons/field-value.svg +++ /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. - --> - -<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"> - <g fill="none" fill-rule="evenodd"> - <rect width="14" height="14" x="1" y="1" fill="#B99BF8" fill-opacity=".6" rx="3"/> - <path fill="#231F20" fill-opacity=".7" d="M2.2939,6 L-0.0001,0 L1.2,0 C2.3886,3.13933333 2.98856667,4.73933333 2.9999,4.8 L4.8,0 L5.9999,0 L3.7059,6 L2.2939,6 Z" transform="translate(5 5)"/> - </g> -</svg> diff --git a/plugins/base/src/main/resources/dokka/images/nav-icons/field-variable.svg b/plugins/base/src/main/resources/dokka/images/nav-icons/field-variable.svg deleted file mode 100644 index e2d2bbd0..00000000 --- a/plugins/base/src/main/resources/dokka/images/nav-icons/field-variable.svg +++ /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. - --> - -<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"> - <g fill="none" fill-rule="evenodd"> - <path fill="#B99BF8" fill-opacity=".6" d="M15,8 C15,11.866 11.866,15 8,15 C4.134,15 1,11.866 1,8 C1,4.134 4.134,1 8,1 C11.866,1 15,4.134 15,8"/> - <path fill="#231F20" fill-opacity=".7" d="M2.2939,6 L-0.0001,0 L1.2,0 C2.3886,3.13933333 2.98856667,4.73933333 2.9999,4.8 L4.8,0 L5.9999,0 L3.7059,6 L2.2939,6 Z" transform="translate(5 5)"/> - </g> -</svg> diff --git a/plugins/base/src/main/resources/dokka/images/nav-icons/function.svg b/plugins/base/src/main/resources/dokka/images/nav-icons/function.svg deleted file mode 100644 index f0da64a0..00000000 --- a/plugins/base/src/main/resources/dokka/images/nav-icons/function.svg +++ /dev/null @@ -1,7 +0,0 @@ -<!-- Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. --> -<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"> - <g fill="none" fill-rule="evenodd"> - <path fill="#F98B9E" fill-opacity=".6" d="M15,8 C15,11.866 11.866,15 8,15 C4.134,15 1,11.866 1,8 C1,4.134 4.134,1 8,1 C11.866,1 15,4.134 15,8"/> - <path fill="#231F20" fill-opacity=".7" d="M1,8 L2,8 L2,4 L3.5,4 L3.5,3 L2,3 C1.99687783,2.36169171 1.99509925,2.02835838 1.99466424,2 C1.98704681,1.50341351 2.13289549,1.0728225 2.43221029,0.972167969 C2.91964141,0.808253079 3.56884985,1.02114795 3.68984985,1.06414795 L3.98519897,0.226043701 C3.90948298,0.198825534 3.4559021,0 2.81140137,0 C2.16690063,1.40512602e-16 1.81677246,0.0614013672 1.4818929,0.388793945 C1.16513106,0.698473875 1.01614114,1.22015248 1.00124609,2 C1.00039414,2.04460465 0.999980878,2.95274463 1,3 C1.00000736,3.01819872 0.666674031,3.01819872 0,3 L0,3.972 L1,3.972 L1,8 Z" transform="translate(6 4)"/> - </g> -</svg> diff --git a/plugins/base/src/main/resources/dokka/images/nav-icons/interface-kotlin.svg b/plugins/base/src/main/resources/dokka/images/nav-icons/interface-kotlin.svg deleted file mode 100644 index 5e163260..00000000 --- a/plugins/base/src/main/resources/dokka/images/nav-icons/interface-kotlin.svg +++ /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. - --> - -<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> -<g id="interfaceKotlin"> -<path id="Vector" fill-rule="evenodd" clip-rule="evenodd" d="M8 15C4.134 15 1 11.866 1 8C1 4.134 4.134 1 8 1C11.866 1 15 4.134 15 8H8V15Z" fill="#62B543" fill-opacity="0.6"/> -<path id="Vector_2" opacity="0.7" d="M8 11H6V10.0065L7.4 10V6H6V5H10V6H8.6V8H8V11Z" fill="#231F20"/> -<g id="⌘/modifier/kotlin"> -<path id="⌘/modifier/kotlin_2" d="M16 16H9V9H16L12.4 12.4L16 16Z" fill="#B99BF8"/> -</g> -</g> -</svg> diff --git a/plugins/base/src/main/resources/dokka/images/nav-icons/interface.svg b/plugins/base/src/main/resources/dokka/images/nav-icons/interface.svg deleted file mode 100644 index 32063ba2..00000000 --- a/plugins/base/src/main/resources/dokka/images/nav-icons/interface.svg +++ /dev/null @@ -1,7 +0,0 @@ -<!-- Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. --> -<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"> - <g fill="none" fill-rule="evenodd"> - <path fill="#62B543" fill-opacity=".6" d="M15,8 C15,11.866 11.866,15 8,15 C4.134,15 1,11.866 1,8 C1,4.134 4.134,1 8,1 C11.866,1 15,4.134 15,8"/> - <polygon fill="#231F20" fill-rule="nonzero" points="8.6 10 8.6 6 10 6 10 5 6 5 6 6 7.4 6 7.4 10 6 10.007 6 11 10 11 10 10" opacity=".7"/> - </g> -</svg> diff --git a/plugins/base/src/main/resources/dokka/images/nav-icons/object.svg b/plugins/base/src/main/resources/dokka/images/nav-icons/object.svg deleted file mode 100644 index 31f0ee3e..00000000 --- a/plugins/base/src/main/resources/dokka/images/nav-icons/object.svg +++ /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. - --> - -<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> -<g id="objectKotlin"> -<path id="Vector" fill-rule="evenodd" clip-rule="evenodd" d="M8 15C4.134 15 1 11.866 1 8C1 4.134 4.134 1 8 1C11.866 1 15 4.134 15 8H8V15Z" fill="#F4AF3D" fill-opacity="0.6"/> -<path id="Vector_2" fill-rule="evenodd" clip-rule="evenodd" d="M11 8H9.94262C9.94262 6.87293 9.13115 5.94475 7.9918 5.94475C6.85246 5.94475 6.05738 6.85635 6.05738 7.98343V8C6.05738 9.12437 6.86496 10.0508 8 10.0552V11C7.99727 11 7.99454 11 7.9918 11C6.22951 11 5 9.64917 5 8.01657V8C5 6.3674 6.2459 5 8.0082 5C9.77049 5 11 6.35083 11 7.98343V8Z" fill="#231F20" fill-opacity="0.7"/> -<g id="⌘/modifier/kotlin"> -<path id="⌘/modifier/kotlin_2" d="M16 16H9V9H16L12.4 12.4L16 16Z" fill="#B99BF8"/> -</g> -</g> -</svg> diff --git a/plugins/base/src/main/resources/dokka/images/nav-icons/typealias-kotlin.svg b/plugins/base/src/main/resources/dokka/images/nav-icons/typealias-kotlin.svg deleted file mode 100644 index f4bb238b..00000000 --- a/plugins/base/src/main/resources/dokka/images/nav-icons/typealias-kotlin.svg +++ /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. - --> - -<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> -<g id="typeAlias"> -<path id="Vector" fill-rule="evenodd" clip-rule="evenodd" d="M8 15C4.134 15 1 11.866 1 8C1 4.134 4.134 1 8 1C11.866 1 15 4.134 15 8H8V15Z" fill="#B99BF8" fill-opacity="0.6"/> -<path id="Vector_2" fill-rule="evenodd" clip-rule="evenodd" d="M8.5 8H8V11H7.5V6H5.5V5H10.5V6H8.5V8Z" fill="#231F20" fill-opacity="0.7"/> -<g id="⌘/modifier/kotlin"> -<path id="⌘/modifier/kotlin_2" d="M16 16H9V9H16L12.4 12.4L16 16Z" fill="#B99BF8"/> -</g> -</g> -</svg> diff --git a/plugins/base/src/main/resources/dokka/images/theme-toggle.svg b/plugins/base/src/main/resources/dokka/images/theme-toggle.svg deleted file mode 100644 index df86202b..00000000 --- a/plugins/base/src/main/resources/dokka/images/theme-toggle.svg +++ /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. - --> - -<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"> - <path d="M19.9824 29.0078C21.7625 29.0078 23.5025 28.48 24.9826 27.491C26.4626 26.5021 27.6161 25.0965 28.2973 23.452C28.9785 21.8074 29.1568 19.9978 28.8095 18.252C28.4622 16.5062 27.6051 14.9025 26.3464 13.6439C25.0877 12.3852 23.4841 11.528 21.7382 11.1807C19.9924 10.8335 18.1828 11.0117 16.5383 11.6929C14.8937 12.3741 13.4881 13.5276 12.4992 15.0077C11.5103 16.4877 10.9824 18.2278 10.9824 20.0078C10.9851 22.3939 11.9342 24.6816 13.6214 26.3688C15.3087 28.0561 17.5963 29.0051 19.9824 29.0078ZM19.9824 13.0078C21.8389 13.0078 23.6194 13.7453 24.9322 15.0581C26.2449 16.3708 26.9824 18.1513 26.9824 20.0078C26.9824 21.8643 26.2449 23.6448 24.9322 24.9576C23.6194 26.2703 21.8389 27.0078 19.9824 27.0078V13.0078Z" fill="white"/> -</svg> diff --git a/plugins/base/src/main/resources/dokka/inbound-link-resolver/dokka-default.properties b/plugins/base/src/main/resources/dokka/inbound-link-resolver/dokka-default.properties deleted file mode 100644 index 214fe8d7..00000000 --- a/plugins/base/src/main/resources/dokka/inbound-link-resolver/dokka-default.properties +++ /dev/null @@ -1,6 +0,0 @@ -# -# Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. -# - -class=org.jetbrains.dokka.InboundExternalLinkResolutionService$Dokka -description=Uses Dokka Default resolver diff --git a/plugins/base/src/main/resources/dokka/inbound-link-resolver/java-layout-html.properties b/plugins/base/src/main/resources/dokka/inbound-link-resolver/java-layout-html.properties deleted file mode 100644 index 285fc11a..00000000 --- a/plugins/base/src/main/resources/dokka/inbound-link-resolver/java-layout-html.properties +++ /dev/null @@ -1,6 +0,0 @@ -# -# Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. -# - -class=org.jetbrains.dokka.Formats.JavaLayoutHtmlInboundLinkResolutionService -description=Resolver for JavaLayoutHtml diff --git a/plugins/base/src/main/resources/dokka/inbound-link-resolver/javadoc.properties b/plugins/base/src/main/resources/dokka/inbound-link-resolver/javadoc.properties deleted file mode 100644 index 66fcc7c9..00000000 --- a/plugins/base/src/main/resources/dokka/inbound-link-resolver/javadoc.properties +++ /dev/null @@ -1,6 +0,0 @@ -# -# Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. -# - -class=org.jetbrains.dokka.InboundExternalLinkResolutionService$Javadoc -description=Uses Javadoc Default resolver diff --git a/plugins/base/src/main/resources/dokka/scripts/clipboard.js b/plugins/base/src/main/resources/dokka/scripts/clipboard.js deleted file mode 100644 index 7a4f33c5..00000000 --- a/plugins/base/src/main/resources/dokka/scripts/clipboard.js +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -window.addEventListener('load', () => { - document.querySelectorAll('span.copy-icon').forEach(element => { - element.addEventListener('click', (el) => copyElementsContentToClipboard(element)); - }) - - document.querySelectorAll('span.anchor-icon').forEach(element => { - element.addEventListener('click', (el) => { - if(element.hasAttribute('pointing-to')){ - const location = hrefWithoutCurrentlyUsedAnchor() + '#' + element.getAttribute('pointing-to') - copyTextToClipboard(element, location) - } - }); - }) -}) - -const copyElementsContentToClipboard = (element) => { - const selection = window.getSelection(); - const range = document.createRange(); - range.selectNodeContents(element.parentNode.parentNode); - selection.removeAllRanges(); - selection.addRange(range); - - copyAndShowPopup(element, () => selection.removeAllRanges()) -} - -const copyTextToClipboard = (element, text) => { - var textarea = document.createElement("textarea"); - textarea.textContent = text; - textarea.style.position = "fixed"; - document.body.appendChild(textarea); - textarea.select(); - - copyAndShowPopup(element, () => document.body.removeChild(textarea)) -} - -const copyAndShowPopup = (element, after) => { - try { - document.execCommand('copy'); - element.nextElementSibling.classList.add('active-popup'); - setTimeout(() => { - element.nextElementSibling.classList.remove('active-popup'); - }, 1200); - } catch (e) { - console.error('Failed to write to clipboard:', e) - } - finally { - if(after) after() - } -} - -const hrefWithoutCurrentlyUsedAnchor = () => window.location.href.split('#')[0] - diff --git a/plugins/base/src/main/resources/dokka/scripts/navigation-loader.js b/plugins/base/src/main/resources/dokka/scripts/navigation-loader.js deleted file mode 100644 index 3df7ac8c..00000000 --- a/plugins/base/src/main/resources/dokka/scripts/navigation-loader.js +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -navigationPageText = fetch(pathToRoot + "navigation.html").then(response => response.text()) - -displayNavigationFromPage = () => { - navigationPageText.then(data => { - document.getElementById("sideMenu").innerHTML = data; - }).then(() => { - document.querySelectorAll(".overview > a").forEach(link => { - link.setAttribute("href", pathToRoot + link.getAttribute("href")); - }) - }).then(() => { - document.querySelectorAll(".sideMenuPart").forEach(nav => { - if (!nav.classList.contains("hidden")) - nav.classList.add("hidden") - }) - }).then(() => { - revealNavigationForCurrentPage() - }).then(() => { - scrollNavigationToSelectedElement() - }) - document.querySelectorAll('.footer a[href^="#"]').forEach(anchor => { - anchor.addEventListener('click', function (e) { - e.preventDefault(); - document.querySelector(this.getAttribute('href')).scrollIntoView({ - behavior: 'smooth' - }); - }); - }); -} - -revealNavigationForCurrentPage = () => { - let pageId = document.getElementById("content").attributes["pageIds"].value.toString(); - let parts = document.querySelectorAll(".sideMenuPart"); - let found = 0; - do { - parts.forEach(part => { - if (part.attributes['pageId'].value.indexOf(pageId) !== -1 && found === 0) { - found = 1; - if (part.classList.contains("hidden")) { - part.classList.remove("hidden"); - part.setAttribute('data-active', ""); - } - revealParents(part) - } - }); - pageId = pageId.substring(0, pageId.lastIndexOf("/")) - } while (pageId.indexOf("/") !== -1 && found === 0) -}; -revealParents = (part) => { - if (part.classList.contains("sideMenuPart")) { - if (part.classList.contains("hidden")) - part.classList.remove("hidden"); - revealParents(part.parentNode) - } -}; - -scrollNavigationToSelectedElement = () => { - let selectedElement = document.querySelector('div.sideMenuPart[data-active]') - if (selectedElement == null) { // nothing selected, probably just the main page opened - return - } - - let hasIcon = selectedElement.querySelectorAll(":scope > div.overview span.nav-icon").length > 0 - - // for instance enums also have children and are expandable, but are not package/module elements - let isPackageElement = selectedElement.children.length > 1 && !hasIcon - if (isPackageElement) { - // if package is selected or linked, it makes sense to align it to top - // so that you can see all the members it contains - selectedElement.scrollIntoView(true) - } else { - // if a member within a package is linked, it makes sense to center it since it, - // this should make it easier to look at surrounding members - selectedElement.scrollIntoView({ - behavior: 'auto', - block: 'center', - inline: 'center' - }) - } -} - -/* - This is a work-around for safari being IE of our times. - It doesn't fire a DOMContentLoaded, presumabely because eventListener is added after it wants to do it -*/ -if (document.readyState == 'loading') { - window.addEventListener('DOMContentLoaded', () => { - displayNavigationFromPage() - }) -} else { - displayNavigationFromPage() -} diff --git a/plugins/base/src/main/resources/dokka/scripts/platform-content-handler.js b/plugins/base/src/main/resources/dokka/scripts/platform-content-handler.js deleted file mode 100644 index 811c4788..00000000 --- a/plugins/base/src/main/resources/dokka/scripts/platform-content-handler.js +++ /dev/null @@ -1,400 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -filteringContext = { - dependencies: {}, - restrictedDependencies: [], - activeFilters: [] -} -let highlightedAnchor; -let topNavbarOffset; -let instances = []; -let sourcesetNotification; - -const samplesDarkThemeName = 'darcula' -const samplesLightThemeName = 'idea' - -window.addEventListener('load', () => { - document.querySelectorAll("div[data-platform-hinted]") - .forEach(elem => elem.addEventListener('click', (event) => togglePlatformDependent(event, elem))) - const filterSection = document.getElementById('filter-section') - if (filterSection) { - filterSection.addEventListener('click', (event) => filterButtonHandler(event)) - initializeFiltering() - } - initTabs() - handleAnchor() - initHidingLeftNavigation() - topNavbarOffset = document.getElementById('navigation-wrapper') - darkModeSwitch() -}) - -const darkModeSwitch = () => { - const localStorageKey = "dokka-dark-mode" - const storage = localStorage.getItem(localStorageKey) - const osDarkSchemePreferred = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches - const darkModeEnabled = storage ? JSON.parse(storage) : osDarkSchemePreferred - const element = document.getElementById("theme-toggle-button") - initPlayground(darkModeEnabled ? samplesDarkThemeName : samplesLightThemeName) - - element.addEventListener('click', () => { - const enabledClasses = document.getElementsByTagName("html")[0].classList - enabledClasses.toggle("theme-dark") - - //if previously we had saved dark theme then we set it to light as this is what we save in local storage - const darkModeEnabled = enabledClasses.contains("theme-dark") - if (darkModeEnabled) { - initPlayground(samplesDarkThemeName) - } else { - initPlayground(samplesLightThemeName) - } - localStorage.setItem(localStorageKey, JSON.stringify(darkModeEnabled)) - }) -} - -const initPlayground = (theme) => { - if (!samplesAreEnabled()) return - instances.forEach(instance => instance.destroy()) - instances = [] - - // Manually tag code fragments as not processed by playground since we also manually destroy all of its instances - document.querySelectorAll('code.runnablesample').forEach(node => { - node.removeAttribute("data-kotlin-playground-initialized"); - }) - - KotlinPlayground('code.runnablesample', { - getInstance: playgroundInstance => { - instances.push(playgroundInstance) - }, - theme: theme - }); -} - -// We check if type is accessible from the current scope to determine if samples script is present -// As an alternative we could extract this samples-specific script to new js file but then we would handle dark mode in 2 separate files which is not ideal -const samplesAreEnabled = () => { - try { - KotlinPlayground - return true - } catch (e) { - return false - } -} - - -const initHidingLeftNavigation = () => { - document.getElementById("menu-toggle").onclick = function (event) { - //Events need to be prevented from bubbling since they will trigger next handler - event.preventDefault(); - event.stopPropagation(); - event.stopImmediatePropagation(); - document.getElementById("leftColumn").classList.toggle("open"); - } - - document.getElementById("main").onclick = () => { - document.getElementById("leftColumn").classList.remove("open"); - } -} - -// Hash change is needed in order to allow for linking inside the same page with anchors -// If this is not present user is forced to refresh the site in order to use an anchor -window.onhashchange = handleAnchor - -function scrollToElementInContent(element) { - const scrollToElement = () => document.getElementById('main').scrollTo({ - top: element.offsetTop - topNavbarOffset.offsetHeight, - behavior: "smooth" - }) - - const waitAndScroll = () => { - setTimeout(() => { - if (topNavbarOffset) { - scrollToElement() - } else { - waitForScroll() - } - }, 50) - } - - if (topNavbarOffset) { - scrollToElement() - } else { - waitAndScroll() - } -} - - -function handleAnchor() { - if (highlightedAnchor) { - highlightedAnchor.classList.remove('anchor-highlight') - highlightedAnchor = null; - } - - let searchForContentTarget = function (element) { - if (element && element.hasAttribute) { - if (element.hasAttribute("data-togglable")) return element.getAttribute("data-togglable"); - else return searchForContentTarget(element.parentNode) - } else return null - } - - let findAnyTab = function (target) { - let result = null - document.querySelectorAll('div[tabs-section] > button[data-togglable]') - .forEach(node => { - if(node.getAttribute("data-togglable").split(",").includes(target)) { - result = node - } - }) - return result - } - - let anchor = window.location.hash - if (anchor != "") { - anchor = anchor.substring(1) - let element = document.querySelector('a[data-name="' + anchor + '"]') - - if (element) { - const content = element.nextElementSibling - const contentStyle = window.getComputedStyle(content) - if(contentStyle.display == 'none') { - let tab = findAnyTab(searchForContentTarget(content)) - if (tab) { - toggleSections(tab) - } - } - - if (content) { - content.classList.add('anchor-highlight') - highlightedAnchor = content - } - - scrollToElementInContent(element) - } - } -} - -function initTabs() { - // we could have only a single type of data - classlike or package - const mainContent = document.querySelector('.main-content'); - const type = mainContent ? mainContent.getAttribute("data-page-type") : null; - const localStorageKey = "active-tab-" + type; - document.querySelectorAll('div[tabs-section]').forEach(element => { - showCorrespondingTabBody(element); - element.addEventListener('click', ({target}) => { - const togglable = target ? target.getAttribute("data-togglable") : null; - if (!togglable) return; - - localStorage.setItem(localStorageKey, JSON.stringify(togglable)); - toggleSections(target); - }); - }); - - const cached = localStorage.getItem(localStorageKey); - if (!cached) return; - - const tab = document.querySelector( - 'div[tabs-section] > button[data-togglable="' + JSON.parse(cached) + '"]' - ); - if (!tab) return; - - toggleSections(tab); -} - -function showCorrespondingTabBody(element) { - const buttonWithKey = element.querySelector("button[data-active]") - if (buttonWithKey) { - toggleSections(buttonWithKey) - } -} - -function filterButtonHandler(event) { - if (event.target.tagName == "BUTTON" && event.target.hasAttribute("data-filter")) { - let sourceset = event.target.getAttribute("data-filter") - if (filteringContext.activeFilters.indexOf(sourceset) != -1) { - filterSourceset(sourceset) - } else { - unfilterSourceset(sourceset) - } - } -} - -function initializeFiltering() { - filteringContext.dependencies = JSON.parse(sourceset_dependencies) - document.querySelectorAll("#filter-section > button") - .forEach(p => filteringContext.restrictedDependencies.push(p.getAttribute("data-filter"))) - Object.keys(filteringContext.dependencies).forEach(p => { - filteringContext.dependencies[p] = filteringContext.dependencies[p] - .filter(q => -1 !== filteringContext.restrictedDependencies.indexOf(q)) - }) - let cached = window.localStorage.getItem('inactive-filters') - if (cached) { - let parsed = JSON.parse(cached) - filteringContext.activeFilters = filteringContext.restrictedDependencies - .filter(q => parsed.indexOf(q) == -1) - } else { - filteringContext.activeFilters = filteringContext.restrictedDependencies - } - refreshFiltering() -} - -function filterSourceset(sourceset) { - filteringContext.activeFilters = filteringContext.activeFilters.filter(p => p != sourceset) - refreshFiltering() - addSourcesetFilterToCache(sourceset) -} - -function unfilterSourceset(sourceset) { - if (filteringContext.activeFilters.length == 0) { - filteringContext.activeFilters = filteringContext.dependencies[sourceset].concat([sourceset]) - refreshFiltering() - filteringContext.dependencies[sourceset].concat([sourceset]).forEach(p => removeSourcesetFilterFromCache(p)) - } else { - filteringContext.activeFilters.push(sourceset) - refreshFiltering() - removeSourcesetFilterFromCache(sourceset) - } - -} - -function addSourcesetFilterToCache(sourceset) { - let cached = localStorage.getItem('inactive-filters') - if (cached) { - let parsed = JSON.parse(cached) - localStorage.setItem('inactive-filters', JSON.stringify(parsed.concat([sourceset]))) - } else { - localStorage.setItem('inactive-filters', JSON.stringify([sourceset])) - } -} - -function removeSourcesetFilterFromCache(sourceset) { - let cached = localStorage.getItem('inactive-filters') - if (cached) { - let parsed = JSON.parse(cached) - localStorage.setItem('inactive-filters', JSON.stringify(parsed.filter(p => p != sourceset))) - } -} - -function toggleSections(target) { - const activateTabs = (containerClass) => { - for (const element of document.getElementsByClassName(containerClass)) { - for (const child of element.children) { - if (child.getAttribute("data-togglable") === target.getAttribute("data-togglable")) { - child.setAttribute("data-active", "") - } else { - child.removeAttribute("data-active") - } - } - } - } - const toggleTargets = target.getAttribute("data-togglable").split(",") - const activateTabsBody = (containerClass) => { - document.querySelectorAll("." + containerClass + " *[data-togglable]") - .forEach(child => { - if (toggleTargets.includes(child.getAttribute("data-togglable"))) { - child.setAttribute("data-active", "") - } else if(!child.classList.contains("sourceset-dependent-content")) { // data-togglable is used to switch source set as well, ignore it - child.removeAttribute("data-active") - } - }) - } - activateTabs("tabs-section") - activateTabsBody("tabs-section-body") -} - -function togglePlatformDependent(e, container) { - let target = e.target - if (target.tagName != 'BUTTON') return; - let index = target.getAttribute('data-toggle') - - for (let child of container.children) { - if (child.hasAttribute('data-toggle-list')) { - for (let bm of child.children) { - if (bm == target) { - bm.setAttribute('data-active', "") - } else if (bm != target) { - bm.removeAttribute('data-active') - } - } - } else if (child.getAttribute('data-togglable') == index) { - child.setAttribute('data-active', "") - } else { - child.removeAttribute('data-active') - } - } -} - -function refreshFiltering() { - let sourcesetList = filteringContext.activeFilters - document.querySelectorAll("[data-filterable-set]") - .forEach( - elem => { - let platformList = elem.getAttribute("data-filterable-set").split(',').filter(v => -1 !== sourcesetList.indexOf(v)) - elem.setAttribute("data-filterable-current", platformList.join(',')) - } - ) - refreshFilterButtons() - refreshPlatformTabs() - refreshNoContentNotification() - refreshPlaygroundSamples() -} - -function refreshPlaygroundSamples() { - document.querySelectorAll('code.runnablesample').forEach(node => { - const playground = node.KotlinPlayground; - /* Some samples may be hidden by filter, they have 0px height for visible code area - * after rendering. Call this method for re-calculate code area height */ - playground && playground.view.codemirror.refresh(); - }); -} - -function refreshNoContentNotification() { - const element = document.getElementsByClassName("main-content")[0] - if(filteringContext.activeFilters.length === 0){ - element.style.display = "none"; - - const appended = document.createElement("div") - appended.className = "filtered-message" - appended.innerText = "All documentation is filtered, please adjust your source set filters in top-right corner of the screen" - sourcesetNotification = appended - element.parentNode.prepend(appended) - } else { - if(sourcesetNotification) sourcesetNotification.remove() - element.style.display = "block" - } -} - -function refreshPlatformTabs() { - document.querySelectorAll(".platform-hinted > .platform-bookmarks-row").forEach( - p => { - let active = false; - let firstAvailable = null - p.childNodes.forEach( - element => { - if (element.getAttribute("data-filterable-current") != '') { - if (firstAvailable == null) { - firstAvailable = element - } - if (element.hasAttribute("data-active")) { - active = true; - } - } - } - ) - if (active == false && firstAvailable) { - firstAvailable.click() - } - } - ) -} - -function refreshFilterButtons() { - document.querySelectorAll("#filter-section > button") - .forEach(f => { - if (filteringContext.activeFilters.indexOf(f.getAttribute("data-filter")) != -1) { - f.setAttribute("data-active", "") - } else { - f.removeAttribute("data-active") - } - }) -} diff --git a/plugins/base/src/main/resources/dokka/scripts/prism.js b/plugins/base/src/main/resources/dokka/scripts/prism.js deleted file mode 100644 index 07423626..00000000 --- a/plugins/base/src/main/resources/dokka/scripts/prism.js +++ /dev/null @@ -1,22 +0,0 @@ -/* PrismJS 1.29.0 -https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+java+javadoc+javadoclike+kotlin&plugins=keep-markup */ -var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(e){var n=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,r={},a={manual:e.Prism&&e.Prism.manual,disableWorkerMessageHandler:e.Prism&&e.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof i?new i(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,"&").replace(/</g,"<").replace(/\u00a0/g," ")},type:function(e){return Object.prototype.toString.call(e).slice(8,-1)},objId:function(e){return e.__id||Object.defineProperty(e,"__id",{value:++t}),e.__id},clone:function e(n,t){var r,i;switch(t=t||{},a.util.type(n)){case"Object":if(i=a.util.objId(n),t[i])return t[i];for(var l in r={},t[i]=r,n)n.hasOwnProperty(l)&&(r[l]=e(n[l],t));return r;case"Array":return i=a.util.objId(n),t[i]?t[i]:(r=[],t[i]=r,n.forEach((function(n,a){r[a]=e(n,t)})),r);default:return n}},getLanguage:function(e){for(;e;){var t=n.exec(e.className);if(t)return t[1].toLowerCase();e=e.parentElement}return"none"},setLanguage:function(e,t){e.className=e.className.replace(RegExp(n,"gi"),""),e.classList.add("language-"+t)},currentScript:function(){if("undefined"==typeof document)return null;if("currentScript"in document)return document.currentScript;try{throw new Error}catch(r){var e=(/at [^(\r\n]*\((.*):[^:]+:[^:]+\)$/i.exec(r.stack)||[])[1];if(e){var n=document.getElementsByTagName("script");for(var t in n)if(n[t].src==e)return n[t]}return null}},isActive:function(e,n,t){for(var r="no-"+n;e;){var a=e.classList;if(a.contains(n))return!0;if(a.contains(r))return!1;e=e.parentElement}return!!t}},languages:{plain:r,plaintext:r,text:r,txt:r,extend:function(e,n){var t=a.util.clone(a.languages[e]);for(var r in n)t[r]=n[r];return t},insertBefore:function(e,n,t,r){var i=(r=r||a.languages)[e],l={};for(var o in i)if(i.hasOwnProperty(o)){if(o==n)for(var s in t)t.hasOwnProperty(s)&&(l[s]=t[s]);t.hasOwnProperty(o)||(l[o]=i[o])}var u=r[e];return r[e]=l,a.languages.DFS(a.languages,(function(n,t){t===u&&n!=e&&(this[n]=l)})),l},DFS:function e(n,t,r,i){i=i||{};var l=a.util.objId;for(var o in n)if(n.hasOwnProperty(o)){t.call(n,o,n[o],r||o);var s=n[o],u=a.util.type(s);"Object"!==u||i[l(s)]?"Array"!==u||i[l(s)]||(i[l(s)]=!0,e(s,t,o,i)):(i[l(s)]=!0,e(s,t,null,i))}}},plugins:{},highlightAll:function(e,n){a.highlightAllUnder(document,e,n)},highlightAllUnder:function(e,n,t){var r={callback:t,container:e,selector:'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'};a.hooks.run("before-highlightall",r),r.elements=Array.prototype.slice.apply(r.container.querySelectorAll(r.selector)),a.hooks.run("before-all-elements-highlight",r);for(var i,l=0;i=r.elements[l++];)a.highlightElement(i,!0===n,r.callback)},highlightElement:function(n,t,r){var i=a.util.getLanguage(n),l=a.languages[i];a.util.setLanguage(n,i);var o=n.parentElement;o&&"pre"===o.nodeName.toLowerCase()&&a.util.setLanguage(o,i);var s={element:n,language:i,grammar:l,code:n.textContent};function u(e){s.highlightedCode=e,a.hooks.run("before-insert",s),s.element.innerHTML=s.highlightedCode,a.hooks.run("after-highlight",s),a.hooks.run("complete",s),r&&r.call(s.element)}if(a.hooks.run("before-sanity-check",s),(o=s.element.parentElement)&&"pre"===o.nodeName.toLowerCase()&&!o.hasAttribute("tabindex")&&o.setAttribute("tabindex","0"),!s.code)return a.hooks.run("complete",s),void(r&&r.call(s.element));if(a.hooks.run("before-highlight",s),s.grammar)if(t&&e.Worker){var c=new Worker(a.filename);c.onmessage=function(e){u(e.data)},c.postMessage(JSON.stringify({language:s.language,code:s.code,immediateClose:!0}))}else u(a.highlight(s.code,s.grammar,s.language));else u(a.util.encode(s.code))},highlight:function(e,n,t){var r={code:e,grammar:n,language:t};if(a.hooks.run("before-tokenize",r),!r.grammar)throw new Error('The language "'+r.language+'" has no grammar.');return r.tokens=a.tokenize(r.code,r.grammar),a.hooks.run("after-tokenize",r),i.stringify(a.util.encode(r.tokens),r.language)},tokenize:function(e,n){var t=n.rest;if(t){for(var r in t)n[r]=t[r];delete n.rest}var a=new s;return u(a,a.head,e),o(e,a,n,a.head,0),function(e){for(var n=[],t=e.head.next;t!==e.tail;)n.push(t.value),t=t.next;return n}(a)},hooks:{all:{},add:function(e,n){var t=a.hooks.all;t[e]=t[e]||[],t[e].push(n)},run:function(e,n){var t=a.hooks.all[e];if(t&&t.length)for(var r,i=0;r=t[i++];)r(n)}},Token:i};function i(e,n,t,r){this.type=e,this.content=n,this.alias=t,this.length=0|(r||"").length}function l(e,n,t,r){e.lastIndex=n;var a=e.exec(t);if(a&&r&&a[1]){var i=a[1].length;a.index+=i,a[0]=a[0].slice(i)}return a}function o(e,n,t,r,s,g){for(var f in t)if(t.hasOwnProperty(f)&&t[f]){var h=t[f];h=Array.isArray(h)?h:[h];for(var d=0;d<h.length;++d){if(g&&g.cause==f+","+d)return;var v=h[d],p=v.inside,m=!!v.lookbehind,y=!!v.greedy,k=v.alias;if(y&&!v.pattern.global){var x=v.pattern.toString().match(/[imsuy]*$/)[0];v.pattern=RegExp(v.pattern.source,x+"g")}for(var b=v.pattern||v,w=r.next,A=s;w!==n.tail&&!(g&&A>=g.reach);A+=w.value.length,w=w.next){var E=w.value;if(n.length>e.length)return;if(!(E instanceof i)){var P,L=1;if(y){if(!(P=l(b,A,e,m))||P.index>=e.length)break;var S=P.index,O=P.index+P[0].length,j=A;for(j+=w.value.length;S>=j;)j+=(w=w.next).value.length;if(A=j-=w.value.length,w.value instanceof i)continue;for(var C=w;C!==n.tail&&(j<O||"string"==typeof C.value);C=C.next)L++,j+=C.value.length;L--,E=e.slice(A,j),P.index-=A}else if(!(P=l(b,0,E,m)))continue;S=P.index;var N=P[0],_=E.slice(0,S),M=E.slice(S+N.length),W=A+E.length;g&&W>g.reach&&(g.reach=W);var z=w.prev;if(_&&(z=u(n,z,_),A+=_.length),c(n,z,L),w=u(n,z,new i(f,p?a.tokenize(N,p):N,k,N)),M&&u(n,w,M),L>1){var I={cause:f+","+d,reach:W};o(e,n,t,w.prev,A,I),g&&I.reach>g.reach&&(g.reach=I.reach)}}}}}}function s(){var e={value:null,prev:null,next:null},n={value:null,prev:e,next:null};e.next=n,this.head=e,this.tail=n,this.length=0}function u(e,n,t){var r=n.next,a={value:t,prev:n,next:r};return n.next=a,r.prev=a,e.length++,a}function c(e,n,t){for(var r=n.next,a=0;a<t&&r!==e.tail;a++)r=r.next;n.next=r,r.prev=n,e.length-=a}if(e.Prism=a,i.stringify=function e(n,t){if("string"==typeof n)return n;if(Array.isArray(n)){var r="";return n.forEach((function(n){r+=e(n,t)})),r}var i={type:n.type,content:e(n.content,t),tag:"span",classes:["token",n.type],attributes:{},language:t},l=n.alias;l&&(Array.isArray(l)?Array.prototype.push.apply(i.classes,l):i.classes.push(l)),a.hooks.run("wrap",i);var o="";for(var s in i.attributes)o+=" "+s+'="'+(i.attributes[s]||"").replace(/"/g,""")+'"';return"<"+i.tag+' class="'+i.classes.join(" ")+'"'+o+">"+i.content+"</"+i.tag+">"},!e.document)return e.addEventListener?(a.disableWorkerMessageHandler||e.addEventListener("message",(function(n){var t=JSON.parse(n.data),r=t.language,i=t.code,l=t.immediateClose;e.postMessage(a.highlight(i,a.languages[r],r)),l&&e.close()}),!1),a):a;var g=a.util.currentScript();function f(){a.manual||a.highlightAll()}if(g&&(a.filename=g.src,g.hasAttribute("data-manual")&&(a.manual=!0)),!a.manual){var h=document.readyState;"loading"===h||"interactive"===h&&g&&g.defer?document.addEventListener("DOMContentLoaded",f):window.requestAnimationFrame?window.requestAnimationFrame(f):window.setTimeout(f,16)}return a}(_self);"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); -Prism.languages.markup={comment:{pattern:/<!--(?:(?!<!--)[\s\S])*?-->/,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/<!DOCTYPE(?:[^>"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|<!--(?:[^-]|-(?!->))*-->)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^<!|>$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern:/<!\[CDATA\[[\s\S]*?\]\]>/i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.languages.markup.doctype.inside["internal-subset"].inside=Prism.languages.markup,Prism.hooks.add("wrap",(function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))})),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(a,e){var s={};s["language-"+e]={pattern:/(^<!\[CDATA\[)[\s\S]+?(?=\]\]>$)/i,lookbehind:!0,inside:Prism.languages[e]},s.cdata=/^<!\[CDATA\[|\]\]>$/i;var t={"included-cdata":{pattern:/<!\[CDATA\[[\s\S]*?\]\]>/i,inside:s}};t["language-"+e]={pattern:/[\s\S]+/,inside:Prism.languages[e]};var n={};n[a]={pattern:RegExp("(<__[^>]*>)(?:<!\\[CDATA\\[(?:[^\\]]|\\](?!\\]>))*\\]\\]>|(?!<!\\[CDATA\\[)[^])*?(?=</__>)".replace(/__/g,(function(){return a})),"i"),lookbehind:!0,greedy:!0,inside:t},Prism.languages.insertBefore("markup","cdata",n)}}),Object.defineProperty(Prism.languages.markup.tag,"addAttribute",{value:function(a,e){Prism.languages.markup.tag.inside["special-attr"].push({pattern:RegExp("(^|[\"'\\s])(?:"+a+")\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s'\">=]+(?=[\\s>]))","i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[e,"language-"+e],inside:Prism.languages[e]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup,Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.ssml=Prism.languages.xml,Prism.languages.atom=Prism.languages.xml,Prism.languages.rss=Prism.languages.xml; -!function(s){var e=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;s.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:RegExp("@[\\w-](?:[^;{\\s\"']|\\s+(?!\\s)|"+e.source+")*?(?:;|(?=\\s*\\{))"),inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+e.source+"|(?:[^\\\\\r\n()\"']|\\\\[^])*)\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+e.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+e.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:e,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},s.languages.css.atrule.inside.rest=s.languages.css;var t=s.languages.markup;t&&(t.tag.addInlined("style","css"),t.tag.addAttribute("style","css"))}(Prism); -Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/}; -Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp("(^|[^\\w$])(?:NaN|Infinity|0[bB][01]+(?:_[01]+)*n?|0[oO][0-7]+(?:_[0-7]+)*n?|0[xX][\\dA-Fa-f]+(?:_[\\dA-Fa-f]+)*n?|\\d+(?:_\\d+)*n|(?:\\d+(?:_\\d+)*(?:\\.(?:\\d+(?:_\\d+)*)?)?|\\.\\d+(?:_\\d+)*)(?:[Ee][+-]?\\d+(?:_\\d+)*)?)(?![\\w$])"),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:RegExp("((?:^|[^$\\w\\xA0-\\uFFFF.\"'\\])\\s]|\\b(?:return|yield))\\s*)/(?:(?:\\[(?:[^\\]\\\\\r\n]|\\\\.)*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}|(?:\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.)*\\])*\\])*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}v[dgimyus]{0,7})(?=(?:\\s|/\\*(?:[^*]|\\*(?!/))*\\*/)*(?:$|[\r\n,.;:})\\]]|//))"),lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:Prism.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),Prism.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),Prism.languages.markup&&(Prism.languages.markup.tag.addInlined("script","javascript"),Prism.languages.markup.tag.addAttribute("on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)","javascript")),Prism.languages.js=Prism.languages.javascript; -!function(e){var n=/\b(?:abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|exports|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|module|native|new|non-sealed|null|open|opens|package|permits|private|protected|provides|public|record(?!\s*[(){}[\]<>=%~.:,;?+\-*/&|^])|requires|return|sealed|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/,t="(?:[a-z]\\w*\\s*\\.\\s*)*(?:[A-Z]\\w*\\s*\\.\\s*)*",s={pattern:RegExp("(^|[^\\w.])"+t+"[A-Z](?:[\\d_A-Z]*[a-z]\\w*)?\\b"),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}},punctuation:/\./}};e.languages.java=e.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"/,lookbehind:!0,greedy:!0},"class-name":[s,{pattern:RegExp("(^|[^\\w.])"+t+"[A-Z]\\w*(?=\\s+\\w+\\s*[;,=()]|\\s*(?:\\[[\\s,]*\\]\\s*)?::\\s*new\\b)"),lookbehind:!0,inside:s.inside},{pattern:RegExp("(\\b(?:class|enum|extends|implements|instanceof|interface|new|record|throws)\\s+)"+t+"[A-Z]\\w*\\b"),lookbehind:!0,inside:s.inside}],keyword:n,function:[e.languages.clike.function,{pattern:/(::\s*)[a-z_]\w*/,lookbehind:!0}],number:/\b0b[01][01_]*L?\b|\b0x(?:\.[\da-f_p+-]+|[\da-f_]+(?:\.[\da-f_p+-]+)?)\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0},constant:/\b[A-Z][A-Z_\d]+\b/}),e.languages.insertBefore("java","string",{"triple-quoted-string":{pattern:/"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,greedy:!0,alias:"string"},char:{pattern:/'(?:\\.|[^'\\\r\n]){1,6}'/,greedy:!0}}),e.languages.insertBefore("java","class-name",{annotation:{pattern:/(^|[^.])@\w+(?:\s*\.\s*\w+)*/,lookbehind:!0,alias:"punctuation"},generics:{pattern:/<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&))*>)*>)*>)*>/,inside:{"class-name":s,keyword:n,punctuation:/[<>(),.:]/,operator:/[?&|]/}},import:[{pattern:RegExp("(\\bimport\\s+)"+t+"(?:[A-Z]\\w*|\\*)(?=\\s*;)"),lookbehind:!0,inside:{namespace:s.inside.namespace,punctuation:/\./,operator:/\*/,"class-name":/\w+/}},{pattern:RegExp("(\\bimport\\s+static\\s+)"+t+"(?:\\w+|\\*)(?=\\s*;)"),lookbehind:!0,alias:"static",inside:{namespace:s.inside.namespace,static:/\b\w+$/,punctuation:/\./,operator:/\*/,"class-name":/\w+/}}],namespace:{pattern:RegExp("(\\b(?:exports|import(?:\\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\\s+)(?!<keyword>)[a-z]\\w*(?:\\.[a-z]\\w*)*\\.?".replace(/<keyword>/g,(function(){return n.source}))),lookbehind:!0,inside:{punctuation:/\./}}})}(Prism); -!function(a){var e=a.languages.javadoclike={parameter:{pattern:/(^[\t ]*(?:\/{3}|\*|\/\*\*)\s*@(?:arg|arguments|param)\s+)\w+/m,lookbehind:!0},keyword:{pattern:/(^[\t ]*(?:\/{3}|\*|\/\*\*)\s*|\{)@[a-z][a-zA-Z-]+\b/m,lookbehind:!0},punctuation:/[{}]/};Object.defineProperty(e,"addSupport",{value:function(e,n){"string"==typeof e&&(e=[e]),e.forEach((function(e){!function(e,n){var t="doc-comment",r=a.languages[e];if(r){var o=r[t];if(o||(o=(r=a.languages.insertBefore(e,"comment",{"doc-comment":{pattern:/(^|[^\\])\/\*\*[^/][\s\S]*?(?:\*\/|$)/,lookbehind:!0,alias:"comment"}}))[t]),o instanceof RegExp&&(o=r[t]={pattern:o}),Array.isArray(o))for(var i=0,s=o.length;i<s;i++)o[i]instanceof RegExp&&(o[i]={pattern:o[i]}),n(o[i]);else n(o)}}(e,(function(a){a.inside||(a.inside={}),a.inside.rest=n}))}))}}),e.addSupport(["java","javascript","php"],e)}(Prism); -!function(a){var e=/(^(?:[\t ]*(?:\*\s*)*))[^*\s].*$/m,n="(?:\\b[a-zA-Z]\\w+\\s*\\.\\s*)*\\b[A-Z]\\w*(?:\\s*<mem>)?|<mem>".replace(/<mem>/g,(function(){return"#\\s*\\w+(?:\\s*\\([^()]*\\))?"}));a.languages.javadoc=a.languages.extend("javadoclike",{}),a.languages.insertBefore("javadoc","keyword",{reference:{pattern:RegExp("(@(?:exception|link|linkplain|see|throws|value)\\s+(?:\\*\\s*)?)(?:"+n+")"),lookbehind:!0,inside:{function:{pattern:/(#\s*)\w+(?=\s*\()/,lookbehind:!0},field:{pattern:/(#\s*)\w+/,lookbehind:!0},namespace:{pattern:/\b(?:[a-z]\w*\s*\.\s*)+/,inside:{punctuation:/\./}},"class-name":/\b[A-Z]\w*/,keyword:a.languages.java.keyword,punctuation:/[#()[\],.]/}},"class-name":{pattern:/(@param\s+)<[A-Z]\w*>/,lookbehind:!0,inside:{punctuation:/[.<>]/}},"code-section":[{pattern:/(\{@code\s+(?!\s))(?:[^\s{}]|\s+(?![\s}])|\{(?:[^{}]|\{(?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})*\})*\})+(?=\s*\})/,lookbehind:!0,inside:{code:{pattern:e,lookbehind:!0,inside:a.languages.java,alias:"language-java"}}},{pattern:/(<(code|pre|tt)>(?!<code>)\s*)\S(?:\S|\s+\S)*?(?=\s*<\/\2>)/,lookbehind:!0,inside:{line:{pattern:e,lookbehind:!0,inside:{tag:a.languages.markup.tag,entity:a.languages.markup.entity,code:{pattern:/.+/,inside:a.languages.java,alias:"language-java"}}}}}],tag:a.languages.markup.tag,entity:a.languages.markup.entity}),a.languages.javadoclike.addSupport("java",a.languages.javadoc)}(Prism); -!function(n){n.languages.kotlin=n.languages.extend("clike",{keyword:{pattern:/(^|[^.])\b(?:abstract|actual|annotation|as|break|by|catch|class|companion|const|constructor|continue|crossinline|data|do|dynamic|else|enum|expect|external|final|finally|for|fun|get|if|import|in|infix|init|inline|inner|interface|internal|is|lateinit|noinline|null|object|open|operator|out|override|package|private|protected|public|reified|return|sealed|set|super|suspend|tailrec|this|throw|to|try|typealias|val|var|vararg|when|where|while)\b/,lookbehind:!0},function:[{pattern:/(?:`[^\r\n`]+`|\b\w+)(?=\s*\()/,greedy:!0},{pattern:/(\.)(?:`[^\r\n`]+`|\w+)(?=\s*\{)/,lookbehind:!0,greedy:!0}],number:/\b(?:0[xX][\da-fA-F]+(?:_[\da-fA-F]+)*|0[bB][01]+(?:_[01]+)*|\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?(?:[eE][+-]?\d+(?:_\d+)*)?[fFL]?)\b/,operator:/\+[+=]?|-[-=>]?|==?=?|!(?:!|==?)?|[\/*%<>]=?|[?:]:?|\.\.|&&|\|\||\b(?:and|inv|or|shl|shr|ushr|xor)\b/}),delete n.languages.kotlin["class-name"];var e={"interpolation-punctuation":{pattern:/^\$\{?|\}$/,alias:"punctuation"},expression:{pattern:/[\s\S]+/,inside:n.languages.kotlin}};n.languages.insertBefore("kotlin","string",{"string-literal":[{pattern:/"""(?:[^$]|\$(?:(?!\{)|\{[^{}]*\}))*?"""/,alias:"multiline",inside:{interpolation:{pattern:/\$(?:[a-z_]\w*|\{[^{}]*\})/i,inside:e},string:/[\s\S]+/}},{pattern:/"(?:[^"\\\r\n$]|\\.|\$(?:(?!\{)|\{[^{}]*\}))*"/,alias:"singleline",inside:{interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$(?:[a-z_]\w*|\{[^{}]*\})/i,lookbehind:!0,inside:e},string:/[\s\S]+/}}],char:{pattern:/'(?:[^'\\\r\n]|\\(?:.|u[a-fA-F0-9]{0,4}))'/,greedy:!0}}),delete n.languages.kotlin.string,n.languages.insertBefore("kotlin","keyword",{annotation:{pattern:/\B@(?:\w+:)?(?:[A-Z]\w*|\[[^\]]+\])/,alias:"builtin"}}),n.languages.insertBefore("kotlin","function",{label:{pattern:/\b\w+@|@\w+\b/,alias:"symbol"}}),n.languages.kt=n.languages.kotlin,n.languages.kts=n.languages.kotlin}(Prism); -"undefined"!=typeof Prism&&"undefined"!=typeof document&&document.createRange&&(Prism.plugins.KeepMarkup=!0,Prism.hooks.add("before-highlight",(function(e){if(e.element.children.length&&Prism.util.isActive(e.element,"keep-markup",!0)){var n=Prism.util.isActive(e.element,"drop-tokens",!1),t=0,o=[];r(e.element),o.length&&(e.keepMarkup=o)}function d(e){if(function(e){return!n||"span"!==e.nodeName.toLowerCase()||!e.classList.contains("token")}(e)){var d={element:e,posOpen:t};o.push(d),r(e),d.posClose=t}else r(e)}function r(e){for(var n=0,o=e.childNodes.length;n<o;n++){var r=e.childNodes[n];1===r.nodeType?d(r):3===r.nodeType&&(t+=r.data.length)}}})),Prism.hooks.add("after-highlight",(function(e){if(e.keepMarkup&&e.keepMarkup.length){var n=function(e,t){for(var o=0,d=e.childNodes.length;o<d;o++){var r=e.childNodes[o];if(1===r.nodeType){if(!n(r,t))return!1}else 3===r.nodeType&&(!t.nodeStart&&t.pos+r.data.length>t.node.posOpen&&(t.nodeStart=r,t.nodeStartPos=t.node.posOpen-t.pos),t.nodeStart&&t.pos+r.data.length>=t.node.posClose&&(t.nodeEnd=r,t.nodeEndPos=t.node.posClose-t.pos),t.pos+=r.data.length);if(t.nodeStart&&t.nodeEnd){var s=document.createRange();return s.setStart(t.nodeStart,t.nodeStartPos),s.setEnd(t.nodeEnd,t.nodeEndPos),t.node.element.innerHTML="",t.node.element.appendChild(s.extractContents()),s.insertNode(t.node.element),s.detach(),!1}}return!0};e.keepMarkup.forEach((function(t){n(e.element,{node:t,pos:0})})),e.highlightedCode=e.element.innerHTML}}))); - -/* - * This is NOT part of the prism.js main script, it's specific to Dokka. - * Dokka generates <br> tags for new lines inside <pre> blocks and it works visually, - * but it causes prism.js to incorrectly parse some tags (such as inline comments) - * - * This can be removed if there are no `<br>` tags inside `<pre>` anymore, but - * if there still are - DO NOT remove this hook when upading prism.js to a newer version - */ -Prism.hooks.add('before-sanity-check', function (env){env.element.innerHTML = env.element.innerHTML.replace(/<br>/g, '\n');env.code = env.element.textContent;}); diff --git a/plugins/base/src/main/resources/dokka/scripts/symbol-parameters-wrapper_deferred.js b/plugins/base/src/main/resources/dokka/scripts/symbol-parameters-wrapper_deferred.js deleted file mode 100644 index 7ecae7a6..00000000 --- a/plugins/base/src/main/resources/dokka/scripts/symbol-parameters-wrapper_deferred.js +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -// helps with some corner cases where <wbr> starts working already, -// but the signature is not yet long enough to be wrapped -(function() { - const leftPaddingPx = 60; - - function createNbspIndent() { - let indent = document.createElement("span"); - indent.append(document.createTextNode("\u00A0\u00A0\u00A0\u00A0")); - indent.classList.add("nbsp-indent"); - return indent; - } - - function wrapSymbolParameters(entry) { - const symbol = entry.target; - const symbolBlockWidth = entry.borderBoxSize && entry.borderBoxSize[0] && entry.borderBoxSize[0].inlineSize; - - // Even though the script is marked as `defer` and we wait for `DOMContentLoaded` event, - // or if this block is a part of hidden tab, it can happen that `symbolBlockWidth` is 0, - // indicating that something hasn't been loaded. - // In this case, observer will be triggered onсe again when it will be ready. - if (symbolBlockWidth > 0) { - const node = symbol.querySelector(".parameters"); - - if (node) { - // if window resize happened and observer was triggered, reset previously wrapped - // parameters as they might not need wrapping anymore, and check again - node.classList.remove("wrapped"); - node.querySelectorAll(".parameter .nbsp-indent") - .forEach(indent => indent.remove()); - - const innerTextWidth = Array.from(symbol.children) - .filter(it => !it.classList.contains("block")) // blocks are usually on their own (like annotations), so ignore it - .map(it => it.getBoundingClientRect().width) - .reduce((a, b) => a + b, 0); - - // if signature text takes up more than a single line, wrap params for readability - if (innerTextWidth > (symbolBlockWidth - leftPaddingPx)) { - node.classList.add("wrapped"); - node.querySelectorAll(".parameter").forEach(param => { - // has to be a physical indent so that it can be copied. styles like - // paddings and `::before { content: " " }` do not work for that - param.prepend(createNbspIndent()); - }); - } - } - } - } - - const symbolsObserver = new ResizeObserver(entries => entries.forEach(wrapSymbolParameters)); - - function initHandlers() { - document.querySelectorAll("div.symbol").forEach(symbol => symbolsObserver.observe(symbol)); - } - - if (document.readyState === 'loading') window.addEventListener('DOMContentLoaded', initHandlers); - else initHandlers(); - - // ToDo: Add `unobserve` if dokka will be SPA-like: - // https://github.com/w3c/csswg-drafts/issues/5155 -})(); diff --git a/plugins/base/src/main/resources/dokka/styles/font-jb-sans-auto.css b/plugins/base/src/main/resources/dokka/styles/font-jb-sans-auto.css deleted file mode 100644 index bdc68723..00000000 --- a/plugins/base/src/main/resources/dokka/styles/font-jb-sans-auto.css +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -/* Light weight */ -@font-face { - font-family: 'JetBrains Sans'; - src: url('https://resources.jetbrains.com/storage/jetbrains-sans/JetBrainsSans-Light.woff2') format('woff2'), url('https://resources.jetbrains.com/storage/jetbrains-sans/JetBrainsSans-Light.woff') format('woff'); - font-weight: 300; - font-style: normal; -} -/* Regular weight */ -@font-face { - font-family: 'JetBrains Sans'; - src: url('https://resources.jetbrains.com/storage/jetbrains-sans/JetBrainsSans-Regular.woff2') format('woff2'), url('https://resources.jetbrains.com/storage/jetbrains-sans/JetBrainsSans-Regular.woff') format('woff'); - font-weight: 400; - font-style: normal; -} -/* SemiBold weight */ -@font-face { - font-family: 'JetBrains Sans'; - src: url('https://resources.jetbrains.com/storage/jetbrains-sans/JetBrainsSans-SemiBold.woff2') format('woff2'), url('https://resources.jetbrains.com/storage/jetbrains-sans/JetBrainsSans-SemiBold.woff') format('woff'); - font-weight: 600; - font-style: normal; -} - -@supports (font-variation-settings: normal) { - @font-face { - font-family: 'JetBrains Sans'; - src: url('https://resources.jetbrains.com/storage/jetbrains-sans/JetBrainsSans.woff2') format('woff2 supports variations'), - url('https://resources.jetbrains.com/storage/jetbrains-sans/JetBrainsSans.woff2') format('woff2-variations'), - url('https://resources.jetbrains.com/storage/jetbrains-sans/JetBrainsSans.woff') format('woff-variations'); - font-weight: 100 900; - font-style: normal; - } -} diff --git a/plugins/base/src/main/resources/dokka/styles/logo-styles.css b/plugins/base/src/main/resources/dokka/styles/logo-styles.css deleted file mode 100644 index 69804e46..00000000 --- a/plugins/base/src/main/resources/dokka/styles/logo-styles.css +++ /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. - */ - -:root { - --dokka-logo-image-url: url('../images/logo-icon.svg'); - --dokka-logo-height: 50px; - --dokka-logo-width: 50px; -} diff --git a/plugins/base/src/main/resources/dokka/styles/prism.css b/plugins/base/src/main/resources/dokka/styles/prism.css deleted file mode 100644 index 2d3a091e..00000000 --- a/plugins/base/src/main/resources/dokka/styles/prism.css +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -/* - * Custom Dokka styles - */ -code .token { - white-space: pre; -} - -/** - * Styles based on webhelp's prism.js styles - * Changes: - * - Since webhelp's styles are in .pcss, they use nesting which is not achievable in native CSS - * so nested css blocks have been unrolled (like dark theme). - * - Webhelp uses "Custom Class" prism.js plugin, so all of their prism classes are prefixed with "--prism". - * Dokka doesn't seem to need this plugin at the moment, so all "--prism" prefixes have been removed. - * - Removed all styles related to `pre` and `code` tags. Kotlinlang's resulting styles are so spread out and complicated - * that it's difficult to gather in one place. Instead use code styles defined in the main Dokka styles, - * which at the moment looks fairly similar. - * - * Based on prism.js default theme - * Based on dabblet (http://dabblet.com) - * @author Lea Verou - */ - -.token.comment, -.token.prolog, -.token.doctype, -.token.cdata { - color: #8c8c8c; -} - -.token.punctuation { - color: #999; -} - -.token.namespace { - opacity: 0.7; -} - -.token.property, -.token.tag, -.token.boolean, -.token.number, -.token.constant, -.token.symbol, -.token.deleted { - color: #871094; -} - -.token.selector, -.token.attr-name, -.token.string, -.token.char, -.token.builtin, -.token.inserted { - color: #067d17; -} - -.token.operator, -.token.entity, -.token.url, -.language-css .token.string, -.style .token.string { - color: #9a6e3a; - /* This background color was intended by the author of this theme. */ - background: hsla(0, 0%, 100%, 0.5); -} - -.token.atrule, -.token.attr-value, -.token.keyword { - font-size: inherit; /* to override .keyword */ - color: #0033b3; -} - -.token.function { - color: #00627a; -} - -.token.class-name { - color: #000000; -} - -.token.regex, -.token.important, -.token.variable { - color: #871094; -} - -.token.important, -.token.bold { - font-weight: bold; -} -.token.italic { - font-style: italic; -} - -.token.entity { - cursor: help; -} - -.token.operator { - background: none; -} - -/* - * DARK THEME - */ -:root.theme-dark .token.comment, -:root.theme-dark .token.prolog, -:root.theme-dark .token.cdata { - color: #808080; -} - -:root.theme-dark .token.delimiter, -:root.theme-dark .token.boolean, -:root.theme-dark .token.keyword, -:root.theme-dark .token.selector, -:root.theme-dark .token.important, -:root.theme-dark .token.atrule { - color: #cc7832; -} - -:root.theme-dark .token.operator, -:root.theme-dark .token.punctuation, -:root.theme-dark .token.attr-name { - color: #a9b7c6; -} - -:root.theme-dark .token.tag, -:root.theme-dark .token.tag .punctuation, -:root.theme-dark .token.doctype, -:root.theme-dark .token.builtin { - color: #e8bf6a; -} - -:root.theme-dark .token.entity, -:root.theme-dark .token.number, -:root.theme-dark .token.symbol { - color: #6897bb; -} - -:root.theme-dark .token.property, -:root.theme-dark .token.constant, -:root.theme-dark .token.variable { - color: #9876aa; -} - -:root.theme-dark .token.string, -:root.theme-dark .token.char { - color: #6a8759; -} - -:root.theme-dark .token.attr-value, -:root.theme-dark .token.attr-value .punctuation { - color: #a5c261; -} - -:root.theme-dark .token.attr-value .punctuation:first-child { - color: #a9b7c6; -} - -:root.theme-dark .token.url { - text-decoration: underline; - - color: #287bde; - background: transparent; -} - -:root.theme-dark .token.function { - color: #ffc66d; -} - -:root.theme-dark .token.regex { - background: #364135; -} - -:root.theme-dark .token.deleted { - background: #484a4a; -} - -:root.theme-dark .token.inserted { - background: #294436; -} - -:root.theme-dark .token.class-name { - color: #a9b7c6; -} - -:root.theme-dark .token.function { - color: #ffc66d; -} - -:root.theme-darkcode .language-css .token.property, -:root.theme-darkcode .language-css, -:root.theme-dark .token.property + .token.punctuation { - color: #a9b7c6; -} - -code.language-css .token.id { - color: #ffc66d; -} - -:root.theme-dark code.language-css .token.selector > .token.class, -:root.theme-dark code.language-css .token.selector > .token.attribute, -:root.theme-dark code.language-css .token.selector > .token.pseudo-class, -:root.theme-dark code.language-css .token.selector > .token.pseudo-element { - color: #ffc66d; -} - -:root.theme-dark .language-plaintext .token { - /* plaintext code should be colored as article text */ - color: inherit !important; -} diff --git a/plugins/base/src/main/resources/dokka/styles/style.css b/plugins/base/src/main/resources/dokka/styles/style.css deleted file mode 100644 index 62b0ddbd..00000000 --- a/plugins/base/src/main/resources/dokka/styles/style.css +++ /dev/null @@ -1,1513 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -@import url('./font-jb-sans-auto.css'); -@import url('https://fonts.googleapis.com/css?family=JetBrains+Mono'); - -/* --- root styles --- */ -:root { - --default-gray: #f4f4f4; - --default-font-color: black; - --header-font-color: var(--default-font-color); - - --breadcrumb-font-color: #637282; - --breadcrumb-margin: 24px; - --hover-link-color: #5B5DEF; - - --footer-height: 64px; - --footer-padding-top: 48px; - --footer-background: var(--default-gray); - --footer-font-color: var(--average-color); - --footer-go-to-top-color: white; - - --horizontal-spacing-for-content: 16px; - --bottom-spacing: 16px; - --color-scrollbar: rgba(39, 40, 44, 0.40); - --color-scrollbar-track: var(--default-gray); - --default-white: #fff; - --background-color: var(--default-white); - --dark-mode-and-search-icon-color: var(--default-white); - --color-dark: #27282c; - --default-font-family: JetBrains Sans, Inter, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI,Roboto, Oxygen, Ubuntu,Cantarell, Droid Sans, Helvetica Neue, Arial, sans-serif; - --default-monospace-font-family: JetBrains Mono, SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace; - --default-font-size: 15px; - --average-color: var(--color-dark); - --brief-color: var(--average-color); - --copy-icon-color: rgba(39, 40, 44, .7); - --copy-icon-hover-color: var(--color-dark); - --code-background: rgba(39, 40, 44, .05); - --border-color: rgba(39, 40, 44, .2); - --navigation-highlight-color: rgba(39, 40, 44, 0.05); - --top-navigation-height: 73px; - --max-width: 1160px; - --white-10: hsla(0, 0%, 100%, .1); - - --active-tab-border-color: #7F52FF; - --inactive-tab-border-color: rgba(164, 164, 170, 0.7); - - --active-section-color: #7F52FF; - --inactive-section-color: rgba(25, 25, 28, .7); - - --sidebar-width: 280px; - --sidemenu-section-active-color: #7F52FF; -} - -html { - height: 100%; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); - scrollbar-color: rgba(39, 40, 44, 0.40) #F4F4F4; - scrollbar-color: var(--color-scrollbar) var(--color-scrollbar-track); - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - color: var(--default-font-color); -} - -html ::-webkit-scrollbar { - width: 8px; - height: 8px; -} - -html ::-webkit-scrollbar-track { - background-color: var(--color-scrollbar-track); -} - -html ::-webkit-scrollbar-thumb { - width: 8px; - border-radius: 6px; - background: rgba(39, 40, 44, 0.40); - background: var(--color-scrollbar); -} - -html, body { - margin: 0; - padding: 0; - height: 100%; - width: 100%; -} -/* /--- root styles --- */ - -/* --- global tags styles --- */ -body, table { - background: var(--background-color); - font-family: var(--default-font-family); - font-style: normal; - font-weight: normal; - font-size: var(--default-font-size); - line-height: 1.6; - margin: 0; -} - -h1 { - font-size: 40px; - line-height: 48px; - letter-spacing: -1px; -} - -h2 { - font-size: 31px; - line-height: 40px; - letter-spacing: -0.5px; -} - -h3 { - font-size: 20px; - line-height: 28px; - letter-spacing: -0.2px; -} - -p, ul, ol, table, pre, dl { - margin: 0; -} - -a { - text-decoration: none; -} - -u { - text-decoration: none; - padding-bottom: 2px; - border-bottom: 1px solid var(--border-color); -} - -blockquote { - border-left: 1ch solid var(--default-gray); - margin: 0; - padding-left: 1ch; - font-style: italic; - color: var(--average-color); -} - -.theme-dark blockquote { - color: var(--default-font-color); - border-left-color: var(--code-background); -} - -pre { - display: block; -} - -dt { - color: #444; - font-weight: 530; -} - -img { - max-width: 100%; -} - -small { - font-size: 11px; -} - -table { - width: 100%; - border-collapse: collapse; - padding: 5px; -} - -th, td { - padding: 12px 10px 11px; - text-align: left; - vertical-align: top; -} - -tbody > tr { - min-height: 56px; -} - -td:first-child { - width: 20vw; -} -/* /--- global tags styles --- */ - -/* --- utils classes --- */ -.w-100 { - width: 100%; -} - -.no-gutters { - margin: 0; - padding: 0; -} - -.d-flex { - display: flex; -} - -.floating-right { - float: right; -} - -.pull-right { - float: right; - margin-left: auto -} - -.clearfix::after { - display: block; - content: ''; - clear: both; - height: 0; -} -/* /--- utils classes --- */ - -/* ---dark theme --- */ -.theme-dark { - --background-color: #27282c; - --color-dark: #3d3d41; - --default-font-color: hsla(0, 0%, 100%, 0.8); - --border-color: hsla(0, 0%, 100%, 0.2); - --code-background: hsla(0, 0%, 100%, 0.05); - --breadcrumb-font-color: #8c8c8e; - --brief-color: hsla(0, 0%, 100%, 0.4); - --copy-icon-color: hsla(0, 0%, 100%, 0.6); - --copy-icon-hover-color: #fff; - - --active-tab-border-color: var(--default-font-color); - --inactive-tab-border-color: hsla(0, 0%, 100%, 0.4); - - --active-section-color: var(--default-font-color); - --inactive-section-color: hsla(0, 0%, 100%, 0.4); - - --navigation-highlight-color: rgba(255, 255, 255, 0.05); - --footer-background: hsla(0, 0%, 100%, 0.05); - --footer-font-color: hsla(0, 0%, 100%, 0.6); - --footer-go-to-top-color: var(--footer-font-color); - - --sidemenu-section-active-color: var(--color-dark); -} -/* /---dark theme --- */ - -.root { - display: flex; - flex-direction: column; - height: 100%; -} - -/* --- Navigation styles --- */ -.navigation { - display: flex; - justify-content: space-between; - - color: #fff; - background-color: var(--color-dark); - font-family: var(--default-font-family); - letter-spacing: -0.1px; - - /* Reset margin and use padding for border */ - margin-left: 0; - margin-right: 0; - padding: 10px var(--horizontal-spacing-for-content); - - z-index: 4; -} - -.navigation--inner { - display: flex; - flex-wrap: wrap; - justify-content: space-between; - flex: 1 1 auto; -} - -.navigation--inner, .navigation-title { - min-height: 40px; -} - -.navigation-title, .filter-section { - align-items: center; -} - -.navigation-title { - display: flex; - align-items: center; -} - -/* --- Navigation MENU --- */ -.menu-toggle { - color: var(--background-color); - line-height: 0; - font-size: 0; - text-indent: -9999px; - - background: transparent; - border: none; - padding: 0; - margin-right: 16px; - outline: none; - - transition: margin .2s ease-out; - z-index: 5; -} - -@media (min-width: 760px) { - .menu-toggle { - display: none; - } -} - -.menu-toggle::before { - display: block; - content: ''; - background: url('../images/burger.svg') no-repeat center; - height: 28px; - width: 28px; -} -/* /--- Navigation MENU --- */ - -.library-version { - position: relative; - top: -4px; - margin-left: 3px; - - color: rgba(255,255,255,.7); - font-size: 13px; - font-weight: normal; - line-height: 16px; -} - -.filter-section { - z-index: 0; -} - -.no-js .filter-section { - display: none; -} - -@media (min-width: 760px) { - .filter-section { - padding: 5px 0 5px; - } -} -/* --- Navigation controls --- */ -.navigation-controls { - display: flex; - margin-left: 4px; -} - -@media (min-width: 760px) { - .navigation-controls { - align-items: center; - } -} - -.no-js .navigation-controls { - display: none; -} - -/* --- Navigation THEME --- */ -.navigation-controls--search { - display: inline-flex; - font-size: 0; - line-height: 0; -} - -.navigation-controls--theme { - display: block; - border-radius: 50%; - background-color: inherit; - padding: 0; - border: none; - cursor: pointer; - font-size: 0; - line-height: 0; -} - -.navigation-controls--theme::before { - height: 40px; - width: 40px; -} - -.navigation-controls--theme:hover { - background: var(--white-10); -} - -.navigation-controls--theme::before { - display: block; - content: url("../images/theme-toggle.svg"); -} - -@media (max-width: 759px) { - .navigation-controls--theme { - display: none; - } -} -/* /--- Navigation THEME --- */ - -/* --- Navigation HOMEPAGE --- */ -.navigation-controls--homepage { - height: 40px; - width: 40px; - display: block; - border-radius: 50%; - cursor: pointer; -} - -.navigation-controls--homepage a::before { - height: 100%; - width: 20px; - margin-left: 10px; - display: block; - content: ""; - background: url("../images/homepage.svg"); - background-size: 100% 100%; -} - -.navigation-controls--homepage:hover { - background: var(--white-10); -} - -@media (max-width: 759px) { - .navigation-controls--homepage { - display: none; - } -} -/* /--- Navigation HOMEPAGE --- */ - -.navigation .platform-selector:not([data-active]) { - color: #fff; -} -/* /--- Navigation controls --- */ -/* /--- Navigation styles --- */ - -/* --- Layout styles --- */ - -#container { - display: flex; - flex: 1 1 auto; - min-height: 0; /* full height exclude header */ -} - -#container > .sidebar, #container > #main { - overflow: auto; -} - -#main { - display: flex; - flex-direction: column; - flex: 1 1 0; /* full width, but no affects for sidebar */ -} - -.sidebar { - display: flex; - flex-direction: column; - box-sizing: border-box; - border-right: 1px solid var(--border-color); - width: var(--sidebar-width); -} - -.no-js .sidebar { - display: none; -} - -@media (max-width: 759px) { - #container { - position: relative; - } - - .sidebar { - position: absolute; - top: 0; - bottom: 0; - box-sizing: border-box; - background: var(--background-color); - margin-left: calc(-1 * var(--sidebar-width)); - transition: margin .2s ease-out; - z-index: 4; - } - - .sidebar.open { - margin-left: 0; - } - - .sidebar.open ~ #main .navigation-controls--search { - display: none; - } - - .sidebar.open ~ #main .menu-toggle { - margin-left: var(--sidebar-width); - } -} - -.sidebar--inner { - font-size: 12px; - font-weight: 400; - line-height: 16px; - padding-top: 22px; - padding-bottom: 16px; -} -/* /--- Layout styles --- */ - -/* --- Main Content styles --- */ -.main-content { - padding-bottom: var(--bottom-spacing); - margin-left: auto; - margin-right: auto; - max-width: var(--max-width); - width: 100%; - z-index: 0; -} - -.main-content > * { - margin-left: var(--horizontal-spacing-for-content); - margin-right: var(--horizontal-spacing-for-content); -} - -.main-content .content > hr { - margin: 30px 0; - border-top: 3px double #8c8b8b; -} - -.main-content :is(h1, h2) { - font-weight: 530; -} -/* /--- Main Content styles --- */ - -/* /--- Breadcrumbs styles --- */ -.breadcrumbs, .breadcrumbs a, .breadcrumbs a:hover { - margin-top: var(--breadcrumb-margin); - color: var(--breadcrumb-font-color); - overflow-wrap: break-word; -} - -.breadcrumbs .delimiter { - margin: auto 2px; -} - -.breadcrumbs .current { - color: var(--default-font-color); -} -/* /--- Breadcrumbs styles --- */ - -.tabs-section, -.platform-hinted > .platform-bookmarks-row { - margin-left: -8px; - margin-right: -8px; -} - -.section-tab, -.platform-hinted > .platform-bookmarks-row > .platform-bookmark { - border: 0; - padding: 11px 3px; - margin: 0 8px; - cursor: pointer; - outline: none; - font-size: var(--default-font-size); - background-color: transparent; - color: var(--inactive-section-color); - border-bottom: 1px solid var(--inactive-tab-border-color); -} - -.platform-hinted > .platform-bookmarks-row { - margin-bottom: 16px; -} - -.no-js .platform-bookmarks-row + .sourceset-dependent-content { - margin-top: 8px; -} - -.no-js .platform-bookmarks-row + .sourceset-dependent-content:last-of-type { - margin-top: 0; -} - -.section-tab:hover { - color: var(--default-font-color); - border-bottom: 2px solid var(--default-font-color); -} - -.section-tab[data-active=''] { - color: var(--active-section-color); - border-bottom: 2px solid var(--active-tab-border-color); -} - -.tabs-section-body > div { - margin-top: 12px; -} - -.tabs-section-body .with-platform-tabs { - padding-top: 12px; - padding-bottom: 12px; -} - -.cover > .platform-hinted { - padding-bottom: 12px; -} - -.cover { - display: flex; - flex-direction: column; -} - -.cover .platform-hinted.with-platform-tabs .sourceset-dependent-content > .block ~ .symbol { - padding-top: 16px; - padding-left: 0; -} - -.cover .sourceset-dependent-content > .block { - padding: 16px 0; - font-size: 18px; - line-height: 28px; -} - -.cover .platform-hinted.with-platform-tabs .sourceset-dependent-content > .block { - padding: 0; - font-size: var(--default-font-size); -} - -.cover ~ .divergent-group { - margin-top: 24px; - padding: 24px 8px 8px 8px; -} - -.cover ~ .divergent-group .main-subrow .symbol { - width: 100%; -} - -.main-content p.paragraph, -.sample-container, blockquote, -.content > .symbol { - margin-top: 8px; -} - -blockquote, -.content > .symbol:first-of-type, -p.paragraph:first-child, -.brief p.paragraph { - margin-top: 0; -} - -.content .kdoc-tag > p.paragraph { - margin-top: 0; -} - -.content h4 { - margin-bottom: 0; -} - -.divergent-group { - background-color: var(--background-color); - padding: 16px 0 8px 0; - margin-bottom: 2px; -} - -.divergent-group .table-row, tbody > tr { - border-bottom: 1px solid var(--border-color); -} - -.divergent-group .table-row:last-of-type, tbody > tr:last-of-type { - border-bottom: none; -} - -.title > .divergent-group:first-of-type { - padding-top: 0; -} - -.sample-container, div.CodeMirror { - position: relative; - display: flex; - flex-direction: column; -} - -code.paragraph { - display: block; -} - -.overview > .navButton { - position: absolute; - align-items: center; - display: flex; - justify-content: flex-end; - padding: 2px 2px 2px 0; - margin-right: 5px; - cursor: pointer; -} - -.strikethrough { - text-decoration: line-through; -} - -.symbol:empty { - padding: 0; -} - -.symbol:not(.token), code { - background-color: var(--code-background); - align-items: center; - box-sizing: border-box; - white-space: pre-wrap; - font-family: var(--default-monospace-font-family); - font-size: var(--default-font-size); -} - -.symbol:not(.token), code.block { - display: block; - padding: 12px 32px 12px 12px; - border-radius: 8px; - line-height: 24px; - position: relative; -} - -code { - overflow-x: auto; - max-width: 100%; -} - -code:not(.block) { - display: inline-block; - vertical-align: middle; -} - -.symbol > a { - color: var(--hover-link-color); -} - -.copy-icon { - cursor: pointer; -} - -.sample-container span.copy-icon { - display: none; -} - -.js .sample-container:hover span.copy-icon { - display: inline-block; -} - -.sample-container span.copy-icon::before { - width: 24px; - height: 24px; - display: inline-block; - content: ''; - /* masks are required if you want to change color of the icon dynamically instead of using those provided with the SVG */ - -webkit-mask: url("../images/copy-icon.svg") no-repeat 50% 50%; - mask: url("../images/copy-icon.svg") no-repeat 50% 50%; - -webkit-mask-size: cover; - mask-size: cover; - background-color: var(--copy-icon-color); -} - -.sample-container span.copy-icon:hover::before { - background-color: var(--copy-icon-hover-color); -} - -.copy-popup-wrapper { - display: none; - align-items: center; - position: absolute; - z-index: 1000; - background: var(--background-color); - font-weight: normal; - font-family: var(--default-font-family); - width: max-content; - font-size: var(--default-font-size); - cursor: default; - border: 1px solid #D8DCE1; - box-sizing: border-box; - box-shadow: 0 5px 10px var(--ring-popup-shadow-color); - border-radius: 3px; - color: var(--default-font-color); -} - -.copy-popup-wrapper > .copy-popup-icon::before { - content: url("../images/copy-successful-icon.svg"); - padding: 8px; -} - -.copy-popup-wrapper > .copy-popup-icon { - position: relative; - top: 3px; -} - -.copy-popup-wrapper.popup-to-left { - /* since it is in position absolute we can just move it to the left to make it always appear on the left side of the icon */ - left: -15em; -} - -.table-row:hover .copy-popup-wrapper.active-popup, -.sample-container:hover .copy-popup-wrapper.active-popup { - display: flex !important; -} - -.copy-popup-wrapper:hover { - font-weight: normal; -} - -.copy-popup-wrapper > span:last-child { - padding-right: 14px; -} - -.symbol .top-right-position, .sample-container .top-right-position { - /* it is important for a parent to have a position: relative */ - position: absolute; - top: 8px; - right: 8px; -} - -.sideMenuPart > .overview { - display: flex; - align-items: center; - position: relative; - user-select: none; /* there's a weird bug with text selection */ - padding: 8px 0; -} - -.sideMenuPart a { - display: block; - align-items: center; - color: var(--default-font-color); - overflow: hidden; - padding-left: 23px; -} - -.sideMenuPart a:hover { - text-decoration: none; - color: var(--default-font-color); -} - -.sideMenuPart > .overview:before { - box-sizing: border-box; - content: ''; - top: 0; - width: var(--sidebar-width); - right: 0; - bottom: 0; - position: absolute; - z-index: -1; -} - -.overview:hover:before { - background-color: var(--navigation-highlight-color); -} - -#nav-submenu { - padding-left: 24px; -} - -.sideMenuPart { - padding-left: 12px; - box-sizing: border-box; -} - -.sideMenuPart.hidden > .overview .navButtonContent::before { - transform: rotate(0deg); -} - -.sideMenuPart > .overview .navButtonContent::before { - content: ''; - - -webkit-mask: url("../images/arrow_down.svg") no-repeat 50% 50%; - mask: url("../images/arrow_down.svg") no-repeat 50% 50%; - -webkit-mask-size: cover; - mask-size: cover; - background-color: var(--default-font-color); - - display: flex; - flex-direction: row; - align-items: center; - justify-content: center; - transform: rotate(90deg); - width: 16px; - height: 16px; -} - -.sideMenuPart[data-active] > .overview .navButtonContent::before { - background-color: var(--default-white); -} - -.sideMenuPart.hidden > .navButton .navButtonContent::after { - content: '\02192'; -} - -.sideMenuPart.hidden > .sideMenuPart { - display: none; -} - -.overview .nav-link-grid { - display: grid; - grid-template-columns: 16px auto; /* first is the icon, then name */ - grid-gap: 6px; - align-items: center; -} - -.nav-icon { - width: 16px; - height: 16px; -} - -.nav-icon.class::before { - content: url("../images/nav-icons/class.svg"); -} - -.nav-icon.class-kt::before { - content: url("../images/nav-icons/class-kotlin.svg"); -} - -.nav-icon.function::before { - content: url("../images/nav-icons/function.svg"); -} - -.nav-icon.enum-class::before { - content: url("../images/nav-icons/enum.svg"); -} - -.nav-icon.enum-class-kt::before { - content: url("../images/nav-icons/enum-kotlin.svg"); -} - -.nav-icon.annotation-class::before { - content: url("../images/nav-icons/annotation.svg"); -} - -.nav-icon.annotation-class-kt::before { - content: url("../images/nav-icons/annotation-kotlin.svg"); -} - -.nav-icon.abstract-class::before { - content: url("../images/nav-icons/abstract-class.svg"); -} - -.nav-icon.abstract-class-kt::before { - content: url("../images/nav-icons/abstract-class-kotlin.svg"); -} - -.nav-icon.exception-class::before { - content: url("../images/nav-icons/exception-class.svg"); -} - -.nav-icon.interface::before { - content: url("../images/nav-icons/interface.svg"); -} - -.nav-icon.interface-kt::before { - content: url("../images/nav-icons/interface-kotlin.svg"); -} - -.nav-icon.object::before { - content: url("../images/nav-icons/object.svg"); -} - -.nav-icon.typealias-kt::before { - content: url("../images/nav-icons/typealias-kotlin.svg"); -} - -.nav-icon.val::before { - content: url("../images/nav-icons/field-value.svg"); -} - -.nav-icon.var::before { - content: url("../images/nav-icons/field-variable.svg"); -} - -.filtered > a, .filtered > .navButton { - display: none; -} - - -.brief { - white-space: pre-wrap; - overflow: hidden; -} - -h1.cover { - font-size: 52px; - line-height: 56px; - letter-spacing: -1.5px; - margin-bottom: 0; - padding-bottom: 32px; - display: block; -} - -@media (max-width: 1119px) { - h1.cover { - font-size: 48px; - line-height: 48px; - padding-bottom: 8px; - } -} - -@media (max-width: 759px) { - h1.cover { - font-size: 32px; - line-height: 32px; - } -} - -.UnderCoverText { - font-size: 16px; - line-height: 28px; -} - -.UnderCoverText code { - font-size: inherit; -} - -.UnderCoverText table { - margin: 8px 0 8px 0; - word-break: break-word; -} - -@media (max-width: 960px) { - .UnderCoverText table { - display: block; - word-break: normal; - overflow: auto; - } -} - -.main-content a:not([data-name]) { - padding-bottom: 2px; - border-bottom: 1px solid var(--border-color); - cursor: pointer; - text-decoration: none; - color: inherit; - font-size: inherit; - line-height: inherit; - transition: color .1s, border-color .1s; -} - -.main-content a:hover { - border-bottom-color: unset; - color: inherit -} - -a small { - font-size: 11px; - margin-top: -0.6em; - display: block; -} - -p.paragraph img { - display: block; -} - -.deprecation-content { - margin: 20px 10px; - border:1px solid var(--border-color); - padding: 13px 15px 16px 15px; -} - -.deprecation-content > h3 { - margin-top: 0; - margin-bottom: 0; -} - -.deprecation-content > h4 { - font-size: 16px; - margin-top: 15px; - margin-bottom: 0; -} - -.deprecation-content code.block { - padding: 5px 10px; - display: inline-block; -} - -.deprecation-content .footnote { - margin-left: 25px; - font-size: 13px; - font-weight: bold; - display: block; -} - -.deprecation-content .footnote > p { - margin: 0; -} - -[data-filterable-current=''] { - display: none !important; -} - -.platform-tags, .filter-section { - display: flex; - flex-wrap: wrap; - margin-bottom: -8px; - margin-left: -4px; -} - -.platform-tag { - --platform-tag-color: #bababb; - border: 0 none; - margin-right: 4px; - margin-bottom: 8px; - - font-family: var(--default-font-family); - font-size: 13px; - line-height: 1.5; - text-transform: capitalize; -} - -.platform-tag.js-like, .platform-tag.jvm-like, .platform-tag.wasm-like { - text-transform: uppercase; -} - -.filter-section .platform-tag { - cursor: pointer; - border-radius: 4px; - padding: 2px 16px; -} - -.filter-section .platform-tag.jvm-like[data-active], .platform-tags .platform-tag.jvm-like { - --platform-tag-color: #4dbb5f; -} - -.filter-section .platform-tag.js-like[data-active], .platform-tags .platform-tag.js-like { - --platform-tag-color: #ffc700; -} - -.filter-section .platform-tag.native-like[data-active], .platform-tags .platform-tag.native-like { - --platform-tag-color: #E082F3; -} - -.filter-section .platform-tag.wasm-like[data-active], .platform-tags .platform-tag.wasm-like { - --platform-tag-color: #9585F9; -} - -.filter-section .platform-tag[data-active]:hover { - color: #fff; - background-color: rgba(186, 186, 187, .7); -} - -.filter-section .platform-tag:not([data-active]) { - color: #fff; - /* Safari doesn't work correctly for `outline` with `border-radius` */ - /* outline: 1px solid rgba(255,255,255,.6); */ - /* ...use `box-shadow` instead: */ - box-shadow: 0 0 0 1px rgb(255 255 255 / 60%); - background-color: rgba(255,255,255,.05); -} - -.filter-section .platform-tag[data-active] { - color: #19191c; - background-color: var(--platform-tag-color); -} - -.platform-tags .platform-tag { - display: flex; - align-items: center; -} - -.platform-tags .platform-tag::before { - display: inline-block; - content: ''; - border-radius: 50%; - background: var(--platform-tag-color); - margin: 0 4px 0 8px; - height: 8px; - width: 8px; - - font-size: 13px; - line-height: 1.6; -} - -td.content { - padding-left: 24px; - padding-top: 16px; - display: flex; - flex-direction: column; -} - -.main-subrow { - display: flex; - flex-direction: row; - padding: 0; - flex-wrap: wrap; -} - -.main-subrow > div { - margin-bottom: 8px; -} - -.main-subrow > div > span { - display: flex; - position: relative; -} - -.js .main-subrow:hover .anchor-icon { - opacity: 1; - transition: 0.2s; -} - -.main-subrow .anchor-icon { - opacity: 0; - transition: 0.2s 0.5s; -} - -.main-subrow .anchor-icon::before { - content: url("../images/anchor-copy-button.svg"); -} - -.main-subrow .anchor-icon:hover { - cursor: pointer; -} - -.main-subrow .anchor-icon:hover > svg path { - fill: var(--hover-link-color); -} - -@media (hover: none) { - .main-subrow .anchor-icon { - display: none; - } -} - -.main-subrow .anchor-wrapper { - position: relative; - width: 24px; - height: 16px; - margin-left: 3px; -} - -.inline-flex { - display: inline-flex; -} - -.platform-hinted { - flex: auto; - display: block; -} - -.platform-hinted > .platform-bookmarks-row > .platform-bookmark { - min-width: 64px; - background: inherit; - flex: none; - order: 5; - align-self: flex-start; -} - -.platform-hinted > .platform-bookmarks-row > .platform-bookmark:hover { - color: var(--default-font-color); - border-bottom: 2px solid var(--default-font-color); -} - -.platform-hinted > .platform-bookmarks-row > .platform-bookmark[data-active=''] { - border-bottom: 2px solid var(--active-tab-border-color); - color: var(--active-section-color); -} - -.no-js .platform-bookmarks-row, .no-js .tabs-section { - display: none; -} - -.js .platform-hinted > .content:not([data-active]), -.js .tabs-section-body *[data-togglable]:not([data-active]) { - display: none; -} - -/* Work around an issue: https://github.com/JetBrains/kotlin-playground/issues/91 -Applies for main description blocks with platform tabs. -Just in case of possible performance degradation it excluding tabs with briefs on classlike page */ -#content > div:not(.tabbedcontent) .sourceset-dependent-content:not([data-active]) { - display: block !important; - visibility: hidden; - height: 0; - position: fixed; - top: 0; -} - -.with-platform-tags { - display: flex; -} - -.with-platform-tags ~ .main-subrow { - padding-top: 8px; -} - -.cover .with-platform-tabs { - font-size: var(--default-font-size); -} - -.cover > .with-platform-tabs > .content { - padding: 8px 16px; - border: 1px solid var(--border-color); -} - -.cover > .block { - padding-top: 48px; - padding-bottom: 24px; - font-size: 18px; - line-height: 28px; -} - -.cover > .block:empty { - padding-bottom: 0; -} - -.parameters.wrapped > .parameter { - display: block; -} - -.table-row .inline-comment { - padding-top: 8px; - padding-bottom: 8px; -} - -.table-row .platform-hinted .sourceset-dependent-content .brief, -.table-row .platform-hinted .sourceset-dependent-content .inline-comment { - padding: 8px; -} - -.sideMenuPart[data-active] > .overview:before { - background: var(--sidemenu-section-active-color); -} - -.sideMenuPart[data-active] > .overview > a { - color: var(--default-white); -} - -.table { - display: flex; - flex-direction: column; -} - -.table-row { - display: flex; - flex-direction: column; - border-bottom: 1px solid var(--border-color); - padding: 11px 0 12px 0; - background-color: var(--background-color); -} - -.table-row:last-of-type { - border-bottom: none; -} - -.table-row .brief-comment { - color: var(--brief-color); -} - -.platform-dependent-row { - display: grid; - padding-top: 8px; -} - -.title-row { - display: grid; - grid-template-columns: auto auto 7em; - width: 100%; -} - -@media print, (min-width: 960px) { - .title-row { - grid-template-columns: 20% auto 7em; - } -} - -.keyValue { - display: grid; - grid-gap: 8px; -} - -@media print, (min-width: 960px) { - .keyValue { - grid-template-columns: 20% 80%; - } - .keyValue > div:first-child { - word-break: break-word; - } -} - -@media print, (max-width: 960px) { - div.wrapper { - width: auto; - margin: 0; - } - - header, section, footer { - float: none; - position: static; - width: auto; - } - - header { - padding-right: 320px; - } - - section { - border: 1px solid #e5e5e5; - border-width: 1px 0; - padding: 20px 0; - margin: 0 0 20px; - } - - header a small { - display: inline; - } - - header ul { - position: absolute; - right: 50px; - top: 52px; - } -} - -.anchor-highlight { - border: 1px solid var(--hover-link-color) !important; - box-shadow: 0 0 0 0.2em #c8e1ff; - margin-top: 0.2em; - margin-bottom: 0.2em; -} - -.filtered-message { - margin: 25px; - font-size: 20px; - font-weight: bolder; -} - -div.runnablesample { - height: fit-content; -} - -/* --- footer --- */ -.footer { - clear: both; - display: flex; - align-items: center; - position: relative; - min-height: var(--footer-height); - font-size: 12px; - line-height: 16px; - letter-spacing: 0.2px; - color: var(--footer-font-color); - margin-top: auto; - background-color: var(--footer-background); -} - -.footer span.go-to-top-icon { - border-radius: 2em; - padding: 11px 10px !important; - background-color: var(--footer-go-to-top-color); -} - -.footer span.go-to-top-icon > a::before { - content: url("../images/go-to-top-icon.svg"); -} - -.footer > span:first-child { - margin-left: var(--horizontal-spacing-for-content); - padding-left: 0; -} - -.footer > span:last-child { - margin-right: var(--horizontal-spacing-for-content); - padding-right: 0; -} - -.footer > span { - padding: 0 16px; -} - -.footer a { - color: var(--breadcrumb-font-color); -} - -.footer span.go-to-top-icon > #go-to-top-link { - padding: 0; - border: none; -} - -.footer .padded-icon { - padding-left: 0.5em; -} - -.footer .padded-icon::before { - content: url("../images/footer-go-to-link.svg"); -} -/* /--- footer --- */ - -/* Logo styles */ -:root { - --dokka-logo-image-url: url('../images/logo-icon.svg'); - --dokka-logo-height: 50px; - --dokka-logo-width: 50px; -} - -.library-name--link { - display: flex; - align-items: center; - color: #fff; - font-weight: 530; -} - -.library-name--link::before { - content: ''; - background: var(--dokka-logo-image-url) center no-repeat; - background-size: var(--dokka-logo-height) var(--dokka-logo-width); - margin-right: 5px; - width: var(--dokka-logo-height); - height: var(--dokka-logo-width); -} - -@media (max-width: 759px) { - .library-name--link::before { - display: none; - } -} -/* / Logo styles */ - -/* -the hack to hide the headers inside tabs for a package page because each tab -has only one header, and the header text is the same as the tab name, so no point in showing it -*/ -.main-content[data-page-type="package"] .tabs-section-body h2 { - display: none; -} diff --git a/plugins/base/src/main/resources/dokka/templates/base.ftl b/plugins/base/src/main/resources/dokka/templates/base.ftl deleted file mode 100644 index 0311f9f8..00000000 --- a/plugins/base/src/main/resources/dokka/templates/base.ftl +++ /dev/null @@ -1,44 +0,0 @@ -<#import "includes/page_metadata.ftl" as page_metadata> -<#import "includes/header.ftl" as header> -<#import "includes/footer.ftl" as footer> -<!DOCTYPE html> -<html class="no-js"> -<head> - <meta name="viewport" content="width=device-width, initial-scale=1" charset="UTF-8"> - <@page_metadata.display/> - <@template_cmd name="pathToRoot"><script>var pathToRoot = "${pathToRoot}";</script></@template_cmd> - <script>document.documentElement.classList.replace("no-js","js");</script> - <#-- This script doesn't need to be there but it is nice to have - since app in dark mode doesn't 'blink' (class is added before it is rendered) --> - <script>const storage = localStorage.getItem("dokka-dark-mode") - if (storage == null) { - const osDarkSchemePreferred = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches - if (osDarkSchemePreferred === true) { - document.getElementsByTagName("html")[0].classList.add("theme-dark") - } - } else { - const savedDarkMode = JSON.parse(storage) - if(savedDarkMode === true) { - document.getElementsByTagName("html")[0].classList.add("theme-dark") - } - } - </script> - <#-- Resources (scripts, stylesheets) are handled by Dokka. - Use customStyleSheets and customAssets to change them. --> - <@resources/> -</head> -<body> - <div class="root"> - <@header.display/> - <div id="container"> - <div class="sidebar" id="leftColumn"> - <div class="sidebar--inner" id="sideMenu"></div> - </div> - <div id="main"> - <@content/> - <@footer.display/> - </div> - </div> - </div> -</body> -</html>
\ No newline at end of file diff --git a/plugins/base/src/main/resources/dokka/templates/includes/footer.ftl b/plugins/base/src/main/resources/dokka/templates/includes/footer.ftl deleted file mode 100644 index 461a8162..00000000 --- a/plugins/base/src/main/resources/dokka/templates/includes/footer.ftl +++ /dev/null @@ -1,7 +0,0 @@ -<#macro display> - <div class="footer"> - <span class="go-to-top-icon"><a href="#content" id="go-to-top-link"></a></span><span>${footerMessage}</span><span - class="pull-right"><span>Generated by </span><a - href="https://github.com/Kotlin/dokka"><span>dokka</span><span class="padded-icon"></span></a></span> - </div> -</#macro>
\ No newline at end of file diff --git a/plugins/base/src/main/resources/dokka/templates/includes/header.ftl b/plugins/base/src/main/resources/dokka/templates/includes/header.ftl deleted file mode 100644 index d399e633..00000000 --- a/plugins/base/src/main/resources/dokka/templates/includes/header.ftl +++ /dev/null @@ -1,31 +0,0 @@ -<#import "source_set_selector.ftl" as source_set_selector> -<#macro display> -<nav class="navigation" id="navigation-wrapper"> - <div class="navigation--inner"> - <div class="navigation-title"> - <button class="menu-toggle" id="menu-toggle" type="button">toggle menu</button> - <div class="library-name"> - <@template_cmd name="pathToRoot"> - <a class="library-name--link" href="${pathToRoot}index.html"> - <@template_cmd name="projectName"> - ${projectName} - </@template_cmd> - </a> - </@template_cmd> - </div> - <div class="library-version"> - <#-- This can be handled by the versioning plugin --> - <@version/> - </div> - </div> - <@source_set_selector.display/> - </div> - <div class="navigation-controls"> - <#if homepageLink?has_content> - <div class="navigation-controls--btn navigation-controls--homepage" id="homepage-link" role="button"><a href="${homepageLink}"></a></div> - </#if> - <button class="navigation-controls--btn navigation-controls--theme" id="theme-toggle-button" type="button">switch theme</button> - <div class="navigation-controls--btn navigation-controls--search" id="searchBar" role="button">search in API</div> - </div> -</nav> -</#macro> diff --git a/plugins/base/src/main/resources/dokka/templates/includes/page_metadata.ftl b/plugins/base/src/main/resources/dokka/templates/includes/page_metadata.ftl deleted file mode 100644 index 7cab4582..00000000 --- a/plugins/base/src/main/resources/dokka/templates/includes/page_metadata.ftl +++ /dev/null @@ -1,6 +0,0 @@ -<#macro display> - <title>${pageName}</title> - <@template_cmd name="pathToRoot"> - <link href="${pathToRoot}images/logo-icon.svg" rel="icon" type="image/svg"> - </@template_cmd> -</#macro> diff --git a/plugins/base/src/main/resources/dokka/templates/includes/source_set_selector.ftl b/plugins/base/src/main/resources/dokka/templates/includes/source_set_selector.ftl deleted file mode 100644 index 2d848071..00000000 --- a/plugins/base/src/main/resources/dokka/templates/includes/source_set_selector.ftl +++ /dev/null @@ -1,9 +0,0 @@ -<#macro display> - <#if sourceSets?has_content> - <div class="filter-section" id="filter-section"> - <#list sourceSets as ss> - <button class="platform-tag platform-selector ${ss.platform}-like" data-active="" data-filter="${ss.filter}">${ss.name}</button> - </#list> - </div> - </#if> -</#macro> diff --git a/plugins/base/src/test/kotlin/basic/AbortGracefullyOnMissingDocumentablesTest.kt b/plugins/base/src/test/kotlin/basic/AbortGracefullyOnMissingDocumentablesTest.kt deleted file mode 100644 index 693174ec..00000000 --- a/plugins/base/src/test/kotlin/basic/AbortGracefullyOnMissingDocumentablesTest.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 basic - -import org.jetbrains.dokka.DokkaGenerator -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import kotlin.test.Test -import kotlin.test.assertTrue - -class AbortGracefullyOnMissingDocumentablesTest: BaseAbstractTest() { - @Test - fun `Generation aborts Gracefully with no Documentables`() { - DokkaGenerator(dokkaConfiguration { }, logger).generate() - - assertTrue( - logger.progressMessages.any { message -> "Exiting Generation: Nothing to document" == message }, - "Expected graceful exit message. Found: ${logger.progressMessages}" - ) - } -} diff --git a/plugins/base/src/test/kotlin/basic/DRITest.kt b/plugins/base/src/test/kotlin/basic/DRITest.kt deleted file mode 100644 index 6fd9d4b0..00000000 --- a/plugins/base/src/test/kotlin/basic/DRITest.kt +++ /dev/null @@ -1,351 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package basic - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.links.* -import org.jetbrains.dokka.links.Callable -import org.jetbrains.dokka.links.Nullable -import org.jetbrains.dokka.links.TypeConstructor -import org.jetbrains.dokka.model.* -import org.jetbrains.dokka.pages.ClasslikePageNode -import org.jetbrains.dokka.pages.ContentPage -import org.jetbrains.dokka.pages.MemberPageNode -import kotlin.test.Test -import kotlin.test.assertEquals - -class DRITest : BaseAbstractTest() { - @Test - fun issue634() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - } - } - } - - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package toplevel - | - |inline fun <T, R : Comparable<R>> Array<out T>.mySortBy( - | crossinline selector: (T) -> R?): Array<out T> = TODO() - |} - """.trimMargin(), - configuration - ) { - documentablesMergingStage = { module -> - val expected = TypeConstructor( - "kotlin.Function1", listOf( - TypeParam(listOf(Nullable(TypeConstructor("kotlin.Any", emptyList())))), - Nullable(TypeParam(listOf(TypeConstructor("kotlin.Comparable", listOf(RecursiveType(0)))))) - ) - ) - val actual = module.packages.single() - .functions.single() - .dri.callable?.params?.single() - assertEquals(expected, actual) - } - } - } - - @Test - fun issue634WithImmediateNullableSelf() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - } - } - } - - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package toplevel - | - |fun <T : Comparable<T>> Array<T>.doSomething(t: T?): Array<T> = TODO() - |} - """.trimMargin(), - configuration - ) { - documentablesMergingStage = { module -> - val expected = Nullable(TypeParam(listOf(TypeConstructor("kotlin.Comparable", listOf(RecursiveType(0)))))) - val actual = module.packages.single() - .functions.single() - .dri.callable?.params?.single() - assertEquals(expected, actual) - } - } - } - - @Test - fun issue634WithGenericNullableReceiver() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - } - } - } - - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package toplevel - | - |fun <T : Comparable<T>> T?.doSomethingWithNullable() = TODO() - |} - """.trimMargin(), - configuration - ) { - documentablesMergingStage = { module -> - val expected = Nullable(TypeParam(listOf(TypeConstructor("kotlin.Comparable", listOf(RecursiveType(0)))))) - val actual = module.packages.single() - .functions.single() - .dri.callable?.receiver - assertEquals(expected, actual) - } - } - } - - @Test - fun issue642WithStarAndAny() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - analysisPlatform = "js" - sourceRoots = listOf("src/") - } - } - } - - testInline( - """ - |/src/main/kotlin/Test.kt - | - |open class Bar<Z> - |class ReBarBar : Bar<StringBuilder>() - |class Foo<out T : Comparable<*>, R : List<Bar<*>>> - | - |fun <T : Comparable<Any?>> Foo<T, *>.qux(): String = TODO() - |fun <T : Comparable<*>> Foo<T, *>.qux(): String = TODO() - | - """.trimMargin(), - configuration - ) { - pagesGenerationStage = { module -> - // DRI(//qux/Foo[TypeParam(bounds=[kotlin.Comparable[kotlin.Any?]]),*]#/PointingToFunctionOrClasslike/) - val expectedDRI = DRI( - "", - null, - Callable( - "qux", TypeConstructor( - "Foo", listOf( - TypeParam( - listOf( - TypeConstructor( - "kotlin.Comparable", listOf( - Nullable(TypeConstructor("kotlin.Any", emptyList())) - ) - ) - ) - ), - StarProjection - ) - ), - emptyList() - ) - ) - - val driCount = module - .withDescendants() - .filterIsInstance<ContentPage>() - .sumBy { it.dri.count { dri -> dri == expectedDRI } } - - assertEquals(1, driCount) - } - } - } - - @Test - fun driForGenericClass(){ - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - } - } - } - testInline( - """ - |/src/main/kotlin/Test.kt - |package example - | - |class Sample<S>(first: S){ } - | - | - """.trimMargin(), - configuration - ) { - pagesGenerationStage = { module -> - val sampleClass = module.dfs { it.name == "Sample" } as ClasslikePageNode - val classDocumentable = sampleClass.documentables.firstOrNull() as DClass - - assertEquals( "example/Sample///PointingToDeclaration/", sampleClass.dri.first().toString()) - assertEquals("example/Sample///PointingToGenericParameters(0)/", classDocumentable.generics.first().dri.toString()) - } - } - } - - @Test - fun driForGenericFunction(){ - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - classpath = listOfNotNull(jvmStdlibPath) - } - } - } - testInline( - """ - |/src/main/kotlin/Test.kt - |package example - | - |class Sample<S>(first: S){ - | fun <T> genericFun(param1: String): Tuple<S,T> = TODO() - |} - | - | - """.trimMargin(), - configuration - ) { - pagesGenerationStage = { module -> - val sampleClass = module.dfs { it.name == "Sample" } as ClasslikePageNode - val functionNode = sampleClass.children.first { it.name == "genericFun" } as MemberPageNode - val functionDocumentable = functionNode.documentables.firstOrNull() as DFunction - val parameter = functionDocumentable.parameters.first() - - assertEquals("example/Sample/genericFun/#kotlin.String/PointingToDeclaration/", functionNode.dri.first().toString()) - - assertEquals(1, functionDocumentable.parameters.size) - assertEquals("example/Sample/genericFun/#kotlin.String/PointingToCallableParameters(0)/", parameter.dri.toString()) - //1 since from the function's perspective there is only 1 new generic declared - //The other one is 'inherited' from class - assertEquals( 1, functionDocumentable.generics.size) - assertEquals( "T", functionDocumentable.generics.first().name) - assertEquals( "example/Sample/genericFun/#kotlin.String/PointingToGenericParameters(0)/", functionDocumentable.generics.first().dri.toString()) - } - } - } - - @Test - fun driForFunctionNestedInsideInnerClass() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - classpath = listOfNotNull(jvmStdlibPath) - } - } - } - testInline( - """ - |/src/main/kotlin/Test.kt - |package example - | - |class Sample<S>(first: S){ - | inner class SampleInner { - | fun foo(): S = TODO() - | } - |} - | - | - """.trimMargin(), - configuration - ) { - pagesGenerationStage = { module -> - val sampleClass = module.dfs { it.name == "Sample" } as ClasslikePageNode - val sampleInner = sampleClass.children.first { it.name == "SampleInner" } as ClasslikePageNode - val foo = sampleInner.children.first { it.name == "foo" } as MemberPageNode - val documentable = foo.documentables.firstOrNull() as DFunction - - val generics = (sampleClass.documentables.firstOrNull() as WithGenerics).generics - assertEquals(generics.first().dri.toString(), (documentable.type as TypeParameter).dri.toString()) - assertEquals(0, documentable.generics.size) - } - } - } - - @Test - fun driForGenericExtensionFunction(){ - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - } - } - } - testInline( - """ - |/src/main/kotlin/Test.kt - |package example - | - | fun <T> List<T>.extensionFunction(): String = "" - | - """.trimMargin(), - configuration - ) { - pagesGenerationStage = { module -> - val extensionFunction = module.dfs { it.name == "extensionFunction" } as MemberPageNode - val documentable = extensionFunction.documentables.firstOrNull() as DFunction - - assertEquals( - "example//extensionFunction/kotlin.collections.List[TypeParam(bounds=[kotlin.Any?])]#/PointingToDeclaration/", - extensionFunction.dri.first().toString() - ) - assertEquals(1, documentable.generics.size) - assertEquals("T", documentable.generics.first().name) - assertEquals( - "example//extensionFunction/kotlin.collections.List[TypeParam(bounds=[kotlin.Any?])]#/PointingToGenericParameters(0)/", - documentable.generics.first().dri.toString() - ) - - } - } - } - - @Test - fun `deep recursive typebound #1342`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - } - } - } - testInline( - """ - |/src/main/kotlin/Test.kt - |package example - | - | fun <T, S, R> recursiveBound(t: T, s: S, r: R) where T: List<S>, S: List<R>, R: List<S> = Unit - | - """.trimMargin(), - configuration - ) { - documentablesMergingStage = { module -> - val function = module.dfs { it.name == "recursiveBound" } - assertEquals( - "example//recursiveBound/#TypeParam(bounds=[kotlin.collections.List[TypeParam(bounds=[kotlin.collections.List[TypeParam(bounds=[kotlin.collections.List[^^]])]])]])#TypeParam(bounds=[kotlin.collections.List[TypeParam(bounds=[kotlin.collections.List[^]])]])#TypeParam(bounds=[kotlin.collections.List[TypeParam(bounds=[kotlin.collections.List[^]])]])/PointingToDeclaration/", - function?.dri?.toString(), - ) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/basic/DokkaBasicTests.kt b/plugins/base/src/test/kotlin/basic/DokkaBasicTests.kt deleted file mode 100644 index 2b353ad8..00000000 --- a/plugins/base/src/test/kotlin/basic/DokkaBasicTests.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 basic - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.pages.ClasslikePageNode -import org.jetbrains.dokka.pages.ModulePageNode -import kotlin.test.Test -import kotlin.test.assertEquals - -class DokkaBasicTests : BaseAbstractTest() { - - @Test - fun basic1() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin/basic/Test.kt") - } - } - } - - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package basic - | - |class Test { - | val tI = 1 - | fun tF() = 2 - |} - """.trimMargin(), - configuration - ) { - pagesGenerationStage = { - val root = it as ModulePageNode - assertEquals(3, root.getClasslikeToMemberMap().filterKeys { it.name == "Test" }.entries.firstOrNull()?.value?.size) - } - } - } - - private fun ModulePageNode.getClasslikeToMemberMap() = - this.parentMap.filterValues { it is ClasslikePageNode }.entries.groupBy({ it.value }) { it.key } -} diff --git a/plugins/base/src/test/kotlin/basic/FailOnWarningTest.kt b/plugins/base/src/test/kotlin/basic/FailOnWarningTest.kt deleted file mode 100644 index ebdf7860..00000000 --- a/plugins/base/src/test/kotlin/basic/FailOnWarningTest.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 basic - -import org.jetbrains.dokka.DokkaException -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.testApi.logger.TestLogger -import org.jetbrains.dokka.utilities.DokkaConsoleLogger -import org.jetbrains.dokka.utilities.DokkaLogger -import org.jetbrains.dokka.utilities.LoggingLevel -import kotlin.test.Test -import kotlin.test.assertFailsWith - -class FailOnWarningTest : BaseAbstractTest() { - - @Test - fun `throws exception if one or more warnings were emitted`() { - val configuration = dokkaConfiguration { - failOnWarning = true - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin") - } - } - } - - assertFailsWith<DokkaException> { - testInline( - """ - |/src/main/kotlin/Bar.kt - |package sample - |class Bar {} - """.trimIndent(), configuration - ) { - pluginsSetupStage = { - logger.warn("Warning!") - } - } - } - } - - @Test - fun `throws exception if one or more error were emitted`() { - val configuration = dokkaConfiguration { - failOnWarning = true - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin") - } - } - } - - assertFailsWith<DokkaException> { - testInline( - """ - |/src/main/kotlin/Bar.kt - |package sample - |class Bar {} - """.trimIndent(), configuration - ) { - pluginsSetupStage = { - logger.error("Error!") - } - } - } - } - - @Test - fun `does not throw if now warning or error was emitted`() { - - val configuration = dokkaConfiguration { - failOnWarning = true - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin") - } - } - } - - - testInline( - """ - |/src/main/kotlin/Bar.kt - |package sample - |class Bar {} - """.trimIndent(), - configuration, - loggerForTest = TestLogger(ZeroErrorOrWarningCountDokkaLogger()) - ) { - /* We expect no Exception */ - } - } - - @Test - fun `does not throw if disabled`() { - val configuration = dokkaConfiguration { - failOnWarning = false - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin") - } - } - } - - - testInline( - """ - |/src/main/kotlin/Bar.kt - |package sample - |class Bar {} - """.trimIndent(), configuration - ) { - pluginsSetupStage = { - logger.warn("Error!") - logger.error("Error!") - } - } - } -} - -private class ZeroErrorOrWarningCountDokkaLogger( - logger: DokkaLogger = DokkaConsoleLogger(LoggingLevel.DEBUG) -) : DokkaLogger by logger { - override var warningsCount: Int = 0 - override var errorsCount: Int = 0 -} diff --git a/plugins/base/src/test/kotlin/basic/LoggerTest.kt b/plugins/base/src/test/kotlin/basic/LoggerTest.kt deleted file mode 100644 index 12c39690..00000000 --- a/plugins/base/src/test/kotlin/basic/LoggerTest.kt +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package basic - -import org.jetbrains.dokka.utilities.DokkaConsoleLogger -import org.jetbrains.dokka.utilities.LoggingLevel -import org.jetbrains.dokka.utilities.MessageEmitter -import kotlin.test.Test -import kotlin.test.assertFalse -import kotlin.test.assertTrue - -class LoggerTest { - class AccumulatingEmitter : MessageEmitter { - val messages: MutableList<String> = mutableListOf() - override fun invoke(message: String) { - messages.add(message) - } - } - - @Test - fun `should display info messages if logging is info`(){ - val emitter = AccumulatingEmitter() - val logger = DokkaConsoleLogger(LoggingLevel.INFO, emitter) - - logger.debug("Debug!") - logger.info("Info!") - - assertTrue(emitter.messages.size > 0) - assertTrue(emitter.messages.any { it == "Info!" }) - assertFalse(emitter.messages.any { it == "Debug!" }) - } - - @Test - fun `should not display info messages if logging is warn`(){ - val emitter = AccumulatingEmitter() - val logger = DokkaConsoleLogger(LoggingLevel.WARN, emitter) - - logger.warn("Warning!") - logger.info("Info!") - - - assertTrue(emitter.messages.size > 0) - assertFalse(emitter.messages.any { it.contains("Info!") }) - assertTrue(emitter.messages.any { it.contains("Warning!") }) - } -} diff --git a/plugins/base/src/test/kotlin/content/ContentInDescriptionTest.kt b/plugins/base/src/test/kotlin/content/ContentInDescriptionTest.kt deleted file mode 100644 index a278795d..00000000 --- a/plugins/base/src/test/kotlin/content/ContentInDescriptionTest.kt +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package content - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.model.doc.* -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertTrue - -class ContentInDescriptionTest : BaseAbstractTest() { - private val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - analysisPlatform = "jvm" - classpath += jvmStdlibPath!! - } - } - } - - val expectedDescription = Description( - CustomDocTag( - listOf( - P( - listOf( - Text("Hello World! Docs with period issue, e.g."), - Text(String(Character.toChars(160)), params = mapOf("content-type" to "html")), - Text("this.") - ) - ) - ), - params = emptyMap(), - name = "MARKDOWN_FILE" - ) - ) - - @Test - fun `nbsp is handled as code in kotlin`() { - testInline( - """ - |/src/main/kotlin/sample/ParentKt.kt - |package sample; - |/** - | * Hello World! Docs with period issue, e.g. this. - | */ - |public class ParentKt { - |} - """.trimIndent(), configuration - ) { - documentablesMergingStage = { - val classlike = it.packages.flatMap { it.classlikes }.find { it.name == "ParentKt" } - - assertTrue(classlike != null) - assertEquals(expectedDescription, classlike.documentation.values.first().children.first()) - } - } - } - - @Test - fun `nbsp is handled as code in java`() { - testInline( - """ - |/src/main/kotlin/sample/Parent.java - |package sample; - |/** - | * Hello World! Docs with period issue, e.g. this. - | */ - |public class Parent { - |} - """.trimIndent(), configuration - ) { - documentablesMergingStage = { - val classlike = it.packages.flatMap { it.classlikes }.find { it.name == "Parent" } - - assertTrue(classlike != null) - assertEquals(expectedDescription, classlike.documentation.values.first().children.first()) - } - } - } - - @Test - fun `same documentation in java and kotlin when nbsp is present`() { - testInline( - """ - |/src/main/kotlin/sample/Parent.java - |package sample; - |/** - | * Hello World! Docs with period issue, e.g. this. - | */ - |public class Parent { - |} - | - |/src/main/kotlin/sample/ParentKt.kt - |package sample; - |/** - | * Hello World! Docs with period issue, e.g. this. - | */ - |public class ParentKt { - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val java = module.packages.flatMap { it.classlikes }.first { it.name == "Parent" } - val kotlin = module.packages.flatMap { it.classlikes }.first { it.name == "ParentKt" } - - assertEquals(java.documentation.values.first(), kotlin.documentation.values.first()) - } - } - } - - @Test - fun `text surrounded by angle brackets is not removed`() { - testInline( - """ - |/src/main/kotlin/sample/Foo.kt - |package sample - |/** - | * My example `CodeInline<Bar>` - | * ``` - | * CodeBlock<Bar> - | * ``` - | */ - |class Foo { - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val cls = module.packages.flatMap { it.classlikes }.first { it.name == "Foo" } - val documentation = cls.documentation.values.first() - val docTags = documentation.children.single().root.children - - assertEquals("CodeInline<Bar>", ((docTags[0].children[1] as CodeInline).children.first() as Text).body) - assertEquals("CodeBlock<Bar>", ((docTags[1] as CodeBlock).children.first() as Text).body) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/content/HighlightingTest.kt b/plugins/base/src/test/kotlin/content/HighlightingTest.kt deleted file mode 100644 index a7fb2bde..00000000 --- a/plugins/base/src/test/kotlin/content/HighlightingTest.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 content - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.model.dfs -import org.jetbrains.dokka.pages.* -import kotlin.test.Test -import kotlin.test.assertTrue - -class HighlightingTest : BaseAbstractTest() { - private val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - classpath = listOf(commonStdlibPath!!, jvmStdlibPath!!) - externalDocumentationLinks = listOf(stdlibExternalDocumentationLink) - } - } - } - - @Test - fun `open suspend fun`() { - testInline( - """ - |/src/main/kotlin/test/Test.kt - |package example - | - | open suspend fun simpleFun(): String = "Celebrimbor" - """, - configuration - ) { - pagesTransformationStage = { module -> - val symbol = (module.dfs { it.name == "simpleFun" } as MemberPageNode).content - .dfs { it is ContentGroup && it.dci.kind == ContentKind.Symbol } - val children = symbol?.children - - for (it in listOf( - Pair(0, TokenStyle.Keyword), Pair(1, TokenStyle.Keyword), Pair(2, TokenStyle.Keyword), - Pair(4, TokenStyle.Punctuation), Pair(5, TokenStyle.Punctuation), Pair(6, TokenStyle.Operator) - )) - assertTrue(children?.get(it.first)?.style?.contains(it.second) == true) - assertTrue(children?.get(3)?.children?.first()?.style?.contains(TokenStyle.Function) == true) - } - } - } - - @Test - fun `plain typealias of plain class with annotation`() { - testInline( - """ - |/src/main/kotlin/common/Test.kt - |package example - | - |@MustBeDocumented - |@Target(AnnotationTarget.TYPEALIAS) - |annotation class SomeAnnotation - | - |@SomeAnnotation - |typealias PlainTypealias = Int - | - """.trimMargin(), - configuration - ) { - pagesTransformationStage = { module -> - val symbol = (module.dfs { it.name == "example" } as PackagePageNode).content - .dfs { it is ContentGroup && it.dci.kind == ContentKind.Symbol } - val children = symbol?.children - - for (it in listOf( - Pair(1, TokenStyle.Keyword), Pair(3, TokenStyle.Operator) - )) - assertTrue(children?.get(it.first)?.style?.contains(it.second) == true) - val annotation = children?.first()?.children?.first() - - assertTrue(annotation?.children?.get(0)?.style?.contains(TokenStyle.Annotation) == true) - assertTrue(annotation?.children?.get(1)?.children?.first()?.style?.contains(TokenStyle.Annotation) == true) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/content/annotations/ContentForAnnotationsTest.kt b/plugins/base/src/test/kotlin/content/annotations/ContentForAnnotationsTest.kt deleted file mode 100644 index 7293b53c..00000000 --- a/plugins/base/src/test/kotlin/content/annotations/ContentForAnnotationsTest.kt +++ /dev/null @@ -1,351 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package content.annotations - -import matchers.content.* -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.base.utils.firstNotNullOfOrNull -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.model.* -import org.jetbrains.dokka.pages.ContentPage -import org.jetbrains.dokka.pages.ContentText -import org.jetbrains.dokka.pages.MemberPageNode -import org.jetbrains.dokka.pages.PackagePageNode -import utils.ParamAttributes -import utils.assertNotNull -import utils.bareSignature -import utils.propertySignature -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertTrue - - -class ContentForAnnotationsTest : BaseAbstractTest() { - - - private val testConfiguration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - analysisPlatform = "jvm" - classpath += jvmStdlibPath!! - } - } - } - - @Test - fun `function with documented annotation`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, - | AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.EXPRESSION, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.FIELD - |) - |@Retention(AnnotationRetention.SOURCE) - |@MustBeDocumented - |annotation class Fancy - | - | - |@Fancy - |fun function(@Fancy abc: String): String { - | return "Hello, " + abc - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } - .children.single { it.name == "function" } as ContentPage - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - mapOf("Fancy" to emptySet()), - "", - "", - emptySet(), - "function", - "String", - "abc" to ParamAttributes(mapOf("Fancy" to emptySet()), emptySet(), "String") - ) - } - } - } - - } - } - } - } - - @Test - fun `function with undocumented annotation`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, - | AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.EXPRESSION, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.FIELD - |) - |@Retention(AnnotationRetention.SOURCE) - |annotation class Fancy - | - |@Fancy - |fun function(@Fancy abc: String): String { - | return "Hello, " + abc - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } - .children.single { it.name == "function" } as ContentPage - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - emptyMap(), - "", - "", - emptySet(), - "function", - "String", - "abc" to ParamAttributes(emptyMap(), emptySet(), "String") - ) - } - } - } - - } - } - } - } - - @Test - fun `property with undocumented annotation`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |@Suppress - |val property: Int = 6 - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } as PackagePageNode - page.content.assertNode { - propertySignature(emptyMap(), "", "", emptySet(), "val", "property", "Int", "6") - } - } - } - } - - @Test - fun `property with documented annotation`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |@MustBeDocumented - |annotation class Fancy - | - |@Fancy - |val property: Int = 6 - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } as PackagePageNode - page.content.assertNode { - propertySignature(mapOf("Fancy" to emptySet()), "", "", emptySet(), "val", "property", "Int", "6") - } - } - } - } - - - @Test - fun `rich documented annotation`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |@MustBeDocumented - |@Retention(AnnotationRetention.SOURCE) - |@Target(AnnotationTarget.PROPERTY) - |annotation class BugReport( - | val assignedTo: String = "[none]", - | val testCase: KClass<ABC> = ABC::class, - | val status: Status = Status.UNCONFIRMED, - | val ref: Reference = Reference(value = 1), - | val reportedBy: Array<Reference>, - | val showStopper: Boolean = false - | val previousReport: BugReport? - |) { - | enum class Status { - | UNCONFIRMED, CONFIRMED, FIXED, NOTABUG - | } - | class ABC - |} - |annotation class Reference(val value: Long) - |annotation class ReferenceReal(val value: Double) - | - | - |@BugReport( - | assignedTo = "me", - | testCase = BugReport.ABC::class, - | status = BugReport.Status.FIXED, - | ref = Reference(value = 2u), - | reportedBy = [Reference(value = 2UL), Reference(value = 4L), - | ReferenceReal(value = 4.9), ReferenceReal(value = 2f)], - | showStopper = true, - | previousReport = null - |) - |val ltint: Int = 5 - """.trimIndent(), testConfiguration - ) { - documentablesCreationStage = { modules -> - - fun expectedAnnotationValue(name: String, value: AnnotationParameterValue) = AnnotationValue(Annotations.Annotation( - dri = DRI("test", name), - params = mapOf("value" to value), - scope = Annotations.AnnotationScope.DIRECT, - mustBeDocumented = false - )) - val property = modules.flatMap { it.packages }.flatMap { it.properties }.first() - val annotation = property.extra[Annotations]?.let { - it.directAnnotations.entries.firstNotNullOfOrNull { (_, annotations) -> annotations.firstOrNull() } - } - val annotationParams = annotation?.params ?: emptyMap() - - assertEquals(expectedAnnotationValue("Reference", IntValue(2)), annotationParams["ref"]) - - val reportedByParam = ArrayValue(listOf( - expectedAnnotationValue("Reference", LongValue(2)), - expectedAnnotationValue("Reference", LongValue(4)), - expectedAnnotationValue("ReferenceReal", DoubleValue(4.9)), - expectedAnnotationValue("ReferenceReal", FloatValue(2f)) - )) - assertEquals(reportedByParam, annotationParams["reportedBy"]) - assertEquals(BooleanValue(true), annotationParams["showStopper"]) - assertEquals(NullValue, annotationParams["previousReport"]) - } - - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } as PackagePageNode - page.content.assertNode { - propertySignature( - mapOf( - "BugReport" to setOf( - "assignedTo", - "testCase", - "status", - "ref", - "reportedBy", - "showStopper", - "previousReport" - ) - ), "", "", emptySet(), "val", "ltint", "Int", "5" - ) - } - } - } - } - - @Test - fun `JvmName for property with setter and getter`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - |@get:JvmName("xd") - |@set:JvmName("asd") - |var property: String - | get() = "" - | set(value) {} - """.trimIndent(), testConfiguration - ) { - documentablesCreationStage = { modules -> - fun expectedAnnotation(name: String) = Annotations.Annotation( - dri = DRI("kotlin.jvm", "JvmName"), - params = mapOf("name" to StringValue(name)), - scope = Annotations.AnnotationScope.DIRECT, - mustBeDocumented = true - ) - - val property = modules.flatMap { it.packages }.flatMap { it.properties }.first() - val getterAnnotation = property.getter?.extra?.get(Annotations)?.let { - it.directAnnotations.entries.firstNotNullOfOrNull { (_, annotations) -> annotations.firstOrNull() } - } - val setterAnnotation = property.getter?.extra?.get(Annotations)?.let { - it.directAnnotations.entries.firstNotNullOfOrNull { (_, annotations) -> annotations.firstOrNull() } - } - - assertEquals(expectedAnnotation("xd"), getterAnnotation) - assertTrue(getterAnnotation?.mustBeDocumented!!) - assertEquals(Annotations.AnnotationScope.DIRECT, getterAnnotation.scope) - - assertEquals(expectedAnnotation("asd"), setterAnnotation) - assertTrue(setterAnnotation?.mustBeDocumented!!) - assertEquals(Annotations.AnnotationScope.DIRECT, setterAnnotation.scope) - } - } - } - - @Test - fun `annotated bounds in Kotlin`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |@MustBeDocumented - |@Target(AnnotationTarget.TYPE_PARAMETER) - |annotation class Hello(val bar: String) - |fun <T: @Hello("abc") String> foo(arg: String): List<T> = TODO() - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { root -> - val fooPage = root.dfs { it.name == "foo" } as MemberPageNode - fooPage.content.dfs { it is ContentText && it.text == "Hello" }.assertNotNull() - } - } - } - - @Test - fun `annotated bounds in Java`() { - testInline( - """ - |/src/main/java/demo/AnnotationTest.java - |package demo; - |import java.lang.annotation.*; - |import java.util.List; - |@Documented - |@Target({ElementType.TYPE_USE, ElementType.TYPE}) - |@interface Hello { - | public String bar() default ""; - |} - |public class AnnotationTest { - | public <T extends @Hello(bar = "baz") String> List<T> foo() { - | return null; - | } - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { root -> - val fooPage = root.dfs { it.name == "foo" } as MemberPageNode - fooPage.content.dfs { it is ContentText && it.text == "Hello" }.assertNotNull() - } - } - } -} diff --git a/plugins/base/src/test/kotlin/content/annotations/FileLevelJvmNameTest.kt b/plugins/base/src/test/kotlin/content/annotations/FileLevelJvmNameTest.kt deleted file mode 100644 index 5809d7df..00000000 --- a/plugins/base/src/test/kotlin/content/annotations/FileLevelJvmNameTest.kt +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package content.annotations - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.model.Annotations -import org.jetbrains.dokka.model.StringValue -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.ValueSource -import kotlin.test.assertEquals - -class FileLevelJvmNameTest : BaseAbstractTest() { - private val testConfiguration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - analysisPlatform = "jvm" - classpath += jvmStdlibPath!! - } - } - } - - companion object { - private const val functionTest = - """ - |/src/main/kotlin/test/source.kt - |@file:JvmName("CustomJvmName") - |package test - | - |fun function(abc: String): String { - | return "Hello, " + abc - |} - """ - - private const val extensionFunctionTest = - """ - |/src/main/kotlin/test/source.kt - |@file:JvmName("CustomJvmName") - |package test - | - |fun String.function(abc: String): String { - | return "Hello, " + abc - |} - """ - - private const val propertyTest = - """ - |/src/main/kotlin/test/source.kt - |@file:JvmName("CustomJvmName") - |package test - | - |val property: String - | get() = "" - """ - - private const val extensionPropertyTest = - """ - |/src/main/kotlin/test/source.kt - |@file:JvmName("CustomJvmName") - |package test - | - |val String.property: String - | get() = "" - """ - } - - @ParameterizedTest - @ValueSource(strings = [functionTest, extensionFunctionTest]) - fun `jvm name should be included in functions extra`(query: String) { - testInline( - query.trimIndent(), testConfiguration - ) { - documentablesCreationStage = { modules -> - val expectedAnnotation = Annotations.Annotation( - dri = DRI("kotlin.jvm", "JvmName"), - params = mapOf("name" to StringValue("CustomJvmName")), - scope = Annotations.AnnotationScope.FILE, - mustBeDocumented = true - ) - val function = modules.flatMap { it.packages }.first().functions.first() - val annotation = function.extra[Annotations]?.fileLevelAnnotations?.entries?.first()?.value?.single() - assertEquals(emptyMap(), function.extra[Annotations]?.directAnnotations) - assertEquals(expectedAnnotation, annotation) - assertEquals(expectedAnnotation.scope, annotation?.scope) - assertEquals(expectedAnnotation.mustBeDocumented, annotation?.mustBeDocumented) - } - } - } - - @ParameterizedTest - @ValueSource(strings = [propertyTest, extensionPropertyTest]) - fun `jvm name should be included in properties extra`(query: String) { - testInline( - query.trimIndent(), testConfiguration - ) { - documentablesCreationStage = { modules -> - val expectedAnnotation = Annotations.Annotation( - dri = DRI("kotlin.jvm", "JvmName"), - params = mapOf("name" to StringValue("CustomJvmName")), - scope = Annotations.AnnotationScope.FILE, - mustBeDocumented = true - ) - val properties = modules.flatMap { it.packages }.first().properties.first() - val annotation = properties.extra[Annotations]?.fileLevelAnnotations?.entries?.first()?.value?.single() - assertEquals(emptyMap(), properties.extra[Annotations]?.directAnnotations) - assertEquals(expectedAnnotation, annotation) - assertEquals(expectedAnnotation.scope, annotation?.scope) - assertEquals(expectedAnnotation.mustBeDocumented, annotation?.mustBeDocumented) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/content/annotations/JavaDeprecatedTest.kt b/plugins/base/src/test/kotlin/content/annotations/JavaDeprecatedTest.kt deleted file mode 100644 index 5a2ff93e..00000000 --- a/plugins/base/src/test/kotlin/content/annotations/JavaDeprecatedTest.kt +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package content.annotations - -import matchers.content.* -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.base.transformers.documentables.deprecatedAnnotation -import org.jetbrains.dokka.base.transformers.documentables.isDeprecated -import org.jetbrains.dokka.model.Documentable -import org.jetbrains.dokka.model.properties.WithExtraProperties -import org.jetbrains.dokka.pages.ContentPage -import org.jetbrains.dokka.pages.ContentStyle -import utils.pWrapped -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertNotNull -import kotlin.test.assertTrue - -class JavaDeprecatedTest : BaseAbstractTest() { - - private val testConfiguration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - analysisPlatform = "jvm" - } - } - } - - @Test - @Suppress("UNCHECKED_CAST") - fun `should assert util functions for deprecation`() { - testInline( - """ - |/src/main/kotlin/deprecated/DeprecatedJavaClass.java - |package deprecated - | - |@Deprecated(forRemoval = true) - |public class DeprecatedJavaClass {} - """.trimIndent(), - testConfiguration - ) { - documentablesTransformationStage = { module -> - val deprecatedClass = module.children - .single { it.name == "deprecated" }.children - .single { it.name == "DeprecatedJavaClass" } - - val isDeprecated = (deprecatedClass as WithExtraProperties<out Documentable>).isDeprecated() - assertTrue(isDeprecated) - - val deprecatedAnnotation = (deprecatedClass as WithExtraProperties<out Documentable>).deprecatedAnnotation - assertNotNull(deprecatedAnnotation) - - assertTrue(deprecatedAnnotation.isDeprecated()) - assertEquals("java.lang", deprecatedAnnotation.dri.packageName) - assertEquals("Deprecated", deprecatedAnnotation.dri.classNames) - } - } - } - - @Test - fun `should change deprecated header if marked for removal`() { - testInline( - """ - |/src/main/kotlin/deprecated/DeprecatedJavaClass.java - |package deprecated - | - |/** - | * Average function description - | */ - |@Deprecated(forRemoval = true) - |public class DeprecatedJavaClass {} - """.trimIndent(), - testConfiguration - ) { - pagesTransformationStage = { module -> - val deprecatedJavaClass = module.children - .single { it.name == "deprecated" }.children - .single { it.name == "DeprecatedJavaClass" } as ContentPage - - deprecatedJavaClass.content.assertNode { - group { - header(1) { +"DeprecatedJavaClass" } - platformHinted { - skipAllNotMatching() - group { - header(3) { - +"Deprecated (for removal)" - } - } - group { pWrapped("Average function description") } - } - } - skipAllNotMatching() - } - } - } - } - - @Test - fun `should add footnote for 'since' param`() { - testInline( - """ - |/src/main/kotlin/deprecated/DeprecatedJavaClass.java - |package deprecated - | - |/** - | * Average function description - | */ - |@Deprecated(since = "11") - |public class DeprecatedJavaClass {} - """.trimIndent(), - testConfiguration - ) { - pagesTransformationStage = { module -> - val deprecatedJavaClass = module.children - .single { it.name == "deprecated" }.children - .single { it.name == "DeprecatedJavaClass" } as ContentPage - - deprecatedJavaClass.content.assertNode { - group { - header(1) { +"DeprecatedJavaClass" } - platformHinted { - skipAllNotMatching() - group { - header(3) { - +"Deprecated" - } - group { - check { assertEquals(ContentStyle.Footnote, this.style.firstOrNull()) } - +"Since version 11" - } - } - group { pWrapped("Average function description") } - } - } - skipAllNotMatching() - } - } - } - } -} diff --git a/plugins/base/src/test/kotlin/content/annotations/KotlinDeprecatedTest.kt b/plugins/base/src/test/kotlin/content/annotations/KotlinDeprecatedTest.kt deleted file mode 100644 index 7612aff8..00000000 --- a/plugins/base/src/test/kotlin/content/annotations/KotlinDeprecatedTest.kt +++ /dev/null @@ -1,401 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package content.annotations - -import matchers.content.* -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.base.transformers.documentables.deprecatedAnnotation -import org.jetbrains.dokka.base.transformers.documentables.isDeprecated -import org.jetbrains.dokka.model.Documentable -import org.jetbrains.dokka.model.properties.WithExtraProperties -import org.jetbrains.dokka.pages.ContentPage -import org.jetbrains.dokka.pages.ContentStyle -import utils.ParamAttributes -import utils.bareSignature -import utils.pWrapped -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertNotNull -import kotlin.test.assertTrue - - -class KotlinDeprecatedTest : BaseAbstractTest() { - - private val testConfiguration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - classpath = listOfNotNull(jvmStdlibPath) - analysisPlatform = "jvm" - } - } - } - - @Test - @Suppress("UNCHECKED_CAST") - fun `should assert util functions for deprecation`() { - testInline( - """ - |/src/main/kotlin/kotlin/KotlinFile.kt - |package deprecated - | - |@Deprecated( - | message = "Fancy message" - |) - |fun simpleFunction() {} - """.trimIndent(), - testConfiguration - ) { - documentablesTransformationStage = { module -> - val deprecatedFunction = module.children - .single { it.name == "deprecated" }.children - .single { it.name == "simpleFunction" } - - val isDeprecated = (deprecatedFunction as WithExtraProperties<out Documentable>).isDeprecated() - assertTrue(isDeprecated) - - val deprecatedAnnotation = (deprecatedFunction as WithExtraProperties<out Documentable>).deprecatedAnnotation - assertNotNull(deprecatedAnnotation) - - assertTrue(deprecatedAnnotation.isDeprecated()) - assertEquals("kotlin", deprecatedAnnotation.dri.packageName) - assertEquals("Deprecated", deprecatedAnnotation.dri.classNames) - } - } - } - - @Test - fun `should change header if deprecation level is not default`() { - testInline( - """ - |/src/main/kotlin/kotlin/DeprecatedKotlin.kt - |package deprecated - | - |/** - | * Average function description - | */ - |@Deprecated( - | message = "Reason for deprecation bla bla", - | level = DeprecationLevel.ERROR - |) - |fun oldLegacyFunction(typedParam: SomeOldType, someLiteral: String): String {} - | - |fun newShinyFunction(typedParam: SomeOldType, someLiteral: String, newTypedParam: SomeNewType): String {} - |class SomeOldType {} - |class SomeNewType {} - """.trimIndent(), - testConfiguration - ) { - pagesTransformationStage = { module -> - val functionWithDeprecatedFunction = module.children - .single { it.name == "deprecated" }.children - .single { it.name == "oldLegacyFunction" } as ContentPage - - functionWithDeprecatedFunction.content.assertNode { - group { - header(1) { +"oldLegacyFunction" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - annotations = emptyMap(), - visibility = "", - modifier = "", - keywords = emptySet(), - name = "oldLegacyFunction", - returnType = "String", - params = arrayOf( - "typedParam" to ParamAttributes(emptyMap(), emptySet(), "SomeOldType"), - "someLiteral" to ParamAttributes(emptyMap(), emptySet(), "String"), - ) - ) - } - after { - group { - header(3) { - +"Deprecated (with error)" - } - p { - +"Reason for deprecation bla bla" - } - } - group { pWrapped("Average function description") } - } - } - } - } - } - } - } - - @Test - fun `should display repalceWith param with imports as code blocks`() { - testInline( - """ - |/src/main/kotlin/kotlin/DeprecatedKotlin.kt - |package deprecated - | - |/** - | * Average function description - | */ - |@Deprecated( - | message = "Reason for deprecation bla bla", - | replaceWith = ReplaceWith( - | "newShinyFunction(typedParam, someLiteral, SomeNewType())", - | imports = [ - | "com.example.dokka.debug.newShinyFunction", - | "com.example.dokka.debug.SomeOldType", - | "com.example.dokka.debug.SomeNewType", - | ] - | ), - |) - |fun oldLegacyFunction(typedParam: SomeOldType, someLiteral: String): String {} - | - |fun newShinyFunction(typedParam: SomeOldType, someLiteral: String, newTypedParam: SomeNewType): String {} - |class SomeOldType {} - |class SomeNewType {} - """.trimIndent(), - testConfiguration - ) { - pagesTransformationStage = { module -> - val functionWithDeprecatedFunction = module.children - .single { it.name == "deprecated" }.children - .single { it.name == "oldLegacyFunction" } as ContentPage - - functionWithDeprecatedFunction.content.assertNode { - group { - header(1) { +"oldLegacyFunction" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - annotations = emptyMap(), - visibility = "", - modifier = "", - keywords = emptySet(), - name = "oldLegacyFunction", - returnType = "String", - params = arrayOf( - "typedParam" to ParamAttributes(emptyMap(), emptySet(), "SomeOldType"), - "someLiteral" to ParamAttributes(emptyMap(), emptySet(), "String"), - ) - ) - } - after { - group { - header(3) { - +"Deprecated" - } - p { - +"Reason for deprecation bla bla" - } - - header(4) { - +"Replace with" - } - codeBlock { - +"import com.example.dokka.debug.newShinyFunction" - br() - +"import com.example.dokka.debug.SomeOldType" - br() - +"import com.example.dokka.debug.SomeNewType" - br() - } - codeBlock { - +"newShinyFunction(typedParam, someLiteral, SomeNewType())" - } - } - group { pWrapped("Average function description") } - } - } - } - } - } - } - } - - @Test - fun `should add footnote for DeprecatedSinceKotlin annotation`() { - testInline( - """ - |/src/main/kotlin/kotlin/DeprecatedKotlin.kt - |package deprecated - | - |/** - | * Average function description - | */ - |@DeprecatedSinceKotlin( - | warningSince = "1.4", - | errorSince = "1.5", - | hiddenSince = "1.6" - |) - |@Deprecated( - | message = "Deprecation reason bla bla" - |) - |fun oldLegacyFunction(typedParam: SomeOldType, someLiteral: String): String {} - | - |fun newShinyFunction(typedParam: SomeOldType, someLiteral: String, newTypedParam: SomeNewType): String {} - |class SomeOldType {} - |class SomeNewType {} - """.trimIndent(), - testConfiguration - ) { - pagesTransformationStage = { module -> - val functionWithDeprecatedFunction = module.children - .single { it.name == "deprecated" }.children - .single { it.name == "oldLegacyFunction" } as ContentPage - - functionWithDeprecatedFunction.content.assertNode { - group { - header(1) { +"oldLegacyFunction" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - annotations = emptyMap(), - visibility = "", - modifier = "", - keywords = emptySet(), - name = "oldLegacyFunction", - returnType = "String", - params = arrayOf( - "typedParam" to ParamAttributes(emptyMap(), emptySet(), "SomeOldType"), - "someLiteral" to ParamAttributes(emptyMap(), emptySet(), "String"), - ) - ) - } - after { - group { - header(3) { - +"Deprecated" - } - group { - check { assertEquals(ContentStyle.Footnote, this.style.firstOrNull()) } - p { - +"Warning since 1.4" - } - p { - +"Error since 1.5" - } - p { - +"Hidden since 1.6" - } - } - p { - +"Deprecation reason bla bla" - } - } - group { pWrapped("Average function description") } - } - } - } - } - } - } - } - - @Test - fun `should generate deprecation block with all parameters present and long description`() { - testInline( - """ - |/src/main/kotlin/kotlin/DeprecatedKotlin.kt - |package deprecated - | - |/** - | * Average function description - | */ - |@Deprecated( - | message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas vel vulputate risus. " + - | "Etiam dictum odio vel vulputate auctor.Nulla facilisi. Duis ullamcorper ullamcorper lectus " + - | "nec rutrum. Quisque eu risus eu purus bibendum ultricies. Maecenas tincidunt dui in sodales " + - | "faucibus. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin id sem felis. " + - | "Praesent et libero lacinia, egestas libero in, ultrices lectus. Suspendisse eget volutpat " + - | "velit. Phasellus laoreet mi eu egestas mattis.", - | replaceWith = ReplaceWith( - | "newShinyFunction(typedParam, someLiteral, SomeNewType())", - | imports = [ - | "com.example.dokka.debug.newShinyFunction", - | "com.example.dokka.debug.SomeOldType", - | "com.example.dokka.debug.SomeNewType", - | ] - | ), - | level = DeprecationLevel.ERROR - |) - |fun oldLegacyFunction(typedParam: SomeOldType, someLiteral: String): String {} - | - |fun newShinyFunction(typedParam: SomeOldType, someLiteral: String, newTypedParam: SomeNewType): String {} - |class SomeOldType {} - |class SomeNewType {} - """.trimIndent(), - testConfiguration - ) { - pagesTransformationStage = { module -> - val functionWithDeprecatedFunction = module.children - .single { it.name == "deprecated" }.children - .single { it.name == "oldLegacyFunction" } as ContentPage - - functionWithDeprecatedFunction.content.assertNode { - group { - header(1) { +"oldLegacyFunction" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - annotations = emptyMap(), - visibility = "", - modifier = "", - keywords = emptySet(), - name = "oldLegacyFunction", - returnType = "String", - params = arrayOf( - "typedParam" to ParamAttributes(emptyMap(), emptySet(), "SomeOldType"), - "someLiteral" to ParamAttributes(emptyMap(), emptySet(), "String"), - ) - ) - } - after { - group { - header(3) { - +"Deprecated (with error)" - } - p { - +("Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + - "Maecenas vel vulputate risus. Etiam dictum odio vel " + - "vulputate auctor.Nulla facilisi. Duis ullamcorper " + - "ullamcorper lectus nec rutrum. Quisque eu risus eu " + - "purus bibendum ultricies. Maecenas tincidunt dui in sodales faucibus. " + - "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + - "Proin id sem felis. Praesent et libero lacinia, egestas " + - "libero in, ultrices lectus. Suspendisse eget volutpat velit. " + - "Phasellus laoreet mi eu egestas mattis.") - } - header(4) { - +"Replace with" - } - codeBlock { - +"import com.example.dokka.debug.newShinyFunction" - br() - +"import com.example.dokka.debug.SomeOldType" - br() - +"import com.example.dokka.debug.SomeNewType" - br() - } - codeBlock { - +"newShinyFunction(typedParam, someLiteral, SomeNewType())" - } - } - group { pWrapped("Average function description") } - } - } - } - } - } - } - } -} diff --git a/plugins/base/src/test/kotlin/content/annotations/SinceKotlinTest.kt b/plugins/base/src/test/kotlin/content/annotations/SinceKotlinTest.kt deleted file mode 100644 index 6ee95bbd..00000000 --- a/plugins/base/src/test/kotlin/content/annotations/SinceKotlinTest.kt +++ /dev/null @@ -1,350 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package content.annotations - -import matchers.content.* -import org.jetbrains.dokka.Platform -import org.jetbrains.dokka.base.transformers.pages.annotations.SinceKotlinTransformer -import org.jetbrains.dokka.base.transformers.pages.annotations.SinceKotlinVersion -import org.jetbrains.dokka.model.DFunction -import org.jetbrains.dokka.model.dfs -import org.jetbrains.dokka.model.doc.CustomTagWrapper -import org.jetbrains.dokka.model.doc.Text -import org.jetbrains.dokka.pages.ContentPage -import signatures.AbstractRenderingTest -import utils.* -import kotlin.test.* - - -class SinceKotlinTest : AbstractRenderingTest() { - - val testConfiguration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - classpath = listOfNotNull(jvmStdlibPath) - analysisPlatform = "jvm" - } - } - } - - @BeforeTest - fun setSystemProperty() { - System.setProperty(SinceKotlinTransformer.SHOULD_DISPLAY_SINCE_KOTLIN_SYS_PROP, "true") - } - @AfterTest - fun clearSystemProperty() { - System.clearProperty(SinceKotlinTransformer.SHOULD_DISPLAY_SINCE_KOTLIN_SYS_PROP) - } - - @Test - fun versionsComparing() { - assertTrue(SinceKotlinVersion("1.0").compareTo(SinceKotlinVersion("1.0")) == 0) - assertTrue(SinceKotlinVersion("1.0.0").compareTo(SinceKotlinVersion("1")) == 0) - assertTrue(SinceKotlinVersion("1.0") >= SinceKotlinVersion("1.0")) - assertTrue(SinceKotlinVersion("1.1") > SinceKotlinVersion("1")) - assertTrue(SinceKotlinVersion("1.0") < SinceKotlinVersion("2.0")) - assertTrue(SinceKotlinVersion("1.0") < SinceKotlinVersion("2.2")) - } - - @Test - fun `rendered SinceKotlin custom tag for typealias, extensions, functions, properties`() { - val writerPlugin = TestOutputWriterPlugin() - - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |@SinceKotlin("1.5") - |fun ring(abc: String): String { - | return "My precious " + abc - |} - |@SinceKotlin("1.5") - |fun String.extension(abc: String): String { - | return "My precious " + abc - |} - |@SinceKotlin("1.5") - |typealias Str = String - |@SinceKotlin("1.5") - |val str = "str" - """.trimIndent(), - testConfiguration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val content = writerPlugin.renderedContent("root/test/index.html") - assertEquals(4, content.getElementsContainingOwnText("Since Kotlin").count()) - } - } - } - - @Test - fun `should propagate SinceKotlin`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |@SinceKotlin("1.5") - |class A { - | fun ring(abc: String): String { - | return "My precious " + abc - | } - |} - """.trimIndent(), testConfiguration - ) { - documentablesTransformationStage = { module -> - @Suppress("UNCHECKED_CAST") val funcs = module.children.single { it.name == "test" } - .children.single { it.name == "A" } - .children.filter { it.name == "ring" && it is DFunction } as List<DFunction> - with(funcs) { - val sinceKotlin = mapOf( - Platform.jvm to SinceKotlinVersion("1.5"), - ) - - for(i in sinceKotlin) { - val tag = - find { it.sourceSets.first().analysisPlatform == i.key }?.documentation?.values?.first() - ?.dfs { it is CustomTagWrapper && it.name == "Since Kotlin" } - .assertNotNull("SinceKotlin[${i.key}]") - assertEquals((tag.children.first() as Text).body, i.value.toString()) - } - } - } - } - } - - @Test - fun `mpp fun without SinceKotlin annotation`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/jvm/") - analysisPlatform = "jvm" - } - sourceSet { - sourceRoots = listOf("src/native/") - analysisPlatform = "native" - name = "native" - } - sourceSet { - sourceRoots = listOf("src/common/") - analysisPlatform = "common" - name = "common" - } - sourceSet { - sourceRoots = listOf("src/js/") - analysisPlatform = "js" - name = "js" - } - sourceSet { - sourceRoots = listOf("src/wasm/") - analysisPlatform = "wasm" - name = "wasm" - } - } - } - testInline( - """ - |/src/jvm/kotlin/test/source.kt - |package test - | - |fun ring(abc: String): String { - | return "My precious " + abc - |} - |/src/native/kotlin/test/source.kt - |package test - | - |fun ring(abc: String): String { - | return "My precious " + abc - |} - |/src/common/kotlin/test/source.kt - |package test - | - |fun ring(abc: String): String { - | return "My precious " + abc - |} - |/src/js/kotlin/test/source.kt - |package test - | - |fun ring(abc: String): String { - | return "My precious " + abc - |} - |/src/wasm/kotlin/test/source.kt - |package test - | - |fun ring(abc: String): String { - | return "My precious " + abc - |} - """.trimIndent(), configuration - ) { - documentablesTransformationStage = { module -> - @Suppress("UNCHECKED_CAST") val funcs = module.children.single { it.name == "test" } - .children.filter { it.name == "ring" && it is DFunction } as List<DFunction> - with(funcs) { - val sinceKotlin = 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"), - ) - - for(i in sinceKotlin) { - val tag = - find { it.sourceSets.first().analysisPlatform == i.key }?.documentation?.values?.first() - ?.dfs { it is CustomTagWrapper && it.name == "Since Kotlin" } - .assertNotNull("SinceKotlin[${i.key}]") - assertEquals((tag.children.first() as Text).body, i.value.toString()) - } - } - } - } - } - - @Test - fun `mpp fun with SinceKotlin annotation`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/jvm/") - classpath = listOfNotNull(jvmStdlibPath) - analysisPlatform = "jvm" - } - sourceSet { - sourceRoots = listOf("src/native/") - analysisPlatform = "native" - name = "native" - } - sourceSet { - sourceRoots = listOf("src/common/") - classpath = listOfNotNull(commonStdlibPath) - analysisPlatform = "common" - name = "common" - } - sourceSet { - sourceRoots = listOf("src/js/") - classpath = listOfNotNull(jsStdlibPath) - analysisPlatform = "js" - name = "js" - } - sourceSet { - sourceRoots = listOf("src/wasm/") - analysisPlatform = "wasm" - name = "wasm" - } - } - } - testInline( - """ - |/src/jvm/kotlin/test/source.kt - |package test - | - |/** dssdd */ - |@SinceKotlin("1.3") - |fun ring(abc: String): String { - | return "My precious " + abc - |} - |/src/native/kotlin/test/source.kt - |package test - | - |/** dssdd */ - |@SinceKotlin("1.3") - |fun ring(abc: String): String { - | return "My precious " + abc - |} - |/src/common/kotlin/test/source.kt - |package test - | - |/** dssdd */ - |@SinceKotlin("1.3") - |fun ring(abc: String): String { - | return "My precious " + abc - |} - |/src/js/kotlin/test/source.kt - |package test - | - |/** dssdd */ - |@SinceKotlin("1.3") - |fun ring(abc: String): String { - | return "My precious " + abc - |} - |/src/wasm/kotlin/test/source.kt - |package test - | - |/** dssdd */ - |@SinceKotlin("1.3") - |fun ring(abc: String): String { - | return "My precious " + abc - |} - """.trimIndent(), configuration - ) { - documentablesTransformationStage = { module -> - @Suppress("UNCHECKED_CAST") val funcs = module.children.single { it.name == "test" } - .children.filter { it.name == "ring" && it is DFunction } as List<DFunction> - with(funcs) { - val sinceKotlin = mapOf( - Platform.common to SinceKotlinVersion("1.3"), - Platform.jvm to SinceKotlinVersion("1.3"), - Platform.js to SinceKotlinVersion("1.3"), - Platform.native to SinceKotlinVersion("1.3"), - Platform.wasm to SinceKotlinVersion("1.8"), - ) - - for(i in sinceKotlin) { - val tag = - find { it.sourceSets.first().analysisPlatform == i.key }?.documentation?.values?.first() - ?.dfs { it is CustomTagWrapper && it.name == "Since Kotlin" } - .assertNotNull("SinceKotlin[${i.key}]") - assertEquals(i.value.toString(), (tag.children.first() as Text).body , "Platform ${i.key}") - } - } - } - } - } - - @Test - fun `should do not render since kotlin tag when flag is unset`() { - clearSystemProperty() - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |@SinceKotlin("1.3") - |fun ring(abc: String): String { - | return "My precious " + abc - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } - .children.single { it.name == "ring" } as ContentPage - page.content.assertNode { - group { - header(1) { +"ring" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - emptyMap(), - "", - "", - emptySet(), - "ring", - "String", - "abc" to ParamAttributes(emptyMap(), emptySet(), "String") - ) - } - } - } - - } - } - } - } -} diff --git a/plugins/base/src/test/kotlin/content/exceptions/ContentForExceptions.kt b/plugins/base/src/test/kotlin/content/exceptions/ContentForExceptions.kt deleted file mode 100644 index 22becb93..00000000 --- a/plugins/base/src/test/kotlin/content/exceptions/ContentForExceptions.kt +++ /dev/null @@ -1,439 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package content.exceptions - -import matchers.content.* -import org.jetbrains.dokka.DokkaConfiguration -import org.jetbrains.dokka.PluginConfigurationImpl -import org.jetbrains.dokka.base.DokkaBase -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.model.DisplaySourceSet -import utils.* -import kotlin.test.Test -import kotlin.test.assertEquals - -class ContentForExceptions : BaseAbstractTest() { - private val testConfiguration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - classpath = listOfNotNull(jvmStdlibPath) - analysisPlatform = "jvm" - } - } - } - - private val mppTestConfiguration = dokkaConfiguration { - moduleName = "example" - sourceSets { - val common = sourceSet { - name = "common" - displayName = "common" - analysisPlatform = "common" - sourceRoots = listOf("src/commonMain/kotlin/pageMerger/Test.kt") - classpath = listOfNotNull(commonStdlibPath) - } - sourceSet { - name = "jvm" - displayName = "jvm" - analysisPlatform = "jvm" - dependentSourceSets = setOf(common.value.sourceSetID) - sourceRoots = listOf("src/jvmMain/kotlin/pageMerger/Test.kt") - classpath = listOfNotNull(jvmStdlibPath) - } - sourceSet { - name = "linuxX64" - displayName = "linuxX64" - analysisPlatform = "native" - dependentSourceSets = setOf(common.value.sourceSetID) - sourceRoots = listOf("src/linuxX64Main/kotlin/pageMerger/Test.kt") - } - } - pluginsConfigurations.add( - PluginConfigurationImpl( - DokkaBase::class.qualifiedName!!, - DokkaConfiguration.SerializationFormat.JSON, - """{ "mergeImplicitExpectActualDeclarations": true }""", - ) - ) - } - - @OnlyDescriptors("Fixed in 1.9.20 (IMPORT STAR)") - @Test - fun `function with navigatable thrown exception`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |/** - |* @throws Exception - |*/ - |fun function(abc: String) { - | println(abc) - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("test", "function") - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - emptyMap(), - "", - "", - emptySet(), - "function", - null, - "abc" to ParamAttributes(emptyMap(), emptySet(), "String") - ) - } - after { - header(4) { +"Throws" } - table { - group { - group { - link { +"Exception" } - } - } - } - } - } - } - } - } - } - } - - @Test - fun `function with non-navigatable thrown exception`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |/** - |* @throws UnavailableException - |*/ - |fun function(abc: String) { - | println(abc) - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("test", "function") - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - emptyMap(), - "", - "", - emptySet(), - "function", - null, - "abc" to ParamAttributes(emptyMap(), emptySet(), "String") - ) - } - after { - header(4) { +"Throws" } - table { - group { - group { - +"UnavailableException" - } - } - } - } - } - } - } - } - } - } - - @Test - fun `multiplatofrm class with throws`() { - testInline( - """ - |/src/commonMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |/** - |* @throws CommonException - |*/ - |expect open class Parent - | - |/src/jvmMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |/** - |* @throws JvmException - |*/ - |actual open class Parent - | - |/src/linuxX64Main/kotlin/pageMerger/Test.kt - |package pageMerger - | - |/** - |* @throws LinuxException - |*/ - |actual open class Parent - | - """.trimMargin(), - mppTestConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("pageMerger", "Parent") - page.content.assertNode { - group { - header(1) { +"Parent" } - platformHinted { - group { - +"expect open class " - link { - +"Parent" - } - } - group { - +"actual open class " - link { - +"Parent" - } - } - group { - +"actual open class " - link { - +"Parent" - } - } - header(4) { +"Throws" } - table { - group { - group { - +"CommonException" - } - check { - assertEquals(1, sourceSets.size) - assertEquals( - "common", - this.sourceSets.first().name - ) - } - } - group { - group { - +"JvmException" - } - check { - sourceSets.assertSourceSet("jvm") - } - } - group { - group { - +"LinuxException" - } - check { - sourceSets.assertSourceSet("linuxX64") - } - } - } - } - } - skipAllNotMatching() - } - } - } - } - - @Test - fun `multiplatofrm class with throws in few platforms`() { - testInline( - """ - |/src/commonMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |/** - |* @throws CommonException - |*/ - |expect open class Parent - | - |/src/jvmMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |/** - |* @throws JvmException - |*/ - |actual open class Parent - | - |/src/linuxX64Main/kotlin/pageMerger/Test.kt - |package pageMerger - | - |actual open class Parent - | - """.trimMargin(), - mppTestConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("pageMerger", "Parent") - page.content.assertNode { - group { - header(1) { +"Parent" } - platformHinted { - group { - +"expect open class " - link { - +"Parent" - } - } - group { - +"actual open class " - link { - +"Parent" - } - } - group { - +"actual open class " - link { - +"Parent" - } - } - header(4) { +"Throws" } - table { - group { - group { - +"CommonException" - } - check { - sourceSets.assertSourceSet("common") - } - } - group { - group { - +"JvmException" - } - check { - sourceSets.assertSourceSet("jvm") - } - } - check { - assertEquals(2, sourceSets.size) - } - } - } - } - skipAllNotMatching() - } - } - } - } - - @Test - fun `throws in merged functions`() { - testInline( - """ - |/src/linuxX64Main/kotlin/pageMerger/Test.kt - |package pageMerger - | - |/** - |* @throws LinuxException - |*/ - |fun function() { - | println() - |} - | - |/src/jvmMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |/** - |* @throws JvmException - |*/ - |fun function() { - | println() - |} - | - """.trimMargin(), - mppTestConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("pageMerger", "function") - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - emptyMap(), - "", - "", - emptySet(), - "function", - null, - ) - } - after { - header(4) { +"Throws" } - table { - group { - group { - +"JvmException" - } - } - check { - sourceSets.assertSourceSet("jvm") - } - } - } - check { - sourceSets.assertSourceSet("jvm") - } - } - divergentInstance { - divergent { - bareSignature( - emptyMap(), - "", - "", - emptySet(), - "function", - null, - ) - } - after { - header(4) { +"Throws" } - table { - group { - group { - +"LinuxException" - } - } - } - } - check { - sourceSets.assertSourceSet("linuxX64") - } - } - } - } - } - } - } -} - -private fun Set<DisplaySourceSet>.assertSourceSet(expectedName: String) { - assertEquals(1, this.size) - assertEquals(expectedName, this.first().name) -} diff --git a/plugins/base/src/test/kotlin/content/functions/ContentForBriefTest.kt b/plugins/base/src/test/kotlin/content/functions/ContentForBriefTest.kt deleted file mode 100644 index d93a6c27..00000000 --- a/plugins/base/src/test/kotlin/content/functions/ContentForBriefTest.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 content.functions - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.links.TypeConstructor -import org.jetbrains.dokka.model.DClass -import org.jetbrains.dokka.model.DPackage -import org.jetbrains.dokka.model.dfs -import org.jetbrains.dokka.pages.* -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertNotNull -import kotlin.test.assertNull - - -class ContentForBriefTest : BaseAbstractTest() { - private val testConfiguration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - analysisPlatform = "jvm" - } - } - } - - private val codeWithSecondaryAndPrimaryConstructorsDocumented = - """ - |/src/main/kotlin/test/source.kt - |package test - | - |/** - | * Dummy text. - | * - | * @constructor constructor docs - | * @param exampleParameter dummy parameter. - | */ - |class Example(val exampleParameter: Int) { - | - | /** - | * secondary constructor - | * @param param1 param1 docs - | */ - | constructor(param1: String) : this(1) - |} - """.trimIndent() - - private val codeWithDocumentedParameter = - """ - |/src/main/kotlin/test/source.kt - |package test - | - |/** - | * Dummy text. - | * - | * @param exampleParameter dummy parameter. - | */ - |class Example(val exampleParameter: Int) { - |} - """.trimIndent() - - - @Test - fun `primary constructor should not inherit docs from its parameter`() { - testInline(codeWithSecondaryAndPrimaryConstructorsDocumented, testConfiguration) { - pagesTransformationStage = { module -> - val classPage = module.findClassPage("Example") - - val constructorsWithBriefs = classPage.findConstructorsWithBriefs() - val constructorDocs = constructorsWithBriefs.findConstructorDocs { - it.callable?.params?.first() == TypeConstructor("kotlin.Int", emptyList()) - } - - assertEquals("constructor docs", constructorDocs.text) - } - } - } - - @Test - fun `secondary constructor should not inherit docs from its parameter`() { - testInline(codeWithSecondaryAndPrimaryConstructorsDocumented, testConfiguration) { - pagesTransformationStage = { module -> - val classPage = module.findClassPage("Example") - - val constructorsWithBriefs = classPage.findConstructorsWithBriefs() - val constructorDocs = constructorsWithBriefs.findConstructorDocs { - it.callable?.params?.first() == TypeConstructor("kotlin.String", emptyList()) - } - - assertEquals("secondary constructor", constructorDocs.text) - } - } - } - - /** - * All constructors are merged in one block (like overloaded functions). - * That leads to the structure where content block (`constructorsWithBriefs`) consist of plain list - * of constructors and briefs. In that list constructor is above, brief is below. - */ - private fun ContentPage.findConstructorsWithBriefs(): List<ContentNode> { - val constructorsTable = this.content.dfs { - it is ContentTable && it.dci.kind == ContentKind.Constructors - } as ContentTable - - val constructorsWithBriefs = constructorsTable.dfs { - it is ContentGroup && it.dci.kind == ContentKind.SourceSetDependentHint - }?.children - assertNotNull(constructorsWithBriefs, "Content node with constructors and briefs is not found") - - return constructorsWithBriefs - } - - private fun List<ContentNode>.findConstructorDocs(constructorMatcher: (DRI) -> Boolean): ContentText { - val constructorIndex = this.indexOfFirst { constructorMatcher(it.dci.dri.first()) } - return this[constructorIndex + 1] // expect that the relevant comment is below the constructor - .dfs { it is ContentText && it.dci.kind == ContentKind.Comment } as ContentText - } - - @Test - fun `primary constructor should not inherit docs from its parameter when no specific docs are provided`() { - testInline(codeWithDocumentedParameter, testConfiguration) { - pagesTransformationStage = { module -> - val classPage = module.findClassPage("Example") - val constructorsTable = - classPage.content.dfs { it is ContentTable && it.dci.kind == ContentKind.Constructors } as ContentTable - - assertEquals(1, constructorsTable.children.size) - val primary = constructorsTable.children.first() - val primaryConstructorDocs = primary.dfs { it is ContentText && it.dci.kind == ContentKind.Comment } - - assertNull(primaryConstructorDocs, "Expected no primary constructor docs to be present") - } - } - } - - @Test - fun `brief should work for typealias`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |/** - |* This is an example <!-- not visible --> of html - |* - |* This is definitely not a brief - |*/ - |typealias A = Int - """.trimIndent(), - testConfiguration - ) { - pagesTransformationStage = { module -> - val functionBriefDocs = module.singleTypeAliasesDescription("test") - - assertEquals( - "This is an example <!-- not visible --> of html", - functionBriefDocs.children.joinToString("") { (it as ContentText).text }) - } - } - } - - @Test - fun `brief for functions should work with html`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |class Example(val exampleParameter: Int) { - | /** - | * This is an example <!-- not visible --> of html - | * - | * This is definitely not a brief - | */ - | fun test(): String = "TODO" - |} - """.trimIndent(), - testConfiguration - ) { - pagesTransformationStage = { module -> - val functionBriefDocs = module.singleFunctionDescription("Example") - - assertEquals( - "This is an example <!-- not visible --> of html", - functionBriefDocs.children.joinToString("") { (it as ContentText).text }) - } - } - } - - @Test - fun `brief for functions should work with ie`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |class Example(val exampleParameter: Int) { - | /** - | * The user token, i.e. "Bearer xyz". Throw an exception if not available. - | * - | * This is definitely not a brief - | */ - | fun test(): String = "TODO" - |} - """.trimIndent(), - testConfiguration - ) { - pagesTransformationStage = { module -> - val functionBriefDocs = module.singleFunctionDescription("Example") - - assertEquals( - "The user token, i.e. \"Bearer xyz\". Throw an exception if not available.", - functionBriefDocs.children.joinToString("") { (it as ContentText).text }) - } - } - } - - @Test - fun `brief for functions should work with eg`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |class Example(val exampleParameter: Int) { - | /** - | * The user token, e.g. "Bearer xyz". Throw an exception if not available. - | * - | * This is definitely not a brief - | */ - | fun test(): String = "TODO" - |} - """.trimIndent(), - testConfiguration - ) { - pagesTransformationStage = { module -> - val functionBriefDocs = module.singleFunctionDescription("Example") - - assertEquals( - "The user token, e.g. \"Bearer xyz\". Throw an exception if not available.", - functionBriefDocs.children.joinToString("") { (it as ContentText).text }) - } - } - } - - @Test - fun `brief for functions should be first sentence for Java`() { - testInline( - """ - |/src/main/java/test/Example.java - |package test; - | - |public class Example { - | /** - | * The user token, or not. This is definitely not a brief in java - | */ - | public static String test() { - | return "TODO"; - | } - |} - """.trimIndent(), - testConfiguration - ) { - pagesTransformationStage = { module -> - val functionBriefDocs = module.singleFunctionDescription("Example") - - assertEquals( - "The user token, or not.", - functionBriefDocs.children.joinToString("") { (it as ContentText).text }) - } - } - } - - @Test - fun `brief for functions should work with ie for Java`() { - testInline( - """ - |/src/main/java/test/Example.java - |package test; - | - |public class Example { - | /** - | * The user token, e.g. "Bearer xyz". This is definitely not a brief in java - | */ - | public static String test() { - | return "TODO"; - | } - |} - """.trimIndent(), - testConfiguration - ) { - pagesTransformationStage = { module -> - val functionBriefDocs = module.singleFunctionDescription("Example") - - assertEquals( - "The user token, e.g. \"Bearer xyz\".", - functionBriefDocs.children.joinToString("") { (it as ContentText).text }) - } - } - } - - //Source: https://www.oracle.com/technical-resources/articles/java/javadoc-tool.html#exampleresult - @Test - fun `brief for functions should work with html comment for Java`() { - testInline( - """ - |/src/main/java/test/Example.java - |package test; - | - |public class Example { - | /** - | * This is a simulation of Prof.<!-- --> Knuth's MIX computer. This is definitely not a brief in java - | */ - | public static String test() { - | return "TODO"; - | } - |} - """.trimIndent(), - testConfiguration - ) { - pagesTransformationStage = { module -> - val functionBriefDocs = module.singleFunctionDescription("Example") - - assertEquals( - "This is a simulation of Prof.<!-- --> Knuth's MIX computer.", - functionBriefDocs.children.joinToString("") { (it as ContentText).text }) - } - } - } - - @Test - fun `brief for functions should work with html comment at the end for Java`() { - testInline( - """ - |/src/main/java/test/Example.java - |package test; - | - |public class Example { - | /** - | * This is a simulation of Prof.<!-- --> Knuth's MIX computer. This is definitely not a brief in java <!-- --> - | */ - | public static String test() { - | return "TODO"; - | } - |} - """.trimIndent(), - testConfiguration - ) { - pagesTransformationStage = { module -> - val functionBriefDocs = module.singleFunctionDescription("Example") - - assertEquals( - "This is a simulation of Prof.<!-- --> Knuth's MIX computer.", - functionBriefDocs.children.joinToString("") { (it as ContentText).text }) - } - } - } - - private fun RootPageNode.findClassPage(className: String): ContentPage { - return this.dfs { - it.name == className && (it as WithDocumentables).documentables.firstOrNull() is DClass - } as ContentPage - } - - private fun RootPageNode.singleFunctionDescription(className: String): ContentGroup { - val classPage = - dfs { it.name == className && (it as WithDocumentables).documentables.firstOrNull() is DClass } as ContentPage - val functionsTable = - classPage.content.dfs { it is ContentTable && it.dci.kind == ContentKind.Functions } as ContentTable - - assertEquals(1, functionsTable.children.size) - val function = functionsTable.children.first() - return function.dfs { it is ContentGroup && it.dci.kind == ContentKind.Comment && it.children.all { it is ContentText } } as ContentGroup - } - private fun RootPageNode.singleTypeAliasesDescription(packageName: String): ContentGroup { - val packagePage = - dfs { it.name == packageName && (it as WithDocumentables).documentables.firstOrNull() is DPackage } as ContentPage - val contentTable = - packagePage.content.dfs { it is ContentTable && it.dci.kind == ContentKind.Classlikes } as ContentTable - - assertEquals(1, contentTable.children.size) - val row = contentTable.children.first() - return row.dfs { it is ContentGroup && it.dci.kind == ContentKind.Comment && it.children.all { it is ContentText } } as ContentGroup - } -} diff --git a/plugins/base/src/test/kotlin/content/functions/ContentForConstructors.kt b/plugins/base/src/test/kotlin/content/functions/ContentForConstructors.kt deleted file mode 100644 index d1ed93dc..00000000 --- a/plugins/base/src/test/kotlin/content/functions/ContentForConstructors.kt +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package content.functions - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.model.DClass -import org.jetbrains.dokka.model.dfs -import org.jetbrains.dokka.pages.* -import utils.assertContains -import utils.assertNotNull -import kotlin.test.Test -import kotlin.test.assertEquals - -class ContentForConstructors : BaseAbstractTest() { - private val testConfiguration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - analysisPlatform = "jvm" - } - } - } - - @Test - fun `constructor name should have RowTitle style`() { - testInline(""" - |/src/main/kotlin/test/source.kt - |package test - | - |/** - | * Dummy text. - | */ - |class Example(val exampleParameter: Int) { - |} - """.trimIndent(), testConfiguration) { - pagesTransformationStage = { module -> - val classPage = - module.dfs { it.name == "Example" && (it as WithDocumentables).documentables.firstOrNull() is DClass } as ContentPage - val constructorsTable = - classPage.content.dfs { it is ContentTable && it.dci.kind == ContentKind.Constructors } as ContentTable - - assertEquals(1, constructorsTable.children.size) - val primary = constructorsTable.children.first() - val constructorName = - primary.dfs { (it as? ContentText)?.text == "Example" }.assertNotNull("constructorName") - - assertContains(constructorName.style, ContentStyle.RowTitle) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/content/inheritors/ContentForInheritorsTest.kt b/plugins/base/src/test/kotlin/content/inheritors/ContentForInheritorsTest.kt deleted file mode 100644 index 245592cc..00000000 --- a/plugins/base/src/test/kotlin/content/inheritors/ContentForInheritorsTest.kt +++ /dev/null @@ -1,499 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package content.inheritors - -import matchers.content.* -import org.jetbrains.dokka.DokkaConfiguration -import org.jetbrains.dokka.PluginConfigurationImpl -import org.jetbrains.dokka.base.DokkaBase -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import utils.OnlyDescriptors -import utils.classSignature -import utils.findTestType -import kotlin.test.Test -import kotlin.test.assertEquals - -class ContentForInheritorsTest : BaseAbstractTest() { - private val testConfiguration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - analysisPlatform = "jvm" - } - } - } - - private val mppTestConfiguration = dokkaConfiguration { - moduleName = "example" - sourceSets { - val common = sourceSet { - name = "common" - displayName = "common" - analysisPlatform = "common" - sourceRoots = listOf("src/commonMain/kotlin/pageMerger/Test.kt") - } - sourceSet { - name = "jvm" - displayName = "jvm" - analysisPlatform = "jvm" - dependentSourceSets = setOf(common.value.sourceSetID) - sourceRoots = listOf("src/jvmMain/kotlin/pageMerger/Test.kt") - } - sourceSet { - name = "linuxX64" - displayName = "linuxX64" - analysisPlatform = "native" - dependentSourceSets = setOf(common.value.sourceSetID) - sourceRoots = listOf("src/linuxX64Main/kotlin/pageMerger/Test.kt") - } - } - pluginsConfigurations.add( - PluginConfigurationImpl( - DokkaBase::class.qualifiedName!!, - DokkaConfiguration.SerializationFormat.JSON, - """{ "mergeImplicitExpectActualDeclarations": true }""", - ) - ) - } - - - //Case from skiko library - private val mppTestConfigurationSharedAsPlatform = dokkaConfiguration { - moduleName = "example" - sourceSets { - val common = sourceSet { - name = "common" - displayName = "common" - analysisPlatform = "common" - sourceRoots = listOf("src/commonMain/kotlin/pageMerger/Test.kt") - } - val jvm = sourceSet { - name = "jvm" - displayName = "jvm" - analysisPlatform = "jvm" - dependentSourceSets = setOf(common.value.sourceSetID) - sourceRoots = listOf("src/jvmMain/kotlin/pageMerger/Test.kt") - } - sourceSet { - name = "android" - displayName = "android" - analysisPlatform = "jvm" - dependentSourceSets = setOf(jvm.value.sourceSetID) - sourceRoots = listOf("src/androidMain/kotlin/pageMerger/Test.kt") - } - sourceSet { - name = "awt" - displayName = "awt" - analysisPlatform = "jvm" - dependentSourceSets = setOf(jvm.value.sourceSetID) - sourceRoots = listOf("src/awtMain/kotlin/pageMerger/Test.kt") - } - - } - } - - @Test - fun `class with one inheritor has table in description`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |class Parent - | - |class Foo : Parent() - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("test", "Parent") - page.content.assertNode { - group { - header(1) { +"Parent" } - platformHinted { - classSignature( - emptyMap(), - "", - "", - emptySet(), - "Parent" - ) - header(4) { +"Inheritors" } - table { - group { - link { +"Foo" } - } - } - } - } - skipAllNotMatching() - } - } - } - } - - @OnlyDescriptors("Order of inheritors is different in K2") - @Test - fun `interface with few inheritors has table in description`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |interface Parent - | - |class Foo : Parent() - |class Bar : Parent() - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("test", "Parent") - page.content.assertNode { - group { - header(1) { +"Parent" } - platformHinted { - group { - +"interface " - link { - +"Parent" - } - } - header(4) { +"Inheritors" } - table { - group { - link { +"Foo" } - } - group { - link { +"Bar" } - } - } - } - } - skipAllNotMatching() - } - } - } - } - - @Test - fun `inherit from one of multiplatoforms actuals`() { - testInline( - """ - |/src/commonMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |expect open class Parent - | - |/src/jvmMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |actual open class Parent - | - |/src/linuxX64Main/kotlin/pageMerger/Test.kt - |package pageMerger - | - |actual open class Parent - |class Child: Parent() - | - """.trimMargin(), - mppTestConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("pageMerger", "Parent") - page.content.assertNode { - group { - header(1) { +"Parent" } - platformHinted { - group { - +"expect open class " - link { - +"Parent" - } - } - group { - +"actual open class " - link { - +"Parent" - } - } - group { - +"actual open class " - link { - +"Parent" - } - } - header(4) { +"Inheritors" } - table { - group { - link { +"Child" } - } - check { - assertEquals(1, sourceSets.size) - assertEquals( - "linuxX64", - this.sourceSets.first().name - ) - } - } - } - } - skipAllNotMatching() - } - } - } - } - - @Test - fun `inherit from class in common code`() { - testInline( - """ - |/src/commonMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |open class Parent - | - |/src/jvmMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |class Child : Parent() - | - """.trimMargin(), - mppTestConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("pageMerger", "Parent") - page.content.assertNode { - group { - header(1) { +"Parent" } - platformHinted { - group { - +"open class " - link { - +"Parent" - } - } - header(4) { +"Inheritors" } - table { - group { - link { +"Child" } - } - check { - assertEquals(1, sourceSets.size) - assertEquals( - "common", - this.sourceSets.first().name - ) - } - } - } - } - skipAllNotMatching() - } - } - } - } - - - @Test - fun `inheritors from merged classes`() { - testInline( - """ - |/src/linuxX64Main/kotlin/pageMerger/Test.kt - |package pageMerger - | - |open class Parent - |class LChild : Parent() - | - |/src/jvmMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |open class Parent - |class JChild : Parent() - | - """.trimMargin(), - mppTestConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("pageMerger", "Parent") - page.content.assertNode { - group { - header(1) { +"Parent" } - platformHinted { - group { - +"open class " - link { - +"Parent" - } - } - header(4) { +"Inheritors" } - table { - group { - link { +"JChild" } - } - check { - assertEquals(1, sourceSets.size) - assertEquals( - "jvm", - this.sourceSets.first().name - ) - } - } - group { - +"open class " - link { - +"Parent" - } - } - header(4) { +"Inheritors" } - table { - group { - link { +"LChild" } - } - check { - assertEquals(1, sourceSets.size) - assertEquals( - "linuxX64", - this.sourceSets.first().name - ) - } - } - } - } - skipAllNotMatching() - } - } - } - } - - - @Test - fun `merged inheritors from merged classes`() { - testInline( - """ - |/src/linuxX64Main/kotlin/pageMerger/Test.kt - |package pageMerger - | - |open class Parent - |class Child : Parent() - | - |/src/jvmMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |open class Parent - |class Child : Parent() - | - """.trimMargin(), - mppTestConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("pageMerger", "Parent") - page.content.assertNode { - group { - header(1) { +"Parent" } - platformHinted { - group { - +"open class " - link { - +"Parent" - } - } - header(4) { +"Inheritors" } - table { - group { - link { +"Child" } - } - check { - assertEquals(1, sourceSets.size) - assertEquals( - "jvm", - this.sourceSets.first().name - ) - } - } - group { - +"open class " - link { - +"Parent" - } - } - header(4) { +"Inheritors" } - table { - group { - link { +"Child" } - } - check { - assertEquals(1, sourceSets.size) - assertEquals( - "linuxX64", - this.sourceSets.first().name - ) - } - } - } - } - skipAllNotMatching() - } - } - } - } - - @Test - fun `parent in shared source set that analyse as platform`() { - testInline( - """ - |/src/jvmMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |interface Parent - | - |/src/androidMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |class Child : Parent - | - |/src/awtMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |class AwtChild : Parent - |class Child : Parent - | - """.trimMargin(), - mppTestConfigurationSharedAsPlatform - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("pageMerger", "Parent") - page.content.assertNode { - group { - header(1) { +"Parent" } - platformHinted { - group { - +"interface " - link { - +"Parent" - } - } - header(4) { +"Inheritors" } - table { - group { - link { +"Child" } - } - group { - link { +"AwtChild" } - } - check { - assertEquals(1, sourceSets.size) - assertEquals( - "jvm", - this.sourceSets.first().name - ) - } - } - } - } - skipAllNotMatching() - } - } - } - } -} diff --git a/plugins/base/src/test/kotlin/content/params/ContentForParamsTest.kt b/plugins/base/src/test/kotlin/content/params/ContentForParamsTest.kt deleted file mode 100644 index d0c6ac9d..00000000 --- a/plugins/base/src/test/kotlin/content/params/ContentForParamsTest.kt +++ /dev/null @@ -1,1529 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package content.params - -import matchers.content.* -import org.jetbrains.dokka.Platform -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.model.DFunction -import org.jetbrains.dokka.model.dfs -import org.jetbrains.dokka.model.doc.DocumentationNode -import org.jetbrains.dokka.model.doc.Param -import org.jetbrains.dokka.model.doc.Text -import org.jetbrains.dokka.pages.* -import org.jetbrains.dokka.utilities.firstIsInstanceOrNull -import utils.* -import kotlin.test.Test -import kotlin.test.assertEquals - -class ContentForParamsTest : BaseAbstractTest() { - private val testConfiguration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - classpath = listOfNotNull(jvmStdlibPath) - analysisPlatform = "jvm" - } - } - } - - @Test - fun `undocumented function`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |fun function(abc: String) { - | println(abc) - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("test", "function") - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - emptyMap(), "", "", emptySet(), "function", null, "abc" to ParamAttributes( - emptyMap(), - emptySet(), - "String" - ) - ) - } - } - } - } - } - } - } - - @Test - fun `undocumented parameter`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | /** - | * comment to function - | */ - |fun function(abc: String) { - | println(abc) - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("test", "function") - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - emptyMap(), - "", - "", - emptySet(), - "function", - null, - "abc" to ParamAttributes(emptyMap(), emptySet(), "String") - ) - } - after { - group { pWrapped("comment to function") } - } - } - } - } - } - } - } - - @Test - fun `undocumented parameter and other tags without function comment`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | /** - | * @author Kordyjan - | * @author Woolfy - | * @since 0.11 - | */ - |fun function(abc: String) { - | println(abc) - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("test", "function") - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - emptyMap(), - "", - "", - emptySet(), - "function", - null, - "abc" to ParamAttributes(emptyMap(), emptySet(), "String") - ) - } - after { - unnamedTag("Author") { - comment { - +"Kordyjan" - } - comment { - +"Woolfy" - } - } - unnamedTag("Since") { comment { +"0.11" } } - } - } - } - } - } - } - } - - @Test - fun `multiple authors`() { - testInline( - """ - |/src/main/java/sample/DocGenProcessor.java - |package sample; - |/** - | * Annotation processor which visits all classes. - | * - | * @author googler1@google.com (Googler 1) - | * @author googler2@google.com (Googler 2) - | */ - | public class DocGenProcessor { } - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val classPage = module.findTestType("sample", "DocGenProcessor") - classPage.content.assertNode { - group { - header { +"DocGenProcessor" } - platformHinted { - group { - skipAllNotMatching() //Signature - } - group { - group { - group { - +"Annotation processor which visits all classes." - } - } - } - group { - header(4) { +"Author" } - comment { +"googler1@google.com (Googler 1)" } - comment { +"googler2@google.com (Googler 2)" } - } - } - } - skipAllNotMatching() - } - } - } - } - - @Test - fun `author delimetered by space`() { - testInline( - """ - |/src/main/java/sample/DocGenProcessor.java - |package sample; - |/** - | * Annotation processor which visits all classes. - | * - | * @author Marcin Aman Senior - | */ - | public class DocGenProcessor { } - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val classPage = module.findTestType("sample", "DocGenProcessor") - classPage.content.assertNode { - group { - header { +"DocGenProcessor" } - platformHinted { - group { - skipAllNotMatching() //Signature - } - group { - group { - group { - +"Annotation processor which visits all classes." - } - } - } - group { - header(4) { +"Author" } - comment { +"Marcin Aman Senior" } - } - } - } - skipAllNotMatching() - } - } - } - } - - - @Test - fun `deprecated with multiple links inside`() { - testInline( - """ - |/src/main/java/sample/DocGenProcessor.java - |package sample; - |/** - | * Return the target fragment set by {@link #setTargetFragment} or {@link - | * #setTargetFragment}. - | * - | * @deprecated Instead of using a target fragment to pass results, the fragment requesting a - | * result should use - | * {@link java.util.HashMap#containsKey(java.lang.Object) FragmentManager#setFragmentResult(String, Bundle)} to deliver results to - | * {@link java.util.HashMap#containsKey(java.lang.Object) - | * FragmentResultListener} instances registered by other fragments via - | * {@link java.util.HashMap#containsKey(java.lang.Object) FragmentManager#setFragmentResultListener(String, LifecycleOwner, - | * FragmentResultListener)}. - | */ - | public class DocGenProcessor { - | public String setTargetFragment(){ - | return ""; - | } - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val classPage = - module.findTestType("sample", "DocGenProcessor") - classPage.content.assertNode { - group { - header { +"DocGenProcessor" } - platformHinted { - group { - skipAllNotMatching() //Signature - } - group { - comment { - +"Return the target fragment set by " - link { +"setTargetFragment" } - +" or " - link { +"setTargetFragment" } - +"." - } - } - group { - header(4) { +"Deprecated" } - comment { - +"Instead of using a target fragment to pass results, the fragment requesting a result should use " - link { +"FragmentManager#setFragmentResult(String, Bundle)" } - +" to deliver results to " - link { +"FragmentResultListener" } - +" instances registered by other fragments via " - link { +"FragmentManager#setFragmentResultListener(String, LifecycleOwner, FragmentResultListener)" } - +"." - } - } - } - } - skipAllNotMatching() - } - } - } - } - - @Test - fun `deprecated with an html link in multiple lines`() { - testInline( - """ - |/src/main/java/sample/DocGenProcessor.java - |package sample; - |/** - | * @deprecated Use - | * <a href="https://developer.android.com/guide/navigation/navigation-swipe-view "> - | * TabLayout and ViewPager</a> instead. - | */ - | public class DocGenProcessor { } - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val classPage = - module.findTestType("sample", "DocGenProcessor") - classPage.content.assertNode { - group { - header { +"DocGenProcessor" } - platformHinted { - group { - skipAllNotMatching() //Signature - } - group { - header(4) { +"Deprecated" } - comment { - +"Use " - link { +"TabLayout and ViewPager" } - +" instead." - } - } - } - } - skipAllNotMatching() - } - } - } - } - - - @Test - fun `deprecated with an multiple inline links`() { - testInline( - """ - |/src/main/java/sample/DocGenProcessor.java - |package sample; - |/** - | * FragmentManagerNonConfig stores the retained instance fragments across - | * activity recreation events. - | * - | * <p>Apps should treat objects of this type as opaque, returned by - | * and passed to the state save and restore process for fragments in - | * {@link java.util.HashMap#containsKey(java.lang.Object) FragmentController#retainNestedNonConfig()} and - | * {@link java.util.HashMap#containsKey(java.lang.Object) FragmentController#restoreAllState(Parcelable, FragmentManagerNonConfig)}.</p> - | * - | * @deprecated Have your {@link java.util.HashMap FragmentHostCallback} implement - | * {@link java.util.HashMap } to automatically retain the Fragment's - | * non configuration state. - | */ - | public class DocGenProcessor { } - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val classPage = - module.findTestType("sample", "DocGenProcessor") - classPage.content.assertNode { - group { - header { +"DocGenProcessor" } - platformHinted { - group { - skipAllNotMatching() //Signature - } - group { - comment { - group { - +"FragmentManagerNonConfig stores the retained instance fragments across activity recreation events. " - } - group { - +"Apps should treat objects of this type as opaque, returned by and passed to the state save and restore process for fragments in " - link { +"FragmentController#retainNestedNonConfig()" } - +" and " - link { +"FragmentController#restoreAllState(Parcelable, FragmentManagerNonConfig)" } - +"." - } - } - } - group { - header(4) { +"Deprecated" } - comment { - +"Have your " - link { +"FragmentHostCallback" } - +" implement " - link { +"java.util.HashMap" } - +" to automatically retain the Fragment's non configuration state." - } - } - } - } - skipAllNotMatching() - } - } - } - } - - @Test - fun `multiline throws with comment`() { - testInline( - """ - |/src/main/java/sample/DocGenProcessor.java - |package sample; - | public class DocGenProcessor { - | /** - | * a normal comment - | * - | * @throws java.lang.IllegalStateException if the Dialog has not yet been created (before - | * onCreateDialog) or has been destroyed (after onDestroyView). - | * @throws java.lang.RuntimeException when {@link java.util.HashMap#containsKey(java.lang.Object) Hash - | * Map} doesn't contain value. - | */ - | public static void sample(){ } - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val functionPage = - module.findTestType( - "sample", - "DocGenProcessor" - ).children.single { it.name == "sample" } as ContentPage - functionPage.content.assertNode { - group { - header(1) { +"sample" } - } - divergentGroup { - divergentInstance { - divergent { - skipAllNotMatching() //Signature - } - after { - group { pWrapped("a normal comment") } - header(4) { +"Throws" } - table { - group { - group { - link { +"IllegalStateException" } - } - comment { +"if the Dialog has not yet been created (before onCreateDialog) or has been destroyed (after onDestroyView)." } - } - group { - group { - link { +"RuntimeException" } - } - comment { - +"when " - link { +"Hash Map" } - +" doesn't contain value." - } - } - } - } - } - } - } - } - } - } - - @OnlyDescriptors("Fixed in 1.9.20 (IMPORT STAR)") - @Test - fun `multiline kotlin throws with comment`() { - testInline( - """ - |/src/main/kotlin/sample/sample.kt - |package sample; - | /** - | * a normal comment - | * - | * @throws java.lang.IllegalStateException if the Dialog has not yet been created (before - | * onCreateDialog) or has been destroyed (after onDestroyView). - | * @exception RuntimeException when [Hash Map][java.util.HashMap.containsKey] doesn't contain value. - | */ - | fun sample(){ } - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val functionPage = module.findTestType("sample", "sample") - functionPage.content.assertNode { - group { - header(1) { +"sample" } - } - divergentGroup { - divergentInstance { - divergent { - skipAllNotMatching() //Signature - } - after { - group { pWrapped("a normal comment") } - header(4) { +"Throws" } - table { - group { - group { - link { - check { - assertEquals( - "java.lang/IllegalStateException///PointingToDeclaration/", - (this as ContentDRILink).address.toString() - ) - } - +"IllegalStateException" - } - } - comment { +"if the Dialog has not yet been created (before onCreateDialog) or has been destroyed (after onDestroyView)." } - } - group { - group { - link { - check { - assertEquals( - "kotlin/RuntimeException///PointingToDeclaration/", - (this as ContentDRILink).address.toString() - ) - } - +"RuntimeException" - } - } - comment { - +"when " - link { +"Hash Map" } - +" doesn't contain value." - } - } - } - } - } - } - } - } - } - } - - @Test - fun `should display fully qualified throws name for unresolved class`() { - testInline( - """ - |/src/main/kotlin/sample/sample.kt - |package sample; - | /** - | * a normal comment - | * - | * @throws com.example.UnknownException description for non-resolved - | */ - | fun sample(){ } - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val functionPage = - module.findTestType("sample", "sample") - functionPage.content.assertNode { - group { - header(1) { +"sample" } - } - divergentGroup { - divergentInstance { - divergent { - skipAllNotMatching() //Signature - } - after { - group { pWrapped("a normal comment") } - header(4) { +"Throws" } - table { - group { - group { - +"com.example.UnknownException" - } - comment { +"description for non-resolved" } - } - } - } - } - } - } - } - } - } - - @Test - fun `multiline throws where exception is not in the same line as description`() { - testInline( - """ - |/src/main/java/sample/DocGenProcessor.java - |package sample; - | public class DocGenProcessor { - | /** - | * a normal comment - | * - | * @throws java.lang.IllegalStateException if the Dialog has not yet been created (before - | * onCreateDialog) or has been destroyed (after onDestroyView). - | * @throws java.lang.RuntimeException when - | * {@link java.util.HashMap#containsKey(java.lang.Object) Hash - | * Map} - | * doesn't contain value. - | */ - | public static void sample(){ } - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val functionPage = - module.findTestType( - "sample", - "DocGenProcessor" - ).children.single { it.name == "sample" } as ContentPage - functionPage.content.assertNode { - group { - header(1) { +"sample" } - } - divergentGroup { - divergentInstance { - divergent { - skipAllNotMatching() //Signature - } - after { - group { pWrapped("a normal comment") } - header(4) { +"Throws" } - table { - group { - group { - link { - check { - assertEquals( - "java.lang/IllegalStateException///PointingToDeclaration/", - (this as ContentDRILink).address.toString() - ) - } - +"IllegalStateException" - } - } - comment { +"if the Dialog has not yet been created (before onCreateDialog) or has been destroyed (after onDestroyView)." } - } - group { - group { - link { - check { - assertEquals( - "java.lang/RuntimeException///PointingToDeclaration/", - (this as ContentDRILink).address.toString() - ) - } - +"RuntimeException" - } - } - comment { - +"when " - link { +"Hash Map" } - +" doesn't contain value." - } - } - } - } - } - - } - } - } - } - } - - - - @Test - fun `documentation splitted in 2 using enters`() { - testInline( - """ - |/src/main/java/sample/DocGenProcessor.java - |package sample; - |/** - | * Listener for handling fragment results. - | * - | * This object should be passed to - | * {@link java.util.HashMap#containsKey(java.lang.Object) FragmentManager#setFragmentResultListener(String, LifecycleOwner, FragmentResultListener)} - | * and it will listen for results with the same key that are passed into - | * {@link java.util.HashMap#containsKey(java.lang.Object) FragmentManager#setFragmentResult(String, Bundle)}. - | * - | */ - | public class DocGenProcessor { } - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val classPage = - module.findTestType("sample", "DocGenProcessor") - classPage.content.assertNode { - group { - header { +"DocGenProcessor" } - platformHinted { - group { - skipAllNotMatching() //Signature - } - group { - comment { - +"Listener for handling fragment results. This object should be passed to " - link { +"FragmentManager#setFragmentResultListener(String, LifecycleOwner, FragmentResultListener)" } - +" and it will listen for results with the same key that are passed into " - link { +"FragmentManager#setFragmentResult(String, Bundle)" } - +"." - } - } - } - } - skipAllNotMatching() - } - } - } - } - - @Test - fun `multiline return tag with param`() { - testInline( - """ - |/src/main/java/sample/DocGenProcessor.java - |package sample; - | public class DocGenProcessor { - | /** - | * a normal comment - | * - | * @param testParam Sample description for test param that has a type of {@link java.lang.String String} - | * @return empty string when - | * {@link java.util.HashMap#containsKey(java.lang.Object) Hash - | * Map} - | * doesn't contain value. - | */ - | public static String sample(String testParam){ - | return ""; - | } - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val functionPage = - module.findTestType( - "sample", - "DocGenProcessor" - ).children.single { it.name == "sample" } as ContentPage - functionPage.content.assertNode { - group { - header(1) { +"sample" } - } - divergentGroup { - divergentInstance { - divergent { - skipAllNotMatching() //Signature - } - after { - group { pWrapped("a normal comment") } - group { - header(4) { +"Return" } - comment { - +"empty string when " - link { +"Hash Map" } - +" doesn't contain value." - } - } - header(4) { +"Parameters" } - table { - group { - +"testParam" - comment { - +"Sample description for test param that has a type of " - link { +"String" } - } - } - } - } - } - } - } - } - } - } - - @Test - fun `return tag in kotlin`() { - testInline( - """ - |/src/main/kotlin/sample/sample.kt - |package sample; - | /** - | * a normal comment - | * - | * @return empty string when [Hash Map][java.util.HashMap.containsKey] doesn't contain value. - | * - | */ - |fun sample(): String { - | return "" - | } - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val functionPage = module.findTestType("sample", "sample") - functionPage.content.assertNode { - group { - header(1) { +"sample" } - } - divergentGroup { - divergentInstance { - divergent { - skipAllNotMatching() //Signature - } - after { - group { pWrapped("a normal comment") } - group { - header(4) { +"Return" } - comment { - +"empty string when " - link { +"Hash Map" } - +" doesn't contain value." - } - } - } - } - } - } - } - } - } - - - @Test - fun `list with links and description`() { - testInline( - """ - |/src/main/java/sample/DocGenProcessor.java - |package sample; - |/** - | * Static library support version of the framework's {@link java.lang.String}. - | * Used to write apps that run on platforms prior to Android 3.0. When running - | * on Android 3.0 or above, this implementation is still used; it does not try - | * to switch to the framework's implementation. See the framework {@link java.lang.String} - | * documentation for a class overview. - | * - | * <p>The main differences when using this support version instead of the framework version are: - | * <ul> - | * <li>Your activity must extend {@link java.lang.String FragmentActivity} - | * <li>You must call {@link java.util.HashMap#containsKey(java.lang.Object) FragmentActivity#getSupportFragmentManager} to get the - | * {@link java.util.HashMap FragmentManager} - | * </ul> - | * - | */ - |public class DocGenProcessor { } - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val classPage = module.findTestType("sample", "DocGenProcessor") - classPage.content.assertNode { - group { - header { +"DocGenProcessor" } - platformHinted { - group { - skipAllNotMatching() //Signature - } - group { - comment { - group { - +"Static library support version of the framework's " - link { +"java.lang.String" } - +". Used to write apps that run on platforms prior to Android 3.0." - +" When running on Android 3.0 or above, this implementation is still used; it does not try to switch to the framework's implementation. See the framework " - link { +"java.lang.String" } - +" documentation for a class overview. " //TODO this probably shouldnt have a space but it is minor - } - group { - +"The main differences when using this support version instead of the framework version are: " - } - list { - group { - +"Your activity must extend " - link { +"FragmentActivity" } - } - group { - +"You must call " - link { +"FragmentActivity#getSupportFragmentManager" } - +" to get the " - link { +"FragmentManager" } - } - } - } - } - } - } - skipAllNotMatching() - } - } - } - } - - @Test - fun `documentation with table`() { - testInline( - """ - |/src/main/java/sample/DocGenProcessor.java - |package sample; - |/** - | * <table> - | * <caption>List of supported types</caption> - | * <tr> - | * <td>cell 11</td> <td>cell 21</td> - | * </tr> - | * <tr> - | * <td>cell 12</td> <td>cell 22</td> - | * </tr> - | * </table> - | */ - | public class DocGenProcessor { } - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val classPage = - module.findTestType("sample", "DocGenProcessor") - classPage.content.assertNode { - group { - header { +"DocGenProcessor" } - platformHinted { - group { - skipAllNotMatching() //Signature - } - comment { - table { - check { - caption!!.assertNode { - caption { - +"List of supported types" - } - } - } - group { - group { - +"cell 11" - } - group { - +"cell 21" - } - } - group { - group { - +"cell 12" - } - group { - +"cell 22" - } - } - } - } - } - } - skipAllNotMatching() - } - } - } - } - - - @Test - fun `undocumented parameter and other tags`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | /** - | * comment to function - | * @author Kordyjan - | * @since 0.11 - | */ - |fun function(abc: String) { - | println(abc) - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("test", "function") - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - emptyMap(), - "", - "", - emptySet(), - "function", - null, - "abc" to ParamAttributes(emptyMap(), emptySet(), "String") - ) - } - after { - group { pWrapped("comment to function") } - unnamedTag("Author") { comment { +"Kordyjan" } } - unnamedTag("Since") { comment { +"0.11" } } - } - } - } - } - } - } - } - - @Test - fun `single parameter`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | /** - | * comment to function - | * @param abc comment to param - | */ - |fun function(abc: String) { - | println(abc) - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("test", "function") - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - emptyMap(), - "", - "", - emptySet(), - "function", - null, - "abc" to ParamAttributes(emptyMap(), emptySet(), "String") - ) - } - after { - group { pWrapped("comment to function") } - header(4) { +"Parameters" } - table { - group { - +"abc" - check { - val textStyles = children.single { it is ContentText }.style - assertContains(textStyles, TextStyle.Underlined) - } - group { group { +"comment to param" } } - } - } - } - } - } - } - } - } - } - - @Test - fun `single parameter in class`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | /** - | * comment to class - | * @param abc comment to param - | */ - |class Foo(abc: String) - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("test", "Foo") - println(page.content) - page.content.assertNode { - group { - header(1) { +"Foo" } - platformHinted { - classSignature( - emptyMap(), - "", - "", - emptySet(), - "Foo", - "abc" to ParamAttributes(emptyMap(), emptySet(), "String") - ) - group { - pWrapped("comment to class") - } - header(4) { +"Parameters" } - table { - group { - +"abc" - check { - val textStyles = children.single { it is ContentText }.style - assertContains(textStyles, TextStyle.Underlined) - } - group { group { +"comment to param" } } - } - } - } - } - skipAllNotMatching() - } - } - } - } - - @Test - fun `multiple parameters`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | /** - | * comment to function - | * @param first comment to first param - | * @param second comment to second param - | * @param[third] comment to third param - | */ - |fun function(first: String, second: Int, third: Double) { - | println(abc) - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("test", "function") - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - emptyMap(), "", "", emptySet(), "function", null, - "first" to ParamAttributes(emptyMap(), emptySet(), "String"), - "second" to ParamAttributes(emptyMap(), emptySet(), "Int"), - "third" to ParamAttributes(emptyMap(), emptySet(), "Double") - ) - } - after { - group { group { group { +"comment to function" } } } - header(4) { +"Parameters" } - table { - group { - +"first" - check { - val textStyles = children.single { it is ContentText }.style - assertContains(textStyles, TextStyle.Underlined) - } - group { group { +"comment to first param" } } - } - group { - +"second" - check { - val textStyles = children.single { it is ContentText }.style - assertContains(textStyles, TextStyle.Underlined) - } - group { group { +"comment to second param" } } - } - group { - +"third" - check { - val textStyles = children.single { it is ContentText }.style - assertContains(textStyles, TextStyle.Underlined) - } - group { group { +"comment to third param" } } - } - } - } - } - } - } - } - } - } - - - @Test - fun `multiple parameters with not natural order`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | /** - | * comment to function - | * @param c comment to c param - | * @param b comment to b param - | * @param[a] comment to a param - | */ - |fun function(c: String, b: Int, a: Double) { - | println(abc) - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("test", "function") - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - emptyMap(), "", "", emptySet(), "function", null, - "c" to ParamAttributes(emptyMap(), emptySet(), "String"), - "b" to ParamAttributes(emptyMap(), emptySet(), "Int"), - "a" to ParamAttributes(emptyMap(), emptySet(), "Double") - ) - } - after { - group { group { group { +"comment to function" } } } - header(4) { +"Parameters" } - table { - group { - +"c" - group { group { +"comment to c param" } } - } - group { - +"b" - group { group { +"comment to b param" } } - } - group { - +"a" - group { group { +"comment to a param" } } - } - } - - } - } - } - } - } - } - } - - @Test - fun `multiple parameters without function description`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | /** - | * @param first comment to first param - | * @param second comment to second param - | * @param[third] comment to third param - | */ - |fun function(first: String, second: Int, third: Double) { - | println(abc) - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("test", "function") - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - emptyMap(), "", "", emptySet(), "function", null, - "first" to ParamAttributes(emptyMap(), emptySet(), "String"), - "second" to ParamAttributes(emptyMap(), emptySet(), "Int"), - "third" to ParamAttributes(emptyMap(), emptySet(), "Double") - ) - } - after { - header(4) { +"Parameters" } - table { - group { - +"first" - group { group { +"comment to first param" } } - } - group { - +"second" - group { group { +"comment to second param" } } - } - group { - +"third" - group { group { +"comment to third param" } } - } - } - } - } - } - } - } - } - } - - @Test - fun `function with receiver`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | /** - | * comment to function - | * @param abc comment to param - | * @receiver comment to receiver - | */ - |fun String.function(abc: String) { - | println(abc) - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("test", "function") - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignatureWithReceiver( - emptyMap(), - "", - "", - emptySet(), - "String", - "function", - null, - "abc" to ParamAttributes(emptyMap(), emptySet(), "String") - ) - } - after { - group { pWrapped("comment to function") } - group { - header(4) { +"Receiver" } - pWrapped("comment to receiver") - } - header(4) { +"Parameters" } - table { - group { - +"abc" - group { group { +"comment to param" } } - } - } - - } - } - } - } - } - } - } - - @Test - fun `missing parameter documentation`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | /** - | * comment to function - | * @param first comment to first param - | * @param[third] comment to third param - | */ - |fun function(first: String, second: Int, third: Double) { - | println(abc) - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("test", "function") - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - emptyMap(), "", "", emptySet(), "function", null, - "first" to ParamAttributes(emptyMap(), emptySet(), "String"), - "second" to ParamAttributes(emptyMap(), emptySet(), "Int"), - "third" to ParamAttributes(emptyMap(), emptySet(), "Double") - ) - } - after { - group { group { group { +"comment to function" } } } - header(4) { +"Parameters" } - table { - group { - +"first" - group { group { +"comment to first param" } } - } - group { - +"third" - group { group { +"comment to third param" } } - } - } - } - } - } - } - } - } - } - - @Test - fun `parameters mixed with other tags`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | /** - | * comment to function - | * @param first comment to first param - | * @author Kordyjan - | * @param second comment to second param - | * @since 0.11 - | * @param[third] comment to third param - | */ - |fun function(first: String, second: Int, third: Double) { - | println(abc) - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("test", "function") - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - emptyMap(), "", "", emptySet(), "function", null, - "first" to ParamAttributes(emptyMap(), emptySet(), "String"), - "second" to ParamAttributes(emptyMap(), emptySet(), "Int"), - "third" to ParamAttributes(emptyMap(), emptySet(), "Double") - ) - } - after { - group { pWrapped("comment to function") } - unnamedTag("Author") { comment { +"Kordyjan" } } - unnamedTag("Since") { comment { +"0.11" } } - header(4) { +"Parameters" } - - table { - group { - +"first" - group { group { +"comment to first param" } } - } - group { - +"second" - group { group { +"comment to second param" } } - } - group { - +"third" - group { group { +"comment to third param" } } - } - } - } - } - } - } - } - } - } - - @Test - fun javaDocCommentWithDocumentedParameters() { - testInline( - """ - |/src/main/java/test/Main.java - |package test - | public class Main { - | - | /** - | * comment to function - | * @param first comment to first param - | * @param second comment to second param - | */ - | public void sample(String first, String second) { - | - | } - | } - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val sampleFunction = module.dfs { - it is MemberPageNode && it.dri.first() - .toString() == "test/Main/sample/#java.lang.String#java.lang.String/PointingToDeclaration/" - } as MemberPageNode - val forJvm = (sampleFunction.documentables.firstOrNull() as DFunction).parameters.mapNotNull { - val jvm = it.documentation.keys.first { it.analysisPlatform == Platform.jvm } - it.documentation[jvm] - } - - assertEquals(2, forJvm.size) - val (first, second) = forJvm.map { it.paramsDescription() } - assertEquals("comment to first param", first) - assertEquals("comment to second param", second) - } - } - } - - private fun DocumentationNode.paramsDescription(): String = - children.firstIsInstanceOrNull<Param>()?.root?.children?.first()?.children?.firstIsInstanceOrNull<Text>()?.body.orEmpty() - -} diff --git a/plugins/base/src/test/kotlin/content/properties/ContentForClassWithParamsAndPropertiesTest.kt b/plugins/base/src/test/kotlin/content/properties/ContentForClassWithParamsAndPropertiesTest.kt deleted file mode 100644 index d244567f..00000000 --- a/plugins/base/src/test/kotlin/content/properties/ContentForClassWithParamsAndPropertiesTest.kt +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package content.properties - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.model.DClass -import org.jetbrains.dokka.model.dfs -import org.jetbrains.dokka.model.doc.* -import org.jetbrains.dokka.pages.ClasslikePageNode -import org.jetbrains.dokka.pages.RootPageNode -import kotlin.test.Test -import kotlin.test.assertEquals - -class ContentForClassWithParamsAndPropertiesTest : BaseAbstractTest() { - private val testConfiguration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - analysisPlatform = "jvm" - } - } - } - - @Test - fun `should work for a simple property`() { - propertyTest { rootPage -> - val node = rootPage.dfs { it.name == "LoadInitialParams" } as ClasslikePageNode - val actualDocsForPlaceholdersEnabled = - (node.documentables.firstOrNull() as DClass).constructors.first().parameters.find { it.name == "placeholdersEnabled" } - ?.documentation?.entries?.first()?.value - assertEquals(DocumentationNode(listOf(docsForPlaceholdersEnabled)), actualDocsForPlaceholdersEnabled) - } - } - - @Test - fun `should work for a simple with linebreak`() { - propertyTest { rootPage -> - val node = rootPage.dfs { it.name == "LoadInitialParams" } as ClasslikePageNode - val actualDocsForRequestedLoadSize = - (node.documentables.firstOrNull() as DClass).constructors.first().parameters.find { it.name == "requestedLoadSize" } - ?.documentation?.entries?.first()?.value - assertEquals(DocumentationNode(listOf(docsForRequestedLoadSize)), actualDocsForRequestedLoadSize) - } - } - - @Test - fun `should work with multiline property inline code`() { - propertyTest { rootPage -> - val node = rootPage.dfs { it.name == "LoadInitialParams" } as ClasslikePageNode - - val actualDocsForRequestedInitialKey = - (node.documentables.firstOrNull() as DClass).constructors.first().parameters.find { it.name == "requestedInitialKey" } - ?.documentation?.entries?.first()?.value - assertEquals(DocumentationNode(listOf(docsForRequestedInitialKey)), actualDocsForRequestedInitialKey) - } - } - - @Test - fun `constructor should only the param and constructor tags`() { - propertyTest { rootPage -> - val constructorDocs = Description( - root = CustomDocTag( - children = listOf( - P( - children = listOf( - Text("Creates an empty group.") - ) - ) - ), - emptyMap(), "MARKDOWN_FILE" - ) - ) - val node = rootPage.dfs { it.name == "LoadInitialParams" } as ClasslikePageNode - - val actualDocs = - (node.documentables.firstOrNull() as DClass).constructors.first().documentation.entries.first().value - assertEquals(DocumentationNode(listOf(constructorDocs, docsForParam)), actualDocs) - } - } - - @Test - fun `class should have all tags`() { - propertyTest { rootPage -> - val ownDescription = Description( - root = CustomDocTag( - children = listOf( - P( - children = listOf( - Text("Holder object for inputs to loadInitial.") - ) - ) - ), - emptyMap(), "MARKDOWN_FILE" - ) - ) - val node = rootPage.dfs { it.name == "LoadInitialParams" } as ClasslikePageNode - - val actualDocs = - (node.documentables.firstOrNull() as DClass).documentation.entries.first().value - assertEquals( - DocumentationNode( - listOf( - ownDescription, - docsForParam, - docsForRequestedInitialKey, - docsForRequestedLoadSize, - docsForPlaceholdersEnabled, - docsForConstructor - ) - ), - actualDocs - ) - } - } - - @Test - fun `property should also work with own docs that override the param tag`() { - propertyTest { rootPage -> - val ownDescription = Description( - root = CustomDocTag( - children = listOf( - P( - children = listOf( - Text("Own docs") - ) - ) - ), - emptyMap(), "MARKDOWN_FILE" - ) - ) - val node = rootPage.dfs { it.name == "ItemKeyedDataSource" } as ClasslikePageNode - - val actualDocs = - (node.documentables.firstOrNull() as DClass).properties.first().documentation.entries.first().value - assertEquals( - DocumentationNode(listOf(ownDescription)), - actualDocs - ) - } - } - - - private fun propertyTest(block: (RootPageNode) -> Unit) { - testInline( - """ |/src/main/kotlin/test/source.kt - |package test - |/** - | * @property tested Docs from class - | */ - |abstract class ItemKeyedDataSource<Key : Any, Value : Any> : DataSource<Key, Value>(ITEM_KEYED) { - | /** - | * Own docs - | */ - | val tested = "" - | - | /** - | * Holder object for inputs to loadInitial. - | * - | * @param Key Type of data used to query Value types out of the DataSource. - | * @property requestedInitialKey Load items around this key, or at the beginning of the data set - | * if `null` is passed. - | * - | * Note that this key is generally a hint, and may be ignored if you want to always load from - | * the beginning. - | * @property requestedLoadSize Requested number of items to load. - | * - | * Note that this may be larger than available data. - | * @property placeholdersEnabled Defines whether placeholders are enabled, and whether the - | * loaded total count will be ignored. - | * - | * @constructor Creates an empty group. - | */ - | open class LoadInitialParams<Key : Any>( - | @JvmField - | val requestedInitialKey: Key?, - | @JvmField - | val requestedLoadSize: Int, - | @JvmField - | val placeholdersEnabled: Boolean - | ) - |}""".trimIndent(), testConfiguration - ) { - pagesGenerationStage = block - } - } - - private val docsForPlaceholdersEnabled = Property( - root = CustomDocTag( - listOf( - P( - children = listOf( - Text("Defines whether placeholders are enabled, and whether the loaded total count will be ignored.") - ) - ) - ), emptyMap(), "MARKDOWN_FILE" - ), - name = "placeholdersEnabled" - ) - - private val docsForRequestedInitialKey = Property( - root = CustomDocTag( - listOf( - P( - children = listOf( - Text("Load items around this key, or at the beginning of the data set if "), - CodeInline( - listOf( - Text("null") - ) - ), - Text(" is passed.") - ), - params = emptyMap() - ), - P( - children = listOf( - Text("Note that this key is generally a hint, and may be ignored if you want to always load from the beginning.") - ) - ) - ), emptyMap(), "MARKDOWN_FILE" - ), - name = "requestedInitialKey" - ) - - private val docsForRequestedLoadSize = Property( - root = CustomDocTag( - listOf( - P( - children = listOf( - Text("Requested number of items to load.") - ) - ), - P( - children = listOf( - Text("Note that this may be larger than available data.") - ) - ) - ), emptyMap(), "MARKDOWN_FILE" - ), - name = "requestedLoadSize" - ) - - private val docsForConstructor = Constructor( - root = CustomDocTag( - children = listOf( - P( - children = listOf( - Text("Creates an empty group.") - ) - ) - ), - emptyMap(), "MARKDOWN_FILE" - ) - ) - - private val docsForParam = Param( - root = CustomDocTag( - children = listOf( - P( - children = listOf( - Text("Type of data used to query Value types out of the DataSource.") - ) - ) - ), - emptyMap(), "MARKDOWN_FILE" - ), - name = "Key" - ) -} - diff --git a/plugins/base/src/test/kotlin/content/receiver/ContentForReceiverTest.kt b/plugins/base/src/test/kotlin/content/receiver/ContentForReceiverTest.kt deleted file mode 100644 index d94c1106..00000000 --- a/plugins/base/src/test/kotlin/content/receiver/ContentForReceiverTest.kt +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package content.receiver - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.model.dfs -import org.jetbrains.dokka.model.doc.Receiver -import org.jetbrains.dokka.model.doc.Text -import org.jetbrains.dokka.pages.ContentHeader -import org.jetbrains.dokka.pages.ContentText -import org.jetbrains.dokka.pages.MemberPageNode -import utils.docs -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertNotNull - -class ContentForReceiverTest: BaseAbstractTest() { - private val testConfiguration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - analysisPlatform = "jvm" - } - } - } - - @Test - fun `should have docs for receiver`(){ - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - |/** - | * docs - | * @receiver docs for string - | */ - |fun String.asd2(): String = this - """.trimIndent(), - testConfiguration - ){ - documentablesTransformationStage = { module -> - with(module.packages.flatMap { it.functions }.first()){ - val receiver = docs().firstOrNull { it is Receiver } - assertNotNull(receiver) - val content = receiver.dfs { it is Text } as Text - assertEquals("docs for string", content.body) - } - } - pagesTransformationStage = { rootPageNode -> - val functionPage = rootPageNode.dfs { it is MemberPageNode } as MemberPageNode - val header = functionPage.content.dfs { it is ContentHeader && it.children.firstOrNull() is ContentText } - val text = functionPage.content.dfs { it is ContentText && it.text == "docs for string" } - - assertNotNull(header) - assertNotNull(text) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/content/samples/ContentForSamplesTest.kt b/plugins/base/src/test/kotlin/content/samples/ContentForSamplesTest.kt deleted file mode 100644 index d166d8f8..00000000 --- a/plugins/base/src/test/kotlin/content/samples/ContentForSamplesTest.kt +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package content.samples - -import matchers.content.* -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.base.transformers.pages.KOTLIN_PLAYGROUND_SCRIPT -import org.jetbrains.dokka.model.DisplaySourceSet -import utils.TestOutputWriterPlugin -import utils.assertContains -import utils.classSignature -import utils.findTestType -import java.nio.file.Paths -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertNotEquals - -class ContentForSamplesTest : BaseAbstractTest() { - private val testDataDir = getTestDataDir("content/samples").toAbsolutePath() - - private val testConfiguration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - analysisPlatform = "jvm" - samples = listOf( - Paths.get("$testDataDir/samples.kt").toString(), - ) - } - } - } - - private val mppTestConfiguration = dokkaConfiguration { - moduleName = "example" - sourceSets { - val common = sourceSet { - name = "common" - displayName = "common" - analysisPlatform = "common" - sourceRoots = listOf("src/commonMain/kotlin/pageMerger/Test.kt") - samples = listOf( - Paths.get("$testDataDir/samples.kt").toString(), - ) - } - sourceSet { - name = "jvm" - displayName = "jvm" - analysisPlatform = "jvm" - dependentSourceSets = setOf(common.value.sourceSetID) - sourceRoots = listOf("src/jvmMain/kotlin/pageMerger/Test.kt") - samples = listOf( - Paths.get("$testDataDir/samples.kt").toString(), - ) - } - sourceSet { - name = "linuxX64" - displayName = "linuxX64" - analysisPlatform = "native" - dependentSourceSets = setOf(common.value.sourceSetID) - sourceRoots = listOf("src/linuxX64Main/kotlin/pageMerger/Test.kt") - samples = listOf( - Paths.get("$testDataDir/samples.kt").toString(), - ) - } - } - } - - @Test - fun `samples block is rendered in the description`() { - val writerPlugin = TestOutputWriterPlugin() - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - | /** - | * @sample [test.sampleForClassDescription] - | */ - |class Foo - """.trimIndent(), testConfiguration, - pluginOverrides = listOf(writerPlugin) - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("test", "Foo") - assertContains(page.embeddedResources, KOTLIN_PLAYGROUND_SCRIPT) - page.content.assertNode { - group { - header(1) { +"Foo" } - platformHinted { - classSignature( - emptyMap(), - "", - "", - emptySet(), - "Foo" - ) - header(4) { +"Samples" } - group { - codeBlock { - +"""| - |fun main() { - | //sampleStart - | print("Hello") - | //sampleEnd - |}""".trimMargin() - } - } - } - } - skipAllNotMatching() - } - } - renderingStage = { _, _ -> - assertNotEquals(-1, writerPlugin.writer.contents["root/test/-foo/index.html"]?.indexOf(KOTLIN_PLAYGROUND_SCRIPT)) - } - } - } - - @Test - fun `multiplatofrm class with samples in few platforms`() { - testInline( - """ - |/src/commonMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |/** - |* @sample [test.sampleForClassDescription] - |*/ - |expect open class Parent - | - |/src/jvmMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |/** - |* @sample unresolved - |*/ - |actual open class Parent - | - |/src/linuxX64Main/kotlin/pageMerger/Test.kt - |package pageMerger - | - |actual open class Parent - | - """.trimMargin(), - mppTestConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("pageMerger", "Parent") - assertContains(page.embeddedResources, KOTLIN_PLAYGROUND_SCRIPT) - page.content.assertNode { - group { - header(1) { +"Parent" } - platformHinted { - group { - +"expect open class " - link { - +"Parent" - } - } - group { - +"actual open class " - link { - +"Parent" - } - } - group { - +"actual open class " - link { - +"Parent" - } - } - header(4) { +"Samples" } - group { - codeBlock { - +"""| - |fun main() { - | //sampleStart - | print("Hello") - | //sampleEnd - |}""".trimMargin() - } - check { - sourceSets.assertSourceSet("common") - } - } - group { - +"unresolved" - check { - sourceSets.assertSourceSet("jvm") - } - } - } - } - skipAllNotMatching() - } - } - } - } -} - - -private fun Set<DisplaySourceSet>.assertSourceSet(expectedName: String) { - assertEquals(1, this.size) - assertEquals(expectedName, this.first().name) -} diff --git a/plugins/base/src/test/kotlin/content/seealso/ContentForSeeAlsoTest.kt b/plugins/base/src/test/kotlin/content/seealso/ContentForSeeAlsoTest.kt deleted file mode 100644 index fb72178b..00000000 --- a/plugins/base/src/test/kotlin/content/seealso/ContentForSeeAlsoTest.kt +++ /dev/null @@ -1,866 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package content.seealso - -import matchers.content.* -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.model.DisplaySourceSet -import org.jetbrains.dokka.pages.ContentDRILink -import utils.* -import kotlin.test.Test -import kotlin.test.assertEquals - -class ContentForSeeAlsoTest : BaseAbstractTest() { - private val testConfiguration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - classpath = listOfNotNull(jvmStdlibPath) - analysisPlatform = "jvm" - } - } - } - - private val mppTestConfiguration = dokkaConfiguration { - moduleName = "example" - sourceSets { - val common = sourceSet { - name = "common" - displayName = "common" - analysisPlatform = "common" - sourceRoots = listOf("src/commonMain/kotlin/pageMerger/Test.kt") - } - sourceSet { - name = "jvm" - displayName = "jvm" - analysisPlatform = "jvm" - dependentSourceSets = setOf(common.value.sourceSetID) - sourceRoots = listOf("src/jvmMain/kotlin/pageMerger/Test.kt") - } - sourceSet { - name = "linuxX64" - displayName = "linuxX64" - analysisPlatform = "native" - dependentSourceSets = setOf(common.value.sourceSetID) - sourceRoots = listOf("src/linuxX64Main/kotlin/pageMerger/Test.kt") - } - } - } - - @Test - fun `undocumented function`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |fun function(abc: String) { - | println(abc) - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("test", "function") - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - emptyMap(), - "", - "", - emptySet(), - "function", - null, - "abc" to ParamAttributes(emptyMap(), emptySet(), "String") - ) - } - } - } - } - } - } - } - - @Test - fun `undocumented seealso`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | /** - | * @see abc - | */ - |fun function(abc: String) { - | println(abc) - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("test", "function") - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - emptyMap(), - "", - "", - emptySet(), - "function", - null, - "abc" to ParamAttributes(emptyMap(), emptySet(), "String") - ) - } - after { - header(4) { +"See also" } - table { - group { - //DRI should be "test//abc/#/-1/" - link { +"abc" } - } - } - } - } - } - } - } - } - } - - @Test - fun `undocumented seealso without reference for class`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | /** - | * @see abc - | */ - |class Foo() - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("test", "Foo") - println(page.content) - page.content.assertNode { - group { - header(1) { +"Foo" } - platformHinted { - classSignature( - emptyMap(), - "", - "", - emptySet(), - "Foo" - ) - header(4) { +"See also" } - table { - group { - +"abc" - } - } - } - } - skipAllNotMatching() - } - } - } - } - - @OnlyDescriptors("No link for `abc` in K1") - @Test - fun `undocumented seealso with reference to parameter for class`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | /** - | * @see abc - | */ - |class Foo(abc: String) - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("test", "Foo") - println(page.content) - page.content.assertNode { - group { - header(1) { +"Foo" } - platformHinted { - classSignature( - emptyMap(), - "", - "", - emptySet(), - "Foo", - "abc" to ParamAttributes(emptyMap(), emptySet(), "String") - ) - header(4) { +"See also" } - table { - group { - +"abc" // link { +"abc" } - } - } - } - } - skipAllNotMatching() - } - } - } - } - - @OnlyDescriptors("issue #3179") - @Test - fun `undocumented seealso with reference to property for class`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | /** - | * @see abc - | */ - |class Foo(val abc: String) - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("test", "Foo") - println(page.content) - page.content.assertNode { - group { - header(1) { +"Foo" } - platformHinted { - classSignature( - emptyMap(), - "", - "", - emptySet(), - "Foo", - "val abc" to ParamAttributes(emptyMap(), emptySet(), "String") - ) - header(4) { +"See also" } - table { - group { - link { +"Foo.abc" } - } - } - } - } - skipAllNotMatching() - } - } - } - } - - @Test - fun `documented seealso`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | /** - | * @see abc Comment to abc - | */ - |fun function(abc: String) { - | println(abc) - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("test", "function") - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - emptyMap(), - "", - "", - emptySet(), - "function", - null, - "abc" to ParamAttributes(emptyMap(), emptySet(), "String") - ) - } - after { - header(4) { +"See also" } - table { - group { - //DRI should be "test//abc/#/-1/" - link { +"abc" } - group { - group { +"Comment to abc" } - } - } - } - } - } - } - } - } - } - } - - @OnlyDescriptors("issue #3179") - @Test - fun `documented seealso with reference to property for class`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | /** - | * @see abc Comment to abc - | */ - |class Foo(val abc: String) - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("test", "Foo") - println(page.content) - page.content.assertNode { - group { - header(1) { +"Foo" } - platformHinted { - classSignature( - emptyMap(), - "", - "", - emptySet(), - "Foo", - "val abc" to ParamAttributes(emptyMap(), emptySet(), "String") - ) - header(4) { +"See also" } - table { - group { - link { +"Foo.abc" } - group { - group { +"Comment to abc" } - } - } - } - } - } - skipAllNotMatching() - } - } - } - } - - @Test - fun `should use fully qualified name for unresolved link`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | /** - | * @see com.example.NonExistingClass description for non-existing - | */ - |fun function(abc: String) { - | println(abc) - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("test", "function") - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - emptyMap(), - "", - "", - emptySet(), - "function", - null, - "abc" to ParamAttributes(emptyMap(), emptySet(), "String") - ) - } - after { - header(4) { +"See also" } - table { - group { - +"com.example.NonExistingClass" - group { - group { +"description for non-existing" } - } - } - } - } - } - } - } - } - } - } - - @Test - fun `undocumented seealso with stdlib link`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | /** - | * @see Collection - | */ - |fun function(abc: String) { - | println(abc) - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("test", "function") - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - emptyMap(), - "", - "", - emptySet(), - "function", - null, - "abc" to ParamAttributes(emptyMap(), emptySet(), "String") - ) - } - after { - header(4) { +"See also" } - table { - group { - link { - check { - assertEquals( - "kotlin.collections/Collection///PointingToDeclaration/", - (this as ContentDRILink).address.toString() - ) - } - +"Collection" - } - } - } - - } - } - } - } - } - } - } - - @Test - fun `documented seealso with stdlib link`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | /** - | * @see Collection Comment to stdliblink - | */ - |fun function(abc: String) { - | println(abc) - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("test", "function") - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - emptyMap(), - "", - "", - emptySet(), - "function", - null, - "abc" to ParamAttributes(emptyMap(), emptySet(), "String") - ) - } - after { - header(4) { +"See also" } - table { - group { - //DRI should be "test//abc/#/-1/" - link { +"Collection" } - group { - group { +"Comment to stdliblink" } - } - } - - } - } - } - } - } - } - } - } - - @Test - fun `documented seealso with stdlib link with other tags`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | /** - | * random comment - | * @see Collection Comment to stdliblink - | * @author pikinier20 - | * @since 0.11 - | */ - |fun function(abc: String) { - | println(abc) - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("test", "function") - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - emptyMap(), - "", - "", - emptySet(), - "function", - null, - "abc" to ParamAttributes(emptyMap(), emptySet(), "String") - ) - } - after { - group { comment { +"random comment" } } - unnamedTag("Author") { comment { +"pikinier20" } } - unnamedTag("Since") { comment { +"0.11" } } - - header(4) { +"See also" } - table { - group { - //DRI should be "test//abc/#/-1/" - link { +"Collection" } - group { - group { +"Comment to stdliblink" } - } - } - } - - } - } - } - } - } - } - } - - @Test - fun `documented multiple see also`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | /** - | * @see abc Comment to abc1 - | * @see abc Comment to abc2 - | */ - |fun function(abc: String) { - | println(abc) - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("test", "function") - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - emptyMap(), - "", - "", - emptySet(), - "function", - null, - "abc" to ParamAttributes(emptyMap(), emptySet(), "String") - ) - } - after { - header(4) { +"See also" } - table { - group { - //DRI should be "test//abc/#/-1/" - link { +"abc" } - group { - group { +"Comment to abc2" } - } - } - } - - } - } - } - } - } - } - } - - @Test - fun `documented multiple see also mixed source`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | /** - | * @see abc Comment to abc1 - | * @see[Collection] Comment to collection - | */ - |fun function(abc: String) { - | println(abc) - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("test", "function") - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - emptyMap(), - "", - "", - emptySet(), - "function", - null, - "abc" to ParamAttributes(emptyMap(), emptySet(), "String") - ) - } - after { - header(4) { +"See also" } - table { - group { - //DRI should be "test//abc/#/-1/" - link { +"abc" } - group { - group { +"Comment to abc1" } - } - } - group { - //DRI should be "test//abc/#/-1/" - link { +"Collection" } - group { group { +"Comment to collection" } } - } - } - } - } - } - } - } - } - } - - @Test - fun `should prefix static function and property links with class name`() { - testInline( - """ - |/src/main/kotlin/com/example/package/CollectionExtensions.kt - |package com.example.util - | - |object CollectionExtensions { - | val property = "Hi" - | fun emptyList() {} - |} - | - |/src/main/kotlin/com/example/foo.kt - |package com.example - | - |import com.example.util.CollectionExtensions.property - |import com.example.util.CollectionExtensions.emptyList - | - |/** - | * @see [property] static property - | * @see [emptyList] static emptyList - | */ - |fun function() {} - """.trimIndent(), - testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("com.example", "function") - - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - annotations = emptyMap(), - visibility = "", - modifier = "", - keywords = emptySet(), - name = "function", - returnType = null, - ) - } - after { - header(4) { +"See also" } - table { - group { - link { +"CollectionExtensions.property" } - group { - group { +"static property" } - } - } - group { - link { +"CollectionExtensions.emptyList" } - group { - group { +"static emptyList" } - } - } - } - } - } - } - } - } - } - } - - @Test - fun `multiplatform class with seealso in few platforms`() { - testInline( - """ - |/src/commonMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |/** - |* @see Unit - |*/ - |expect open class Parent - | - |/src/jvmMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |val x = 0 - |/** - |* @see x resolved - |* @see y unresolved - |*/ - |actual open class Parent - | - |/src/linuxX64Main/kotlin/pageMerger/Test.kt - |package pageMerger - | - |actual open class Parent - | - """.trimMargin(), - mppTestConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.findTestType("pageMerger", "Parent") - page.content.assertNode { - group { - header(1) { +"Parent" } - platformHinted { - group { - +"expect open class " - link { - +"Parent" - } - } - group { - +"actual open class " - link { - +"Parent" - } - } - group { - +"actual open class " - link { - +"Parent" - } - } - header(4) { - +"See also" - check { - assertEquals(2, sourceSets.size) - } - } - table { - group { - link { +"Unit" } - check { - sourceSets.assertSourceSet("common") - } - } - group { - link { +"Unit" } - check { - sourceSets.assertSourceSet("jvm") - } - } - group { - link { +"x" } - group { group { +"resolved" } } - check { - sourceSets.assertSourceSet("jvm") - } - } - group { - +"y" - group { group { +"unresolved" } } - check { - sourceSets.assertSourceSet("jvm") - } - } - - check { - assertEquals(2, sourceSets.size) - } - } - } - } - skipAllNotMatching() - } - } - } - } -} - -private fun Set<DisplaySourceSet>.assertSourceSet(expectedName: String) { - assertEquals(1, this.size) - assertEquals(expectedName, this.first().name) -} diff --git a/plugins/base/src/test/kotlin/content/signatures/ConstructorsSignaturesTest.kt b/plugins/base/src/test/kotlin/content/signatures/ConstructorsSignaturesTest.kt deleted file mode 100644 index 9a413e0e..00000000 --- a/plugins/base/src/test/kotlin/content/signatures/ConstructorsSignaturesTest.kt +++ /dev/null @@ -1,469 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package content.signatures - -import matchers.content.* -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.pages.BasicTabbedContentType -import org.jetbrains.dokka.pages.ContentPage -import kotlin.test.Test -import utils.OnlyDescriptors - -class ConstructorsSignaturesTest : BaseAbstractTest() { - private val testConfiguration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - analysisPlatform = "jvm" - } - } - } - - @Test - fun `class name without parenthesis`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |class SomeClass - | - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } - .children.single { it.name == "SomeClass" } as ContentPage - page.content.assertNode { - group { - header(1) { +"SomeClass" } - platformHinted { - group { - +"class " - link { +"SomeClass" } - } - } - } - skipAllNotMatching() - } - } - } - } - - @Test - fun `class name with empty parenthesis`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |class SomeClass() - | - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } - .children.single { it.name == "SomeClass" } as ContentPage - page.content.assertNode { - group { - header(1) { +"SomeClass" } - platformHinted { - group { - +"class " - link { +"SomeClass" } - } - } - } - skipAllNotMatching() - } - } - } - } - - @Test - fun `class with a parameter`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |class SomeClass(a: String) - | - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } - .children.single { it.name == "SomeClass" } as ContentPage - page.content.assertNode { - group { - header(1) { +"SomeClass" } - platformHinted { - group { - +"class " - link { +"SomeClass" } - +"(" - group { - group { - +"a: " - group { link { +"String" } } - } - } - +")" - } - } - } - skipAllNotMatching() - } - } - } - } - - @Test - fun `class with a val parameter`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |class SomeClass(val a: String, var i: Int) - | - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } - .children.single { it.name == "SomeClass" } as ContentPage - page.content.assertNode { - group { - header(1) { +"SomeClass" } - platformHinted { - group { - +"class " - link { +"SomeClass" } - +"(" - group { - group { - +"val a: " - group { link { +"String" } } - +", " - } - group { - +"var i: " - group { link { +"Int" } } - } - } - +")" - } - } - } - skipAllNotMatching() - } - } - } - } - - @OnlyDescriptors("Order of constructors is different in K2") - @Test - fun `class with a parameterless secondary constructor`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |class SomeClass(a: String) { - | constructor() - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } - .children.single { it.name == "SomeClass" } as ContentPage - page.content.assertNode { - group { - header(1) { +"SomeClass" } - platformHinted { - group { - +"class " - link { +"SomeClass" } - +"(" - group { - group { - +"a: " - group { link { +"String" } } - } - } - +")" - } - } - } - tabbedGroup { - group { - tab(BasicTabbedContentType.CONSTRUCTOR) { - header { +"Constructors" } - table { - group { - link { +"SomeClass" } - platformHinted { - group { - +"constructor" - +"(" - +")" - } - group { - +"constructor" - +"(" - group { - group { - +"a: " - group { link { +"String" } } - } - } - +")" - } - } - } - } - } - } - skipAllNotMatching() - } - } - } - } - } - - - @OnlyDescriptors("Order of constructors is different in K2") - @Test - fun `class with a few documented constructors`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - | /** - | * some comment - | * @constructor ctor comment - | **/ - |class SomeClass(a: String){ - | /** - | * ctor one - | **/ - | constructor(): this("") - | - | /** - | * ctor two - | **/ - | constructor(b: Int): this("") - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } - .children.single { it.name == "SomeClass" } as ContentPage - page.content.assertNode { - group { - header(1) { +"SomeClass" } - platformHinted { - group { - +"class " - link { +"SomeClass" } - +"(" - group { - group { - +"a: " - group { link { +"String" } } - } - } - +")" - } - skipAllNotMatching() - } - } - tabbedGroup { - group { - tab(BasicTabbedContentType.CONSTRUCTOR) { - header { +"Constructors" } - table { - group { - link { +"SomeClass" } - platformHinted { - group { - +"constructor" - +"(" - +")" - } - group { - group { - group { +"ctor one" } - } - } - group { - +"constructor" - +"(" - group { - group { - +"b: " - group { - link { +"Int" } - } - } - } - +")" - } - group { - group { - group { +"ctor two" } - } - } - group { - +"constructor" - +"(" - group { - group { - +"a: " - group { - link { +"String" } - } - } - } - +")" - } - group { - group { - group { +"ctor comment" } - } - } - } - } - } - } - } - skipAllNotMatching() - } - } - } - } - } - - @Test - fun `class with explicitly documented constructor`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - | /** - | * some comment - | * @constructor ctor comment - | **/ - |class SomeClass(a: String) - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } - .children.single { it.name == "SomeClass" } as ContentPage - page.content.assertNode { - group { - header(1) { +"SomeClass" } - platformHinted { - group { - +"class " - link { +"SomeClass" } - +"(" - group { - group { - +"a: " - group { link { +"String" } } - } - } - +")" - } - skipAllNotMatching() - } - } - tabbedGroup { - group { - tab(BasicTabbedContentType.CONSTRUCTOR) { - header { +"Constructors" } - table { - group { - link { +"SomeClass" } - platformHinted { - group { - +"constructor" - +"(" - group { - group { - +"a: " - group { - link { +"String" } - } - } - } - +")" - } - group { - group { - group { +"ctor comment" } - } - } - } - } - } - } - } - skipAllNotMatching() - } - } - } - } - } - - @Test - fun `should render primary constructor, but not constructors block for annotation class`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |annotation class MyAnnotation(val param: String) {} - """.trimIndent(), - testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } - .children.single { it.name == "MyAnnotation" } as ContentPage - page.content.assertNode { - group { - header(1) { +"MyAnnotation" } - platformHinted { - group { - +"annotation class " - link { +"MyAnnotation" } - +"(" - group { - group { - +"val param: " - group { link { +"String" } } - } - } - +")" - } - } - } - group { - group { - group { - header { +"Properties" } - table { - skipAllNotMatching() - } - } - } - } - } - } - } - } -} diff --git a/plugins/base/src/test/kotlin/content/signatures/ContentForSignaturesTest.kt b/plugins/base/src/test/kotlin/content/signatures/ContentForSignaturesTest.kt deleted file mode 100644 index 8af9e082..00000000 --- a/plugins/base/src/test/kotlin/content/signatures/ContentForSignaturesTest.kt +++ /dev/null @@ -1,515 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package content.signatures - -import matchers.content.* -import org.jetbrains.dokka.DokkaConfiguration -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.pages.ContentPage -import org.jetbrains.dokka.pages.PackagePageNode -import utils.ParamAttributes -import utils.bareSignature -import utils.propertySignature -import utils.typealiasSignature -import kotlin.test.Test - -class ContentForSignaturesTest : BaseAbstractTest() { - - private val testConfiguration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - analysisPlatform = "jvm" - documentedVisibilities = setOf( - DokkaConfiguration.Visibility.PUBLIC, - DokkaConfiguration.Visibility.PRIVATE, - DokkaConfiguration.Visibility.PROTECTED, - DokkaConfiguration.Visibility.INTERNAL, - ) - } - } - } - - @Test - fun `function`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |fun function(abc: String): String { - | return "Hello, " + abc - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } - .children.single { it.name == "function" } as ContentPage - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - emptyMap(), - "", - "", - emptySet(), - "function", - "String", - "abc" to ParamAttributes(emptyMap(), emptySet(), "String") - ) - } - } - } - } - } - } - } - - @Test - fun `private function`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |private fun function(abc: String): String { - | return "Hello, " + abc - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } - .children.single { it.name == "function" } as ContentPage - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - emptyMap(), - "private", - "", - emptySet(), - "function", - "String", - "abc" to ParamAttributes(emptyMap(), emptySet(), "String") - ) - } - } - } - } - } - } - } - - @Test - fun `open function`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |open fun function(abc: String): String { - | return "Hello, " + abc - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } - .children.single { it.name == "function" } as ContentPage - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - emptyMap(), - "", - "open", - emptySet(), - "function", - "String", - "abc" to ParamAttributes(emptyMap(), emptySet(), "String") - ) - } - } - } - } - } - } - } - - @Test - fun `function without parameters`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |fun function(): String { - | return "Hello" - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } - .children.single { it.name == "function" } as ContentPage - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - annotations = emptyMap(), - visibility = "", - modifier = "", - keywords = emptySet(), - name = "function", - returnType = "String", - ) - } - } - } - - } - } - } - } - - - @Test - fun `suspend function`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |suspend fun function(abc: String): String { - | return "Hello, " + abc - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } - .children.single { it.name == "function" } as ContentPage - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - emptyMap(), - "", - "", - setOf("suspend"), - "function", - "String", - "abc" to ParamAttributes(emptyMap(), emptySet(), "String") - ) - } - } - } - } - } - } - } - - @Test - fun `protected open suspend function`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |protected open suspend fun function(abc: String): String { - | return "Hello, " + abc - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } - .children.single { it.name == "function" } as ContentPage - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - emptyMap(), - "protected", - "open", - setOf("suspend"), - "function", - "String", - "abc" to ParamAttributes(emptyMap(), emptySet(), "String") - ) - } - } - } - } - } - } - } - - @Test - fun `protected open suspend inline function`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |protected open suspend inline fun function(abc: String): String { - | return "Hello, " + abc - |} - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } - .children.single { it.name == "function" } as ContentPage - page.content.assertNode { - group { - header(1) { +"function" } - } - divergentGroup { - divergentInstance { - divergent { - bareSignature( - emptyMap(), - "protected", - "open", - setOf("inline", "suspend"), - "function", - "String", - "abc" to ParamAttributes(emptyMap(), emptySet(), "String") - ) - } - } - } - } - } - } - } - - @Test - fun `property`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |val property: Int = 6 - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } as PackagePageNode - page.content.assertNode { - propertySignature(emptyMap(), "", "", emptySet(), "val", "property", "Int", "6") - } - } - } - } - - @Test - fun `const property`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |const val property: Int = 6 - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } as PackagePageNode - page.content.assertNode { - propertySignature(emptyMap(), "", "", setOf("const"), "val", "property", "Int", "6") - } - } - } - } - - @Test - fun `protected property`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |protected val property: Int = 6 - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } as PackagePageNode - page.content.assertNode { - propertySignature(emptyMap(), "protected", "", emptySet(), "val", "property", "Int", "6") - } - } - } - } - - @Test - fun `protected lateinit property`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |protected lateinit var property: Int = 6 - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } as PackagePageNode - page.content.assertNode { - propertySignature(emptyMap(), "protected", "", setOf("lateinit"), "var", "property", "Int", null) - } - } - } - } - - @Test - fun `should not display default value for mutable property`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |var property: Int = 6 - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } as PackagePageNode - page.content.assertNode { - propertySignature( - annotations = emptyMap(), - visibility = "", - modifier = "", - keywords = setOf(), - preposition = "var", - name = "property", - type = "Int", - value = null - ) - } - } - } - } - - @Test - fun `typealias to String`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |typealias Alias = String - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } as PackagePageNode - page.content.assertNode { - typealiasSignature("Alias", "String") - } - } - } - } - - @Test - fun `typealias to Int`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |typealias Alias = Int - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } as PackagePageNode - page.content.assertNode { - typealiasSignature("Alias", "Int") - } - } - } - } - - @Test - fun `typealias to type in same package`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |typealias Alias = X - |class X - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } as PackagePageNode - page.content.assertNode { - typealiasSignature("Alias", "X") - } - } - } - } - - @Test - fun `typealias to type in different package`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - |import other.X - |typealias Alias = X - | - |/src/main/kotlin/test/source2.kt - |package other - |class X - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } as PackagePageNode - page.content.assertNode { - typealiasSignature("Alias", "X") - } - } - } - } - - @Test - fun `typealias to type in different package with same name`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - |typealias Alias = other.Alias - | - |/src/main/kotlin/test/source2.kt - |package other - |class Alias - """.trimIndent(), testConfiguration - ) { - pagesTransformationStage = { module -> - val page = module.children.single { it.name == "test" } as PackagePageNode - page.content.assertNode { - typealiasSignature("Alias", "other.Alias") - } - } - } - } -} diff --git a/plugins/base/src/test/kotlin/content/typealiases/TypealiasTest.kt b/plugins/base/src/test/kotlin/content/typealiases/TypealiasTest.kt deleted file mode 100644 index 4015e0f4..00000000 --- a/plugins/base/src/test/kotlin/content/typealiases/TypealiasTest.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 content.typealiases - -import matchers.content.* -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.model.dfs -import org.jetbrains.dokka.pages.ClasslikePageNode -import org.jetbrains.dokka.pages.PlatformHintedContent -import utils.assertNotNull -import kotlin.test.Test - - -class TypealiasTest : BaseAbstractTest() { - private val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - classpath = listOf(commonStdlibPath!!, jvmStdlibPath!!) - externalDocumentationLinks = listOf(stdlibExternalDocumentationLink) - } - } - } - - @Test - fun `typealias should have a dedicated page with full documentation`() { - testInline( - """ - |/src/main/kotlin/test/Test.kt - |package example - | - | /** - | * Brief text - | * - | * some text - | * - | * @see String - | * @throws Unit - | */ - | typealias A = String - """, - configuration - ) { - pagesTransformationStage = { module -> - val content = (module.dfs { it.name == "A" } as ClasslikePageNode).content - val platformHinted = content.dfs { it is PlatformHintedContent } - platformHinted.assertNotNull("platformHinted").assertNode { - group { - group { - group { - +"typealias " - group { group { link { +"A" } } } - +" = " - group { link { +"String" } } - } - } - - group { - group { - group { - group { +"Brief text" } - group { +"some text" } - } - } - } - - header { +"See also" } - table { - group { link { +"String" } } - } - - header { +"Throws" } - table { - group { group { link { +"Unit" } } } - } - } - } - } - } - } -} diff --git a/plugins/base/src/test/kotlin/enums/JavaEnumsTest.kt b/plugins/base/src/test/kotlin/enums/JavaEnumsTest.kt deleted file mode 100644 index 39c893e9..00000000 --- a/plugins/base/src/test/kotlin/enums/JavaEnumsTest.kt +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package enums - -import org.jetbrains.dokka.SourceLinkDefinitionImpl -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import signatures.renderedContent -import utils.TestOutputWriterPlugin -import java.net.URL -import kotlin.test.Test -import kotlin.test.assertEquals - -class JavaEnumsTest : BaseAbstractTest() { - - private val basicConfiguration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - } - } - } - - // Shouldn't try to give source links to synthetic methods (values, valueOf) if any are present - // https://github.com/Kotlin/dokka/issues/2544 - @Test - fun `java enum with configured source links should not fail build due to any synthetic methods`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - sourceLinks = listOf( - SourceLinkDefinitionImpl( - localDirectory = "src/main/java", - remoteUrl = URL("https://github.com/user/repo/tree/master/src/main/java"), - remoteLineSuffix = "#L" - ) - ) - } - } - } - - val writerPlugin = TestOutputWriterPlugin() - - testInline( - """ - |/src/main/java/basic/JavaEnum.java - |package testpackage - | - |/** - |* doc - |*/ - |public enum JavaEnum { - | ONE, TWO, THREE - |} - """.trimMargin(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val enumPage = writerPlugin.writer.renderedContent("root/testpackage/-java-enum/index.html") - val sourceLink = enumPage.select(".symbol .floating-right") - .select("a[href]") - .attr("href") - - - assertEquals( - "https://github.com/user/repo/tree/master/src/main/java/basic/JavaEnum.java#L6", - sourceLink - ) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/enums/KotlinEnumsTest.kt b/plugins/base/src/test/kotlin/enums/KotlinEnumsTest.kt deleted file mode 100644 index c32a5cc2..00000000 --- a/plugins/base/src/test/kotlin/enums/KotlinEnumsTest.kt +++ /dev/null @@ -1,471 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package enums - -import matchers.content.* -import org.jetbrains.dokka.SourceLinkDefinitionImpl -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.model.DEnum -import org.jetbrains.dokka.model.dfs -import org.jetbrains.dokka.pages.ClasslikePage -import org.jetbrains.dokka.pages.ClasslikePageNode -import org.jetbrains.dokka.pages.ContentGroup -import org.jsoup.Jsoup -import org.jsoup.nodes.Element -import signatures.renderedContent -import utils.* -import java.net.URL -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertNotNull -import kotlin.test.assertTrue - -class KotlinEnumsTest : BaseAbstractTest() { - - @Test - fun `should preserve enum source ordering for documentables`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - } - } - } - - val writerPlugin = TestOutputWriterPlugin() - - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package testpackage - | - |enum class TestEnum { - | ZERO, - | ONE, - | TWO, - | THREE, - | FOUR, - | FIVE, - | SIX, - | SEVEN, - | EIGHT, - | NINE - |} - """.trimMargin(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - documentablesTransformationStage = { module -> - val testPackage = module.packages[0] - assertEquals("testpackage", testPackage.name) - - val testEnum = testPackage.classlikes[0] as DEnum - assertEquals("TestEnum", testEnum.name) - - val enumEntries = testEnum.entries - assertEquals(10, enumEntries.count()) - - assertEquals("ZERO", enumEntries[0].name) - assertEquals("ONE", enumEntries[1].name) - assertEquals("TWO", enumEntries[2].name) - assertEquals("THREE", enumEntries[3].name) - assertEquals("FOUR", enumEntries[4].name) - assertEquals("FIVE", enumEntries[5].name) - assertEquals("SIX", enumEntries[6].name) - assertEquals("SEVEN", enumEntries[7].name) - assertEquals("EIGHT", enumEntries[8].name) - assertEquals("NINE", enumEntries[9].name) - } - } - } - - @Test - fun `should preserve enum source ordering for generated pages`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - } - } - } - - val writerPlugin = TestOutputWriterPlugin() - - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package testpackage - | - |enum class TestEnum { - | ZERO, - | ONE, - | TWO, - | THREE, - | FOUR, - | FIVE, - | SIX, - | SEVEN, - | EIGHT, - | NINE - |} - """.trimMargin(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - pagesGenerationStage = { rootPage -> - val packagePage = rootPage.children[0] - assertEquals("testpackage", packagePage.name) - - val testEnumNode = packagePage.children[0] - assertEquals("TestEnum", testEnumNode.name) - - val enumEntries = testEnumNode.children.filterIsInstance<ClasslikePage>() - assertEquals(10, enumEntries.size) - - assertEquals("ZERO", enumEntries[0].name) - assertEquals("ONE", enumEntries[1].name) - assertEquals("TWO", enumEntries[2].name) - assertEquals("THREE", enumEntries[3].name) - assertEquals("FOUR", enumEntries[4].name) - assertEquals("FIVE", enumEntries[5].name) - assertEquals("SIX", enumEntries[6].name) - assertEquals("SEVEN", enumEntries[7].name) - assertEquals("EIGHT", enumEntries[8].name) - assertEquals("NINE", enumEntries[9].name) - } - } - } - - @Test - fun `should preserve enum source ordering for rendered entries`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - } - } - } - - val writerPlugin = TestOutputWriterPlugin() - - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package testpackage - | - |enum class TestEnum { - | ZERO, - | ONE, - | TWO, - | THREE, - | FOUR, - | FIVE, - | SIX, - | SEVEN, - | EIGHT, - | NINE - |} - """.trimMargin(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val enumEntriesOnPage = writerPlugin.writer.renderedContent("root/testpackage/-test-enum/index.html") - .select("div[data-togglable=ENTRY] .table") - .select("div.table-row") - .select("div.keyValue") - .select("div.title") - .select("a") - - val enumEntries = enumEntriesOnPage.map { it.text() } - assertEquals(10, enumEntries.size) - - assertEquals("ZERO", enumEntries[0]) - assertEquals("ONE", enumEntries[1]) - assertEquals("TWO", enumEntries[2]) - assertEquals("THREE", enumEntries[3]) - assertEquals("FOUR", enumEntries[4]) - assertEquals("FIVE", enumEntries[5]) - assertEquals("SIX", enumEntries[6]) - assertEquals("SEVEN", enumEntries[7]) - assertEquals("EIGHT", enumEntries[8]) - assertEquals("NINE", enumEntries[9]) - } - } - } - - @Test - fun `should preserve enum source ordering for navigation menu`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - } - } - } - - val writerPlugin = TestOutputWriterPlugin() - - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package testpackage - | - |enum class TestEnum { - | ZERO, - | ONE, - | TWO, - | THREE, - | FOUR, - | FIVE, - | SIX, - | SEVEN, - | EIGHT, - | NINE - |} - """.trimMargin(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val sideMenu = writerPlugin.writer.navigationHtml().select("div.sideMenuPart") - - assertEquals("ZERO", sideMenu.select("#root-nav-submenu-0-0-0").text()) - assertEquals("ONE", sideMenu.select("#root-nav-submenu-0-0-1").text()) - assertEquals("TWO", sideMenu.select("#root-nav-submenu-0-0-2").text()) - assertEquals("THREE", sideMenu.select("#root-nav-submenu-0-0-3").text()) - assertEquals("FOUR", sideMenu.select("#root-nav-submenu-0-0-4").text()) - assertEquals("FIVE", sideMenu.select("#root-nav-submenu-0-0-5").text()) - assertEquals("SIX", sideMenu.select("#root-nav-submenu-0-0-6").text()) - assertEquals("SEVEN", sideMenu.select("#root-nav-submenu-0-0-7").text()) - assertEquals("EIGHT", sideMenu.select("#root-nav-submenu-0-0-8").text()) - assertEquals("NINE", sideMenu.select("#root-nav-submenu-0-0-9").text()) - } - } - } - - fun TestOutputWriter.navigationHtml(): Element = contents.getValue("navigation.html").let { Jsoup.parse(it) } - - @Test - fun `should handle companion object within enum`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - } - } - } - - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package testpackage - | - |enum class TestEnum { - | E1, - | E2; - | companion object {} - |} - """.trimMargin(), - configuration - ) { - documentablesTransformationStage = { m -> - m.packages.let { p -> - assertTrue(p.isNotEmpty(), "Package list cannot be empty") - p.first().classlikes.let { c -> - assertTrue(c.isNotEmpty(), "Classlikes list cannot be empty") - - val enum = c.first() as DEnum - assertNotNull(enum.companion) - } - } - } - } - } - - @Test - fun enumWithMethods() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - classpath = listOfNotNull(jvmStdlibPath) - } - } - } - - testInline( - """ - |/src/main/kotlin/basic/TestEnum.kt - |package testpackage - | - | - |interface Sample { - | fun toBeImplemented(): String - |} - | - |enum class TestEnum: Sample { - | E1 { - | override fun toBeImplemented(): String = "e1" - | } - |} - """.trimMargin(), - configuration - ) { - documentablesTransformationStage = { m -> - m.packages.let { p -> - p.first().classlikes.let { c -> - val enum = c.first { it is DEnum } as DEnum - val first = enum.entries.first() - - assertNotNull(first.functions.find { it.name == "toBeImplemented" }) - } - } - } - } - } - - @Test - @OnlyDescriptors("K2 has `compareTo`, that should be suppressed, due to #3196") - fun `enum should have functions on page`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - } - } - } - - testInline( - """ - |/src/main/kotlin/basic/TestEnum.kt - |package testpackage - | - | - |interface Sample { - | fun toBeImplemented(): String - |} - | - |enum class TestEnum: Sample { - | E1 { - | override fun toBeImplemented(): String = "e1" - | } - |} - """.trimMargin(), - configuration - ) { - pagesTransformationStage = { root -> - root.contentPage<ClasslikePageNode>("E1") { - assertHasFunctions("toBeImplemented") - } - - root.contentPage<ClasslikePageNode>("TestEnum") { - assertHasFunctions("toBeImplemented", "valueOf", "values") - } - } - } - } - - @Test - fun enumWithAnnotationsOnEntries() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - } - } - } - - testInline( - """ - |/src/main/kotlin/basic/TestEnum.kt - |package testpackage - | - |enum class TestEnum { - | /** - | Sample docs for E1 - | **/ - | @SinceKotlin("1.3") // This annotation is transparent due to lack of @MustBeDocumented annotation - | E1 - |} - """.trimMargin(), - configuration - ) { - pagesTransformationStage = { m -> - val entryNode = m.children.first { it.name == "testpackage" }.children.first { it.name == "TestEnum" }.children.filterIsInstance<ClasslikePageNode>().first() - val signature = (entryNode.content as ContentGroup).dfs { it is ContentGroup && it.dci.toString() == "[testpackage/TestEnum.E1///PointingToDeclaration/{\"org.jetbrains.dokka.links.EnumEntryDRIExtra\":{\"key\":\"org.jetbrains.dokka.links.EnumEntryDRIExtra\"}}][Cover]" } as ContentGroup - - signature.assertNode { - header(1) { +"E1" } - platformHinted { - group { - group { - link { +"E1" } - } - } - group { - group { - group { - +"Sample docs for E1" - } - } - } - } - } - } - } - } - - // Shouldn't try to give source links to synthetic methods (values, valueOf) if any are present - // Initially reported for Java, making sure it doesn't fail for Kotlin either - // https://github.com/Kotlin/dokka/issues/2544 - @Test - fun `kotlin enum with configured source links should not fail the build due to synthetic methods`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - sourceLinks = listOf( - SourceLinkDefinitionImpl( - localDirectory = "src/main/kotlin", - remoteUrl = URL("https://github.com/user/repo/tree/master/src/main/kotlin"), - remoteLineSuffix = "#L" - ) - ) - } - } - } - - val writerPlugin = TestOutputWriterPlugin() - - testInline( - """ - |/src/main/kotlin/basic/KotlinEnum.kt - |package testpackage - | - |/** - |* Doc - |*/ - |enum class KotlinEnum { - | ONE, TWO, THREE - |} - """.trimMargin(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val sourceLink = writerPlugin.writer.renderedContent("root/testpackage/-kotlin-enum/index.html") - .select(".symbol .floating-right") - .select("a[href]") - .attr("href") - - assertEquals( - "https://github.com/user/repo/tree/master/src/main/kotlin/basic/KotlinEnum.kt#L6", - sourceLink - ) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/expect/AbstractExpectTest.kt b/plugins/base/src/test/kotlin/expect/AbstractExpectTest.kt deleted file mode 100644 index 7f187127..00000000 --- a/plugins/base/src/test/kotlin/expect/AbstractExpectTest.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 expect - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import java.nio.file.Files -import java.nio.file.Path -import java.nio.file.Paths -import java.util.concurrent.TimeUnit -import kotlin.test.assertEquals -import kotlin.test.assertTrue - -abstract class AbstractExpectTest( - val testDir: Path? = Paths.get("src/test", "resources", "expect"), - val formats: List<String> = listOf("html") -) : BaseAbstractTest() { - - protected fun generateOutput(path: Path, outFormat: String): Path? { - val config = dokkaConfiguration { - format = outFormat - sourceSets { - sourceSet { - sourceRoots = listOf(path.toAbsolutePath().asString()) - } - } - } - - var result: Path? = null - testFromData(config, cleanupOutput = false) { - renderingStage = { _, context -> result = context.configuration.outputDir.toPath() } - } - return result - } - - protected fun compareOutput(expected: Path, obtained: Path?, gitTimeout: Long = 500) { - obtained?.let { path -> - val gitCompare = ProcessBuilder( - "git", - "--no-pager", - "diff", - expected.asString(), - path.asString() - ).also { logger.info("git diff command: ${it.command().joinToString(" ")}") } - .also { it.redirectErrorStream() }.start() - - assertTrue(gitCompare.waitFor(gitTimeout, TimeUnit.MILLISECONDS), "Git timed out after $gitTimeout") - gitCompare.inputStream.bufferedReader().lines().forEach { logger.info(it) } - assertEquals(0, gitCompare.exitValue(), "${path.fileName}: outputs don't match") - } ?: throw AssertionError("obtained path is null") - } - - protected fun compareOutputWithExcludes( - expected: Path, - obtained: Path?, - excludes: List<String>, - timeout: Long = 500 - ) { - obtained?.let { _ -> - val (res, out, err) = runDiff(expected, obtained, excludes, timeout) - assertEquals(0, res, "Outputs differ:\nstdout - $out\n\nstderr - ${err ?: ""}") - } ?: throw AssertionError("obtained path is null") - } - - protected fun runDiff(exp: Path, obt: Path, excludes: List<String>, timeout: Long): ProcessResult = - ProcessBuilder().command( - listOf("diff", "-ru") + excludes.flatMap { listOf("-x", it) } + listOf("--", exp.asString(), obt.asString()) - ).also { - it.redirectErrorStream() - }.start().also { assertTrue(it.waitFor(timeout, TimeUnit.MILLISECONDS), "diff timed out") }.let { - ProcessResult(it.exitValue(), it.inputStream.bufferResult()) - } - - - protected fun testOutput(p: Path, outFormat: String) { - val expectOut = p.resolve("out/$outFormat") - val testOut = generateOutput(p.resolve("src"), outFormat) - .also { logger.info("Test out: ${it?.asString()}") } - - compareOutput(expectOut.toAbsolutePath(), testOut?.toAbsolutePath()) - testOut?.deleteRecursively() - } - - protected fun testOutputWithExcludes( - p: Path, - outFormat: String, - ignores: List<String> = emptyList(), - timeout: Long = 500 - ) { - val expected = p.resolve("out/$outFormat") - generateOutput(p.resolve("src"), outFormat) - ?.let { obtained -> - compareOutputWithExcludes(expected, obtained, ignores, timeout) - - obtained.deleteRecursively() - } ?: throw AssertionError("Output not generated for ${p.fileName}") - } - - protected fun generateExpect(p: Path, outFormat: String) { - val out = p.resolve("out/$outFormat/") - Files.createDirectories(out) - - val ret = generateOutput(p.resolve("src"), outFormat) - Files.list(out).forEach { it.deleteRecursively() } - ret?.let { Files.list(it).forEach { f -> f.copyRecursively(out.resolve(f.fileName)) } } - } - -} diff --git a/plugins/base/src/test/kotlin/expect/ExpectGenerator.kt b/plugins/base/src/test/kotlin/expect/ExpectGenerator.kt deleted file mode 100644 index 0568ba74..00000000 --- a/plugins/base/src/test/kotlin/expect/ExpectGenerator.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 expect - -import kotlin.test.Ignore -import kotlin.test.Test - -class ExpectGenerator : AbstractExpectTest() { - - @Ignore - @Test - fun generateAll() = testDir?.dirsWithFormats(formats).orEmpty().forEach { (p, f) -> - generateExpect(p, f) - } -} diff --git a/plugins/base/src/test/kotlin/expect/ExpectTest.kt b/plugins/base/src/test/kotlin/expect/ExpectTest.kt deleted file mode 100644 index f1eb2a77..00000000 --- a/plugins/base/src/test/kotlin/expect/ExpectTest.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 expect - -import org.junit.jupiter.api.DynamicTest.dynamicTest -import org.junit.jupiter.api.TestFactory -import kotlin.test.Ignore - -class ExpectTest : AbstractExpectTest() { - private val ignores: List<String> = listOf( - "images", - "scripts", - "images", - "styles", - "*.js", - "*.css", - "*.svg", - "*.map" - ) - - @Ignore - @TestFactory - fun expectTest() = testDir?.dirsWithFormats(formats).orEmpty().map { (p, f) -> - dynamicTest("${p.fileName}-$f") { testOutputWithExcludes(p, f, ignores) } - } -} diff --git a/plugins/base/src/test/kotlin/expect/ExpectUtils.kt b/plugins/base/src/test/kotlin/expect/ExpectUtils.kt deleted file mode 100644 index a8b1b187..00000000 --- a/plugins/base/src/test/kotlin/expect/ExpectUtils.kt +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package expect - -import java.io.InputStream -import java.nio.file.Files -import java.nio.file.Path -import kotlin.streams.toList - -data class ProcessResult(val code: Int, val out: String, val err: String? = null) - -internal fun Path.dirsWithFormats(formats: List<String>): List<Pair<Path, String>> = - Files.list(this).toList().filter { Files.isDirectory(it) }.flatMap { p -> formats.map { p to it } } - -internal fun Path.asString() = normalize().toString() -internal fun Path.deleteRecursively() = toFile().deleteRecursively() - -internal fun Path.copyRecursively(target: Path) = toFile().copyRecursively(target.toFile()) - -internal fun Path.listRecursively(filter: (Path) -> Boolean): List<Path> = when { - Files.isDirectory(this) -> listOfNotNull(takeIf(filter)) + Files.list(this).toList().flatMap { - it.listRecursively( - filter - ) - } - Files.isRegularFile(this) -> listOfNotNull(this.takeIf(filter)) - else -> emptyList() - } - -internal fun InputStream.bufferResult(): String = this.bufferedReader().lines().toList().joinToString("\n") diff --git a/plugins/base/src/test/kotlin/expectActuals/ExpectActualsTest.kt b/plugins/base/src/test/kotlin/expectActuals/ExpectActualsTest.kt deleted file mode 100644 index 3fc6e5c5..00000000 --- a/plugins/base/src/test/kotlin/expectActuals/ExpectActualsTest.kt +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package expectActuals - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.model.withDescendants -import org.jetbrains.dokka.pages.ClasslikePageNode -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertTrue - - -class ExpectActualsTest : BaseAbstractTest() { - - @Test - fun `three same named expect actual classes`() { - - val configuration = dokkaConfiguration { - moduleName = "example" - sourceSets { - val common = sourceSet { - name = "common" - displayName = "common" - analysisPlatform = "common" - sourceRoots = listOf("src/commonMain/kotlin/pageMerger/Test.kt") - } - val commonJ = sourceSet { - name = "commonJ" - displayName = "commonJ" - analysisPlatform = "common" - sourceRoots = listOf("src/commonJMain/kotlin/pageMerger/Test.kt") - dependentSourceSets = setOf(common.value.sourceSetID) - } - val commonN1 = sourceSet { - name = "commonN1" - displayName = "commonN1" - analysisPlatform = "common" - sourceRoots = listOf("src/commonN1Main/kotlin/pageMerger/Test.kt") - dependentSourceSets = setOf(common.value.sourceSetID) - } - val commonN2 = sourceSet { - name = "commonN2" - displayName = "commonN2" - analysisPlatform = "common" - sourceRoots = listOf("src/commonN2Main/kotlin/pageMerger/Test.kt") - dependentSourceSets = setOf(common.value.sourceSetID) - } - sourceSet { - name = "js" - displayName = "js" - analysisPlatform = "js" - dependentSourceSets = setOf(commonJ.value.sourceSetID) - sourceRoots = listOf("src/jsMain/kotlin/pageMerger/Test.kt") - } - sourceSet { - name = "jvm" - displayName = "jvm" - analysisPlatform = "jvm" - dependentSourceSets = setOf(commonJ.value.sourceSetID) - sourceRoots = listOf("src/jvmMain/kotlin/pageMerger/Test.kt") - } - sourceSet { - name = "linuxX64" - displayName = "linuxX64" - analysisPlatform = "native" - dependentSourceSets = setOf(commonN1.value.sourceSetID) - sourceRoots = listOf("src/linuxX64Main/kotlin/pageMerger/Test.kt") - } - sourceSet { - name = "mingwX64" - displayName = "mingwX64" - analysisPlatform = "native" - dependentSourceSets = setOf(commonN1.value.sourceSetID) - sourceRoots = listOf("src/mingwX64Main/kotlin/pageMerger/Test.kt") - } - sourceSet { - name = "iosArm64" - displayName = "iosArm64" - analysisPlatform = "native" - dependentSourceSets = setOf(commonN2.value.sourceSetID) - sourceRoots = listOf("src/iosArm64Main/kotlin/pageMerger/Test.kt") - } - sourceSet { - name = "iosX64" - displayName = "iosX64" - analysisPlatform = "native" - dependentSourceSets = setOf(commonN2.value.sourceSetID) - sourceRoots = listOf("src/iosX64Main/kotlin/pageMerger/Test.kt") - } - } - } - - testInline( - """ - |/src/commonMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |/src/commonJMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |expect class A - | - |/src/commonN1Main/kotlin/pageMerger/Test.kt - |package pageMerger - | - |expect class A - | - |/src/commonN2Main/kotlin/pageMerger/Test.kt - |package pageMerger - | - |expect class A - | - |/src/jsMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |actual class A - | - |/src/jvmMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |actual class A - | - |/src/linuxX64Main/kotlin/pageMerger/Test.kt - |package pageMerger - | - |actual class A - | - |/src/mingwX64Main/kotlin/pageMerger/Test.kt - |package pageMerger - | - |actual class A - | - |/src/iosArm64Main/kotlin/pageMerger/Test.kt - |package pageMerger - | - |actual class A - | - |/src/iosX64Main/kotlin/pageMerger/Test.kt - |package pageMerger - | - |actual class A - | - """.trimMargin(), - configuration - ) { - pagesTransformationStage = { - val allChildren = it.withDescendants().filterIsInstance<ClasslikePageNode>().toList() - val commonJ = allChildren.filter { it.name == "[jvm, js]A" } - val commonN1 = allChildren.filter { it.name == "[mingwX64, linuxX64]A" } - val commonN2 = allChildren.filter { it.name == "[iosX64, iosArm64]A" } - val noClass = allChildren.filter { it.name == "A" } - assertEquals(1, commonJ.size, "There can be only one [jvm, js]A page") - assertTrue( - commonJ.first().documentables.firstOrNull()?.sourceSets?.map { it.displayName } - ?.containsAll(listOf("commonJ", "js", "jvm")) ?: false, - "A(jvm, js)should have commonJ, js, jvm sources" - ) - - assertEquals(1, commonN1.size, "There can be only one [mingwX64, linuxX64]A page") - assertTrue( - commonN1.first().documentables.firstOrNull()?.sourceSets?.map { it.displayName } - ?.containsAll(listOf("commonN1", "linuxX64", "mingwX64")) ?: false, - "[mingwX64, linuxX64]A should have commonN1, linuxX64, mingwX64 sources" - ) - - assertEquals(1, commonN2.size, "There can be only one [iosX64, iosArm64]A page") - assertTrue( - commonN2.first().documentables.firstOrNull()?.sourceSets?.map { it.displayName } - ?.containsAll(listOf("commonN2", "iosArm64", "iosX64")) ?: false, - "[iosX64, iosArm64]A should have commonN2, iosArm64, iosX64 sources" - ) - - assertTrue(noClass.isEmpty(), "There can't be any A page") - } - } - } -} diff --git a/plugins/base/src/test/kotlin/filter/DeprecationFilterTest.kt b/plugins/base/src/test/kotlin/filter/DeprecationFilterTest.kt deleted file mode 100644 index 75d82e9b..00000000 --- a/plugins/base/src/test/kotlin/filter/DeprecationFilterTest.kt +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package filter - -import org.jetbrains.dokka.DokkaDefaults -import org.jetbrains.dokka.PackageOptionsImpl -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import kotlin.test.Test -import kotlin.test.assertTrue - -class DeprecationFilterTest : BaseAbstractTest() { - - @Test - fun `should skip hidden deprecated level regardless of skipDeprecated`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin/basic/Test.kt") - classpath = listOfNotNull(jvmStdlibPath) - skipDeprecated = false - perPackageOptions = mutableListOf( - PackageOptionsImpl( - "example.*", - true, - false, - false, - false, - DokkaDefaults.documentedVisibilities - ) - ) - } - } - } - - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package example - | - |@Deprecated("dep", level = DeprecationLevel.HIDDEN) - |fun testFunction() { } - | - """.trimMargin(), - configuration - ) { - preMergeDocumentablesTransformationStage = { - assertTrue( - it.first().packages.first().functions.isEmpty() - ) - } - } - } - - @Test - fun `function with false global skipDeprecated`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - skipDeprecated = false - sourceRoots = listOf("src/main/kotlin/basic/Test.kt") - } - } - } - - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package example - | - |fun testFunction() { } - | - | - | - """.trimMargin(), - configuration - ) { - preMergeDocumentablesTransformationStage = { - assertTrue( - it.first().packages.first().functions.size == 1 - ) - } - } - } - - @Test - fun `deprecated function with false global skipDeprecated`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - skipDeprecated = false - sourceRoots = listOf("src/main/kotlin/basic/Test.kt") - } - } - } - - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package example - | - |@Deprecated("dep") - |fun testFunction() { } - | - | - """.trimMargin(), - configuration - ) { - preMergeDocumentablesTransformationStage = { - assertTrue( - it.first().packages.first().functions.size == 1 - ) - } - } - } - - @Test - fun `deprecated function with true global skipDeprecated`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin/basic/Test.kt") - skipDeprecated = true - } - } - } - - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package example - | - |@Deprecated("dep") - |fun testFunction() { } - | - | - """.trimMargin(), - configuration - ) { - preMergeDocumentablesTransformationStage = { - assertTrue( - it.first().packages.first().functions.isEmpty() - ) - } - } - } - - @Test - fun `should skip deprecated companion object`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin/basic/Test.kt") - skipDeprecated = true - } - } - } - - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package example - | - |class Test { - | @Deprecated("dep") - | companion object { - | fun method() {} - | } - |} - | - | - """.trimMargin(), - configuration - ) { - preMergeDocumentablesTransformationStage = { - assertTrue( - it.first().packages.first().classlikes.first().classlikes.isEmpty() - ) - } - } - } - - @Test - fun `deprecated function with false global true package skipDeprecated`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin/basic/Test.kt") - skipDeprecated = false - perPackageOptions = mutableListOf( - PackageOptionsImpl( - "example.*", - true, - false, - true, - false, - DokkaDefaults.documentedVisibilities - ) - ) - } - } - } - - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package example - | - |@Deprecated("dep") - |fun testFunction() { } - | - | - """.trimMargin(), - configuration - ) { - preMergeDocumentablesTransformationStage = { - assertTrue( - it.first().packages.first().functions.isEmpty() - ) - } - } - } - - @Test - fun `deprecated function with true global false package skipDeprecated`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin/basic/Test.kt") - skipDeprecated = true - perPackageOptions = mutableListOf( - PackageOptionsImpl("example", - false, - false, - false, - false, - DokkaDefaults.documentedVisibilities - ) - ) - } - } - } - - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package example - | - |@Deprecated("dep") - |fun testFunction() { } - | - | - """.trimMargin(), - configuration - ) { - preMergeDocumentablesTransformationStage = { - assertTrue( - it.first().packages.first().functions.size == 1 - ) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/filter/EmptyPackagesFilterTest.kt b/plugins/base/src/test/kotlin/filter/EmptyPackagesFilterTest.kt deleted file mode 100644 index c6c6b160..00000000 --- a/plugins/base/src/test/kotlin/filter/EmptyPackagesFilterTest.kt +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package filter - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertTrue - -class EmptyPackagesFilterTest : BaseAbstractTest() { - @Test - fun `empty package with false skipEmptyPackages`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - skipEmptyPackages = false - sourceRoots = listOf("src/main/kotlin/basic/Test.kt") - } - } - } - - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package example - | - | - | - """.trimMargin(), - configuration - ) { - preMergeDocumentablesTransformationStage = { - assertTrue( - it.first().packages.isNotEmpty() - ) - } - } - } - @Test - fun `empty package with true skipEmptyPackages`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - skipEmptyPackages = true - sourceRoots = listOf("src/main/kotlin") - } - } - } - - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package example - | - | class ThisShouldBePresent { } - |/src/main/kotlin/empty/TestEmpty.kt - |package empty - """.trimMargin(), - configuration - ) { - preMergeDocumentablesTransformationStage = { modules -> - modules.forEach { module -> - assertEquals(listOf("example"), module.packages.map { it.name }) - } - } - } - } -} diff --git a/plugins/base/src/test/kotlin/filter/JavaFileFilterTest.kt b/plugins/base/src/test/kotlin/filter/JavaFileFilterTest.kt deleted file mode 100644 index 1c74c7ce..00000000 --- a/plugins/base/src/test/kotlin/filter/JavaFileFilterTest.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 filter - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import kotlin.test.Test -import kotlin.test.assertTrue - -class JavaFileFilterTest : BaseAbstractTest() { - @Test - fun `java file should be included`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - skipEmptyPackages = false - sourceRoots = listOf("src/main/java/basic/Test.java") - } - } - } - - testInline( - """ - |/src/main/java/basic/Test.java - |package example; - | - | - | - """.trimMargin(), - configuration - ) { - preMergeDocumentablesTransformationStage = { - assertTrue( - it.first().packages.isNotEmpty() - ) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/filter/JavaVisibilityFilterTest.kt b/plugins/base/src/test/kotlin/filter/JavaVisibilityFilterTest.kt deleted file mode 100644 index b648f802..00000000 --- a/plugins/base/src/test/kotlin/filter/JavaVisibilityFilterTest.kt +++ /dev/null @@ -1,308 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package filter - -import org.jetbrains.dokka.DokkaConfiguration -import org.jetbrains.dokka.DokkaConfigurationImpl -import org.jetbrains.dokka.DokkaDefaults -import org.jetbrains.dokka.PackageOptionsImpl -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.model.DClass -import org.jetbrains.dokka.model.DModule -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.MethodSource -import testApi.testRunner.dokkaConfiguration -import kotlin.test.Test -import kotlin.test.assertEquals - -class JavaVisibilityFilterTest : BaseAbstractTest() { - - @Test - fun `should document nothing private if no visibilities are included`() { - testVisibility( - """ - | public class JavaVisibilityTest { - | public String publicProperty = "publicProperty"; - | private String privateProperty = "privateProperty"; - | - | public void publicFunction() { } - | private void privateFunction() { } - | } - """.trimIndent(), - includedVisibility = DokkaDefaults.documentedVisibilities - ) { module -> - val clazz = module.first().packages.first().classlikes.filterIsInstance<DClass>().first() - clazz.properties.also { - assertEquals(1, it.size) - assertEquals("publicProperty", it[0].name) - } - clazz.functions.also { - assertEquals(1, it.size) - assertEquals("publicFunction", it[0].name) - } - } - } - - @Test - fun `should document private within public class`() { - testVisibility( - """ - | public class JavaVisibilityTest { - | public String publicProperty = "publicProperty"; - | protected String noise = "noise"; - | - | private String privateProperty = "privateProperty"; - | - | public void publicFunction() { } - | private void privateFunction() { } - | } - """.trimIndent(), - includedVisibility = setOf(DokkaConfiguration.Visibility.PUBLIC, DokkaConfiguration.Visibility.PRIVATE) - ) { module -> - val clazz = module.first().packages.first().classlikes.filterIsInstance<DClass>().first() - clazz.properties.also { - assertEquals(2, it.size) - assertEquals("publicProperty", it[0].name) - assertEquals("privateProperty", it[1].name) - } - clazz.functions.also { - assertEquals(2, it.size) - assertEquals("publicFunction", it[0].name) - assertEquals("privateFunction", it[1].name) - } - } - } - - @Test - fun `should document package private within private class`() { - testVisibility( - """ - | public class JavaVisibilityTest { - | public String publicProperty = "publicProperty"; - | protected String noise = "noise"; - | - | String packagePrivateProperty = "packagePrivateProperty"; - | - | public void publicFunction() { } - | void packagePrivateFunction() { } - | } - """.trimIndent(), - includedVisibility = setOf(DokkaConfiguration.Visibility.PUBLIC, DokkaConfiguration.Visibility.PACKAGE) - ) { module -> - val clazz = module.first().packages.first().classlikes.filterIsInstance<DClass>().first() - clazz.properties.also { - assertEquals(2, it.size) - assertEquals("publicProperty", it[0].name) - assertEquals("packagePrivateProperty", it[1].name) - } - clazz.functions.also { - assertEquals(2, it.size) - assertEquals("publicFunction", it[0].name) - assertEquals("packagePrivateFunction", it[1].name) - } - } - } - - @Test - fun `should document protected within public class`() { - testVisibility( - """ - | public class JavaVisibilityTest { - | public String publicProperty = "publicProperty"; - | String noise = "noise"; - | - | protected String protectedProperty = "protectedProperty"; - | - | public void publicFunction() { } - | protected void protectedFunction() { } - | } - """.trimIndent(), - includedVisibility = setOf(DokkaConfiguration.Visibility.PUBLIC, DokkaConfiguration.Visibility.PROTECTED) - ) { module -> - val clazz = module.first().packages.first().classlikes.filterIsInstance<DClass>().first() - clazz.properties.also { - assertEquals(2, it.size) - assertEquals("publicProperty", it[0].name) - assertEquals("protectedProperty", it[1].name) - } - clazz.functions.also { - assertEquals(2, it.size) - assertEquals("publicFunction", it[0].name) - assertEquals("protectedFunction", it[1].name) - } - } - } - - @Test - fun `should include all visibilities`() { - testVisibility( - """ - | public class JavaVisibilityTest { - | public String publicProperty = "publicProperty"; - | private String privateProperty = "privateProperty"; - | String packagePrivateProperty = "packagePrivateProperty"; - | protected String protectedProperty = "protectedProperty"; - | - | public void publicFunction() { } - | private void privateFunction() { } - | void packagePrivateFunction() { } - | protected void protectedFunction() { } - | } - """.trimIndent(), - includedVisibility = setOf( - DokkaConfiguration.Visibility.PUBLIC, - DokkaConfiguration.Visibility.PRIVATE, - DokkaConfiguration.Visibility.PROTECTED, - DokkaConfiguration.Visibility.PACKAGE, - ) - ) { module -> - val clazz = module.first().packages.first().classlikes.filterIsInstance<DClass>().first() - clazz.properties.also { - assertEquals(4, it.size) - assertEquals("publicProperty", it[0].name) - assertEquals("privateProperty", it[1].name) - assertEquals("packagePrivateProperty", it[2].name) - assertEquals("protectedProperty", it[3].name) - } - clazz.functions.also { - assertEquals(4, it.size) - assertEquals("publicFunction", it[0].name) - assertEquals("privateFunction", it[1].name) - assertEquals("packagePrivateFunction", it[2].name) - assertEquals("protectedFunction", it[3].name) - } - } - } - - private fun testVisibility(body: String, includedVisibility: Set<DokkaConfiguration.Visibility>, asserts: (List<DModule>) -> Unit) { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - documentedVisibilities = includedVisibility - sourceRoots = listOf("src/") - } - } - } - - testInline( - """ - |/src/main/java/basic/JavaVisibilityTest.java - |package example; - | - $body - | - """.trimMargin(), - configuration - ) { - preMergeDocumentablesTransformationStage = asserts - } - } - - @ParameterizedTest - @MethodSource(value = ["nonPublicPermutations", "publicPermutations"]) - fun `includeNonPublic - should include package private java class`(configuration: ConfigurationWithVisibility) { - testInline( - """ - |/src/main/java/basic/VisibilityTest.java - |package basic; - | - |${configuration.visibilityKeyword} class VisibilityTest { - | static void test() { - | - | } - |} - """.trimMargin(), - configuration.configuration - ) { - preMergeDocumentablesTransformationStage = { - assertEquals(configuration.expectedClasslikes, it.first().packages.first().classlikes.size) - } - } - } - - data class ConfigurationWithVisibility( - val visibilityKeyword: String, - val configuration: DokkaConfigurationImpl, - val expectedClasslikes: Int - ) - - companion object TestDataSources { - @Suppress("DEPRECATION") // for includeNonPublic - val globalExcludes = dokkaConfiguration { - sourceSets { - sourceSet { - includeNonPublic = false - sourceRoots = listOf("src/") - } - } - } - - @Suppress("DEPRECATION") // for includeNonPublic - val globalIncludes = dokkaConfiguration { - sourceSets { - sourceSet { - includeNonPublic = true - sourceRoots = listOf("src/") - } - } - } - - @Suppress("DEPRECATION") // for includeNonPublic - val globalIncludesPackageExcludes = dokkaConfiguration { - sourceSets { - sourceSet { - includeNonPublic = true - sourceRoots = listOf("src/") - perPackageOptions = mutableListOf( - PackageOptionsImpl( - "basic", - includeNonPublic = false, - reportUndocumented = false, - skipDeprecated = false, - suppress = false, - documentedVisibilities = DokkaDefaults.documentedVisibilities - ) - ) - } - } - } - - @Suppress("DEPRECATION") // for includeNonPublic - val globalExcludesPackageIncludes = dokkaConfiguration { - sourceSets { - sourceSet { - includeNonPublic = false - sourceRoots = listOf("src/") - perPackageOptions = mutableListOf( - PackageOptionsImpl( - "basic", - true, - false, - false, - false, - DokkaDefaults.documentedVisibilities - ) - ) - } - } - } - - @JvmStatic - fun nonPublicPermutations() = listOf("protected", "", "private").flatMap { keyword -> - listOf(globalIncludes, globalExcludesPackageIncludes).map { configuration -> - ConfigurationWithVisibility(keyword, configuration, expectedClasslikes = 1) - } + listOf(globalExcludes, globalExcludes).map { configuration -> - ConfigurationWithVisibility(keyword, configuration, expectedClasslikes = 0) - } - } - - @JvmStatic - fun publicPermutations() = - listOf(globalIncludes, globalExcludesPackageIncludes, globalExcludes, globalExcludes).map { configuration -> - ConfigurationWithVisibility("public", configuration, expectedClasslikes = 1) - } - } -} - diff --git a/plugins/base/src/test/kotlin/filter/KotlinArrayDocumentableReplacerTest.kt b/plugins/base/src/test/kotlin/filter/KotlinArrayDocumentableReplacerTest.kt deleted file mode 100644 index 240982c5..00000000 --- a/plugins/base/src/test/kotlin/filter/KotlinArrayDocumentableReplacerTest.kt +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package filter - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.model.DClass -import org.jetbrains.dokka.model.FunctionalTypeConstructor -import org.jetbrains.dokka.model.GenericTypeConstructor -import org.jetbrains.dokka.model.Invariance -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertNotEquals -import utils.OnlyDescriptors - -class KotlinArrayDocumentableReplacerTest : BaseAbstractTest() { - private val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin/basic/Test.kt") - } - } - } - - @Test - fun `function with array type params`() { - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package example - | - |fun testFunction(param1: Array<Int>, param2: Array<Boolean>, - | param3: Array<Float>, param4: Array<Double>, - | param5: Array<Long>, param6: Array<Short>, - | param7: Array<Char>, param8: Array<Byte>) { } - | - | - | - """.trimMargin(), - configuration - ) { - preMergeDocumentablesTransformationStage = { - val params = it.firstOrNull()?.packages?.firstOrNull()?.functions?.firstOrNull()?.parameters - - val typeArrayNames = listOf("IntArray", "BooleanArray", "FloatArray", "DoubleArray", "LongArray", "ShortArray", - "CharArray", "ByteArray") - - assertEquals(typeArrayNames.size, params?.size) - params?.forEachIndexed{ i, param -> - assertEquals(GenericTypeConstructor(DRI("kotlin", typeArrayNames[i]), emptyList()), - param.type) - } - } - } - } - @Test - fun `function with specific parameters of array type`() { - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package example - | - |fun testFunction(param1: Array<Array<Int>>, param2: (Array<Int>) -> Array<Int>) { } - | - | - | - """.trimMargin(), - configuration - ) { - preMergeDocumentablesTransformationStage = { - val params = it.firstOrNull()?.packages?.firstOrNull()?.functions?.firstOrNull()?.parameters - assertEquals( - Invariance(GenericTypeConstructor(DRI("kotlin", "IntArray"), emptyList())), - (params?.firstOrNull()?.type as? GenericTypeConstructor)?.projections?.firstOrNull()) - assertEquals( - Invariance(GenericTypeConstructor(DRI("kotlin", "IntArray"), emptyList())), - (params?.get(1)?.type as? FunctionalTypeConstructor)?.projections?.get(0)) - assertEquals( - Invariance(GenericTypeConstructor(DRI("kotlin", "IntArray"), emptyList())), - (params?.get(1)?.type as? FunctionalTypeConstructor)?.projections?.get(1)) - } - } - } - @Test - fun `property with array type`() { - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package example - | - |class MyTest { - | val isEmpty: Array<Boolean> - | get() = emptyList - | set(value) { - | field = value - | } - |} - | - | - """.trimMargin(), - configuration - ) { - preMergeDocumentablesTransformationStage = { - val myTestClass = it.firstOrNull()?.packages?.firstOrNull()?.classlikes?.firstOrNull() - val property = myTestClass?.properties?.firstOrNull() - - assertEquals(GenericTypeConstructor(DRI("kotlin", "BooleanArray"), emptyList()), - property?.type) - assertEquals(GenericTypeConstructor(DRI("kotlin", "BooleanArray"), emptyList()), - property?.getter?.type) - assertEquals(GenericTypeConstructor(DRI("kotlin", "BooleanArray"), emptyList()), - property?.setter?.parameters?.firstOrNull()?.type) - } - } - } - @Test - fun `typealias with array type`() { - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package example - | - |typealias arr = Array<Int> - | - | - """.trimMargin(), - configuration - ) { - preMergeDocumentablesTransformationStage = { - val arrTypealias = it.firstOrNull()?.packages?.firstOrNull()?.typealiases?.firstOrNull() - - assertEquals(GenericTypeConstructor(DRI("kotlin", "IntArray"), emptyList()), - arrTypealias?.underlyingType?.values?.firstOrNull()) - } - } - } - - // Unreal case: Upper bound of a type parameter cannot be an array - @Test - fun `generic fun and class`() { - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package example - | - |fun<T : Array<Int>> testFunction() { } - |class myTestClass<T : Array<Int>>{ } - | - | - """.trimMargin(), - configuration - ) { - preMergeDocumentablesTransformationStage = { - val testFun = it.firstOrNull()?.packages?.firstOrNull()?.functions?.firstOrNull() - val myTestClass = it.firstOrNull()?.packages?.firstOrNull()?.classlikes?.firstOrNull() as? DClass - - assertEquals(GenericTypeConstructor(DRI("kotlin","IntArray"), emptyList()), - testFun?.generics?.firstOrNull()?.bounds?.firstOrNull()) - assertEquals(GenericTypeConstructor(DRI("kotlin","IntArray"), emptyList()), - myTestClass?.generics?.firstOrNull()?.bounds?.firstOrNull()) - } - } - } - - @OnlyDescriptors("Fix module.contentScope in new Standalone API") // TODO fix module.contentScope [getKtModuleForKtElement] - @Test - fun `no jvm source set`() { - val configurationWithNoJVM = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin/basic/Test.kt") - analysisPlatform = "jvm" - } - sourceSet { - sourceRoots = listOf("src/main/kotlin/basic/TestJS.kt") - analysisPlatform = "js" - } - } - } - - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package example - | - |fun testFunction(param: Array<Int>) - | - | - |/src/main/kotlin/basic/TestJS.kt - |package example - | - |fun testFunction(param: Array<Int>) - """.trimMargin(), - configurationWithNoJVM - ) { - preMergeDocumentablesTransformationStage = { - val paramsJS = it[1].packages.firstOrNull()?.functions?.firstOrNull()?.parameters - assertNotEquals( - GenericTypeConstructor(DRI("kotlin", "IntArray"), emptyList()), - paramsJS?.firstOrNull()?.type) - - val paramsJVM = it.firstOrNull()?.packages?.firstOrNull()?.functions?.firstOrNull()?.parameters - assertEquals( - GenericTypeConstructor(DRI("kotlin", "IntArray"), emptyList()), - paramsJVM?.firstOrNull()?.type) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/filter/VisibilityFilterTest.kt b/plugins/base/src/test/kotlin/filter/VisibilityFilterTest.kt deleted file mode 100644 index 872e5865..00000000 --- a/plugins/base/src/test/kotlin/filter/VisibilityFilterTest.kt +++ /dev/null @@ -1,755 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package filter - -import org.jetbrains.dokka.DokkaConfiguration.Visibility -import org.jetbrains.dokka.DokkaDefaults -import org.jetbrains.dokka.PackageOptionsImpl -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.model.DClass -import org.jetbrains.dokka.model.DEnum -import org.jetbrains.dokka.model.DModule -import kotlin.test.* - -class VisibilityFilterTest : BaseAbstractTest() { - - @Test - fun `should document only public for defaults`() { - testVisibility( - """ - | val publicProperty: String = "publicProperty" - | private val privateProperty: String = "privateProperty" - | - | fun publicFun() { } - | private fun privateFun() { } - """.trimIndent(), - visibilities = DokkaDefaults.documentedVisibilities - ) { module -> - val pckg = module.first().packages.first() - pckg.properties.also { - assertEquals(1, it.size) - assertEquals("publicProperty", it[0].name) - } - pckg.functions.also { - assertEquals(1, it.size) - assertEquals("publicFun", it[0].name) - } - } - } - - @Test - fun `should document public`() { - testVisibility( - """ - | class TestClass<out V> { - | private var privateToThisVisibility: V? = null - | val publicProperty: String = "publicProperty" - | internal val noise: String = "noise" - | - | private val privateProperty: String = "privateProperty" - | - | fun publicFun() { } - | - | private fun privateFun() { } - | } - """.trimIndent(), - visibilities = setOf(Visibility.PUBLIC) - ) { module -> - val clazz = module.first().packages.first().classlikes.filterIsInstance<DClass>().first() - clazz.properties.also { - assertEquals(1, it.size) - assertEquals("publicProperty", it[0].name) - } - clazz.functions.also { - assertEquals(1, it.size) - assertEquals("publicFun", it[0].name) - } - } - } - - @Test - fun `should document only private`() { - testVisibility( - """ - | public val noiseMember: String = "noise" - | internal fun noiseFun() { } - | class NoisePublicClass { } - | - | private val privateProperty: String = "privateProperty" - | private fun privateFun() { } - """.trimIndent(), - visibilities = setOf(Visibility.PRIVATE) - ) { module -> - val pckg = module.first().packages.first() - - assertTrue(pckg.classlikes.isEmpty()) - pckg.properties.also { - assertEquals(1, it.size) - assertEquals("privateProperty", it[0].name) - } - pckg.functions.also { - assertEquals(1, it.size) - assertEquals("privateFun", it[0].name) - } - } - } - - @Test - fun `should document only internal`() { - testVisibility( - """ - | public val noiseMember: String = "noise" - | private fun noiseFun() { } - | class NoisePublicClass { } - | - | internal val internalProperty: String = "privateProperty" - | internal fun internalFun() { } - """.trimIndent(), - visibilities = setOf(Visibility.INTERNAL) - ) { module -> - val pckg = module.first().packages.first() - - assertTrue(pckg.classlikes.isEmpty()) - pckg.properties.also { - assertEquals(1, it.size) - assertEquals("internalProperty", it[0].name) - } - pckg.functions.also { - assertEquals(1, it.size) - assertEquals("internalFun", it[0].name) - } - } - } - - @Test - fun `should document private within public class`() { - testVisibility( - """ - | class TestClass { - | val publicProperty: String = "publicProperty" - | internal val noise: String = "noise" - | - | private val privateProperty: String = "privateProperty" - | - | fun publicFun() { } - | - | private fun privateFun() { } - | } - """.trimIndent(), - visibilities = setOf(Visibility.PUBLIC, Visibility.PRIVATE) - ) { module -> - val clazz = module.first().packages.first().classlikes.filterIsInstance<DClass>().first() - clazz.properties.also { - assertEquals(2, it.size) - assertEquals("publicProperty", it[0].name) - assertEquals("privateProperty", it[1].name) - } - clazz.functions.also { - assertEquals(2, it.size) - assertEquals("publicFun", it[0].name) - assertEquals("privateFun", it[1].name) - } - } - } - - @Test - fun `should document internal within public class`() { - testVisibility( - """ - | class TestClass { - | val publicProperty: String = "publicProperty" - | protected val noise: String = "noise" - | - | internal val internalProperty: String = "internalProperty" - | - | fun publicFun() { } - | - | internal fun internalFun() { } - | } - """.trimIndent(), - visibilities = setOf(Visibility.PUBLIC, Visibility.INTERNAL) - ) { module -> - val clazz = module.first().packages.first().classlikes.filterIsInstance<DClass>().first() - clazz.properties.also { - assertEquals(2, it.size) - assertEquals("publicProperty", it[0].name) - assertEquals("internalProperty", it[1].name) - } - clazz.functions.also { - assertEquals(2, it.size) - assertEquals("publicFun", it[0].name) - assertEquals("internalFun", it[1].name) - } - } - } - - @Test - fun `should document protected within public class`() { - testVisibility( - """ - | class TestClass { - | val publicProperty: String = "publicProperty" - | internal val noise: String = "noise" - | - | protected val protectedProperty: String = "protectedProperty" - | - | fun publicFun() { } - | - | protected fun protectedFun() { } - | } - """.trimIndent(), - visibilities = setOf(Visibility.PUBLIC, Visibility.PROTECTED) - ) { module -> - val clazz = module.first().packages.first().classlikes.filterIsInstance<DClass>().first() - clazz.properties.also { - assertEquals(2, it.size) - assertEquals("publicProperty", it[0].name) - assertEquals("protectedProperty", it[1].name) - } - clazz.functions.also { - assertEquals(2, it.size) - assertEquals("publicFun", it[0].name) - assertEquals("protectedFun", it[1].name) - } - } - } - - @Test - fun `should document all visibilities`() { - testVisibility( - """ - | class TestClass { - | val publicProperty: String = "publicProperty" - | - | private val privateProperty: String = "privateProperty" - | internal val internalProperty: String = "internalProperty" - | protected val protectedProperty: String = "protectedProperty" - | - | fun publicFun() { } - | - | private fun privateFun() { } - | internal fun internalFun() { } - | protected fun protectedFun() { } - | } - """.trimIndent(), - visibilities = setOf( - Visibility.PUBLIC, - Visibility.PRIVATE, - Visibility.PROTECTED, - Visibility.INTERNAL - ) - ) { module -> - val clazz = module.first().packages.first().classlikes.filterIsInstance<DClass>().first() - clazz.properties.also { - assertEquals(4, it.size) - assertEquals("publicProperty", it[0].name) - assertEquals("privateProperty", it[1].name) - assertEquals("internalProperty", it[2].name) - assertEquals("protectedProperty", it[3].name) - } - clazz.functions.also { - assertEquals(4, it.size) - assertEquals("publicFun", it[0].name) - assertEquals("privateFun", it[1].name) - assertEquals("internalFun", it[2].name) - assertEquals("protectedFun", it[3].name) - } - } - } - - @Test - fun `should ignore visibility settings for another package`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - perPackageOptions = listOf( - PackageOptionsImpl( - matchingRegex = "other", - documentedVisibilities = setOf(Visibility.PRIVATE), - includeNonPublic = false, - reportUndocumented = false, - skipDeprecated = false, - suppress = false - ) - ) - sourceRoots = listOf("src/main/kotlin/basic/Test.kt") - } - } - } - - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package example - | - | fun publicFun() { } - | - | private fun privateFun() { } - | - """.trimMargin(), - configuration - ) { - preMergeDocumentablesTransformationStage = { - val functions = it.first().packages.first().functions - assertEquals(1, functions.size) - assertEquals("publicFun", functions[0].name) - } - } - } - - @Test - fun `should choose package visibility settings over global`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - documentedVisibilities = setOf(Visibility.INTERNAL) - perPackageOptions = listOf( - PackageOptionsImpl( - matchingRegex = "example", - documentedVisibilities = setOf(Visibility.PRIVATE), - includeNonPublic = false, - reportUndocumented = false, - skipDeprecated = false, - suppress = false - ) - ) - sourceRoots = listOf("src/main/kotlin/basic/Test.kt") - } - } - } - - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package example - | - | internal fun internalFun() { } - | - | private fun privateFun() { } - | - """.trimMargin(), - configuration - ) { - preMergeDocumentablesTransformationStage = { - val functions = it.first().packages.first().functions - assertEquals(1, functions.size) - assertEquals("privateFun", functions[0].name) - } - } - } - - @Test - fun `private setter should be hidden if only PUBLIC is documented`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - documentedVisibilities = setOf(Visibility.PUBLIC) - sourceRoots = listOf("src/main/kotlin/basic/Test.kt") - } - } - } - - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package example - | - |var property: Int = 0 - |private set - | - | - """.trimMargin(), - configuration - ) { - preMergeDocumentablesTransformationStage = { - assertNull( - it.first().packages.first().properties.first().setter - ) - } - } - } - - @Test - fun `should choose new documentedVisibilities over deprecated includeNonPublic`() { - @Suppress("DEPRECATION") - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - includeNonPublic = true - documentedVisibilities = setOf(Visibility.INTERNAL) - sourceRoots = listOf("src/main/kotlin/basic/Test.kt") - } - } - } - - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package example - | - | internal fun internalFun() { } - | - | private fun privateFun() { } - | - """.trimMargin(), - configuration - ) { - preMergeDocumentablesTransformationStage = { - val functions = it.first().packages.first().functions - assertEquals(1, functions.size) - assertEquals("internalFun", functions[0].name) - } - } - } - - @Test - fun `includeNonPublic - public function with false global`() { - @Suppress("DEPRECATION") - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - includeNonPublic = false - sourceRoots = listOf("src/main/kotlin/basic/Test.kt") - } - } - } - - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package example - | - |fun testFunction() { } - | - | - | - """.trimMargin(), - configuration - ) { - preMergeDocumentablesTransformationStage = { - assertTrue( - it.first().packages.first().functions.size == 1 - ) - } - } - } - - @Test - fun `includeNonPublic - private function with false global`() { - @Suppress("DEPRECATION") - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - includeNonPublic = false - sourceRoots = listOf("src/main/kotlin/basic/Test.kt") - } - } - } - - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package example - | - |private fun testFunction() { } - | - | - | - """.trimMargin(), - configuration - ) { - preMergeDocumentablesTransformationStage = { - assertTrue( - it.first().packages.first().functions.isEmpty() - ) - } - } - } - - @Test - fun `includeNonPublic - private function with true global`() { - @Suppress("DEPRECATION") - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin/basic/Test.kt") - includeNonPublic = true - } - } - } - - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package example - | - |private fun testFunction() { } - | - | - | - """.trimMargin(), - configuration - ) { - preMergeDocumentablesTransformationStage = { - assertTrue( - it.first().packages.first().functions.size == 1 - ) - } - } - } - - @Test - fun `private setter with false global includeNonPublic`() { - @Suppress("DEPRECATION") - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - includeNonPublic = false - sourceRoots = listOf("src/main/kotlin/basic/Test.kt") - } - } - } - - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package example - | - |var property: Int = 0 - |private set - | - | - """.trimMargin(), - configuration - ) { - preMergeDocumentablesTransformationStage = { - assertNull( - it.first().packages.first().properties.first().setter - ) - } - } - } - - @Test - fun `includeNonPublic - private function with false global true package`() { - @Suppress("DEPRECATION") - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin/basic/Test.kt") - includeNonPublic = false - perPackageOptions = mutableListOf( - PackageOptionsImpl( - "example", - true, - false, - false, - false, - DokkaDefaults.documentedVisibilities - ) - ) - } - } - } - - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package example - | - |private fun testFunction() { } - | - | - | - """.trimMargin(), - configuration - ) { - preMergeDocumentablesTransformationStage = { - assertTrue( - it.first().packages.first().functions.size == 1 - ) - } - } - } - - @Test - fun `includeNonPublic - private function with true global false package`() { - @Suppress("DEPRECATION") - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin/basic/Test.kt") - includeNonPublic = true - perPackageOptions = mutableListOf( - PackageOptionsImpl( - "example", - false, - false, - false, - false, - DokkaDefaults.documentedVisibilities - ) - ) - } - } - } - - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package example - | - |private fun testFunction() { } - | - | - | - """.trimMargin(), - configuration - ) { - preMergeDocumentablesTransformationStage = { - assertTrue( - it.first().packages.first().functions.isEmpty() - ) - } - } - } - - @Test - fun `includeNonPublic - private typealias should be skipped`() { - @Suppress("DEPRECATION") - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - includeNonPublic = false - sourceRoots = listOf("src/main/kotlin/basic/Test.kt") - } - } - } - - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package example - | - |private typealias ABC = Int - """.trimMargin(), - configuration - ) { - preMergeDocumentablesTransformationStage = { - assertEquals(0, it.first().packages.first().typealiases.size) - } - } - } - - @Test - fun `includeNonPublic - internal property from enum should be skipped`() { - @Suppress("DEPRECATION") - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - includeNonPublic = false - sourceRoots = listOf("src/main/kotlin/basic/Test.kt") - } - } - } - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package enums - | - |enum class Test(internal val value: Int) { - | A(0) { - | override fun testFun(): Float = 0.05F - | }, - | B(1) { - | override fun testFun(): Float = 0.1F - | }; - | - | internal open fun testFun(): Float = 0.5F - |} - """.trimMargin(), - configuration - ) { - documentablesTransformationStage = { module -> - val enum = module.packages.flatMap { it.classlikes }.filterIsInstance<DEnum>().first() - val entry = enum.entries.first() - - assertFalse("testFun" in entry.functions.map { it.name }) - assertFalse("value" in entry.properties.map { it.name }) - assertFalse("testFun" in enum.functions.map { it.name }) - } - } - } - - @Test - fun `includeNonPublic - internal property from enum`() { - @Suppress("DEPRECATION") - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - includeNonPublic = true - sourceRoots = listOf("src/main/kotlin/basic/Test.kt") - classpath = listOfNotNull(jvmStdlibPath) - } - } - } - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package enums - | - |enum class Test(internal val value: Int) { - | A(0) { - | override fun testFun(): Float = 0.05F - | }, - | B(1) { - | override fun testFun(): Float = 0.1F - | }; - | - | internal open fun testFun(): Float = 0.5F - |} - """.trimMargin(), - configuration - ) { - documentablesTransformationStage = { module -> - val enum = module.packages.flatMap { it.classlikes }.filterIsInstance<DEnum>().first() - val entry = enum.entries.first() - - assertTrue("testFun" in entry.functions.map { it.name }) - assertTrue("value" in entry.properties.map { it.name }) - assertTrue("testFun" in enum.functions.map { it.name }) - } - } - } - - - private fun testVisibility( - body: String, - visibilities: Set<Visibility>, - asserts: (List<DModule>) -> Unit - ) { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - documentedVisibilities = visibilities - sourceRoots = listOf("src/main/kotlin/basic/Test.kt") - } - } - } - - testInline( - """ - |/src/main/kotlin/basic/Test.kt - |package example - | - $body - | - """.trimMargin(), - configuration - ) { - preMergeDocumentablesTransformationStage = asserts - } - } -} diff --git a/plugins/base/src/test/kotlin/issues/IssuesTest.kt b/plugins/base/src/test/kotlin/issues/IssuesTest.kt deleted file mode 100644 index 007b01ff..00000000 --- a/plugins/base/src/test/kotlin/issues/IssuesTest.kt +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package issues - -import org.jetbrains.dokka.model.DClass -import org.jetbrains.dokka.model.DFunction -import utils.AbstractModelTest -import utils.name -import kotlin.test.Test - -class IssuesTest : AbstractModelTest("/src/main/kotlin/issues/Test.kt", "issues") { - - @Test - fun errorClasses() { - inlineModelTest( - """ - |class Test(var value: String) { - | fun test(): List<String> = emptyList() - | fun brokenApply(v: String) = apply { value = v } - | - | fun brokenRun(v: String) = run { - | value = v - | this - | } - | - | fun brokenLet(v: String) = let { - | it.value = v - | it - | } - | - | fun brokenGenerics() = listOf("a", "b", "c") - | - | fun working(v: String) = doSomething() - | - | fun doSomething(): String = "Hello" - |} - """, - configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - classpath = listOfNotNull(jvmStdlibPath) - } - } - } - ) { - with((this / "issues" / "Test").cast<DClass>()) { - (this / "working").cast<DFunction>().type.name equals "String" - (this / "doSomething").cast<DFunction>().type.name equals "String" - (this / "brokenGenerics").cast<DFunction>().type.name equals "List" - (this / "brokenApply").cast<DFunction>().type.name equals "Test" - (this / "brokenRun").cast<DFunction>().type.name equals "Test" - (this / "brokenLet").cast<DFunction>().type.name equals "Test" - } - } - } -} diff --git a/plugins/base/src/test/kotlin/linkableContent/LinkableContentTest.kt b/plugins/base/src/test/kotlin/linkableContent/LinkableContentTest.kt deleted file mode 100644 index 1b73ffee..00000000 --- a/plugins/base/src/test/kotlin/linkableContent/LinkableContentTest.kt +++ /dev/null @@ -1,418 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package linkableContent - -import org.jetbrains.dokka.SourceLinkDefinitionImpl -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.base.transformers.pages.sourcelinks.SourceLinksTransformer -import org.jetbrains.dokka.model.WithGenerics -import org.jetbrains.dokka.model.dfs -import org.jetbrains.dokka.model.doc.Text -import org.jetbrains.dokka.pages.* -import org.jsoup.Jsoup -import utils.TestOutputWriterPlugin -import utils.assertNotNull -import java.net.URL -import java.nio.file.Paths -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertNotEquals -import kotlin.test.assertNotNull -import utils.OnlyDescriptorsMPP - -class LinkableContentTest : BaseAbstractTest() { - - @OnlyDescriptorsMPP("#3238") - @Test - fun `Include module and package documentation`() { - - val testDataDir = getTestDataDir("multiplatform/basicMultiplatformTest").toAbsolutePath() - val includesDir = getTestDataDir("linkable/includes").toAbsolutePath() - - val configuration = dokkaConfiguration { - moduleName = "example" - sourceSets { - val common = sourceSet { - name = "common" - displayName = "common" - analysisPlatform = "common" - sourceRoots = listOf(Paths.get("$testDataDir/commonMain/kotlin").toString()) - } - val jvmAndJsSecondCommonMain = sourceSet { - name = "jvmAndJsSecondCommonMain" - displayName = "jvmAndJsSecondCommonMain" - analysisPlatform = "common" - dependentSourceSets = setOf(common.value.sourceSetID) - sourceRoots = listOf(Paths.get("$testDataDir/jvmAndJsSecondCommonMain/kotlin").toString()) - } - sourceSet { - name = "js" - displayName = "js" - analysisPlatform = "js" - dependentSourceSets = setOf(common.value.sourceSetID, jvmAndJsSecondCommonMain.value.sourceSetID) - sourceRoots = listOf(Paths.get("$testDataDir/jsMain/kotlin").toString()) - includes = listOf(Paths.get("$includesDir/include2.md").toString()) - } - sourceSet { - name = "jvm" - displayName = "jvm" - analysisPlatform = "jvm" - dependentSourceSets = setOf(common.value.sourceSetID, jvmAndJsSecondCommonMain.value.sourceSetID) - sourceRoots = listOf(Paths.get("$testDataDir/jvmMain/kotlin").toString()) - includes = listOf(Paths.get("$includesDir/include1.md").toString()) - } - } - } - - testFromData(configuration) { - documentablesMergingStage = { - assertEquals(2, it.documentation.size) - assertEquals(2, it.packages.size) - assertEquals(1, it.packages.first().documentation.size) - assertEquals(1, it.packages.last().documentation.size) - } - } - - } - - @Test - fun `Sources multiplatform class documentation`() { - - val testDataDir = getTestDataDir("linkable/sources").toAbsolutePath() - - val configuration = dokkaConfiguration { - moduleName = "example" - - sourceSets { - val common = sourceSet { - name = "common" - displayName = "common" - analysisPlatform = "common" - sourceRoots = listOf(Paths.get("$testDataDir/commonMain/kotlin").toString()) - } - val jvmAndJsSecondCommonMain = sourceSet { - name = "jvmAndJsSecondCommonMain" - displayName = "jvmAndJsSecondCommonMain" - analysisPlatform = "common" - dependentSourceSets = setOf(common.value.sourceSetID) - sourceRoots = listOf(Paths.get("$testDataDir/jvmAndJsSecondCommonMain/kotlin").toString()) - } - sourceSet { - name = "js" - displayName = "js" - analysisPlatform = "js" - dependentSourceSets = setOf(common.value.sourceSetID, jvmAndJsSecondCommonMain.value.sourceSetID) - sourceRoots = listOf(Paths.get("$testDataDir/jsMain/kotlin").toString()) - sourceLinks = listOf( - SourceLinkDefinitionImpl( - localDirectory = "$testDataDir/jsMain/kotlin", - remoteUrl = URL("https://github.com/user/repo/tree/master/src/jsMain/kotlin"), - remoteLineSuffix = "#L" - ) - ) - } - sourceSet { - name = "jvm" - displayName = "jvm" - analysisPlatform = "jvm" - dependentSourceSets = setOf(common.value.sourceSetID, jvmAndJsSecondCommonMain.value.sourceSetID) - sourceRoots = listOf(Paths.get("$testDataDir/jvmMain/kotlin").toString()) - sourceLinks = listOf( - SourceLinkDefinitionImpl( - localDirectory = "$testDataDir/jvmMain/kotlin", - remoteUrl = URL("https://github.com/user/repo/tree/master/src/jvmMain/kotlin"), - remoteLineSuffix = "#L" - ) - ) - } - } - } - - testFromData(configuration) { - renderingStage = { rootPageNode, dokkaContext -> - val newRoot = SourceLinksTransformer(dokkaContext).invoke(rootPageNode) - val moduleChildren = newRoot.children - assertEquals(1, moduleChildren.size) - val packageChildren = moduleChildren.first().children - assertEquals(2, packageChildren.size) - packageChildren.forEach { - val name = it.name.substringBefore("Class") - val signature = (it as? ClasslikePageNode)?.content?.dfs { it is ContentGroup && it.dci.kind == ContentKind.Symbol }.assertNotNull("signature") - val crl = signature.children.last().children[1] as? ContentResolvedLink - assertEquals( - "https://github.com/user/repo/tree/master/src/${name.toLowerCase()}Main/kotlin/${name}Class.kt#L7", - crl?.address - ) - } - } - } - } - - @OnlyDescriptorsMPP("#3238") - @Test - fun `Samples multiplatform documentation`() { - - val testDataDir = getTestDataDir("linkable/samples").toAbsolutePath() - - val configuration = dokkaConfiguration { - moduleName = "example" - sourceSets { - val common = sourceSet { - name = "common" - displayName = "common" - analysisPlatform = "common" - sourceRoots = listOf(Paths.get("$testDataDir/commonMain/kotlin").toString()) - } - val jvmAndJsSecondCommonMain = sourceSet { - name = "jvmAndJsSecondCommonMain" - displayName = "jvmAndJsSecondCommonMain" - analysisPlatform = "common" - dependentSourceSets = setOf(common.value.sourceSetID) - sourceRoots = listOf(Paths.get("$testDataDir/jvmAndJsSecondCommonMain/kotlin").toString()) - } - sourceSet { - name = "js" - displayName = "js" - analysisPlatform = "js" - dependentSourceSets = setOf(common.value.sourceSetID, jvmAndJsSecondCommonMain.value.sourceSetID) - sourceRoots = listOf(Paths.get("$testDataDir/jsMain/kotlin").toString()) - samples = listOf("$testDataDir/jsMain/resources/Samples.kt") - } - sourceSet { - name = "jvm" - displayName = "jvm" - analysisPlatform = "jvm" - dependentSourceSets = setOf(common.value.sourceSetID, jvmAndJsSecondCommonMain.value.sourceSetID) - sourceRoots = listOf(Paths.get("$testDataDir/jvmMain/kotlin").toString()) - samples = listOf("$testDataDir/jvmMain/resources/Samples.kt") - } - } - } - - testFromData(configuration) { - renderingStage = { rootPageNode, _ -> - // TODO [beresnev] :((( -// val newRoot = DefaultSamplesTransformer(dokkaContext).invoke(rootPageNode) - val newRoot = rootPageNode - val moduleChildren = newRoot.children - assertEquals(1, moduleChildren.size) - val packageChildren = moduleChildren.first().children - assertEquals(2, packageChildren.size) - packageChildren.forEach { pageNode -> - val name = pageNode.name.substringBefore("Class") - val classChildren = pageNode.children - assertEquals(2, classChildren.size) - val function = classChildren.find { it.name == "printWithExclamation" } - val text = (function as MemberPageNode).content.let { it as ContentGroup }.children.last() - .let { it as ContentDivergentGroup }.children.single().after - .let { it as ContentGroup }.children.last() - .let { it as ContentGroup }.children.single() - .let { it as ContentCodeBlock }.children.single() - .let { it as ContentText }.text - assertEquals( - """|import p2.${name}Class - |fun main() { - | //sampleStart - | ${name}Class().printWithExclamation("Hi, $name") - | //sampleEnd - |}""".trimMargin(), - text - ) - } - } - } - } - - @Test - fun `Documenting return type for a function in inner class with generic parent`() { - testInline( - """ - |/src/main/kotlin/test/source.kt - |package test - | - |class Sample<S>(first: S){ - | inner class SampleInner { - | fun foo(): S = TODO() - | } - |} - | - """.trimIndent(), - dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - analysisPlatform = "jvm" - name = "js" - } - } - } - ) { - renderingStage = { module, _ -> - val sample = module.children.single { it.name == "test" } - .children.single { it.name == "Sample" } as ClasslikePageNode - val foo = sample - .children - .single { it.name == "SampleInner" } - .let { it as ClasslikePageNode } - .children - .single { it.name == "foo" } - .let { it as MemberPageNode } - - val returnTypeNode = foo.content.dfs { - val link = (it as? ContentDRILink)?.children - val child = link?.first() as? ContentText - child?.text == "S" - } as? ContentDRILink - - assertEquals( - (sample.documentables.firstOrNull() as WithGenerics).generics.first().dri, - returnTypeNode?.address - ) - } - } - } - - @Test - fun `Include module and package documentation with codeblock`() { - - val testDataDir = getTestDataDir("multiplatform/basicMultiplatformTest").toAbsolutePath() - val includesDir = getTestDataDir("linkable/includes").toAbsolutePath() - - val configuration = dokkaConfiguration { - moduleName = "example" - sourceSets { - sourceSet { - analysisPlatform = "js" - sourceRoots = listOf("jsMain").map { - Paths.get("$testDataDir/$it/kotlin").toString() - } - name = "js" - includes = listOf(Paths.get("$includesDir/include2.md").toString()) - } - sourceSet { - analysisPlatform = "jvm" - sourceRoots = listOf("jvmMain").map { - Paths.get("$testDataDir/$it/kotlin").toString() - } - name = "jvm" - includes = listOf(Paths.get("$includesDir/include1.md").toString()) - } - } - } - - testFromData(configuration) { - documentablesMergingStage = { - assertNotEquals(null, it.packages.first().documentation.values.single().dfs { - (it as? Text)?.body?.contains("@SqlTable") ?: false - }) - } - } - - } - - @Test - fun `Include module with description parted in two files`() { - - val testDataDir = getTestDataDir("multiplatform/basicMultiplatformTest").toAbsolutePath() - val includesDir = getTestDataDir("linkable/includes").toAbsolutePath() - - val configuration = dokkaConfiguration { - moduleName = "example" - sourceSets { - val common = sourceSet { - name = "common" - displayName = "common" - analysisPlatform = "common" - sourceRoots = listOf(Paths.get("$testDataDir/commonMain/kotlin").toString()) - } - val jvmAndJsSecondCommonMain = sourceSet { - name = "jvmAndJsSecondCommonMain" - displayName = "jvmAndJsSecondCommonMain" - analysisPlatform = "common" - dependentSourceSets = setOf(common.value.sourceSetID) - sourceRoots = listOf(Paths.get("$testDataDir/jvmAndJsSecondCommonMain/kotlin").toString()) - } - sourceSet { - name = "js" - displayName = "js" - analysisPlatform = "js" - dependentSourceSets = setOf(common.value.sourceSetID, jvmAndJsSecondCommonMain.value.sourceSetID) - sourceRoots = listOf(Paths.get("$testDataDir/jsMain/kotlin").toString()) - includes = listOf(Paths.get("$includesDir/include2.md").toString()) - } - sourceSet { - name = "jvm" - displayName = "jvm" - analysisPlatform = "jvm" - dependentSourceSets = setOf(common.value.sourceSetID, jvmAndJsSecondCommonMain.value.sourceSetID) - sourceRoots = listOf(Paths.get("$testDataDir/jvmMain/kotlin").toString()) - includes = listOf( - Paths.get("$includesDir/include1.md").toString(), - Paths.get("$includesDir/include11.md").toString() - ) - } - } - } - - testFromData(configuration) { - documentablesMergingStage = { module -> - val value = module.documentation.entries.single { - it.key.displayName == "jvm" - }.value - assertNotNull(value.dfs { - (it as? Text)?.body == "This is second JVM documentation for module example" - }) - - assertNotNull(value.dfs { - (it as? Text)?.body == "This is JVM documentation for module example" - }) - } - } - } - - @Test - fun `should have a correct link to declaration from another source set`() { - val writerPlugin = TestOutputWriterPlugin() - val configuration = dokkaConfiguration { - sourceSets { - val common = sourceSet { - sourceRoots = listOf("src/commonMain") - analysisPlatform = "common" - name = "common" - displayName = "common" - } - sourceSet { - sourceRoots = listOf("src/jvmMain/") - analysisPlatform = "jvm" - name = "jvm" - displayName = "jvm" - dependentSourceSets = setOf(common.value.sourceSetID) - } - } - } - - testInline( - """ - /src/commonMain/main.kt - class A - /src/jvmMain/main.kt - /** - * link to [A] - */ - class B - """.trimIndent() - , - pluginOverrides = listOf(writerPlugin), - configuration = configuration - ) { - renderingStage = { _, _ -> - val page = - Jsoup.parse(writerPlugin.writer.contents.getValue("root/[root]/-b/index.html")) - val link = page.select(".paragraph a").single() - assertEquals("../-a/index.html", link.attr("href")) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/linking/EnumValuesLinkingTest.kt b/plugins/base/src/test/kotlin/linking/EnumValuesLinkingTest.kt deleted file mode 100644 index 6dce09fc..00000000 --- a/plugins/base/src/test/kotlin/linking/EnumValuesLinkingTest.kt +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package linking - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.links.DRIExtraContainer -import org.jetbrains.dokka.links.EnumEntryDRIExtra -import org.jetbrains.dokka.model.dfs -import org.jetbrains.dokka.model.doc.DocumentationLink -import org.jetbrains.dokka.pages.ContentDRILink -import org.jetbrains.dokka.pages.ContentPage -import org.jsoup.Jsoup -import utils.TestOutputWriterPlugin -import java.nio.file.Paths -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertNotNull -import utils.OnlyDescriptors - -class EnumValuesLinkingTest : BaseAbstractTest() { - - @OnlyDescriptors // TODO - @Test - fun `check if enum values are correctly linked`() { - val writerPlugin = TestOutputWriterPlugin() - val testDataDir = getTestDataDir("linking").toAbsolutePath() - testFromData( - dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf(Paths.get("$testDataDir/jvmMain/kotlin").toString()) - analysisPlatform = "jvm" - name = "jvm" - } - } - }, - pluginOverrides = listOf(writerPlugin) - ) { - documentablesTransformationStage = { - val classlikes = it.packages.single().children - assertEquals(4, classlikes.size) - - val javaLinker = classlikes.single { it.name == "JavaLinker" } - javaLinker.documentation.values.single().children.run { - when (val kotlinLink = this[0].children[1].children[1]) { - is DocumentationLink -> kotlinLink.dri.run { - assertEquals("KotlinEnum.ON_CREATE", this.classNames) - assertEquals(null, this.callable) - assertNotNull(DRIExtraContainer(extra)[EnumEntryDRIExtra]) - } - else -> throw AssertionError("Link node is not DocumentationLink type") - } - - when (val javaLink = this[0].children[2].children[1]) { - is DocumentationLink -> javaLink.dri.run { - assertEquals("JavaEnum.ON_DECEIT", this.classNames) - assertEquals(null, this.callable) - assertNotNull(DRIExtraContainer(extra)[EnumEntryDRIExtra]) - } - else -> throw AssertionError("Link node is not DocumentationLink type") - } - } - - val kotlinLinker = classlikes.single { it.name == "KotlinLinker" } - kotlinLinker.documentation.values.single().children.run { - when (val kotlinLink = this[0].children[0].children[5]) { - is DocumentationLink -> kotlinLink.dri.run { - assertEquals("KotlinEnum.ON_CREATE", this.classNames) - assertEquals(null, this.callable) - assertNotNull(DRIExtraContainer(extra)[EnumEntryDRIExtra]) - } - else -> throw AssertionError("Link node is not DocumentationLink type") - } - - when (val javaLink = this[0].children[0].children[9]) { - is DocumentationLink -> javaLink.dri.run { - assertEquals("JavaEnum.ON_DECEIT", this.classNames) - assertEquals(null, this.callable) - assertNotNull(DRIExtraContainer(extra)[EnumEntryDRIExtra]) - } - else -> throw AssertionError("Link node is not DocumentationLink type") - } - } - - assertEquals( - javaLinker.documentation.values.single().children[0].children[1].children[1].let { it as? DocumentationLink }?.dri, - kotlinLinker.documentation.values.single().children[0].children[0].children[5].let { it as? DocumentationLink }?.dri - ) - - assertEquals( - javaLinker.documentation.values.single().children[0].children[2].children[1].let { it as? DocumentationLink }?.dri, - kotlinLinker.documentation.values.single().children[0].children[0].children[9].let { it as? DocumentationLink }?.dri - ) - } - - renderingStage = { rootPageNode, _ -> - val classlikes = rootPageNode.children.single().children - assertEquals(4, classlikes.size) - - val javaLinker = classlikes.single { it.name == "JavaLinker" } - (javaLinker as ContentPage).run { - assertNotNull(content.dfs { it is ContentDRILink && it.address.classNames == "KotlinEnum.ON_CREATE" }) - assertNotNull(content.dfs { it is ContentDRILink && it.address.classNames == "JavaEnum.ON_DECEIT" }) - } - - val kotlinLinker = classlikes.single { it.name == "KotlinLinker" } - (kotlinLinker as ContentPage).run { - assertNotNull(content.dfs { it is ContentDRILink && it.address.classNames == "KotlinEnum.ON_CREATE" }) - assertNotNull(content.dfs { it is ContentDRILink && it.address.classNames == "JavaEnum.ON_DECEIT" }) - } - - Jsoup - .parse(writerPlugin.writer.contents.getValue("root/linking.source/-java-linker/index.html")) - .select("a[href=\"../-kotlin-enum/-o-n_-c-r-e-a-t-e/index.html\"]") - .assertOnlyOneElement() - - Jsoup - .parse(writerPlugin.writer.contents.getValue("root/linking.source/-java-linker/index.html")) - .select("a[href=\"../-java-enum/-o-n_-d-e-c-e-i-t/index.html\"]") - .assertOnlyOneElement() - - Jsoup - .parse(writerPlugin.writer.contents.getValue("root/linking.source/-kotlin-linker/index.html")) - .select("a[href=\"../-kotlin-enum/-o-n_-c-r-e-a-t-e/index.html\"]") - .assertOnlyOneElement() - - Jsoup - .parse(writerPlugin.writer.contents.getValue("root/linking.source/-kotlin-linker/index.html")) - .select("a[href=\"../-java-enum/-o-n_-d-e-c-e-i-t/index.html\"]") - .assertOnlyOneElement() - } - } - } - - private fun <T> List<T>.assertOnlyOneElement() { - if (isEmpty() || size > 1) { - throw AssertionError("Single element expected in list: $this") - } - } -} diff --git a/plugins/base/src/test/kotlin/locationProvider/AndroidExternalLocationProviderTest.kt b/plugins/base/src/test/kotlin/locationProvider/AndroidExternalLocationProviderTest.kt deleted file mode 100644 index 1d107947..00000000 --- a/plugins/base/src/test/kotlin/locationProvider/AndroidExternalLocationProviderTest.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 locationProvider - -import org.jetbrains.dokka.base.resolvers.external.DefaultExternalLocationProvider -import org.jetbrains.dokka.base.resolvers.external.javadoc.AndroidExternalLocationProvider -import org.jetbrains.dokka.base.resolvers.shared.ExternalDocumentation -import org.jetbrains.dokka.base.resolvers.shared.PackageList -import org.jetbrains.dokka.base.resolvers.shared.RecognizedLinkFormat -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.links.Callable -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.links.TypeConstructor -import org.jetbrains.dokka.plugability.DokkaContext -import java.net.URL -import kotlin.test.Test -import kotlin.test.assertEquals - -class AndroidExternalLocationProviderTest : BaseAbstractTest() { - private val android = ExternalDocumentation( - URL("https://developer.android.com/reference/kotlin"), - PackageList( - RecognizedLinkFormat.DokkaHtml, - mapOf("" to setOf("android.content", "android.net")), - emptyMap(), - URL("file://not-used") - ) - ) - private val androidx = ExternalDocumentation( - URL("https://developer.android.com/reference/kotlin"), - PackageList( - RecognizedLinkFormat.DokkaHtml, - mapOf("" to setOf("androidx.appcompat.app")), - emptyMap(), - URL("file://not-used") - ) - ) - private val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - classpath += jvmStdlibPath!! - } - } - } - - private fun getTestLocationProvider( - externalDocumentation: ExternalDocumentation, - context: DokkaContext? = null - ): DefaultExternalLocationProvider { - val dokkaContext = context ?: DokkaContext.create(configuration, logger, emptyList()) - return AndroidExternalLocationProvider(externalDocumentation, dokkaContext) - } - - @Test - fun `#1230 anchor to a method from AndroidX`() { - val locationProvider = getTestLocationProvider(androidx) - val dri = DRI( - "androidx.appcompat.app", - "AppCompatActivity", - Callable("findViewById", null, listOf(TypeConstructor("kotlin.Int", emptyList()))) - ) - - assertEquals( - "${androidx.documentationURL}/androidx/appcompat/app/AppCompatActivity.html#findviewbyid", - locationProvider.resolve(dri) - ) - } - - @Test - fun `anchor to a method from Android`() { - val locationProvider = getTestLocationProvider(android) - val dri = DRI( - "android.content", - "ContextWrapper", - Callable( - "checkCallingUriPermission", - null, - listOf( - TypeConstructor("android.net.Uri", emptyList()), - TypeConstructor("kotlin.Int", emptyList()) - ) - ) - ) - - assertEquals( - "${android.documentationURL}/android/content/ContextWrapper.html#checkcallinguripermission", - locationProvider.resolve(dri) - ) - } - - @Test - fun `should return null for method not in list`() { - val locationProvider = getTestLocationProvider(android) - val dri = DRI( - "foo", - "Bar", - Callable( - "baz", - null, - emptyList() - ) - ) - - assertEquals(null, locationProvider.resolve(dri)) - } -} diff --git a/plugins/base/src/test/kotlin/locationProvider/DefaultExternalLocationProviderTest.kt b/plugins/base/src/test/kotlin/locationProvider/DefaultExternalLocationProviderTest.kt deleted file mode 100644 index c4c3c1e4..00000000 --- a/plugins/base/src/test/kotlin/locationProvider/DefaultExternalLocationProviderTest.kt +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package locationProvider - -import org.jetbrains.dokka.base.resolvers.external.DefaultExternalLocationProvider -import org.jetbrains.dokka.base.resolvers.shared.ExternalDocumentation -import org.jetbrains.dokka.base.resolvers.shared.PackageList -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.links.Callable -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.links.TypeConstructor -import org.jetbrains.dokka.plugability.DokkaContext -import java.net.URL -import kotlin.test.Test -import kotlin.test.assertEquals - -class DefaultExternalLocationProviderTest : BaseAbstractTest() { - private val testDataDir = - getTestDataDir("locationProvider").toAbsolutePath().toString().removePrefix("/").let { "/$it" } - private val kotlinLang = "https://kotlinlang.org/api/latest/jvm/stdlib" - private val packageListURL = URL("file://$testDataDir/stdlib-package-list") - private val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - classpath += jvmStdlibPath!! - } - } - } - - private fun getTestLocationProvider(context: DokkaContext? = null): DefaultExternalLocationProvider { - val dokkaContext = context ?: DokkaContext.create(configuration, logger, emptyList()) - val packageList = PackageList.load(packageListURL, 8, true)!! - val externalDocumentation = - ExternalDocumentation(URL(kotlinLang), packageList) - return DefaultExternalLocationProvider(externalDocumentation, ".html", dokkaContext) - } - - @Test - fun `ordinary link`() { - val locationProvider = getTestLocationProvider() - val dri = DRI("kotlin.reflect", "KVisibility") - - assertEquals("$kotlinLang/kotlin.reflect/-k-visibility/index.html", locationProvider.resolve(dri)) - } - - @Test - fun `relocation in package list`() { - val locationProvider = getTestLocationProvider() - val dri = DRI( - "", - "", - Callable( - "longArray", - null, - listOf( - TypeConstructor("kotlin.Int", emptyList()), - TypeConstructor("kotlin.Any", emptyList()) - ) - ) - ) - - assertEquals("$kotlinLang/kotlin-stdlib/[JS root]/long-array.html", locationProvider.resolve(dri)) - } - - @Test - fun `should return null for class not in list`() { - val locationProvider = getTestLocationProvider() - val dri = DRI( - "foo", - "Bar" - ) - - assertEquals(null, locationProvider.resolve(dri)) - } -} diff --git a/plugins/base/src/test/kotlin/locationProvider/Dokka010ExternalLocationProviderTest.kt b/plugins/base/src/test/kotlin/locationProvider/Dokka010ExternalLocationProviderTest.kt deleted file mode 100644 index 338e7495..00000000 --- a/plugins/base/src/test/kotlin/locationProvider/Dokka010ExternalLocationProviderTest.kt +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package locationProvider - -import org.jetbrains.dokka.base.resolvers.external.Dokka010ExternalLocationProvider -import org.jetbrains.dokka.base.resolvers.shared.ExternalDocumentation -import org.jetbrains.dokka.base.resolvers.shared.PackageList -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.links.Callable -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.links.TypeConstructor -import org.jetbrains.dokka.plugability.DokkaContext -import java.net.URL -import kotlin.test.Test -import kotlin.test.assertEquals - -class Dokka010ExternalLocationProviderTest : BaseAbstractTest() { - private val testDataDir = - getTestDataDir("locationProvider").toAbsolutePath().toString().removePrefix("/").let { "/$it" } - private val kotlinLang = "https://kotlinlang.org/api/latest/jvm/stdlib" - private val packageListURL = URL("file://$testDataDir/old-package-list") - private val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - classpath += jvmStdlibPath!! - } - } - } - - private fun getTestLocationProvider(context: DokkaContext? = null): Dokka010ExternalLocationProvider { - val dokkaContext = context ?: DokkaContext.create(configuration, logger, emptyList()) - val packageList = PackageList.load(packageListURL, 8, true)!! - val externalDocumentation = - ExternalDocumentation(URL(kotlinLang), packageList) - return Dokka010ExternalLocationProvider(externalDocumentation, ".html", dokkaContext) - } - - @Test - fun `ordinary link`() { - val locationProvider = getTestLocationProvider() - val dri = DRI("kotlin.reflect", "KVisibility") - - assertEquals("$kotlinLang/kotlin.reflect/-k-visibility/index.html", locationProvider.resolve(dri)) - } - - @Test - fun `relocation in package list`() { - val locationProvider = getTestLocationProvider() - val dri = DRI("kotlin.text", "StringBuilder") - - assertEquals("$kotlinLang/kotlin.relocated.text/-string-builder/index.html", locationProvider.resolve(dri)) - } - - @Test - fun `method relocation in package list`() { - val locationProvider = getTestLocationProvider() - val dri = DRI( - "kotlin", - "", - Callable( - "minus", - null, - listOf( - TypeConstructor("java.math.BigDecimal", emptyList()), - TypeConstructor("java.math.BigDecimal", emptyList()) - ) - ) - ) - - assertEquals("$kotlinLang/kotlin/java.math.-big-decimal/minus.html", locationProvider.resolve(dri)) - } - - @Test - fun `#1268 companion part should be stripped`() { - val locationProvider = getTestLocationProvider() - val dri = DRI( - "kotlin", - "Int.Companion", - Callable( - "MIN_VALUE", - null, - emptyList() - ) - ) - - assertEquals("$kotlinLang/kotlin/-int/-m-i-n_-v-a-l-u-e.html", locationProvider.resolve(dri)) - } - - @Test - fun `companion part should be stripped in relocations`() { - val locationProvider = getTestLocationProvider() - val dri = DRI( - "kotlin", - "Int.Companion", - Callable( - "MAX_VALUE", - null, - emptyList() - ) - ) - - assertEquals("$kotlinLang/kotlin/-int/max-value.html", locationProvider.resolve(dri)) - } - - @Test - fun `should return null for method not in list`() { - val locationProvider = getTestLocationProvider() - val dri = DRI( - "foo", - "Bar", - Callable( - "baz", - null, - emptyList() - ) - ) - - assertEquals(null, locationProvider.resolve(dri)) - } -} diff --git a/plugins/base/src/test/kotlin/locationProvider/DokkaLocationProviderTest.kt b/plugins/base/src/test/kotlin/locationProvider/DokkaLocationProviderTest.kt deleted file mode 100644 index dce19f70..00000000 --- a/plugins/base/src/test/kotlin/locationProvider/DokkaLocationProviderTest.kt +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package locationProvider - -import org.jetbrains.dokka.base.resolvers.local.DokkaLocationProvider -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.pages.* -import org.jetbrains.dokka.plugability.DokkaContext -import kotlin.test.Test -import kotlin.test.assertEquals - -class DokkaLocationProviderTest : BaseAbstractTest() { - - private val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - classpath += jvmStdlibPath!! - } - } - } - - private fun getTestLocationProvider(root: RootPageNode, context: DokkaContext? = null): DokkaLocationProvider { - val dokkaContext = context ?: DokkaContext.create(configuration, logger, emptyList()) - return DokkaLocationProvider(root, dokkaContext, ".html") - } - - @DslMarker - annotation class TestNavigationDSL - - @TestNavigationDSL - class NavigationDSL { - companion object { - private val stubDCI = DCI( - setOf( - DRI("kotlin", "Any") - ), - ContentKind.Comment - ) - val stubContentNode = ContentText("", stubDCI, emptySet()) - } - - operator fun invoke(name: String, fn: ModulesDsl.() -> Unit): RendererSpecificRootPage { - val modules = ModulesDsl().also { it.fn() } - return RendererSpecificRootPage(name = name, children = modules.pages, RenderingStrategy.DoNothing) - } - - @TestNavigationDSL - class ModulesDsl(val pages: MutableList<ModulePageNode> = mutableListOf()) { - fun modulePage(name: String, fn: PackageDsl.() -> Unit) { - val packages = PackageDsl().also { it.fn() } - pages.add( - ModulePageNode( - name = name, - children = packages.pages, - content = stubContentNode - ) - ) - } - } - - @TestNavigationDSL - class PackageDsl(val pages: MutableList<PackagePageNode> = mutableListOf()) { - fun packagePage(name: String, fn: ClassDsl.() -> Unit) { - val packages = ClassDsl().also { it.fn() } - pages.add( - PackagePageNode( - name = name, - children = packages.pages, - content = stubContentNode, - dri = emptySet() - ) - ) - } - } - - @TestNavigationDSL - class ClassDsl(val pages: MutableList<ClasslikePageNode> = mutableListOf()) { - fun classPage(name: String) { - pages.add( - ClasslikePageNode( - name = name, - children = emptyList(), - content = stubContentNode, - dri = emptySet() - ) - ) - } - } - } - - @Test - fun `links to a package with or without a class`() { - val root = NavigationDSL()("Root") { - modulePage("Module") { - packagePage("Package") {} - } - } - val packagePage = root.children.first().children.first() as PackagePageNode - val locationProvider = getTestLocationProvider(root) - val resolvedLink = locationProvider.resolve(packagePage) - val localToRoot = locationProvider.pathToRoot(packagePage) - - val rootWithClass = NavigationDSL()("Root") { - modulePage("Module") { - packagePage("Package") { - classPage("ClassA") - } - } - } - val packagePageWithClass = rootWithClass.children.first().children.first() as PackagePageNode - - val locationProviderWithClass = getTestLocationProvider(rootWithClass) - val localToRootWithClass = locationProviderWithClass.pathToRoot(packagePageWithClass) - val resolvedLinkWithClass = locationProviderWithClass.resolve(packagePageWithClass) - - assertEquals("-module/Package.html", resolvedLink) - assertEquals("../", localToRoot) - - assertEquals("-module/Package/index.html", resolvedLinkWithClass) - assertEquals("../../", localToRootWithClass) - } -} diff --git a/plugins/base/src/test/kotlin/locationProvider/JavadocExternalLocationProviderTest.kt b/plugins/base/src/test/kotlin/locationProvider/JavadocExternalLocationProviderTest.kt deleted file mode 100644 index 1a747429..00000000 --- a/plugins/base/src/test/kotlin/locationProvider/JavadocExternalLocationProviderTest.kt +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package locationProvider - -import org.jetbrains.dokka.base.resolvers.external.DefaultExternalLocationProvider -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.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.links.DRIExtraContainer -import org.jetbrains.dokka.links.EnumEntryDRIExtra -import org.jetbrains.dokka.links.PointingToDeclaration -import org.jetbrains.dokka.plugability.DokkaContext -import java.net.URL -import kotlin.test.Test -import kotlin.test.assertEquals - -class JavadocExternalLocationProviderTest : BaseAbstractTest() { - private val testDataDir = - getTestDataDir("locationProvider").toAbsolutePath().toString().removePrefix("/").let { "/$it" } - - private val jdk = "https://docs.oracle.com/javase/8/docs/api/" - private val jdkPackageListURL = URL("file://$testDataDir/jdk8-package-list") - - private val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - classpath += jvmStdlibPath!! - } - } - } - - private fun getTestLocationProvider(context: DokkaContext? = null): DefaultExternalLocationProvider { - val dokkaContext = context ?: DokkaContext.create(configuration, logger, emptyList()) - val packageList = PackageList.load(jdkPackageListURL, 8, true)!! - val externalDocumentation = - ExternalDocumentation(URL(jdk), packageList) - return JavadocExternalLocationProvider(externalDocumentation, "--", "-", dokkaContext) - } - - @Test - fun `link to enum entity of javadoc`() { - val locationProvider = getTestLocationProvider() - val ktDri = DRI( - "java.nio.file", - "StandardOpenOption.CREATE", - extra = DRIExtraContainer().also { it[EnumEntryDRIExtra] = EnumEntryDRIExtra }.encode() - ) - val javaDri = DRI( - "java.nio.file", - "StandardOpenOption.CREATE", - null, - PointingToDeclaration, - DRIExtraContainer().also { it[EnumEntryDRIExtra] = EnumEntryDRIExtra }.encode() - ) - - assertEquals( - "https://docs.oracle.com/javase/8/docs/api/java/nio/file/StandardOpenOption.html#CREATE", - locationProvider.resolve(ktDri) - ) - - assertEquals( - "https://docs.oracle.com/javase/8/docs/api/java/nio/file/StandardOpenOption.html#CREATE", - locationProvider.resolve(javaDri) - ) - } - - @Test - fun `link to nested class of javadoc`() { - val locationProvider = getTestLocationProvider() - val dri = DRI( - "java.rmi.activation", - "ActivationGroupDesc.CommandEnvironment" - ) - - assertEquals( - "https://docs.oracle.com/javase/8/docs/api/java/rmi/activation/ActivationGroupDesc.CommandEnvironment.html", - locationProvider.resolve(dri) - ) - } -} diff --git a/plugins/base/src/test/kotlin/locationProvider/MultiModuleLinkingTest.kt b/plugins/base/src/test/kotlin/locationProvider/MultiModuleLinkingTest.kt deleted file mode 100644 index 17327c4c..00000000 --- a/plugins/base/src/test/kotlin/locationProvider/MultiModuleLinkingTest.kt +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package locationProvider - -import org.jetbrains.dokka.base.resolvers.external.DefaultExternalLocationProvider -import org.jetbrains.dokka.base.resolvers.shared.ExternalDocumentation -import org.jetbrains.dokka.base.resolvers.shared.PackageList -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.plugability.DokkaContext -import java.net.URL -import kotlin.test.Test -import kotlin.test.assertEquals - -class MultiModuleLinkingTest : BaseAbstractTest() { - private val testDataDir = - getTestDataDir("locationProvider").toAbsolutePath().toString().removePrefix("/").let { "/$it" } - private val exampleDomain = "https://example.com" - private val packageListURL = URL("file://$testDataDir/multi-module-package-list") - private val kotlinLang = "https://kotlinlang.org/api/latest/jvm/stdlib" - private val stdlibPackageListURL = URL("file://$testDataDir/stdlib-package-list") - private val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - classpath += jvmStdlibPath!! - } - } - } - - private fun getTestLocationProvider(context: DokkaContext? = null): DefaultExternalLocationProvider { - val dokkaContext = context ?: DokkaContext.create(configuration, logger, emptyList()) - val packageList = PackageList.load(packageListURL, 8, true)!! - val externalDocumentation = - ExternalDocumentation(URL(exampleDomain), packageList) - return DefaultExternalLocationProvider(externalDocumentation, ".html", dokkaContext) - } - - private fun getStdlibTestLocationProvider(context: DokkaContext? = null): DefaultExternalLocationProvider { - val dokkaContext = context ?: DokkaContext.create(configuration, logger, emptyList()) - val packageList = PackageList.load(stdlibPackageListURL, 8, true)!! - val externalDocumentation = - ExternalDocumentation(URL(kotlinLang), packageList) - return DefaultExternalLocationProvider(externalDocumentation, ".html", dokkaContext) - } - - @Test - fun `should link to a multi-module declaration`() { - val locationProvider = getTestLocationProvider() - val dri = DRI("baz", "BazClass") - - assertEquals("$exampleDomain/moduleB/baz/-baz-class/index.html", locationProvider.resolve(dri)) - } - - @Test - fun `should not fail on non-present package`() { - val stdlibLocationProvider = getStdlibTestLocationProvider() - val locationProvider = getTestLocationProvider() - val dri = DRI("baz", "BazClass") - - assertEquals(null, stdlibLocationProvider.resolve(dri)) - assertEquals("$exampleDomain/moduleB/baz/-baz-class/index.html", locationProvider.resolve(dri)) - } - - @Test - fun `should handle relocations`() { - val locationProvider = getTestLocationProvider() - val dri = DRI("", "NoPackageClass") - - assertEquals("$exampleDomain/moduleB/[root]/-no-package-class/index.html", locationProvider.resolve(dri)) - } -} diff --git a/plugins/base/src/test/kotlin/markdown/KDocTest.kt b/plugins/base/src/test/kotlin/markdown/KDocTest.kt deleted file mode 100644 index 89f58f1b..00000000 --- a/plugins/base/src/test/kotlin/markdown/KDocTest.kt +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package markdown - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.model.DPackage -import org.jetbrains.dokka.model.doc.DocumentationNode -import org.jetbrains.dokka.pages.ModulePageNode -import kotlin.test.assertEquals - -abstract class KDocTest : BaseAbstractTest() { - - private val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin/example/Test.kt") - } - } - } - - private fun interpolateKdoc(kdoc: String) = """ - |/src/main/kotlin/example/Test.kt - |package example - | /** - ${kdoc.split("\n").joinToString("") { "| *$it\n" } } - | */ - |class Test - """.trimMargin() - - private fun actualDocumentationNode(modulePageNode: ModulePageNode) = - (modulePageNode.documentables.firstOrNull()?.children?.first() as DPackage) - .classlikes.single() - .documentation.values.single() - - - protected fun executeTest(kdoc: String, expectedDocumentationNode: DocumentationNode) { - testInline( - interpolateKdoc(kdoc), - configuration - ) { - pagesGenerationStage = { - assertEquals( - expectedDocumentationNode, - actualDocumentationNode(it as ModulePageNode) - ) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/markdown/LinkTest.kt b/plugins/base/src/test/kotlin/markdown/LinkTest.kt deleted file mode 100644 index f783892f..00000000 --- a/plugins/base/src/test/kotlin/markdown/LinkTest.kt +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package markdown - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.links.* -import org.jetbrains.dokka.model.WithGenerics -import org.jetbrains.dokka.model.dfs -import org.jetbrains.dokka.model.doc.* -import org.jetbrains.dokka.pages.ClasslikePageNode -import org.jetbrains.dokka.pages.ContentDRILink -import org.jetbrains.dokka.pages.MemberPageNode -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertNotNull - -class LinkTest : BaseAbstractTest() { - - @Test - fun linkToClassLoader() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin/parser") - } - } - } - testInline( - """ - |/src/main/kotlin/parser/Test.kt - |package parser - | - | /** - | * Some docs that link to [ClassLoader.clearAssertionStatus] - | */ - |fun test(x: ClassLoader) = x.clearAssertionStatus() - | - """.trimMargin(), - configuration - ) { - renderingStage = { rootPageNode, _ -> - assertNotNull((rootPageNode.children.single().children.single() as MemberPageNode) - .content - .dfs { node -> - node is ContentDRILink && - node.address.toString() == "parser//test/#java.lang.ClassLoader/PointingToDeclaration/" - } - ) - } - } - } - - @Test - fun returnTypeShouldHaveLinkToOuterClassFromInner() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin") - displayName = "JVM" - } - } - } - //This does not contain a package to check for situation when the package has to be artificially generated - testInline( - """ - |/src/main/kotlin/parser/Test.kt - | - |class Outer<OUTER> { - | inner class Inner<INNER> { - | fun foo(): OUTER = TODO() - | } - |} - """.trimMargin(), - configuration - ) { - renderingStage = { rootPageNode, _ -> - val root = rootPageNode.children.single().children.single() as ClasslikePageNode - val innerClass = root.children.first { it is ClasslikePageNode } - val foo = innerClass.children.first { it.name == "foo" } as MemberPageNode - val destinationDri = (root.documentables.firstOrNull() as WithGenerics).generics.first().dri.toString() - - assertEquals(destinationDri, "/Outer///PointingToGenericParameters(0)/") - assertNotNull(foo.content.dfs { it is ContentDRILink && it.address.toString() == destinationDri }) - } - } - } - - @Test - fun `link to parameter #238`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - } - } - } - - testInline( - """ - |/src/main/kotlin/Test.kt - |package example - | - |/** - |* Link to [waitAMinute] - |*/ - |fun stop(hammerTime: String, waitAMinute: String) {} - | - """.trimMargin(), - configuration - ) { - documentablesMergingStage = { module -> - val parameter = module.dfs { it.name == "waitAMinute" } - val link = module.dfs { it.name == "stop" }!!.documentation.values.single() - .dfs { it is DocumentationLink } as DocumentationLink - - assertEquals(parameter!!.dri, link.dri) - } - } - } - - @Test - fun `link with exclamation mark`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - } - } - } - - testInline( - """ - |/src/main/kotlin/Test.kt - |package example - | - |/** - |* Link to ![waitAMinute] - |*/ - |fun stop(hammerTime: String, waitAMinute: String) {} - | - """.trimMargin(), - configuration - ) { - documentablesMergingStage = { module -> - val functionDocs = module.packages.flatMap { it.functions }.first().documentation.values.first() - val expected = Description( - root = CustomDocTag( - children = listOf( - P( - children = listOf( - Text("Link to !"), - DocumentationLink( - dri = DRI( - packageName = "example", - callable = Callable( - "stop", - receiver = null, - params = listOf( - TypeConstructor("kotlin.String", emptyList()), - TypeConstructor("kotlin.String", emptyList()) - ) - ), - target = PointingToCallableParameters(1) - ), - children = listOf( - Text("waitAMinute") - ), - params = mapOf("href" to "[waitAMinute]") - ) - ) - ) - ), - name = "MARKDOWN_FILE" - ) - ) - - assertEquals(expected, functionDocs.children.first()) - } - } - } - - @Test - fun `link to property with exclamation mark`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - } - } - } - - testInline( - """ - |/src/main/kotlin/Testing.kt - |package example - | - |/** - |* Link to ![Testing.property] - |*/ - |class Testing { - | var property = "" - |} - | - """.trimMargin(), - configuration - ) { - documentablesMergingStage = { module -> - val functionDocs = module.packages.flatMap { it.classlikes }.first().documentation.values.first() - val expected = Description( - root = CustomDocTag( - children = listOf( - P( - children = listOf( - Text("Link to !"), - DocumentationLink( - dri = DRI( - packageName = "example", - classNames = "Testing", - callable = Callable("property", null, emptyList()), - target = PointingToDeclaration - ), - children = listOf( - Text("Testing.property") - ), - params = mapOf("href" to "[Testing.property]") - ) - ) - ) - ), - name = "MARKDOWN_FILE" - ) - ) - - assertEquals(expected, functionDocs.children.first()) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/markdown/ParserTest.kt b/plugins/base/src/test/kotlin/markdown/ParserTest.kt deleted file mode 100644 index bcca27c4..00000000 --- a/plugins/base/src/test/kotlin/markdown/ParserTest.kt +++ /dev/null @@ -1,1633 +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.tests - -import markdown.KDocTest - -import org.jetbrains.dokka.analysis.markdown.jb.MARKDOWN_ELEMENT_FILE_NAME -import org.jetbrains.dokka.analysis.markdown.jb.MarkdownParser -import org.jetbrains.dokka.model.doc.* -import kotlin.test.Ignore -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertTrue - - -class ParserTest : KDocTest() { - - private fun parseMarkdownToDocNode(text: String) = - MarkdownParser( { null }, "").parseStringToDocNode(text) - - @Test - fun `Simple text`() { - val kdoc = """ - | This is simple test of string - | Next line - """.trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf(P(listOf(Text("This is simple test of string Next line")))), - name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Simple text with new line`() { - val kdoc = """ - | This is simple test of string\ - | Next line - """.trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - P( - listOf( - Text("This is simple test of string"), - Br, - Text("Next line") - ) - ) - ), - name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Text with Bold and Emphasis decorators`() { - val kdoc = """ - | This is **simple** test of _string_ - | Next **_line_** - """.trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - P( - listOf( - Text("This is "), - B(listOf(Text("simple"))), - Text(" test of "), - I(listOf(Text("string"))), - Text(" Next "), - B(listOf(I(listOf(Text("line"))))) - ) - ) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Text with Colon`() { - val kdoc = """ - | This is simple text with: colon! - """.trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf(P(listOf(Text("This is simple text with: colon!")))), - name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Multilined text`() { - val kdoc = """ - | Text - | and - | String - """.trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf(P(listOf(Text("Text and String")))), - name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Paragraphs`() { - val kdoc = """ - | Paragraph number - | one - | - | Paragraph\ - | number two - """.trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - P(listOf(Text("Paragraph number one"))), - P(listOf(Text("Paragraph"), Br, Text("number two"))) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Emphasis with star`() { - val kdoc = " *text*" - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf(P(listOf(I(listOf(Text("text")))))), - name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Underscores that are not Emphasis`() { - val kdoc = "text_with_underscores" - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf(P(listOf(Text("text_with_underscores")))), - name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Emphasis with underscores`() { - val kdoc = "_text_" - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf(P(listOf(I(listOf(Text("text")))))), - name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Stars as italic bounds`() { - val kdoc = "The abstract syntax tree node for a multiplying expression. A multiplying\n" + - "expression is a binary expression where the operator is a multiplying operator\n" + - "such as \"*\", \"/\", or \"mod\". A simple example would be \"5*x\"." - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - P( - listOf( - Text( - "The abstract syntax tree node for a multiplying expression. A multiplying " + - "expression is a binary expression where the operator is a multiplying operator " + - "such as \"" - ), - I(listOf(Text("\", \"/\", or \"mod\". A simple example would be \"5"))), - Text("x\".") - ) - ) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Stars as bold bounds`() { - val kdoc = "The abstract syntax tree node for a multiplying expression. A multiplying\n" + - "expression is a binary expression where the operator is a multiplying operator\n" + - "such as \"**\", \"/\", or \"mod\". A simple example would be \"5**x\"." - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - P( - listOf( - Text( - "The abstract syntax tree node for a multiplying expression. A multiplying " + - "expression is a binary expression where the operator is a multiplying operator " + - "such as \"" - ), - B(listOf(Text("\", \"/\", or \"mod\". A simple example would be \"5"))), - Text("x\".") - ) - ) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Embedded star`() { - val kdoc = "Embedded*Star" - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - P(listOf(Text("Embedded*Star"))) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - - @Test - fun `Unordered list`() { - val kdoc = """ - | * list item 1 - | * list item 2 - """.trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - Ul( - listOf( - Li(listOf(P(listOf(Text("list item 1"))))), - Li(listOf(P(listOf(Text("list item 2"))))) - ) - ) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Unordered list with multilines`() { - val kdoc = """ - | * list item 1 - | continue 1 - | * list item 2\ - | continue 2 - """.trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - Ul( - listOf( - Li(listOf(P(listOf(Text("list item 1 continue 1"))))), - Li(listOf(P(listOf(Text("list item 2"), Br, Text("continue 2"))))) - ) - ) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Unordered list with Bold`() { - val kdoc = """ - | * list **item** 1 - | continue 1 - | * list __item__ 2 - | continue 2 - """.trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - Ul( - listOf( - Li( - listOf( - P( - listOf( - Text("list "), - B(listOf(Text("item"))), - Text(" 1 continue 1") - ) - ) - ) - ), - Li( - listOf( - P( - listOf( - Text("list "), - B(listOf(Text("item"))), - Text(" 2 continue 2") - ) - ) - ) - ) - ) - ) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Unordered list with nested bullets`() { - val kdoc = """ - | * Outer first - | Outer next line - | * Outer second - | - Middle first - | Middle next line - | - Middle second - | + Inner first - | Inner next line - | - Middle third - | * Outer third - | - | New paragraph""".trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - Ul( - listOf( - Li(listOf(P(listOf(Text("Outer first Outer next line"))))), - Li(listOf(P(listOf(Text("Outer second"))))), - Ul( - listOf( - Li(listOf(P(listOf(Text("Middle first Middle next line"))))), - Li(listOf(P(listOf(Text("Middle second"))))), - Ul( - listOf( - Li(listOf(P(listOf(Text("Inner first Inner next line"))))) - ) - ), - Li(listOf(P(listOf(Text("Middle third"))))) - ) - ), - Li(listOf(P(listOf(Text("Outer third"))))) - ) - ), - P(listOf(Text("New paragraph"))) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Ordered list`() { - val kdoc = """ - | 1. list item 1 - | 2. list item 2 - """.trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - Ol( - listOf( - Li(listOf(P(listOf(Text("list item 1"))))), - Li(listOf(P(listOf(Text("list item 2"))))) - ), - mapOf("start" to "1") - ) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - - @Test - fun `Ordered list beginning from other number`() { - val kdoc = """ - | 9. list item 1 - | 12. list item 2 - """.trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - Ol( - listOf( - Li(listOf(P(listOf(Text("list item 1"))))), - Li(listOf(P(listOf(Text("list item 2"))))) - ), - mapOf("start" to "9") - ) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Ordered list with multilines`() { - val kdoc = """ - | 2. list item 1 - | continue 1 - | 3. list item 2 - | continue 2 - """.trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - Ol( - listOf( - Li(listOf(P(listOf(Text("list item 1 continue 1"))))), - Li(listOf(P(listOf(Text("list item 2 continue 2"))))) - ), - mapOf("start" to "2") - ) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Ordered list with Bold`() { - val kdoc = """ - | 1. list **item** 1 - | continue 1 - | 2. list __item__ 2 - | continue 2 - """.trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - Ol( - listOf( - Li( - listOf( - P( - listOf( - Text("list "), - B(listOf(Text("item"))), - Text(" 1 continue 1") - ) - ) - ) - ), - Li( - listOf( - P( - listOf( - Text("list "), - B(listOf(Text("item"))), - Text(" 2 continue 2") - ) - ) - ) - ) - ), - mapOf("start" to "1") - ) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Ordered list with nested bullets`() { - val kdoc = """ - | 1. Outer first - | Outer next line - | 2. Outer second - | 1. Middle first - | Middle next line - | 2. Middle second - | 1. Inner first - | Inner next line - | 5. Middle third - | 4. Outer third - | - | New paragraph""".trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - Ol( - listOf( - Li(listOf(P(listOf(Text("Outer first Outer next line"))))), - Li(listOf(P(listOf(Text("Outer second"))))), - Ol( - listOf( - Li(listOf(P(listOf(Text("Middle first Middle next line"))))), - Li(listOf(P(listOf(Text("Middle second"))))), - Ol( - listOf( - Li(listOf(P(listOf(Text("Inner first Inner next line"))))) - ), - mapOf("start" to "1") - ), - Li(listOf(P(listOf(Text("Middle third"))))) - ), - mapOf("start" to "1") - ), - Li(listOf(P(listOf(Text("Outer third"))))) - ), - mapOf("start" to "1") - ), - P(listOf(Text("New paragraph"))) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Ordered nested in Unordered nested in Ordered list`() { - val kdoc = """ - | 1. Outer first - | Outer next line - | 2. Outer second - | + Middle first - | Middle next line - | + Middle second - | 1. Inner first - | Inner next line - | + Middle third - | 4. Outer third - | - | New paragraph""".trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - Ol( - listOf( - Li(listOf(P(listOf(Text("Outer first Outer next line"))))), - Li(listOf(P(listOf(Text("Outer second"))))), - Ul( - listOf( - Li(listOf(P(listOf(Text("Middle first Middle next line"))))), - Li(listOf(P(listOf(Text("Middle second"))))), - Ol( - listOf( - Li(listOf(P(listOf(Text("Inner first Inner next line"))))) - ), - mapOf("start" to "1") - ), - Li(listOf(P(listOf(Text("Middle third"))))) - ) - ), - Li(listOf(P(listOf(Text("Outer third"))))) - ), - mapOf("start" to "1") - ), - P(listOf(Text("New paragraph"))) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Header and two paragraphs`() { - val kdoc = """ - | # Header 1 - | Following text - | - | New paragraph - """.trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - H1(listOf(Text("Header 1"))), - P(listOf(Text("Following text"))), - P(listOf(Text("New paragraph"))) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Ignore //TODO: ATX_2 to ATX_6 and sometimes ATX_1 from jetbrains parser consumes white space. Need to handle it in their library - @Test - fun `All headers`() { - val kdoc = """ - | # Header 1 - | Text 1 - | ## Header 2 - | Text 2 - | ### Header 3 - | Text 3 - | #### Header 4 - | Text 4 - | ##### Header 5 - | Text 5 - | ###### Header 6 - | Text 6 - """.trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - H1(listOf(Text("Header 1"))), - P(listOf(Text("Text 1"))), - H2(listOf(Text("Header 2"))), - P(listOf(Text("Text 2"))), - H3(listOf(Text("Header 3"))), - P(listOf(Text("Text 3"))), - H4(listOf(Text("Header 4"))), - P(listOf(Text("Text 4"))), - H5(listOf(Text("Header 5"))), - P(listOf(Text("Text 5"))), - H6(listOf(Text("Header 6"))), - P(listOf(Text("Text 6"))) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Bold New Line Bold`() { - val kdoc = """ - | **line 1**\ - | **line 2** - """.trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - P( - listOf( - B(listOf(Text("line 1"))), - Br, - B(listOf(Text("line 2"))) - ) - ) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Horizontal rule`() { - val kdoc = """ - | *** - | text 1 - | ___ - | text 2 - | *** - | text 3 - | ___ - | text 4 - | *** - """.trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - HorizontalRule, - P(listOf(Text("text 1"))), - HorizontalRule, - P(listOf(Text("text 2"))), - HorizontalRule, - P(listOf(Text("text 3"))), - HorizontalRule, - P(listOf(Text("text 4"))), - HorizontalRule - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Blockquote`() { - val kdoc = """ - | > Blockquotes are very handy in email to emulate reply text. - | > This line is part of the same quote. - | - | Quote break. - | - | > Quote - """.trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - BlockQuote( - listOf( - P( - listOf( - Text("Blockquotes are very handy in email to emulate reply text. This line is part of the same quote.") - ) - ) - ) - ), - P(listOf(Text("Quote break."))), - BlockQuote( - listOf( - P(listOf(Text("Quote"))) - ) - ) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - - @Test - fun `Blockquote nested`() { - val kdoc = """ - | > text 1 - | > text 2 - | >> text 3 - | >> text 4 - | > - | > text 5 - | - | Quote break. - | - | > Quote - """.trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - BlockQuote( - listOf( - P(listOf(Text("text 1 text 2"))), - BlockQuote( - listOf( - P(listOf(Text("text 3 text 4"))) - ) - ), - P(listOf(Text("text 5"))) - ) - ), - P(listOf(Text("Quote break."))), - BlockQuote( - listOf( - P(listOf(Text("Quote"))) - ) - ) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Ignore //TODO: Again ATX_1 consumes white space - @Test - fun `Blockquote nested with fancy text enhancement`() { - val kdoc = """ - | > text **1** - | > text 2 - | >> # text 3 - | >> * text 4 - | >> * text 5 - | > - | > text 6 - | - | Quote break. - | - | > Quote - """.trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - BlockQuote( - listOf( - P( - listOf( - Text("text "), - B(listOf(Text("1"))), - Text("\ntext 2") - ) - ), - BlockQuote( - listOf( - H1(listOf(Text("text 3"))), - Ul( - listOf( - Li(listOf(P(listOf(Text("text 4"))))), - Ul( - listOf( - Li(listOf(P(listOf(Text("text 5"))))) - ) - ) - ) - ) - ) - ), - P(listOf(Text("text 6"))) - ) - ), - P(listOf(Text("Quote break."))), - BlockQuote( - listOf( - P(listOf(Text("Quote"))) - ) - ) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Simple Code Block`() { - val kdoc = """ - | `Some code` - | Sample text - """.trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - P( - listOf( - CodeInline(listOf(Text("Some code"))), - Text(" Sample text") - ) - ) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Multilined Code Block`() { - val kdoc = """ - | ```kotlin - | @Suppress("UNUSED_VARIABLE") - | val x: Int = 0 - | val y: String = "Text" - | - | val z: Boolean = true - | for(i in 0..10) { - | println(i) - | } - | ``` - | Sample text - """.trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - CodeBlock( - listOf( - Text("@Suppress(\"UNUSED_VARIABLE\")"), Br, - Text("val x: Int = 0"), Br, - Text("val y: String = \"Text\""), Br, Br, - Text(" val z: Boolean = true"), Br, - Text("for(i in 0..10) {"), Br, - Text(" println(i)"), Br, - Text("}") - ), - mapOf("lang" to "kotlin") - ), - P(listOf(Text("Sample text"))) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - - @Test - fun `Inline link`() { - val kdoc = """ - | [I'm an inline-style link](https://www.google.com) - """.trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - P( - listOf( - A( - listOf(Text("I'm an inline-style link")), - mapOf("href" to "https://www.google.com") - ) - ) - ) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Inline link with title`() { - val kdoc = """ - | [I'm an inline-style link with title](https://www.google.com "Google's Homepage") - """.trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - P( - listOf( - A( - listOf(Text("I'm an inline-style link with title")), - mapOf("href" to "https://www.google.com", "title" to "Google's Homepage") - ) - ) - ) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Full reference link`() { - val kdoc = """ - | [I'm a reference-style link][Arbitrary case-insensitive reference text] - | - | [arbitrary case-insensitive reference text]: https://www.mozilla.org - """.trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - P( - listOf( - A( - listOf(Text("I'm a reference-style link")), - mapOf("href" to "https://www.mozilla.org") - ) - ) - ) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Full reference link with number`() { - val kdoc = """ - | [You can use numbers for reference-style link definitions][1] - | - | [1]: http://slashdot.org - """.trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - P( - listOf( - A( - listOf(Text("You can use numbers for reference-style link definitions")), - mapOf("href" to "http://slashdot.org") - ) - ) - ) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Short reference link`() { - val kdoc = """ - | Or leave it empty and use the [link text itself]. - | - | [link text itself]: http://www.reddit.com - """.trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - P( - listOf( - Text("Or leave it empty and use the "), - A( - listOf(Text("link text itself")), - mapOf("href" to "http://www.reddit.com") - ), - Text(".") - ) - ) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Autolink`() { - val kdoc = """ - | URLs and URLs in angle brackets will automatically get turned into links. - | http://www.example.com or <http://www.example.com> and sometimes - | example.com (but not on Github, for example). - """.trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - P( - listOf( - Text("URLs and URLs in angle brackets will automatically get turned into links. http://www.example.com or "), - A( - listOf(Text("http://www.example.com")), - mapOf("href" to "http://www.example.com") - ), - Text(" and sometimes example.com (but not on Github, for example).") - ) - ) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Various links`() { - val kdoc = """ - | [I'm an inline-style link](https://www.google.com) - | - | [I'm an inline-style link with title](https://www.google.com "Google's Homepage") - | - | [I'm a reference-style link][Arbitrary case-insensitive reference text] - | - | [You can use numbers for reference-style link definitions][1] - | - | Or leave it empty and use the [link text itself]. - | - | URLs and URLs in angle brackets will automatically get turned into links. - | http://www.example.com or <http://www.example.com> and sometimes - | example.com (but not on Github, for example). - | - | Some text to show that the reference links can follow later. - | - | [arbitrary case-insensitive reference text]: https://www.mozilla.org - | [1]: http://slashdot.org - | [link text itself]: http://www.reddit.com - """.trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - P( - listOf( - A( - listOf(Text("I'm an inline-style link")), - mapOf("href" to "https://www.google.com") - ) - ) - ), - P( - listOf( - A( - listOf(Text("I'm an inline-style link with title")), - mapOf("href" to "https://www.google.com", "title" to "Google's Homepage") - ) - ) - ), - P( - listOf( - A( - listOf(Text("I'm a reference-style link")), - mapOf("href" to "https://www.mozilla.org") - ) - ) - ), - P( - listOf( - A( - listOf(Text("You can use numbers for reference-style link definitions")), - mapOf("href" to "http://slashdot.org") - ) - ) - ), - P( - listOf( - Text("Or leave it empty and use the "), - A( - listOf(Text("link text itself")), - mapOf("href" to "http://www.reddit.com") - ), - Text(".") - ) - ), - P( - listOf( - Text("URLs and URLs in angle brackets will automatically get turned into links. http://www.example.com or "), - A( - listOf(Text("http://www.example.com")), - mapOf("href" to "http://www.example.com") - ), - Text(" and sometimes example.com (but not on Github, for example).") - ) - ), - P(listOf(Text("Some text to show that the reference links can follow later."))) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Windows Carriage Return Line Feed`() { - val kdoc = "text\r\ntext" - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - P( - listOf( - Text("text text") - ) - ) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun image() { - val kdoc = "![Sample image](https://www.google.pl/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png)" - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - P( - listOf( - Img( - emptyList(), - mapOf( - "href" to "https://www.google.pl/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png", - "alt" to "Sample image" - ) - ) - ) - ) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Bold + italic + link`() { - val kdoc = "It's very easy to make some words **bold** and other words *italic* with Markdown.\n" + - "You can even [link to Google!](http://google.com)" - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - P( - listOf( - Text("It's very easy to make some words "), - B(listOf(Text("bold"))), - Text(" and other words "), - I(listOf(Text("italic"))), - Text(" with Markdown. You can even "), - A(listOf(Text("link to Google!")), mapOf("href" to "http://google.com")) - ) - ) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Codeblock from indent`() { - val kdoc = "Here is some example how to use conditional instructions:\n\n" + - " val x = 1\n" + - " val y = 2\n" + - " if (x == 1) {\n" + - " println(y)\n" + - " }" - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - P(listOf(Text("Here is some example how to use conditional instructions:"))), - CodeBlock( - listOf( - Text( - "val x = 1\n" + - "val y = 2\n" + - "if (x == 1) {\n" + - " println(y)\n" + - "}" - ) - ) - ) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Table`() { - val kdoc = "First Header | Second Header\n" + - "------------ | -------------\n" + - "Content from cell 1 | Content from cell 2\n" + - "Content in the first column | Content in the second column" - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - Table( - listOf( - Th( - listOf( - Td( - listOf( - Text("First Header") - ) - ), - Td( - listOf( - Text("Second Header") - ) - ) - ) - ), - Tr( - listOf( - Td( - listOf( - Text("Content from cell 1") - ) - ), - Td( - listOf( - Text("Content from cell 2") - ) - ) - ) - ), - Tr( - listOf( - Td( - listOf( - Text("Content in the first column") - ) - ), - Td( - listOf( - Text("Content in the second column") - ) - ) - ) - ) - ) - ) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `Text with Strikethrough`() { - val kdoc = """ - | This is ~~strikethroughed~~ - """.trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - P( - listOf( - Text("This is "), - Strikethrough(listOf(Text("strikethroughed"))) - ) - ) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `short link without destination`() { - val kdoc = """ - | This is [link]() - """.trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - P( - listOf( - Text("This is "), - A( - listOf(Text("link")), - mapOf("href" to "") - ) - ) - ) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - - @Test - fun `exception thrown by empty header should point to location of a file`() { - val kdoc = """ - | ### - """.trimMargin() - val expectedDocumentationNode = DocumentationNode(emptyList()) - val exception = runCatching { executeTest(kdoc, expectedDocumentationNode) }.exceptionOrNull() - - val expectedMessage = "Wrong AST Tree. Header does not contain expected content in Test.kt/example.Test, element starts from offset 0 and ends 3: ###" - assertTrue( - exception?.message == expectedMessage - || /* for K2 */ exception?.cause?.cause?.message == expectedMessage - ) - } - - @Test - fun `should ignore html comments`() { - val kdoc = """ - | # Example <!--- not visible in header --> Kdoc - | <!-- not visible alone --> - | Pre <!--- not visible --> visible - """.trimMargin() - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - H1( - listOf( - Text("Example "), - Text("<!--- not visible in header -->", params = mapOf("content-type" to "html")), - Text(" Kdoc") - ) - ), - Text("<!-- not visible alone -->", params = mapOf("content-type" to "html")), - P( - listOf( - Text("Pre "), - Text("<!--- not visible -->", params = mapOf("content-type" to "html")), - Text(" visible") - ) - ) - ), - name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `code with backticks`() { - val kdoc = "` `` ` ` ``` `" - val expectedDocumentationNode = DocumentationNode( - listOf( - Description( - CustomDocTag( - listOf( - P( - listOf( - CodeInline(listOf(Text("`` "))), - Text(" "), - CodeInline(listOf(Text("``` "))), - ) - ) - ), name = MARKDOWN_ELEMENT_FILE_NAME - ) - ) - ) - ) - executeTest(kdoc, expectedDocumentationNode) - } - - @Test - fun `should filter spaces in markdown`() { - val markdown = """ - | sdsdds f,*()hhh - | dssd hf - | - | sdsdsds sdd - | - | - | eweww - | - | - | - """.trimMargin() - val actualDocumentationNode = parseMarkdownToDocNode(markdown).children - val expectedDocumentationNode = listOf( - P(listOf(Text(" sdsdds f,*()hhh dssd hf"))), - P(listOf(Text(" sdsdsds sdd"))), - P(listOf(Text(" eweww "))) - ) - assertEquals(actualDocumentationNode, expectedDocumentationNode) - } - - @Test // exists due to #3231 - fun `should ignore the leading whitespace in header in-between the hash symbol and header text`() { - val markdown = """ - | # first header - | ## second header - | ### third header - """.trimMargin() - val actualDocumentationNode = parseMarkdownToDocNode(markdown).children - val expectedDocumentationNode = listOf( - H1(listOf(Text("first header"))), - H2(listOf(Text("second header"))), - H3(listOf(Text("third header"))), - ) - assertEquals(actualDocumentationNode, expectedDocumentationNode) - } - - @Test // exists due to #3231 - fun `should ignore trailing whitespace in header`() { - val markdown = """ - | # first header - | ## second header - | ### third header - """.trimMargin() - val actualDocumentationNode = parseMarkdownToDocNode(markdown).children - val expectedDocumentationNode = listOf( - H1(listOf(Text("first header"))), - H2(listOf(Text("second header"))), - H3(listOf(Text("third header"))), - ) - assertEquals(actualDocumentationNode, expectedDocumentationNode) - } - - @Test // exists due to #3231 - fun `should ignore leading and trailing whitespace in header, but not whitespace in the middle`() { - val markdown = """ - | # first header - | ## second ~~header~~ in a **long** sentence ending with whitespaces - | ### third header - """.trimMargin() - val actualDocumentationNode = parseMarkdownToDocNode(markdown).children - val expectedDocumentationNode = listOf( - H1(listOf(Text("first header"))), - H2(listOf( - Text("second "), - Strikethrough(listOf(Text("header"))), - Text(" in a "), - B(listOf(Text("long"))), - Text(" sentence ending with whitespaces") - )), - H3(listOf(Text("third header"))), - ) - assertEquals(actualDocumentationNode, expectedDocumentationNode) - } -} - diff --git a/plugins/base/src/test/kotlin/model/ClassesTest.kt b/plugins/base/src/test/kotlin/model/ClassesTest.kt deleted file mode 100644 index c18dfafb..00000000 --- a/plugins/base/src/test/kotlin/model/ClassesTest.kt +++ /dev/null @@ -1,594 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package model - -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.links.TypeConstructor -import org.jetbrains.dokka.links.sureClassNames -import org.jetbrains.dokka.model.* -import org.jetbrains.dokka.model.KotlinModifier.* -import kotlin.test.assertNull -import kotlin.test.Test -import utils.* - - -class ClassesTest : AbstractModelTest("/src/main/kotlin/classes/Test.kt", "classes") { - - @Test - fun emptyClass() { - inlineModelTest( - """ - |class Klass {}""" - ) { - with((this / "classes" / "Klass").cast<DClass>()) { - name equals "Klass" - children counts 4 - } - } - } - - @Test - fun classWithConstructor() { - inlineModelTest( - """ - |class Klass(name: String) - """ - ) { - with((this / "classes" / "Klass").cast<DClass>()) { - name equals "Klass" - children counts 4 - - with(constructors.firstOrNull().assertNotNull("Constructor")) { - visibility.values allEquals KotlinVisibility.Public - parameters counts 1 - with(parameters.firstOrNull().assertNotNull("Constructor parameter")) { - name equals "name" - type.name equals "String" - } - } - - } - } - } - - @Test - fun classWithFunction() { - inlineModelTest( - """ - |class Klass { - | fun fn() {} - |} - """ - ) { - with((this / "classes" / "Klass").cast<DClass>()) { - name equals "Klass" - children counts 5 - - with((this / "fn").cast<DFunction>()) { - type.name equals "Unit" - parameters counts 0 - visibility.values allEquals KotlinVisibility.Public - } - } - } - } - - @Test - fun classWithProperty() { - inlineModelTest( - """ - |class Klass { - | val name: String = "" - |} - """ - ) { - with((this / "classes" / "Klass").cast<DClass>()) { - name equals "Klass" - children counts 5 - - with((this / "name").cast<DProperty>()) { - name equals "name" - // TODO property name - } - } - } - } - - @Test - fun classWithCompanionObject() { - inlineModelTest( - """ - |class Klass() { - | companion object { - | val x = 1 - | fun foo() {} - | } - |} - """ - ) { - with((this / "classes" / "Klass").cast<DClass>()) { - name equals "Klass" - children counts 5 - - with((this / "Companion").cast<DObject>()) { - name equals "Companion" - children counts 5 - - with((this / "x").cast<DProperty>()) { - name equals "x" - } - - with((this / "foo").cast<DFunction>()) { - name equals "foo" - parameters counts 0 - type.name equals "Unit" - } - } - - with((this.companion).cast<DObject>()) { - name equals "Companion" - children counts 5 - - with((this / "x").cast<DProperty>()) { - name equals "x" - } - - with((this / "foo").cast<DFunction>()) { - name equals "foo" - parameters counts 0 - type.name equals "Unit" - } - } - } - } - } - - @Test - fun dataClass() { - inlineModelTest( - """ - |data class Klass() {} - """ - ) { - with((this / "classes" / "Klass").cast<DClass>()) { - name equals "Klass" - visibility.values allEquals KotlinVisibility.Public - with(extra[AdditionalModifiers]!!.content.entries.single().value.assertNotNull("Extras")) { - this counts 1 - first() equals ExtraModifiers.KotlinOnlyModifiers.Data - } - } - } - } - - @Test - fun sealedClass() { - inlineModelTest( - """ - |sealed class Klass() {} - """ - ) { - with((this / "classes" / "Klass").cast<DClass>()) { - name equals "Klass" - modifier.values.forEach { it equals Sealed } - } - } - } - - @Test - fun annotatedClassWithAnnotationParameters() { - inlineModelTest( - """ - |@Deprecated("should no longer be used") class Foo() {} - """ - ) { - with((this / "classes" / "Foo").cast<DClass>()) { - with(extra[Annotations]!!.directAnnotations.entries.single().value.assertNotNull("Annotations")) { - this counts 1 - with(first()) { - dri.classNames equals "Deprecated" - params.entries counts 1 - (params["message"].assertNotNull("message") as StringValue).value equals "should no longer be used" - } - } - } - } - } - - @Test - fun notOpenClass() { - inlineModelTest( - """ - |open class C() { - | open fun f() {} - |} - | - |class D() : C() { - | override fun f() {} - |} - """ - ) { - val C = (this / "classes" / "C").cast<DClass>() - val D = (this / "classes" / "D").cast<DClass>() - - with(C) { - modifier.values.forEach { it equals Open } - with((this / "f").cast<DFunction>()) { - modifier.values.forEach { it equals Open } - } - } - with(D) { - modifier.values.forEach { it equals Final } - with((this / "f").cast<DFunction>()) { - modifier.values.forEach { it equals Open } - } - D.supertypes.flatMap { it.component2() }.firstOrNull()?.typeConstructor?.dri equals C.dri - } - } - } - - @Test - fun indirectOverride() { - inlineModelTest( - """ - |abstract class C() { - | abstract fun foo() - |} - | - |abstract class D(): C() - | - |class E(): D() { - | override fun foo() {} - |} - """ - ) { - val C = (this / "classes" / "C").cast<DClass>() - val D = (this / "classes" / "D").cast<DClass>() - val E = (this / "classes" / "E").cast<DClass>() - - with(C) { - modifier.values.forEach { it equals Abstract } - ((this / "foo").cast<DFunction>()).modifier.values.forEach { it equals Abstract } - } - - with(D) { - modifier.values.forEach { it equals Abstract } - } - - with(E) { - modifier.values.forEach { it equals Final } - - } - D.supers.single().typeConstructor.dri equals C.dri - E.supers.single().typeConstructor.dri equals D.dri - } - } - - @Test - fun innerClass() { - inlineModelTest( - """ - |class C { - | inner class D {} - |} - """ - ) { - with((this / "classes" / "C").cast<DClass>()) { - - with((this / "D").cast<DClass>()) { - with(extra[AdditionalModifiers]!!.content.entries.single().value.assertNotNull("AdditionalModifiers")) { - this counts 1 - first() equals ExtraModifiers.KotlinOnlyModifiers.Inner - } - } - } - } - } - - @Test - fun companionObjectExtension() { - inlineModelTest( - """ - |class Klass { - | companion object Default {} - |} - | - |/** - | * The def - | */ - |val Klass.Default.x: Int get() = 1 - """ - ) { - with((this / "classes").cast<DPackage>()) { - properties.single().name equals "x" - (properties.single().receiver?.dri?.callable?.receiver as? TypeConstructor)?.fullyQualifiedName equals "classes.Klass.Default" - } - } - } - - @Test - fun secondaryConstructor() { - inlineModelTest( - """ - |class C() { - | /** This is a secondary constructor. */ - | constructor(s: String): this() {} - |} - """ - ) { - with((this / "classes" / "C").cast<DClass>()) { - name equals "C" - constructors counts 2 - - constructors.map { it.name } allEquals "C" - - with(constructors.find { it.parameters.isEmpty() } notNull "C()") { - parameters counts 0 - } - - with(constructors.find { it.parameters.isNotEmpty() } notNull "C(String)") { - parameters counts 1 - with(parameters.firstOrNull() notNull "Constructor parameter") { - name equals "s" - type.name equals "String" - } - } - } - } - } - - @Test - fun sinceKotlin() { - inlineModelTest( - """ - |/** - | * Useful - | */ - |@SinceKotlin("1.1") - |class C - """ - ) { - with((this / "classes" / "C").cast<DClass>()) { - with(extra[Annotations]!!.directAnnotations.entries.single().value.assertNotNull("Annotations")) { - this counts 1 - with(first()) { - dri.classNames equals "SinceKotlin" - params.entries counts 1 - (params["version"].assertNotNull("version") as StringValue).value equals "1.1" - } - } - } - } - } - - @Test - fun privateCompanionObject() { - inlineModelTest( - """ - |class Klass { - | private companion object { - | fun fn() {} - | val a = 0 - | } - |} - """ - ) { - with((this / "classes" / "Klass").cast<DClass>()) { - name equals "Klass" - assertNull(companion, "Companion should not be visible by default") - } - } - } - - @Test - fun companionObject() { - inlineModelTest( - """ - |class Klass { - | companion object { - | fun fn() {} - | val a = 0 - | } - |} - """ - ) { - with((this / "classes" / "Klass").cast<DClass>()) { - name equals "Klass" - with((this / "Companion").cast<DObject>()) { - name equals "Companion" - visibility.values allEquals KotlinVisibility.Public - - with((this / "fn").cast<DFunction>()) { - name equals "fn" - parameters counts 0 - receiver equals null - } - } - } - } - } - - @Test - fun annotatedClass() { - inlineModelTest( - """@Suppress("abc") class Foo() {}""" - ) { - with((this / "classes" / "Foo").cast<DClass>()) { - with( - extra[Annotations]?.directAnnotations?.values?.firstOrNull()?.firstOrNull() - .assertNotNull("annotations") - ) { - dri.toString() equals "kotlin/Suppress///PointingToDeclaration/" - (params["names"].assertNotNull("param") as ArrayValue).value equals listOf(StringValue("abc")) - } - } - } - } - - @OnlyDescriptors("Bug in descriptors, DRI of entry should have [EnumEntryDRIExtra]") - @Test - fun javaAnnotationClass() { - inlineModelTest( - """ - |import java.lang.annotation.Retention - |import java.lang.annotation.RetentionPolicy - | - |@Retention(RetentionPolicy.SOURCE) - |public annotation class throws() - """ - ) { - with((this / "classes" / "throws").cast<DAnnotation>()) { - with(extra[Annotations]!!.directAnnotations.entries.single().value.assertNotNull("Annotations")) { - this counts 1 - with(first()) { - dri.classNames equals "Retention" - params["value"].assertNotNull("value") equals EnumValue( - "RetentionPolicy.SOURCE", - DRI("java.lang.annotation", "RetentionPolicy.SOURCE") - ) - } - } - } - } - } - - @Test - fun genericAnnotationClass() { - inlineModelTest( - """annotation class Foo<A,B,C,D:Number>() {}""" - ) { - with((this / "classes" / "Foo").cast<DAnnotation>()) { - generics.map { it.name to it.bounds.first().name } equals listOf( - "A" to "Any", - "B" to "Any", - "C" to "Any", - "D" to "Number" - ) - } - } - } - - @Test - fun nestedGenericClasses() { - inlineModelTest( - """ - |class Outer<OUTER> { - | inner class Inner<INNER, T : OUTER> { } - |} - """.trimMargin() - ) { - with((this / "classes" / "Outer").cast<DClass>()) { - val inner = classlikes.single().cast<DClass>() - inner.generics.map { it.name to it.bounds.first().name } equals listOf("INNER" to "Any", "T" to "OUTER") - } - } - } - - @Test - fun allImplementedInterfaces() { - inlineModelTest( - """ - | interface Highest { } - | open class HighestImpl: Highest { } - | interface Lower { } - | interface LowerImplInterface: Lower { } - | class Tested : HighestImpl(), LowerImplInterface { } - """.trimIndent() - ) { - with((this / "classes" / "Tested").cast<DClass>()) { - extra[ImplementedInterfaces]?.interfaces?.entries?.single()?.value?.map { it.dri.sureClassNames } - ?.sorted() equals listOf("Highest", "Lower", "LowerImplInterface").sorted() - } - } - } - - @Test - fun multipleClassInheritance() { - inlineModelTest( - """ - | open class A { } - | open class B: A() { } - | class Tested : B() { } - """.trimIndent() - ) { - with((this / "classes" / "Tested").cast<DClass>()) { - supertypes.entries.single().value.map { it.typeConstructor.dri.sureClassNames }.single() equals "B" - } - } - } - - @Test - fun multipleClassInheritanceWithInterface() { - inlineModelTest( - """ - | open class A { } - | open class B: A() { } - | interface X { } - | interface Y : X { } - | class Tested : B(), Y { } - """.trimIndent() - ) { - with((this / "classes" / "Tested").cast<DClass>()) { - supertypes.entries.single().value.map { it.typeConstructor.dri.sureClassNames to it.kind } - .sortedBy { it.first } equals listOf( - "B" to KotlinClassKindTypes.CLASS, - "Y" to KotlinClassKindTypes.INTERFACE - ) - } - } - } - - @Test - fun doublyTypealiasedException() { - inlineModelTest( - """ - | typealias B = RuntimeException - | typealias A = B - """.trimMargin() - ) { - with((this / "classes" / "A").cast<DTypeAlias>()) { - extra[ExceptionInSupertypes].assertNotNull("Typealias A should have ExceptionInSupertypes in its extra field") - } - with((this / "classes" / "B").cast<DTypeAlias>()) { - extra[ExceptionInSupertypes].assertNotNull("Typealias B should have ExceptionInSupertypes in its extra field") - } - } - } - - @Test - fun `inline classes`() { - inlineModelTest( - """ - | inline class X(val example: String) - | - | @JvmInline - | value class InlineTest(val x: String) - """.trimMargin() - ) { - with((this / "classes" / "X").cast<DClass>()) { - name equals "X" - properties.first().name equals "example" - extra[AdditionalModifiers]?.content?.values?.firstOrNull() - ?.firstOrNull() equals ExtraModifiers.KotlinOnlyModifiers.Inline - } - } - } - - @Test - fun `value classes`() { - inlineModelTest( - """ - | @JvmInline - | value class InlineTest(val example: String) - """.trimMargin() - ) { - val classlike = packages.flatMap { it.classlikes }.first() as DClass - classlike.name equals "InlineTest" - classlike.properties.first().name equals "example" - classlike.extra[AdditionalModifiers]?.content?.values?.firstOrNull() - ?.firstOrNull() equals ExtraModifiers.KotlinOnlyModifiers.Value - } - } -} diff --git a/plugins/base/src/test/kotlin/model/CommentTest.kt b/plugins/base/src/test/kotlin/model/CommentTest.kt deleted file mode 100644 index 6b00f2f0..00000000 --- a/plugins/base/src/test/kotlin/model/CommentTest.kt +++ /dev/null @@ -1,338 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package model - -import org.jetbrains.dokka.model.DClass -import org.jetbrains.dokka.model.DProperty -import org.jetbrains.dokka.model.doc.* -import utils.AbstractModelTest -import utils.assertNotNull -import utils.comments -import utils.docs -import kotlin.test.Test - -class CommentTest : AbstractModelTest("/src/main/kotlin/comment/Test.kt", "comment") { - - @Test - fun codeBlockComment() { - inlineModelTest( - """ - |/** - | * ```brainfuck - | * ++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>. - | * ``` - | */ - |val prop1 = "" - | - | - |/** - | * ``` - | * a + b - c - | * ``` - | */ - |val prop2 = "" - """ - ) { - with((this / "comment" / "prop1").cast<DProperty>()) { - name equals "prop1" - with(this.docs().firstOrNull()?.children?.firstOrNull()?.assertNotNull("Code")) { - (this?.children?.firstOrNull() as? Text) - ?.body equals "++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>." - - this?.params?.get("lang") equals "brainfuck" - } - } - with((this / "comment" / "prop2").cast<DProperty>()) { - name equals "prop2" - with(this.docs().firstOrNull()?.children?.firstOrNull()?.assertNotNull("Code")) { - (this?.children?.firstOrNull() as? Text) - ?.body equals "a + b - c" - - this?.params?.get("lang") equals null - } - } - } - } - - @Test - fun codeBlockWithIndentationComment() { - inlineModelTest( - """ - |/** - | * 1. - | * ``` - | * line 1 - | * line 2 - | * ``` - | */ - |val prop1 = "" - """ - ) { - with((this / "comment" / "prop1").cast<DProperty>()) { - name equals "prop1" - with(this.docs().firstOrNull()?.children?.firstOrNull()?.assertNotNull("Code")) { - val codeBlockChildren = ((this?.children?.firstOrNull() as? Li)?.children?.firstOrNull() as? CodeBlock)?.children - (codeBlockChildren?.get(0) as? Text)?.body equals " line 1" - (codeBlockChildren?.get(1) as? Br) notNull "Br" - (codeBlockChildren?.get(2) as? Text)?.body equals " line 2" - } - } - } - } - - @Test - fun emptyDoc() { - inlineModelTest( - """ - val property = "test" - """ - ) { - with((this / "comment" / "property").cast<DProperty>()) { - name equals "property" - comments() equals "" - } - } - } - - @Test - fun emptyDocButComment() { - inlineModelTest( - """ - |/* comment */ - |val property = "test" - |fun tst() = property - """ - ) { - with((this / "comment" / "property").cast<DProperty>()) { - comments() equals "" - } - } - } - - @Test - fun multilineDoc() { - inlineModelTest( - """ - |/** - | * doc1 - | * - | * doc2 - | * doc3 - | */ - |val property = "test" - """ - ) { - with((this / "comment" / "property").cast<DProperty>()) { - comments() equals "doc1\ndoc2 doc3\n" - } - } - } - - @Test - fun multilineDocWithComment() { - inlineModelTest( - """ - |/** - | * doc1 - | * - | * doc2 - | * doc3 - | */ - |// comment - |val property = "test" - """ - ) { - with((this / "comment" / "property").cast<DProperty>()) { - comments() equals "doc1\ndoc2 doc3\n" - } - } - } - - @Test - fun oneLineDoc() { - inlineModelTest( - """ - |/** doc */ - |val property = "test" - """ - ) { - with((this / "comment" / "property").cast<DProperty>()) { - comments() equals "doc\n" - } - } - } - - @Test - fun oneLineDocWithComment() { - inlineModelTest( - """ - |/** doc */ - |// comment - |val property = "test" - """ - ) { - with((this / "comment" / "property").cast<DProperty>()) { - comments() equals "doc\n" - } - } - } - - @Test - fun oneLineDocWithEmptyLine() { - inlineModelTest( - """ - |/** doc */ - | - |val property = "test" - """ - ) { - with((this / "comment" / "property").cast<DProperty>()) { - comments() equals "doc\n" - } - } - } - - @Test - fun emptySection() { - inlineModelTest( - """ - |/** - | * Summary - | * @one - | */ - |val property = "test" - """ - ) { - with((this / "comment" / "property").cast<DProperty>()) { - comments() equals "Summary\n\none: []" - with(docs().find { it is CustomTagWrapper && it.name == "one" }.assertNotNull("'one' entry")) { - root.children counts 0 - root.params.keys counts 0 - } - } - } - } - - @Test - fun quotes() { - inlineModelTest( - """ - |/** it's "useful" */ - |val property = "test" - """ - ) { - with((this / "comment" / "property").cast<DProperty>()) { - comments() equals """it's "useful" -""" - } - } - } - - @Test - fun section1() { - inlineModelTest( - """ - |/** - | * Summary - | * @one section one - | */ - |val property = "test" - """ - ) { - with((this / "comment" / "property").cast<DProperty>()) { - comments() equals "Summary\n\none: [section one\n]" - } - } - } - - - @Test - fun section2() { - inlineModelTest( - """ - |/** - | * Summary - | * @one section one - | * @two section two - | */ - |val property = "test" - """ - ) { - with((this / "comment" / "property").cast<DProperty>()) { - comments() equals "Summary\n\none: [section one\n]\ntwo: [section two\n]" - } - } - } - - @Test - fun multilineSection() { - inlineModelTest( - """ - |/** - | * Summary - | * @one - | * line one - | * line two - | */ - |val property = "test" - """ - ) { - with((this / "comment" / "property").cast<DProperty>()) { - comments() equals "Summary\n\none: [line one line two\n]" - } - } - } - - @Test - fun `should be space between Markdown nodes`() { - inlineModelTest( - """ - |/** - | * Rotates paths by `amount` **radians** around (`x`, `y`). - | */ - |val property = "test" - """ - ) { - with((this / "comment" / "property").cast<DProperty>()) { - comments() equals "Rotates paths by amount radians around (x, y).\n" - } - } - } - - @Test - fun `should remove spaces inside indented code block`() { - inlineModelTest( - """ - |/** - | * Welcome: - | * - | * ```kotlin - | * fun main() { - | * println("Hello World!") - | * } - | * ``` - | * - | * fun thisIsACodeBlock() { - | * val butWhy = "per markdown spec, because four-spaces prefix" - | * } - | */ - |class Foo - """ - ) { - with((this / "comment" / "Foo").cast<DClass>()) { - docs()[0].children[2] equals CodeBlock( - listOf( - Text( - "fun thisIsACodeBlock() {\n" + - " val butWhy = \"per markdown spec, because four-spaces prefix\"\n" + - "}" - ) - ) - ) - } - } - } - -} diff --git a/plugins/base/src/test/kotlin/model/ExtensionsTest.kt b/plugins/base/src/test/kotlin/model/ExtensionsTest.kt deleted file mode 100644 index a428dd1d..00000000 --- a/plugins/base/src/test/kotlin/model/ExtensionsTest.kt +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package model - -import org.jetbrains.dokka.base.transformers.documentables.CallableExtensions -import org.jetbrains.dokka.model.DClass -import org.jetbrains.dokka.model.DFunction -import org.jetbrains.dokka.model.DInterface -import org.jetbrains.dokka.model.Documentable -import org.jetbrains.dokka.model.properties.WithExtraProperties -import utils.AbstractModelTest -import kotlin.test.Test - -class ExtensionsTest : AbstractModelTest("/src/main/kotlin/classes/Test.kt", "classes") { - private fun <T : WithExtraProperties<R>, R : Documentable> T.checkExtension(name: String = "extension") = - with(extra[CallableExtensions]?.extensions) { - this notNull "extensions" - this counts 1 - (this?.single() as? DFunction)?.name equals name - } - - @Test - fun `should be extension for subclasses`() { - inlineModelTest( - """ - |open class A - |open class B: A() - |open class C: B() - |open class D: C() - |fun B.extension() = "" - """ - ) { - with((this / "classes" / "B").cast<DClass>()) { - checkExtension() - } - with((this / "classes" / "C").cast<DClass>()) { - checkExtension() - } - with((this / "classes" / "D").cast<DClass>()) { - checkExtension() - } - with((this / "classes" / "A").cast<DClass>()) { - extra[CallableExtensions] equals null - } - } - } - - @Test - fun `should be extension for interfaces`() { - inlineModelTest( - """ - |interface I - |interface I2 : I - |open class A: I2 - |fun I.extension() = "" - """ - ) { - - with((this / "classes" / "A").cast<DClass>()) { - checkExtension() - } - with((this / "classes" / "I2").cast<DInterface>()) { - checkExtension() - } - with((this / "classes" / "I").cast<DInterface>()) { - checkExtension() - } - } - } - - @Test - fun `should be extension for external classes`() { - inlineModelTest( - """ - |abstract class A<T>: AbstractList<T>() - |fun<T> AbstractCollection<T>.extension() {} - | - |class B:Exception() - |fun Throwable.extension() = "" - """ - ) { - with((this / "classes" / "A").cast<DClass>()) { - checkExtension() - } - with((this / "classes" / "B").cast<DClass>()) { - checkExtension() - } - } - } - - @Test - fun `should be extension for typealias`() { - inlineModelTest( - """ - |open class A - |open class B: A() - |open class C: B() - |open class D: C() - |typealias B2 = B - |fun B2.extension() = "" - """ - ) { - with((this / "classes" / "B").cast<DClass>()) { - checkExtension() - } - with((this / "classes" / "C").cast<DClass>()) { - checkExtension() - } - with((this / "classes" / "D").cast<DClass>()) { - checkExtension() - } - with((this / "classes" / "A").cast<DClass>()) { - extra[CallableExtensions] equals null - } - } - } - - @Test - fun `should be extension for java classes`() { - val testConfiguration = dokkaConfiguration { - suppressObviousFunctions = false - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin/") - classpath += jvmStdlibPath!! - } - } - } - testInline( - """ - |/src/main/kotlin/classes/Test.kt - | package classes - | fun A.extension() = "" - | - |/src/main/kotlin/classes/A.java - | package classes; - | public class A {} - | - | /src/main/kotlin/classes/B.java - | package classes; - | public class B extends A {} - """, - configuration = testConfiguration - ) { - documentablesTransformationStage = { - it.run { - with((this / "classes" / "B").cast<DClass>()) { - checkExtension() - } - with((this / "classes" / "A").cast<DClass>()) { - checkExtension() - } - } - } - } - } -} diff --git a/plugins/base/src/test/kotlin/model/FunctionsTest.kt b/plugins/base/src/test/kotlin/model/FunctionsTest.kt deleted file mode 100644 index a6291bb1..00000000 --- a/plugins/base/src/test/kotlin/model/FunctionsTest.kt +++ /dev/null @@ -1,403 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package model - -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.model.* -import utils.AbstractModelTest -import utils.assertNotNull -import utils.comments -import utils.OnlyDescriptors -import utils.name -import kotlin.test.Test - -class FunctionTest : AbstractModelTest("/src/main/kotlin/function/Test.kt", "function") { - - @Test - fun function() { - inlineModelTest( - """ - |/** - | * Function fn - | */ - |fun fn() {} - """ - ) { - with((this / "function" / "fn").cast<DFunction>()) { - name equals "fn" - type.name equals "Unit" - this.children.assertCount(0, "Function children: ") - } - } - } - - @Test - fun overloads() { - inlineModelTest( - """ - |/** - | * Function fn - | */ - |fun fn() {} - | /** - | * Function fn(Int) - | */ - |fun fn(i: Int) {} - """ - ) { - with((this / "function").cast<DPackage>()) { - val fn1 = functions.find { - it.name == "fn" && it.parameters.isEmpty() - }.assertNotNull("fn()") - val fn2 = functions.find { - it.name == "fn" && it.parameters.isNotEmpty() - }.assertNotNull("fn(Int)") - - with(fn1) { - name equals "fn" - parameters.assertCount(0) - } - - with(fn2) { - name equals "fn" - parameters.assertCount(1) - parameters.first().type.name equals "Int" - } - } - } - } - - @Test - fun functionWithReceiver() { - inlineModelTest( - """ - |/** - | * Function with receiver - | */ - |fun String.fn() {} - | - |/** - | * Function with receiver - | */ - |fun String.fn(x: Int) {} - """ - ) { - with((this / "function").cast<DPackage>()) { - val fn1 = functions.find { - it.name == "fn" && it.parameters.isEmpty() - }.assertNotNull("fn()") - val fn2 = functions.find { - it.name == "fn" && it.parameters.count() == 1 - }.assertNotNull("fn(Int)") - - with(fn1) { - name equals "fn" - parameters counts 0 - receiver.assertNotNull("fn() receiver") - } - - with(fn2) { - name equals "fn" - parameters counts 1 - receiver.assertNotNull("fn(Int) receiver") - parameters.first().type.name equals "Int" - } - } - } - } - - @Test - fun functionWithParams() { - inlineModelTest( - """ - |/** - | * Multiline - | * - | * Function - | * Documentation - | */ - |fun function(/** parameter */ x: Int) { - |} - """ - ) { - with((this / "function" / "function").cast<DFunction>()) { - comments() equals "Multiline\nFunction Documentation\n" - - name equals "function" - parameters counts 1 - parameters.firstOrNull().assertNotNull("Parameter: ").also { - it.name equals "x" - it.type.name equals "Int" - it.comments() equals "parameter\n" - } - - type.assertNotNull("Return type: ").name equals "Unit" - } - } - } - - @Test - fun functionWithNotDocumentedAnnotation() { - inlineModelTest( - """ - |@Suppress("FOO") fun f() {} - """ - ) { - with((this / "function" / "f").cast<DFunction>()) { - with(extra[Annotations]!!.directAnnotations.entries.single().value.assertNotNull("Annotations")) { - this counts 1 - with(first()) { - dri.classNames equals "Suppress" - params.entries counts 1 - (params["names"].assertNotNull("param") as ArrayValue).value equals listOf(StringValue("FOO")) - } - } - } - } - } - - @Test - fun inlineFunction() { - inlineModelTest( - """ - |inline fun f(a: () -> String) {} - """ - ) { - with((this / "function" / "f").cast<DFunction>()) { - extra[AdditionalModifiers]!!.content.entries.single().value counts 1 - extra[AdditionalModifiers]!!.content.entries.single().value exists ExtraModifiers.KotlinOnlyModifiers.Inline - } - } - } - - @Test - fun suspendFunction() { - inlineModelTest( - """ - |suspend fun f() {} - """ - ) { - with((this / "function" / "f").cast<DFunction>()) { - extra[AdditionalModifiers]!!.content.entries.single().value counts 1 - extra[AdditionalModifiers]!!.content.entries.single().value exists ExtraModifiers.KotlinOnlyModifiers.Suspend - } - } - } - - @Test - fun suspendInlineFunctionOrder() { - inlineModelTest( - """ - |suspend inline fun f(a: () -> String) {} - """ - ) { - with((this / "function" / "f").cast<DFunction>()) { - extra[AdditionalModifiers]!!.content.entries.single().value counts 2 - extra[AdditionalModifiers]!!.content.entries.single().value exists ExtraModifiers.KotlinOnlyModifiers.Suspend - extra[AdditionalModifiers]!!.content.entries.single().value exists ExtraModifiers.KotlinOnlyModifiers.Inline - } - } - } - - @Test - fun inlineSuspendFunctionOrderChanged() { - inlineModelTest( - """ - |inline suspend fun f(a: () -> String) {} - """ - ) { - with((this / "function" / "f").cast<DFunction>()) { - with(extra[AdditionalModifiers]!!.content.entries.single().value.assertNotNull("AdditionalModifiers")) { - this counts 2 - this exists ExtraModifiers.KotlinOnlyModifiers.Suspend - this exists ExtraModifiers.KotlinOnlyModifiers.Inline - } - } - } - } - - @OnlyDescriptors("Bug in descriptors, DRI of entry should have [EnumEntryDRIExtra]") - @Test - fun functionWithAnnotatedParam() { - inlineModelTest( - """ - |@Target(AnnotationTarget.VALUE_PARAMETER) - |@Retention(AnnotationRetention.SOURCE) - |@MustBeDocumented - |public annotation class Fancy - | - |fun function(@Fancy notInlined: () -> Unit) {} - """ - ) { - with((this / "function" / "Fancy").cast<DAnnotation>()) { - with(extra[Annotations]!!.directAnnotations.entries.single().value.assertNotNull("Annotations")) { - this counts 3 - with(associate { it.dri.classNames to it }) { - with(this["Target"].assertNotNull("Target")) { - (params["allowedTargets"].assertNotNull("allowedTargets") as ArrayValue).value equals listOf( - EnumValue( - "AnnotationTarget.VALUE_PARAMETER", - DRI("kotlin.annotation", "AnnotationTarget.VALUE_PARAMETER") - ) - ) - } - with(this["Retention"].assertNotNull("Retention")) { - (params["value"].assertNotNull("value") as EnumValue) equals EnumValue( - "AnnotationRetention.SOURCE", - DRI("kotlin.annotation", "AnnotationRetention.SOURCE") - ) - } - this["MustBeDocumented"].assertNotNull("MustBeDocumented").params.entries counts 0 - } - } - - } - with((this / "function" / "function" / "notInlined").cast<DParameter>()) { - with(this.extra[Annotations]!!.directAnnotations.entries.single().value.assertNotNull("Annotations")) { - this counts 1 - with(first()) { - dri.classNames equals "Fancy" - params.entries counts 0 - } - } - } - } - } - - @Test - fun functionWithNoinlineParam() { - inlineModelTest( - """ - |fun f(noinline notInlined: () -> Unit) {} - """ - ) { - with((this / "function" / "f" / "notInlined").cast<DParameter>()) { - extra[AdditionalModifiers]!!.content.entries.single().value counts 1 - extra[AdditionalModifiers]!!.content.entries.single().value exists ExtraModifiers.KotlinOnlyModifiers.NoInline - } - } - } - - @OnlyDescriptors("Bug in descriptors, DRI of entry should have [EnumEntryDRIExtra]") - @Test - fun annotatedFunctionWithAnnotationParameters() { - inlineModelTest( - """ - |@Target(AnnotationTarget.VALUE_PARAMETER) - |@Retention(AnnotationRetention.SOURCE) - |@MustBeDocumented - |public annotation class Fancy(val size: Int) - | - |@Fancy(1) fun f() {} - """ - ) { - with((this / "function" / "Fancy").cast<DAnnotation>()) { - constructors counts 1 - with(constructors.first()) { - parameters counts 1 - with(parameters.first()) { - type.name equals "Int" - name equals "size" - } - } - - with(extra[Annotations]!!.directAnnotations.entries.single().value.assertNotNull("Annotations")) { - this counts 3 - with(associate { it.dri.classNames to it }) { - with(this["Target"].assertNotNull("Target")) { - (params["allowedTargets"].assertNotNull("allowedTargets") as ArrayValue).value equals listOf( - EnumValue( - "AnnotationTarget.VALUE_PARAMETER", - DRI("kotlin.annotation", "AnnotationTarget.VALUE_PARAMETER") - ) - ) - } - with(this["Retention"].assertNotNull("Retention")) { - (params["value"].assertNotNull("value") as EnumValue) equals EnumValue( - "AnnotationRetention.SOURCE", - DRI("kotlin.annotation", "AnnotationRetention.SOURCE") - ) - } - this["MustBeDocumented"].assertNotNull("MustBeDocumented").params.entries counts 0 - } - } - - } - with((this / "function" / "f").cast<DFunction>()) { - with(this.extra[Annotations]!!.directAnnotations.entries.single().value.assertNotNull("Annotations")) { - this counts 1 - with(this.first()) { - dri.classNames equals "Fancy" - params.entries counts 1 - (params["size"] as IntValue).value equals 1 - } - } - } - } - } - - @Test - fun functionWithDefaultStringParameter() { - inlineModelTest( - """ - |/src/main/kotlin/function/Test.kt - |package function - |fun f(x: String = "") {} - """ - ) { - with((this / "function" / "f").cast<DFunction>()) { - parameters.forEach { p -> - p.name equals "x" - p.type.name.assertNotNull("Parameter type: ") equals "String" - p.extra[DefaultValue]?.expression?.get(sourceSets.single()) equals StringConstant("") - } - } - } - } - - @Test - fun functionWithDefaultFloatParameter() { - inlineModelTest( - """ - |/src/main/kotlin/function/Test.kt - |package function - |fun f(x: Float = 3.14f) {} - """ - ) { - with((this / "function" / "f").cast<DFunction>()) { - parameters.forEach { p -> - p.name equals "x" - p.type.name.assertNotNull("Parameter type: ") equals "Float" - p.extra[DefaultValue]?.expression?.get(sourceSets.single()) equals FloatConstant(3.14f) - } - } - } - } - - @Test - fun sinceKotlin() { - inlineModelTest( - """ - |/** - | * Quite useful [String] - | */ - |@SinceKotlin("1.1") - |fun f(): String = "1.1 rulezz" - """ - ) { - with((this / "function" / "f").cast<DFunction>()) { - with(extra[Annotations]!!.directAnnotations.entries.single().value.assertNotNull("Annotations")) { - this counts 1 - with(first()) { - dri.classNames equals "SinceKotlin" - params.entries counts 1 - (params["version"].assertNotNull("version") as StringValue).value equals "1.1" - } - } - } - } - } - -} diff --git a/plugins/base/src/test/kotlin/model/InheritorsTest.kt b/plugins/base/src/test/kotlin/model/InheritorsTest.kt deleted file mode 100644 index 459dd9ac..00000000 --- a/plugins/base/src/test/kotlin/model/InheritorsTest.kt +++ /dev/null @@ -1,428 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package model - -import org.jetbrains.dokka.Platform -import org.jetbrains.dokka.base.transformers.documentables.InheritorsInfo -import org.jetbrains.dokka.model.DClass -import org.jetbrains.dokka.model.DFunction -import org.jetbrains.dokka.model.DInterface -import org.jetbrains.dokka.model.doc.P -import org.jetbrains.dokka.model.doc.Text -import utils.AbstractModelTest -import utils.assertNotNull -import kotlin.test.Test -import kotlin.test.assertTrue - -class InheritorsTest : AbstractModelTest("/src/main/kotlin/inheritors/Test.kt", "inheritors") { - - @Test - fun simple() { - inlineModelTest( - """|interface A{} - |class B() : A {} - """.trimMargin(), - ) { - with((this / "inheritors" / "A").cast<DInterface>()) { - val map = extra[InheritorsInfo].assertNotNull("InheritorsInfo").value - with(map.keys.also { it counts 1 }.find { it.analysisPlatform == Platform.jvm }.assertNotNull("jvm key").let { map[it]!! } - ) { - this counts 1 - first().classNames equals "B" - } - } - } - } - - @Test - fun sealed() { - inlineModelTest( - """|sealed class A {} - |class B() : A() {} - |class C() : A() {} - |class D() - """.trimMargin(), - ) { - with((this / "inheritors" / "A").cast<DClass>()) { - val map = extra[InheritorsInfo].assertNotNull("InheritorsInfo").value - with(map.keys.also { it counts 1 }.find { it.analysisPlatform == Platform.jvm }.assertNotNull("jvm key").let { map[it]!! } - ) { - this counts 2 - mapNotNull { it.classNames }.sorted() equals listOf("B", "C") - } - } - } - } - - @Test - fun multiplatform() { - val configuration = dokkaConfiguration { - sourceSets { - val commonSourceSet = sourceSet { - name = "common" - sourceRoots = listOf("common/src/") - analysisPlatform = "common" - } - sourceSet { - name = "jvm" - sourceRoots = listOf("jvm/src/") - analysisPlatform = "jvm" - dependentSourceSets = setOf(commonSourceSet.value.sourceSetID) - } - sourceSet { - name = "js" - sourceRoots = listOf("js/src/") - analysisPlatform = "js" - dependentSourceSets = setOf(commonSourceSet.value.sourceSetID) - } - } - } - - testInline( - """ - |/common/src/main/kotlin/inheritors/Test.kt - |package inheritors - |interface A{} - |/jvm/src/main/kotlin/inheritors/Test.kt - |package inheritors - |class B() : A {} - |/js/src/main/kotlin/inheritors/Test.kt - |package inheritors - |class B() : A {} - |class C() : A {} - """.trimMargin(), - configuration, - cleanupOutput = false, - ) { - documentablesTransformationStage = { m -> - with((m / "inheritors" / "A").cast<DInterface>()) { - val map = extra[InheritorsInfo].assertNotNull("InheritorsInfo").value - with(map.keys.also { it counts 2 }) { - with(find { it.analysisPlatform == Platform.jvm }.assertNotNull("jvm key").let { map[it]!! }) { - this counts 1 - first().classNames equals "B" - } - with(find { it.analysisPlatform == Platform.js }.assertNotNull("js key").let { map[it]!! }) { - this counts 2 - val classes = listOf("B", "C") - assertTrue(all { classes.contains(it.classNames) }, "One of subclasses missing in js" ) - } - } - - } - } - } - } - - @Test - fun `should inherit docs`() { - val expectedDoc = listOf(P(listOf(Text("some text")))) - inlineModelTest( - """|interface A<out E> { - | /** - | * some text - | */ - | val a: Int - | - | /** - | * some text - | */ - | fun b(): E - |} - |open class C - |class B<out E>() : C(), A<out E> { - | val a = 0 - | override fun b(): E {} - |} - """.trimMargin(), - platform = Platform.common.toString() - ) { - with((this / "inheritors" / "A").cast<DInterface>()) { - with(this / "a") { - val propDoc = this?.documentation?.values?.single()?.children?.first()?.children - propDoc equals expectedDoc - } - with(this / "b") { - val funDoc = this?.documentation?.values?.single()?.children?.first()?.children - funDoc equals expectedDoc - } - - } - - with((this / "inheritors" / "B").cast<DClass>()) { - with(this / "a") { - val propDoc = this?.documentation?.values?.single()?.children?.first()?.children - propDoc equals expectedDoc - } - } - } - } - -// TODO [beresnev] fix, needs access to analysis -// class IgnoreCommonBuiltInsPlugin : DokkaPlugin() { -// private val kotlinAnalysisPlugin by lazy { plugin<DescriptorKotlinAnalysisPlugin>() } -// @Suppress("unused") -// val stdLibKotlinAnalysis by extending { -// kotlinAnalysisPlugin.kotlinAnalysis providing { ctx -> -// ProjectKotlinAnalysis( -// sourceSets = ctx.configuration.sourceSets, -// logger = ctx.logger, -// analysisConfiguration = DokkaAnalysisConfiguration(ignoreCommonBuiltIns = true) -// ) -// } override kotlinAnalysisPlugin.defaultKotlinAnalysis -// } -// -// @OptIn(DokkaPluginApiPreview::class) -// override fun pluginApiPreviewAcknowledgement(): PluginApiPreviewAcknowledgement = -// PluginApiPreviewAcknowledgement -// } -// @Test -// fun `should inherit docs for stdLib #2638`() { -// val testConfiguration = dokkaConfiguration { -// suppressObviousFunctions = false -// sourceSets { -// sourceSet { -// sourceRoots = listOf("src/") -// analysisPlatform = "common" -// languageVersion = "1.4" -// } -// } -// } -// -// inlineModelTest( -// """ -// package kotlin.collections -// -// import kotlin.internal.PlatformDependent -// -// /** -// * Classes that inherit from this interface can be represented as a sequence of elements that can -// * be iterated over. -// * @param T the type of element being iterated over. The iterator is covariant in its element type. -// */ -// public interface Iterable<out T> { -// /** -// * Returns an iterator over the elements of this object. -// */ -// public operator fun iterator(): Iterator<T> -// } -// -// /** -// * Classes that inherit from this interface can be represented as a sequence of elements that can -// * be iterated over and that supports removing elements during iteration. -// * @param T the type of element being iterated over. The mutable iterator is invariant in its element type. -// */ -// public interface MutableIterable<out T> : Iterable<T> { -// /** -// * Returns an iterator over the elements of this sequence that supports removing elements during iteration. -// */ -// override fun iterator(): MutableIterator<T> -// } -// -// /** -// * A generic collection of elements. Methods in this interface support only read-only access to the collection; -// * read/write access is supported through the [MutableCollection] interface. -// * @param E the type of elements contained in the collection. The collection is covariant in its element type. -// */ -// public interface Collection<out E> : Iterable<E> { -// // Query Operations -// /** -// * Returns the size of the collection. -// */ -// public val size: Int -// -// /** -// * Returns `true` if the collection is empty (contains no elements), `false` otherwise. -// */ -// public fun isEmpty(): Boolean -// -// /** -// * Checks if the specified element is contained in this collection. -// */ -// public operator fun contains(element: @UnsafeVariance E): Boolean -// -// override fun iterator(): Iterator<E> -// -// // Bulk Operations -// /** -// * Checks if all elements in the specified collection are contained in this collection. -// */ -// public fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean -// } -// -// /** -// * A generic collection of elements that supports adding and removing elements. -// * -// * @param E the type of elements contained in the collection. The mutable collection is invariant in its element type. -// */ -// public interface MutableCollection<E> : Collection<E>, MutableIterable<E> { -// // Query Operations -// override fun iterator(): MutableIterator<E> -// -// // Modification Operations -// /** -// * Adds the specified element to the collection. -// * -// * @return `true` if the element has been added, `false` if the collection does not support duplicates -// * and the element is already contained in the collection. -// */ -// public fun add(element: E): Boolean -// -// /** -// * Removes a single instance of the specified element from this -// * collection, if it is present. -// * -// * @return `true` if the element has been successfully removed; `false` if it was not present in the collection. -// */ -// public fun remove(element: E): Boolean -// -// // Bulk Modification Operations -// /** -// * Adds all of the elements of the specified collection to this collection. -// * -// * @return `true` if any of the specified elements was added to the collection, `false` if the collection was not modified. -// */ -// public fun addAll(elements: Collection<E>): Boolean -// -// /** -// * Removes all of this collection's elements that are also contained in the specified collection. -// * -// * @return `true` if any of the specified elements was removed from the collection, `false` if the collection was not modified. -// */ -// public fun removeAll(elements: Collection<E>): Boolean -// -// /** -// * Retains only the elements in this collection that are contained in the specified collection. -// * -// * @return `true` if any element was removed from the collection, `false` if the collection was not modified. -// */ -// public fun retainAll(elements: Collection<E>): Boolean -// -// /** -// * Removes all elements from this collection. -// */ -// public fun clear(): Unit -// } -// -// /** -// * A generic ordered collection of elements. Methods in this interface support only read-only access to the list; -// * read/write access is supported through the [MutableList] interface. -// * @param E the type of elements contained in the list. The list is covariant in its element type. -// */ -// public interface List<out E> : Collection<E> { -// // Query Operations -// -// override val size: Int -// override fun isEmpty(): Boolean -// override fun contains(element: @UnsafeVariance E): Boolean -// override fun iterator(): Iterator<E> -// -// // Bulk Operations -// override fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean -// -// // Positional Access Operations -// /** -// * Returns the element at the specified index in the list. -// */ -// public operator fun get(index: Int): E -// -// // Search Operations -// /** -// * Returns the index of the first occurrence of the specified element in the list, or -1 if the specified -// * element is not contained in the list. -// */ -// public fun indexOf(element: @UnsafeVariance E): Int -// -// /** -// * Returns the index of the last occurrence of the specified element in the list, or -1 if the specified -// * element is not contained in the list. -// */ -// public fun lastIndexOf(element: @UnsafeVariance E): Int -// -// // List Iterators -// /** -// * Returns a list iterator over the elements in this list (in proper sequence). -// */ -// public fun listIterator(): ListIterator<E> -// -// /** -// * Returns a list iterator over the elements in this list (in proper sequence), starting at the specified [index]. -// */ -// public fun listIterator(index: Int): ListIterator<E> -// -// // View -// /** -// * Returns a view of the portion of this list between the specified [fromIndex] (inclusive) and [toIndex] (exclusive). -// * The returned list is backed by this list, so non-structural changes in the returned list are reflected in this list, and vice-versa. -// * -// * Structural changes in the base list make the behavior of the view undefined. -// */ -// public fun subList(fromIndex: Int, toIndex: Int): List<E> -// } -// -// // etc -// """.trimMargin(), -// platform = Platform.common.toString(), -// configuration = testConfiguration, -// prependPackage = false, -// pluginsOverrides = listOf(IgnoreCommonBuiltInsPlugin()) -// ) { -// with((this / "kotlin.collections" / "List" / "contains").cast<DFunction>()) { -// documentation.size equals 1 -// -// } -// } -// } - - @Test - fun `should inherit docs in case of diamond inheritance`() { - inlineModelTest( - """ - public interface Collection2<out E> { - /** - * Returns `true` if the collection is empty (contains no elements), `false` otherwise. - */ - public fun isEmpty(): Boolean - - /** - * Checks if the specified element is contained in this collection. - */ - public operator fun contains(element: @UnsafeVariance E): Boolean - } - - public interface MutableCollection2<E> : Collection2<E>, MutableIterable2<E> - - - public interface List2<out E> : Collection2<E> { - override fun isEmpty(): Boolean - override fun contains(element: @UnsafeVariance E): Boolean - } - - public interface MutableList2<E> : List2<E>, MutableCollection2<E> - - public class AbstractMutableList2<E> : MutableList2<E> { - protected constructor() - - // From List - - override fun isEmpty(): Boolean = size == 0 - public override fun contains(element: E): Boolean = indexOf(element) != -1 - } - public class ArrayDeque2<E> : AbstractMutableList2<E> { - override fun isEmpty(): Boolean = size == 0 - public override fun contains(element: E): Boolean = indexOf(element) != -1 - - } - """.trimMargin() - ) { - with((this / "inheritors" / "ArrayDeque2" / "isEmpty").cast<DFunction>()) { - documentation.size equals 1 - } - with((this / "inheritors" / "ArrayDeque2" / "contains").cast<DFunction>()) { - documentation.size equals 1 - } - } - } -} diff --git a/plugins/base/src/test/kotlin/model/JavaTest.kt b/plugins/base/src/test/kotlin/model/JavaTest.kt deleted file mode 100644 index ff706c5e..00000000 --- a/plugins/base/src/test/kotlin/model/JavaTest.kt +++ /dev/null @@ -1,491 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package model - -import org.jetbrains.dokka.DokkaConfiguration -import org.jetbrains.dokka.Platform -import org.jetbrains.dokka.base.transformers.documentables.InheritorsInfo -import org.jetbrains.dokka.links.* -import org.jetbrains.dokka.model.* -import org.jetbrains.dokka.model.doc.Param -import org.jetbrains.dokka.model.doc.Text -import utils.AbstractModelTest -import utils.assertContains -import utils.assertNotNull -import utils.name -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertTrue - -class JavaTest : AbstractModelTest("/src/main/kotlin/java/Test.java", "java") { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - analysisPlatform = Platform.jvm.toString() - classpath += jvmStdlibPath!! - documentedVisibilities = setOf( - DokkaConfiguration.Visibility.PUBLIC, - DokkaConfiguration.Visibility.PRIVATE, - DokkaConfiguration.Visibility.PROTECTED, - DokkaConfiguration.Visibility.PACKAGE, - ) - } - } - } - - @Test - fun function() { - inlineModelTest( - """ - |class Test { - | /** - | * Summary for Function - | * @param name is String parameter - | * @param value is int parameter - | */ - | public void fn(String name, int value) {} - |} - """, configuration = configuration - ) { - with((this / "java" / "Test").cast<DClass>()) { - name equals "Test" - children counts 2 // default constructor and function - with((this / "fn").cast<DFunction>()) { - name equals "fn" - val params = parameters.map { it.documentation.values.first().children.first() as Param } - params.map { it.firstMemberOfType<Text>().body } equals listOf( - "is String parameter", - "is int parameter" - ) - } - } - } - } - - @Test fun allImplementedInterfacesInJava() { - inlineModelTest( - """ - |interface Highest { } - |interface Lower extends Highest { } - |class Extendable { } - |class Tested extends Extendable implements Lower { } - """, configuration = configuration){ - with((this / "java" / "Tested").cast<DClass>()){ - extra[ImplementedInterfaces]?.interfaces?.entries?.single()?.value?.map { it.dri.sureClassNames }?.sorted() equals listOf("Highest", "Lower").sorted() - } - } - } - - @Test fun multipleClassInheritanceWithInterface() { - inlineModelTest( - """ - |interface Highest { } - |interface Lower extends Highest { } - |class Extendable { } - |class Tested extends Extendable implements Lower { } - """, configuration = configuration){ - with((this / "java" / "Tested").cast<DClass>()) { - supertypes.entries.single().value.map { it.typeConstructor.dri.sureClassNames to it.kind }.sortedBy { it.first } equals listOf("Extendable" to JavaClassKindTypes.CLASS, "Lower" to JavaClassKindTypes.INTERFACE) - } - } - } - - @Test - fun superClass() { - inlineModelTest( - """ - |public class Foo extends Exception implements Cloneable {} - """, configuration = configuration - ) { - with((this / "java" / "Foo").cast<DClass>()) { - val sups = listOf("Exception", "Cloneable") - assertTrue( - sups.all { s -> supertypes.values.flatten().any { it.typeConstructor.dri.classNames == s } }) - "Foo must extend ${sups.joinToString(", ")}" - } - } - } - - @Test - fun arrayType() { - inlineModelTest( - """ - |class Test { - | public String[] arrayToString(int[] data) { - | return null; - | } - |} - """, configuration = configuration - ) { - with((this / "java" / "Test").cast<DClass>()) { - name equals "Test" - children counts 2 // default constructor and function - - with((this / "arrayToString").cast<DFunction>()) { - name equals "arrayToString" - type.name equals "Array" - with(parameters.firstOrNull().assertNotNull("parameters")) { - name equals "data" - type.name equals "Array" - } - } - } - } - } - - @Test - fun typeParameter() { - inlineModelTest( - """ - |class Foo<T extends Comparable<T>> { - | public <E> E foo(); - |} - """, configuration = configuration - ) { - with((this / "java" / "Foo").cast<DClass>()) { - generics counts 1 - generics[0].dri.classNames equals "Foo" - (functions[0].type as? TypeParameter)?.dri?.run { - packageName equals "java" - name equals "Foo" - callable?.name equals "foo" - } - } - } - } - - @Test - fun typeParameterIntoDifferentClasses2596() { - inlineModelTest( - """ - |class GenericDocument { } - |public interface DocumentClassFactory<T> { - | String getSchemaName(); - | GenericDocument toGenericDocument(T document); - | T fromGenericDocument(GenericDocument genericDoc); - |} - | - |public final class DocumentClassFactoryRegistry { - | public <T> DocumentClassFactory<T> getOrCreateFactory(T documentClass) { - | return null; - | } - |} - """, configuration = configuration - ) { - with((this / "java" / "DocumentClassFactory").cast<DInterface>()) { - generics counts 1 - generics[0].dri.classNames equals "DocumentClassFactory" - } - with((this / "java" / "DocumentClassFactoryRegistry").cast<DClass>()) { - functions.forEach { - (it.type as GenericTypeConstructor).dri.classNames equals "DocumentClassFactory" - ((it.type as GenericTypeConstructor).projections[0] as TypeParameter).dri.classNames equals "DocumentClassFactoryRegistry" - } - } - } - } - - @Test - fun constructors() { - inlineModelTest( - """ - |class Test { - | public Test() {} - | - | public Test(String s) {} - |} - """, configuration = configuration - ) { - with((this / "java" / "Test").cast<DClass>()) { - name equals "Test" - - constructors counts 2 - constructors.forEach { it.name equals "Test" } - constructors.find { it.parameters.isEmpty() }.assertNotNull("Test()") - - with(constructors.find { it.parameters.isNotEmpty() }.assertNotNull("Test(String)")) { - parameters.firstOrNull()?.type?.name equals "String" - } - } - } - } - - @Test - fun innerClass() { - inlineModelTest( - """ - |class InnerClass { - | public class D {} - |} - """, configuration = configuration - ) { - with((this / "java" / "InnerClass").cast<DClass>()) { - children counts 2 // default constructor and inner class - with((this / "D").cast<DClass>()) { - name equals "D" - children counts 1 // default constructor - } - } - } - } - - @Test - fun varargs() { - inlineModelTest( - """ - |class Foo { - | public void bar(String... x); - |} - """, configuration = configuration - ) { - with((this / "java" / "Foo").cast<DClass>()) { - name equals "Foo" - children counts 2 // default constructor and function - - with((this / "bar").cast<DFunction>()) { - name equals "bar" - with(parameters.firstOrNull().assertNotNull("parameter")) { - name equals "x" - type.name equals "Array" - } - } - } - } - } - - @Test - fun fields() { - inlineModelTest( - """ - |class Test { - | public int i; - | public static final String s; - |} - """, configuration = configuration - ) { - with((this / "java" / "Test").cast<DClass>()) { - children counts 3 // default constructor + 2 props - - with((this / "i").cast<DProperty>()) { - getter equals null - setter equals null - } - - with((this / "s").cast<DProperty>()) { - getter equals null - setter equals null - } - } - } - } - - @Test - fun staticMethod() { - inlineModelTest( - """ - |class C { - | public static void foo() {} - |} - """, configuration = configuration - ) { - with((this / "java" / "C" / "foo").cast<DFunction>()) { - with(extra[AdditionalModifiers]!!.content.entries.single().value.assertNotNull("AdditionalModifiers")) { - this counts 1 - first() equals ExtraModifiers.JavaOnlyModifiers.Static - } - } - } - } - - @Test - fun throwsList() { - inlineModelTest( - """ - |class C { - | public void foo() throws java.io.IOException, ArithmeticException {} - |} - """, configuration = configuration - ) { - with((this / "java" / "C" / "foo").cast<DFunction>()) { - with(extra[CheckedExceptions]?.exceptions?.entries?.single()?.value.assertNotNull("CheckedExceptions")) { - this counts 2 - first().packageName equals "java.io" - first().classNames equals "IOException" - get(1).packageName equals "java.lang" - get(1).classNames equals "ArithmeticException" - } - } - } - } - - @Test - fun annotatedAnnotation() { - inlineModelTest( - """ - |import java.lang.annotation.*; - | - |@Target({ElementType.FIELD, ElementType.TYPE, ElementType.METHOD}) - |public @interface Attribute { - | String value() default ""; - |} - """, configuration = configuration - ) { - with((this / "java" / "Attribute").cast<DAnnotation>()) { - with(extra[Annotations]!!.directAnnotations.entries.single().value.assertNotNull("Annotations")) { - with(single()) { - dri.classNames equals "Target" - (params["value"].assertNotNull("value") as ArrayValue).value equals listOf( - EnumValue("ElementType.FIELD", DRI("java.lang.annotation", "ElementType")), - EnumValue("ElementType.TYPE", DRI("java.lang.annotation", "ElementType")), - EnumValue("ElementType.METHOD", DRI("java.lang.annotation", "ElementType")) - ) - } - } - } - } - } - - @Test - fun javaLangObject() { - inlineModelTest( - """ - |class Test { - | public Object fn() { return null; } - |} - """, configuration = configuration - ) { - with((this / "java" / "Test" / "fn").cast<DFunction>()) { - assertTrue(type is JavaObject) - } - } - } - - @Test - fun enumValues() { - inlineModelTest( - """ - |enum E { - | Foo - |} - """, configuration = configuration - ) { - with((this / "java" / "E").cast<DEnum>()) { - name equals "E" - entries counts 1 - with((this / "Foo").cast<DEnumEntry>()) { - name equals "Foo" - } - } - } - } - - @Test - fun inheritorLinks() { - inlineModelTest( - """ - |public class InheritorLinks { - | public static class Foo {} - | - | public static class Bar extends Foo {} - |} - """, configuration = configuration - ) { - with((this / "java" / "InheritorLinks").cast<DClass>()) { - val dri = (this / "Bar").assertNotNull("Foo dri").dri - with((this / "Foo").cast<DClass>()) { - with(extra[InheritorsInfo].assertNotNull("InheritorsInfo")) { - with(value.values.flatten().distinct()) { - this counts 1 - first() equals dri - } - } - } - } - } - } - - @Test - fun `retention should work with static import`() { - inlineModelTest( - """ - |import java.lang.annotation.Retention; - |import java.lang.annotation.RetentionPolicy; - |import static java.lang.annotation.RetentionPolicy.RUNTIME; - | - |@Retention(RUNTIME) - |public @interface JsonClass { - |}; - """, configuration = configuration - ) { - with((this / "java" / "JsonClass").cast<DAnnotation>()) { - val annotation = extra[Annotations]?.directAnnotations?.entries - ?.firstOrNull()?.value //First sourceset - ?.firstOrNull() - - val expectedDri = DRI("java.lang.annotation", "Retention", null, PointingToDeclaration) - val expectedParams = "value" to EnumValue( - "RUNTIME", - DRI( - "java.lang.annotation", - "RetentionPolicy.RUNTIME", - null, - PointingToDeclaration, - DRIExtraContainer().also { it[EnumEntryDRIExtra] = EnumEntryDRIExtra }.encode() - ) - ) - - assertEquals(expectedDri, annotation?.dri) - assertEquals(expectedParams.first, annotation?.params?.entries?.first()?.key) - assertEquals(expectedParams.second, annotation?.params?.entries?.first()?.value) - } - } - } - - @Test - fun variances() { - inlineModelTest( - """ - |public class Foo { - | public void superBound(java.util.List<? super String> param) {} - | public void extendsBound(java.util.List<? extends String> param) {} - | public void unbounded(java.util.List<?> param) {} - |} - """, configuration = configuration - ) { - with((this / "java" / "Foo").cast<DClass>()) { - val functionNames = functions.map { it.name } - assertContains(functionNames, "superBound") - assertContains(functionNames, "extendsBound") - assertContains(functionNames, "unbounded") - - for (function in functions) { - val param = function.parameters.single() - val type = param.type as GenericTypeConstructor - val variance = type.projections.single() - - when (function.name) { - "superBound" -> { - assertTrue(variance is Contravariance<*>) - val bound = variance.inner - assertEquals((bound as GenericTypeConstructor).dri.classNames, "String") - } - "extendsBound" -> { - assertTrue(variance is Covariance<*>) - val bound = variance.inner - assertEquals((bound as GenericTypeConstructor).dri.classNames, "String") - } - "unbounded" -> { - assertTrue(variance is Covariance<*>) - val bound = variance.inner - assertTrue(bound is JavaObject) - } - } - } - } - } - } - -} diff --git a/plugins/base/src/test/kotlin/model/MultiLanguageInheritanceTest.kt b/plugins/base/src/test/kotlin/model/MultiLanguageInheritanceTest.kt deleted file mode 100644 index 9b646f24..00000000 --- a/plugins/base/src/test/kotlin/model/MultiLanguageInheritanceTest.kt +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package model - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.links.PointingToDeclaration -import org.jetbrains.dokka.model.dfs -import org.jetbrains.dokka.model.doc.* -import org.jetbrains.dokka.model.withDescendants -import org.jetbrains.dokka.utilities.firstIsInstanceOrNull -import translators.documentationOf -import utils.docs -import kotlin.test.Test -import kotlin.test.assertEquals - -class MultiLanguageInheritanceTest : BaseAbstractTest() { - val configuration = dokkaConfiguration { - suppressObviousFunctions = false - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin") - } - } - } - - @Test - fun `from java to kotlin`() { - testInline( - """ - |/src/main/kotlin/sample/Parent.java - |package sample; - | - |/** - | * Sample description from parent - | */ - |public class Parent { - | /** - | * parent function docs - | * @see java.lang.String for details - | */ - | public void parentFunction(){ - | } - |} - | - |/src/main/kotlin/sample/Child.kt - |package sample - |public class Child : Parent() { - | override fun parentFunction(){ - | - | } - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val function = module.packages.flatMap { it.classlikes } - .find { it.name == "Child" }?.functions?.find { it.name == "parentFunction" } - val seeTag = function?.documentation?.values?.first()?.children?.firstIsInstanceOrNull<See>() - - assertEquals("", module.documentationOf("Child")) - assertEquals("parent function docs", module.documentationOf("Child", "parentFunction")) - assertEquals("for details", (seeTag?.root?.dfs { it is Text } as Text).body) - assertEquals("java.lang.String", seeTag.name) - } - } - } - - @Test - fun `from kotlin to java`() { - testInline( - """ - |/src/main/kotlin/sample/ParentInKotlin.kt - |package sample - | - |/** - | * Sample description from parent - | */ - |public open class ParentInKotlin { - | /** - | * parent `function docs` - | * - | * ``` - | * code block - | * ``` - | * @see java.lang.String for details - | */ - | public open fun parentFun(){ - | - | } - |} - | - | - |/src/main/kotlin/sample/ChildInJava.java - |package sample; - |public class ChildInJava extends ParentInKotlin { - | @Override - | public void parentFun() { - | super.parentFun(); - | } - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val function = module.packages.flatMap { it.classlikes } - .find { it.name == "ChildInJava" }?.functions?.find { it.name == "parentFun" } - val seeTag = function?.documentation?.values?.first()?.children?.firstIsInstanceOrNull<See>() - - val expectedDocs = CustomDocTag( - children = listOf( - P( - listOf( - Text("parent "), - CodeInline( - listOf(Text("function docs")) - ) - ) - ), - CodeBlock( - listOf(Text("code block")) - ) - - ), - params = emptyMap(), - name = "MARKDOWN_FILE" - ) - - assertEquals("", module.documentationOf("ChildInJava")) - assertEquals(expectedDocs, function?.docs()?.firstIsInstanceOrNull<Description>()?.root) - assertEquals("for details", (seeTag?.root?.dfs { it is Text } as Text).body) - assertEquals("java.lang.String", seeTag.name) - } - } - } - - @Test - fun `inherit doc on method`() { - testInline( - """ - |/src/main/kotlin/sample/ParentInKotlin.kt - |package sample - | - |/** - | * Sample description from parent - | */ - |public open class ParentInKotlin { - | /** - | * parent `function docs` with a link to [defaultString][java.lang.String] - | * - | * ``` - | * code block - | * ``` - | */ - | public open fun parentFun(){ - | - | } - |} - | - | - |/src/main/kotlin/sample/ChildInJava.java - |package sample; - |public class ChildInJava extends ParentInKotlin { - | /** - | * {@inheritDoc} - | */ - | @Override - | public void parentFun() { - | super.parentFun(); - | } - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val function = module.packages.flatMap { it.classlikes } - .find { it.name == "ChildInJava" }?.functions?.find { it.name == "parentFun" } - - val expectedDocs = CustomDocTag( - children = listOf( - P( - listOf( - P( - listOf( - Text("parent "), - CodeInline( - listOf(Text("function docs")) - ), - Text(" with a link to "), - DocumentationLink( - DRI("java.lang", "String", null, PointingToDeclaration), - listOf(Text("defaultString")), - params = mapOf("href" to "[java.lang.String]") - ) - ) - ), - CodeBlock( - listOf(Text("code block")) - ) - ) - ) - ), - params = emptyMap(), - name = "MARKDOWN_FILE" - ) - - assertEquals("", module.documentationOf("ChildInJava")) - assertEquals(expectedDocs, function?.docs()?.firstIsInstanceOrNull<Description>()?.root) - } - } - } - - @Test - fun `inline inherit doc on method`() { - testInline( - """ - |/src/main/kotlin/sample/ParentInKotlin.kt - |package sample - | - |/** - | * Sample description from parent - | */ - |public open class ParentInKotlin { - | /** - | * parent function docs - | * @see java.lang.String string - | */ - | public open fun parentFun(){ - | - | } - |} - | - | - |/src/main/kotlin/sample/ChildInJava.java - |package sample; - |public class ChildInJava extends ParentInKotlin { - | /** - | * Start {@inheritDoc} end - | */ - | @Override - | public void parentFun() { - | super.parentFun(); - | } - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val function = module.packages.flatMap { it.classlikes } - .find { it.name == "ChildInJava" }?.functions?.find { it.name == "parentFun" }?.documentation?.values?.first()?.children?.first() - assertEquals("", module.documentationOf("ChildInJava")) - assertEquals("Start parent function docs end", function?.root?.withDescendants()?.filter { it is Text }?.toList()?.joinToString("") { (it as Text).body }) - } - } - } - - @Test - fun `inherit doc on multiple throws`() { - testInline( - """ - |/src/main/kotlin/sample/ParentInKotlin.kt - |package sample - | - |/** - | * Sample description from parent - | */ - |public open class ParentInKotlin { - | /** - | * parent function docs - | * @throws java.lang.RuntimeException runtime - | * @throws java.lang.Exception exception - | */ - | public open fun parentFun(){ - | - | } - |} - | - | - |/src/main/kotlin/sample/ChildInJava.java - |package sample; - |public class ChildInJava extends ParentInKotlin { - | /** - | * Start {@inheritDoc} end - | * @throws java.lang.RuntimeException Testing {@inheritDoc} - | */ - | @Override - | public void parentFun() { - | super.parentFun(); - | } - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val function = module.packages.flatMap { it.classlikes } - .find { it.name == "ChildInJava" }?.functions?.find { it.name == "parentFun" } - val docs = function?.documentation?.values?.first()?.children?.first() - val throwsTag = function?.documentation?.values?.first()?.children?.firstIsInstanceOrNull<Throws>() - - assertEquals("", module.documentationOf("ChildInJava")) - assertEquals("Start parent function docs end", docs?.root?.withDescendants()?.filter { it is Text }?.toList()?.joinToString("") { (it as Text).body }) - assertEquals("Testing runtime", throwsTag?.root?.withDescendants()?.filter { it is Text }?.toList()?.joinToString("") { (it as Text).body }) - assertEquals("RuntimeException", throwsTag?.exceptionAddress?.classNames) - } - } - } - - @Test - fun `inherit doc on params`() { - testInline( - """ - |/src/main/kotlin/sample/ParentInKotlin.kt - |package sample - | - |/** - | * Sample description from parent - | */ - |public open class ParentInKotlin { - | /** - | * parent function docs - | * @param fst first docs - | * @param snd second docs - | */ - | public open fun parentFun(fst: String, snd: Int){ - | - | } - |} - | - | - |/src/main/kotlin/sample/ChildInJava.java - |package sample; - | - |import org.jetbrains.annotations.NotNull; - | - |public class ChildInJava extends ParentInKotlin { - | /** - | * @param fst start {@inheritDoc} end - | * @param snd start {@inheritDoc} end - | */ - | @Override - | public void parentFun(@NotNull String fst, int snd) { - | super.parentFun(); - | } - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val function = module.packages.flatMap { it.classlikes } - .find { it.name == "ChildInJava" }?.functions?.find { it.name == "parentFun" } - val params = function?.documentation?.values?.first()?.children?.filterIsInstance<Param>() - - val fst = params?.first { it.name == "fst" } - val snd = params?.first { it.name == "snd" } - - assertEquals("", module.documentationOf("ChildInJava")) - assertEquals("", module.documentationOf("ChildInJava", "parentFun")) - assertEquals("start first docs end", fst?.root?.withDescendants()?.filter { it is Text }?.toList()?.joinToString("") { (it as Text).body }) - assertEquals("start second docs end", snd?.root?.withDescendants()?.filter { it is Text }?.toList()?.joinToString("") { (it as Text).body }) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/model/ObjectTest.kt b/plugins/base/src/test/kotlin/model/ObjectTest.kt deleted file mode 100644 index 009b406e..00000000 --- a/plugins/base/src/test/kotlin/model/ObjectTest.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 model - -import org.jetbrains.dokka.model.AdditionalModifiers -import org.jetbrains.dokka.model.DObject -import org.jetbrains.dokka.model.ExtraModifiers -import utils.AbstractModelTest -import kotlin.test.Test - -class ObjectTest : AbstractModelTest("/src/main/kotlin/objects/Test.kt", "objects") { - - @Test - fun emptyObject() { - inlineModelTest( - """ - |object Obj {} - """.trimIndent() - ) { - with((this / "objects" / "Obj").cast<DObject>()) { - name equals "Obj" - children counts 3 - } - } - } - - @Test - fun `data object class`() { - inlineModelTest( - """ - |data object KotlinDataObject {} - """.trimIndent() - ) { - with((this / "objects" / "KotlinDataObject").cast<DObject>()) { - name equals "KotlinDataObject" - extra[AdditionalModifiers]?.content?.values?.single() - ?.single() equals ExtraModifiers.KotlinOnlyModifiers.Data - } - } - } -} diff --git a/plugins/base/src/test/kotlin/model/PackagesTest.kt b/plugins/base/src/test/kotlin/model/PackagesTest.kt deleted file mode 100644 index b32f214d..00000000 --- a/plugins/base/src/test/kotlin/model/PackagesTest.kt +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package model - -import org.jetbrains.dokka.model.DPackage -import utils.AbstractModelTest -import kotlin.test.Test - -class PackagesTest : AbstractModelTest("/src/main/kotlin/packages/Test.kt", "packages") { - - @Test - fun rootPackage() { - inlineModelTest( - """ - | - """.trimIndent(), - prependPackage = false, - configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin") - displayName = "JVM" - } - } - } - ) { - with((this / "[root]").cast<DPackage>()) { - packageName equals "" - children counts 0 - } - } - } - - @Test - fun simpleNamePackage() { - inlineModelTest( - """ - |package simple - """.trimIndent(), - prependPackage = false - ) { - with((this / "simple").cast<DPackage>()) { - packageName equals "simple" - children counts 0 - } - } - } - - @Test - fun dottedNamePackage() { - inlineModelTest( - """ - |package dot.name - """.trimIndent(), - prependPackage = false - ) { - with((this / "dot.name").cast<DPackage>()) { - packageName equals "dot.name" - children counts 0 - } - } - - } - - @Test - fun multipleFiles() { - inlineModelTest( - """ - |package dot.name - |/src/main/kotlin/packages/Test2.kt - |package simple - """.trimIndent(), - prependPackage = false - ) { - children counts 2 - with((this / "dot.name").cast<DPackage>()) { - packageName equals "dot.name" - children counts 0 - } - with((this / "simple").cast<DPackage>()) { - packageName equals "simple" - children counts 0 - } - } - } - - @Test - fun multipleFilesSamePackage() { - inlineModelTest( - """ - |package simple - |/src/main/kotlin/packages/Test2.kt - |package simple - """.trimIndent(), - prependPackage = false - ) { - children counts 1 - with((this / "simple").cast<DPackage>()) { - packageName equals "simple" - children counts 0 - } - } - } - - @Test - fun classAtPackageLevel() { - inlineModelTest( - """ - |package simple.name - | - |class Foo {} - """.trimIndent(), - prependPackage = false - ) { - with((this / "simple.name").cast<DPackage>()) { - packageName equals "simple.name" - children counts 1 - } - } - } -} diff --git a/plugins/base/src/test/kotlin/model/PropertyTest.kt b/plugins/base/src/test/kotlin/model/PropertyTest.kt deleted file mode 100644 index 92dc56de..00000000 --- a/plugins/base/src/test/kotlin/model/PropertyTest.kt +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package model - -import org.jetbrains.dokka.model.* -import utils.AbstractModelTest -import utils.assertNotNull -import utils.name -import kotlin.test.Test - -class PropertyTest : AbstractModelTest("/src/main/kotlin/property/Test.kt", "property") { - - @Test - fun valueProperty() { - inlineModelTest( - """ - |val property = "test"""" - ) { - with((this / "property" / "property").cast<DProperty>()) { - name equals "property" - children counts 0 - with(getter.assertNotNull("Getter")) { - type.name equals "String" - } - type.name equals "String" - } - } - } - - @Test - fun variableProperty() { - inlineModelTest( - """ - |var property = "test" - """ - ) { - with((this / "property" / "property").cast<DProperty>()) { - name equals "property" - children counts 0 - setter.assertNotNull("Setter") - with(getter.assertNotNull("Getter")) { - type.name equals "String" - } - type.name equals "String" - } - } - } - - @Test - fun valuePropertyWithGetter() { - inlineModelTest( - """ - |val property: String - | get() = "test" - """ - ) { - with((this / "property" / "property").cast<DProperty>()) { - name equals "property" - children counts 0 - with(getter.assertNotNull("Getter")) { - type.name equals "String" - } - type.name equals "String" - } - } - } - - @Test - fun variablePropertyWithAccessors() { - inlineModelTest( - """ - |var property: String - | get() = "test" - | set(value) {} - """ - ) { - with((this / "property" / "property").cast<DProperty>()) { - name equals "property" - children counts 0 - setter.assertNotNull("Setter") - with(getter.assertNotNull("Getter")) { - type.name equals "String" - } - visibility.values allEquals KotlinVisibility.Public - } - } - } - - @Test - fun propertyWithReceiver() { - inlineModelTest( - """ - |val String.property: Int - | get() = size() * 2 - """ - ) { - with((this / "property" / "property").cast<DProperty>()) { - name equals "property" - children counts 0 - with(receiver.assertNotNull("property receiver")) { - name equals null - type.name equals "String" - } - with(getter.assertNotNull("Getter")) { - type.name equals "Int" - } - visibility.values allEquals KotlinVisibility.Public - } - } - } - - @Test - fun propertyOverride() { - inlineModelTest( - """ - |open class Foo() { - | open val property: Int get() = 0 - |} - |class Bar(): Foo() { - | override val property: Int get() = 1 - |} - """ - ) { - with((this / "property").cast<DPackage>()) { - with((this / "Foo" / "property").cast<DProperty>()) { - dri.classNames equals "Foo" - name equals "property" - children counts 0 - with(getter.assertNotNull("Getter")) { - type.name equals "Int" - } - } - with((this / "Bar" / "property").cast<DProperty>()) { - dri.classNames equals "Bar" - name equals "property" - children counts 0 - with(getter.assertNotNull("Getter")) { - type.name equals "Int" - } - } - } - } - } - - @Test - fun propertyInherited() { - inlineModelTest( - """ - |open class Foo() { - | open val property: Int get() = 0 - |} - |class Bar(): Foo() - """ - ) { - with((this / "property").cast<DPackage>()) { - with((this / "Bar" / "property").cast<DProperty>()) { - dri.classNames equals "Foo" - name equals "property" - children counts 0 - with(getter.assertNotNull("Getter")) { - type.name equals "Int" - } - extra[InheritedMember]?.inheritedFrom?.values?.single()?.run { - classNames equals "Foo" - callable equals null - } - } - } - } - } - - @Test - fun sinceKotlin() { - inlineModelTest( - """ - |/** - | * Quite useful [String] - | */ - |@SinceKotlin("1.1") - |val prop: String = "1.1 rulezz" - """ - ) { - with((this / "property" / "prop").cast<DProperty>()) { - with(extra[Annotations]!!.directAnnotations.entries.single().value.assertNotNull("Annotations")) { - this counts 1 - with(first()) { - dri.classNames equals "SinceKotlin" - params.entries counts 1 - (params["version"].assertNotNull("version") as StringValue).value equals "1.1" - } - } - } - } - } - - @Test - fun annotatedProperty() { - inlineModelTest( - """ - |@Strictfp var property = "test" - """, - configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - classpath = listOfNotNull(jvmStdlibPath) - } - } - } - ) { - with((this / "property" / "property").cast<DProperty>()) { - with(extra[Annotations]!!.directAnnotations.entries.single().value.assertNotNull("Annotations")) { - this counts 1 - with(first()) { - dri.classNames equals "Strictfp" - params.entries counts 0 - } - } - } - } - } - - @Test fun genericTopLevelExtensionProperty(){ - inlineModelTest( - """ | val <T : Number> List<T>.sampleProperty: T - | get() { TODO() } - """.trimIndent() - ){ - with((this / "property" / "sampleProperty").cast<DProperty>()) { - name equals "sampleProperty" - with(receiver.assertNotNull("Property receiver")) { - type.name equals "List" - } - with(getter.assertNotNull("Getter")) { - type.name equals "T" - } - setter equals null - generics counts 1 - generics.forEach { - it.name equals "T" - it.bounds.first().name equals "Number" - } - visibility.values allEquals KotlinVisibility.Public - } - } - } - - @Test fun genericExtensionPropertyInClass(){ - inlineModelTest( - """ | package test - | class XD<T> { - | var List<T>.sampleProperty: T - | get() { TODO() } - | set(value) { TODO() } - | } - """.trimIndent() - ){ - with((this / "property" / "XD" / "sampleProperty").cast<DProperty>()) { - name equals "sampleProperty" - children counts 0 - with(receiver.assertNotNull("Property receiver")) { - type.name equals "List" - } - with(getter.assertNotNull("Getter")) { - type.name equals "T" - } - with(setter.assertNotNull("Setter")){ - type.name equals "Unit" - } - generics counts 0 - visibility.values allEquals KotlinVisibility.Public - } - } - } -} diff --git a/plugins/base/src/test/kotlin/model/annotations/JavaAnnotationsForParametersTest.kt b/plugins/base/src/test/kotlin/model/annotations/JavaAnnotationsForParametersTest.kt deleted file mode 100644 index 9800006b..00000000 --- a/plugins/base/src/test/kotlin/model/annotations/JavaAnnotationsForParametersTest.kt +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package model.annotations - -import org.jetbrains.dokka.base.signatures.KotlinSignatureUtils.annotations -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.model.* -import org.jetbrains.dokka.utilities.cast -import utils.AbstractModelTest -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertTrue - -class JavaAnnotationsForParametersTest : AbstractModelTest("/src/main/kotlin/java/Test.java", "java") { - - @Test - fun `function with deprecated parameter`() { - inlineModelTest( - """ - |public class Test { - | public void fn(@Deprecated String name) {} - |} - """.trimIndent() - ) { - with((this / "java" / "Test").cast<DClass>()) { - with((this / "fn").cast<DFunction>()) { - val dri = - parameters.first().extra[Annotations]?.directAnnotations?.flatMap { it.value }?.map { it.dri } - assertEquals(listOf(DRI("java.lang", "Deprecated")), dri) - } - } - } - } - - @Test - fun `function with parameter that has custom annotation`() { - inlineModelTest( - """ - |@Retention(RetentionPolicy.RUNTIME) - |@Target(ElementType.PARAMETER) - |public @interface Hello { - | public String bar() default ""; - |} - |public class Test { - | public void foo(@Hello(bar = "baz") String arg){ } - |} - """.trimIndent() - ) { - with((this / "java" / "Test").cast<DClass>()) { - with((this / "foo").cast<DFunction>()) { - val annotations = - parameters.first().extra[Annotations]?.directAnnotations?.flatMap { it.value } - val driOfHello = DRI("java", "Hello") - val annotationsValues = annotations?.flatMap { it.params.values }?.map { it.toString() }?.toList() - - assertEquals(listOf(driOfHello), annotations?.map { it.dri }) - assertEquals(listOf("baz"), annotationsValues) - } - } - } - } - - @Test - fun `function with annotated generic parameter`() { - inlineModelTest( - """ - |@Retention(RetentionPolicy.RUNTIME) - |@Target(ElementType.TYPE_PARAMETER) - |@interface Hello { - | public String bar() default ""; - |} - |public class Test { - | public <@Hello(bar = "baz") T> List<T> foo() { - | return null; - | } - |} - """.trimIndent() - ) { - with((this / "java" / "Test").cast<DClass>()) { - with((this / "foo").cast<DFunction>()) { - val annotations = generics.first().extra[Annotations]?.directAnnotations?.flatMap { it.value } - val driOfHello = DRI("java", "Hello") - val annotationsValues = annotations?.flatMap { it.params.values }?.map { it.toString() }?.toList() - - assertEquals(listOf(driOfHello), annotations?.map { it.dri }) - assertEquals(listOf("baz"), annotationsValues) - } - } - } - } - - @Test - fun `function with generic parameter that has annotated bounds`() { - inlineModelTest( - """ - |@Retention(RetentionPolicy.RUNTIME) - |@Target({ElementType.TYPE_USE}) - |@interface Hello { - | public String bar() default ""; - |} - |public class Test { - | public <T extends @Hello(bar = "baz") String> List<T> foo() { - | return null; - | } - |} - """.trimIndent() - ) { - with((this / "java" / "Test").cast<DClass>()) { - with((this / "foo").cast<DFunction>()) { - val annotations = ((generics.first().bounds.first() as Nullable).inner as GenericTypeConstructor) - .extra[Annotations]?.directAnnotations?.flatMap { it.value } - val driOfHello = DRI("java", "Hello") - val annotationsValues = annotations?.flatMap { it.params.values }?.map { it.toString() }?.toList() - - assertEquals(listOf(driOfHello), annotations?.map { it.dri }) - assertEquals(listOf("baz"), annotationsValues) - } - } - } - } - - @Test - fun `type parameter annotations should be visible even if type declaration has none`() { - inlineModelTest( - """ - |@Retention(RetentionPolicy.RUNTIME) - |@Target(ElementType.PARAMETER) - |public @interface Hello { - | public String bar() default ""; - |} - |public class Test { - | public <T> void foo(java.util.List<@Hello T> param) {} - |} - """.trimIndent() - ) { - with((this / "java" / "Test").cast<DClass>()) { - with((this / "foo").cast<DFunction>()) { - val paramAnnotations = parameters.first() - .type.cast<GenericTypeConstructor>() - .projections.first().cast<TypeParameter>() - .annotations() - .values - .flatten() - - assertEquals(1, paramAnnotations.size) - assertEquals(DRI("java", "Hello"), paramAnnotations[0].dri) - } - } - } - } - - @Test - fun `type parameter annotations should not be propagated from resolved type`() { - inlineModelTest( - """ - |@Retention(RetentionPolicy.RUNTIME) - |@Target(ElementType.PARAMETER) - |public @interface Hello { - | public String bar() default ""; - |} - |public class Test { - | public <@Hello T> void foo(java.util.List<T> param) {} - |} - """.trimIndent() - ) { - with((this / "java" / "Test").cast<DClass>()) { - with((this / "foo").cast<DFunction>()) { - val paramAnnotations = parameters.first() - .type.cast<GenericTypeConstructor>() - .projections.first().cast<TypeParameter>() - .annotations() - - assertTrue(paramAnnotations.isEmpty()) - } - } - } - } -} - diff --git a/plugins/base/src/test/kotlin/model/annotations/JavaAnnotationsTest.kt b/plugins/base/src/test/kotlin/model/annotations/JavaAnnotationsTest.kt deleted file mode 100644 index daab7dc9..00000000 --- a/plugins/base/src/test/kotlin/model/annotations/JavaAnnotationsTest.kt +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package model.annotations - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.model.* -import translators.findClasslike -import kotlin.test.* - -class JavaAnnotationsTest : BaseAbstractTest() { - - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/java") - } - } - } - - @Test // see https://github.com/Kotlin/dokka/issues/2350 - fun `should hande array used as annotation param value`() { - testInline( - """ - |/src/main/java/annotation/TestClass.java - |package annotation; - |public class TestClass { - | @SimpleAnnotation(clazz = String[].class) - | public boolean simpleAnnotation() { - | return false; - | } - |} - | - |/src/main/java/annotation/SimpleAnnotation.java - |package annotation; - |@Retention(RetentionPolicy.RUNTIME) - |@Target(ElementType.METHOD) - |public @interface SimpleAnnotation { - | Class<?> clazz(); - |} - """.trimIndent(), - configuration - ) { - documentablesTransformationStage = { module -> - val testClass = module.findClasslike("annotation", "TestClass") as DClass - assertNotNull(testClass) - - val annotatedFunction = testClass.functions.single { it.name == "simpleAnnotation" } - val annotation = - annotatedFunction.extra[Annotations]?.directAnnotations?.entries?.single()?.value?.single() - assertNotNull(annotation) { "Expected to find an annotation on simpleAnnotation function, found none" } - assertEquals("annotation", annotation.dri.packageName) - assertEquals("SimpleAnnotation", annotation.dri.classNames) - assertEquals(1, annotation.params.size) - - val param = annotation.params.values.single() - assertTrue(param is ClassValue) - // should probably be Array instead - // String matches parsing of Kotlin sources as of now - assertEquals("String", param.className) - assertEquals("java.lang", param.classDRI.packageName) - assertEquals("String", param.classDRI.classNames) - } - } - } - - @Test // see https://github.com/Kotlin/dokka/issues/2551 - fun `should hande annotation used within annotation params with class param value`() { - testInline( - """ - |/src/main/java/annotation/TestClass.java - |package annotation; - |public class TestClass { - | @XmlElementRefs({ - | @XmlElementRef(name = "NotOffered", namespace = "http://www.gaeb.de/GAEB_DA_XML/DA86/3.3", type = JAXBElement.class, required = false) - | }) - | public List<JAXBElement<Object>> content; - |} - | - |/src/main/java/annotation/XmlElementRefs.java - |package annotation; - |public @interface XmlElementRefs { - | XmlElementRef[] value(); - |} - | - |/src/main/java/annotation/XmlElementRef.java - |package annotation; - |public @interface XmlElementRef { - | String name(); - | - | String namespace(); - | - | boolean required(); - | - | Class<JAXBElement> type(); - |} - | - |/src/main/java/annotation/JAXBElement.java - |package annotation; - |public class JAXBElement<T> { - |} - """.trimIndent(), - configuration - ) { - documentablesTransformationStage = { module -> - val testClass = module.findClasslike("annotation", "TestClass") as DClass - assertNotNull(testClass) - - val contentField = testClass.properties.find { it.name == "content" } - assertNotNull(contentField) - - val annotation = contentField.extra[Annotations]?.directAnnotations?.entries?.single()?.value?.single() - assertNotNull(annotation) { "Expected to find an annotation on content field, found none" } - assertEquals("XmlElementRefs", annotation.dri.classNames) - assertEquals(1, annotation.params.size) - - val arrayParam = annotation.params.values.single() - assertTrue(arrayParam is ArrayValue, "Expected single annotation param to be array") - assertEquals(1, arrayParam.value.size) - - val arrayParamValue = arrayParam.value.single() - assertTrue(arrayParamValue is AnnotationValue) - - val arrayParamAnnotationValue = arrayParamValue.annotation - assertEquals(4, arrayParamAnnotationValue.params.size) - assertEquals("XmlElementRef", arrayParamAnnotationValue.dri.classNames) - - val annotationParams = arrayParamAnnotationValue.params.values.toList() - - val nameParam = annotationParams[0] - assertTrue(nameParam is StringValue) - assertEquals("NotOffered", nameParam.value) - - val namespaceParam = annotationParams[1] - assertTrue(namespaceParam is StringValue) - assertEquals("http://www.gaeb.de/GAEB_DA_XML/DA86/3.3", namespaceParam.value) - - val typeParam = annotationParams[2] - assertTrue(typeParam is ClassValue) - assertEquals("JAXBElement", typeParam.className) - assertEquals("annotation", typeParam.classDRI.packageName) - assertEquals("JAXBElement", typeParam.classDRI.classNames) - - val requiredParam = annotationParams[3] - assertTrue(requiredParam is BooleanValue) - assertFalse(requiredParam.value) - } - } - } - - @Test // see https://github.com/Kotlin/dokka/issues/2509 - fun `should handle generic class in annotation`() { - testInline( - """ - |/src/main/java/annotation/Breaking.java - |package annotation; - |public class Breaking<Y> { - |} - | - |/src/main/java/annotation/TestAnnotate.java - |package annotation; - |public @interface TestAnnotate { - | Class<?> value(); - |} - | - |/src/main/java/annotation/TestClass.java - |package annotation; - |@TestAnnotate(Breaking.class) - |public class TestClass { - |} - """.trimIndent(), - configuration - ) { - documentablesTransformationStage = { module -> - val testClass = module.findClasslike("annotation", "TestClass") as DClass - assertNotNull(testClass) - - val annotation = testClass.extra[Annotations]?.directAnnotations?.entries?.single()?.value?.single() - assertNotNull(annotation) { "Expected to find an annotation on TestClass, found none" } - - assertEquals("TestAnnotate", annotation.dri.classNames) - assertEquals(1, annotation.params.size) - - val valueParameter = annotation.params.values.single() - assertTrue(valueParameter is ClassValue) - - assertEquals("Breaking", valueParameter.className) - - assertEquals("annotation", valueParameter.classDRI.packageName) - assertEquals("Breaking", valueParameter.classDRI.classNames) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/model/annotations/KotlinAnnotationsForParametersTest.kt b/plugins/base/src/test/kotlin/model/annotations/KotlinAnnotationsForParametersTest.kt deleted file mode 100644 index e3b17818..00000000 --- a/plugins/base/src/test/kotlin/model/annotations/KotlinAnnotationsForParametersTest.kt +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package model.annotations - -import org.jetbrains.dokka.base.signatures.KotlinSignatureUtils.annotations -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.model.* -import org.jetbrains.dokka.utilities.cast -import utils.AbstractModelTest -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertTrue - -class KotlinAnnotationsForParametersTest : AbstractModelTest("/src/main/kotlin/annotations/Test.kt", "annotations") { - @Test - fun `generic receiver with annotations`() { - inlineModelTest( - """ - |@Target(AnnotationTarget.TYPE_PARAMETER) - |annotation class Hello(val bar: String) - |fun <@Hello("abc") T> foo(arg: String): List<T> = TODO() - """.trimIndent() - ) { - with((this / "annotations" / "foo").cast<DFunction>()) { - val annotations = generics.first().extra[Annotations]?.directAnnotations?.flatMap { it.value } - val driOfHello = DRI("annotations", "Hello") - val annotationsValues = annotations?.flatMap { it.params.values }?.map { it.toString() }?.toList() - - assertEquals(listOf(driOfHello), annotations?.map { it.dri }) - assertEquals(listOf("abc"), annotationsValues) - } - } - } - - @Test - fun `generic receiver with annotated bounds`() { - inlineModelTest( - """ - |@Target(AnnotationTarget.TYPE_PARAMETER) - |annotation class Hello(val bar: String) - |fun <T: @Hello("abc") String> foo(arg: String): List<T> = TODO() - """.trimIndent() - ) { - with((this / "annotations" / "foo").cast<DFunction>()) { - val annotations = (generics.first().bounds.first() as GenericTypeConstructor) - .extra[Annotations]?.directAnnotations?.flatMap { it.value } - val driOfHello = DRI("annotations", "Hello") - val annotationsValues = annotations?.flatMap { it.params.values }?.map { it.toString() }?.toList() - - assertEquals(listOf(driOfHello), annotations?.map { it.dri }) - assertEquals(listOf("abc"), annotationsValues) - } - } - } - - @Test - fun `type parameter annotations should be visible even if type declaration has none`() { - inlineModelTest( - """ - |@Target(AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.TYPE) - |annotation class Hello - | - |fun <T> foo(param: List<@Hello T>) {} - """.trimIndent() - ) { - with((this / "annotations" / "foo").cast<DFunction>()) { - val paramAnnotations = parameters.first() - .type.cast<GenericTypeConstructor>() - .projections - .first().cast<Invariance<TypeParameter>>() - .inner.cast<TypeParameter>() - .annotations() - .values - .flatten() - - assertEquals(1, paramAnnotations.size) - assertEquals(DRI("annotations", "Hello"), paramAnnotations[0].dri) - } - } - } - - @Test - fun `type parameter annotations should not be propagated from resolved type`() { - inlineModelTest( - """ - |@Target(AnnotationTarget.TYPE_PARAMETER, AnnotationTarget.TYPE) - |annotation class Hello - | - |fun <@Hello T> foo(param: List<T>) {} - """.trimIndent() - ) { - with((this / "annotations" / "foo").cast<DFunction>()) { - val paramAnnotations = parameters.first() - .type.cast<GenericTypeConstructor>() - .projections.first().cast<Invariance<TypeParameter>>() - .inner.cast<TypeParameter>() - .annotations() - - assertTrue(paramAnnotations.isEmpty()) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/multiplatform/BasicMultiplatformTest.kt b/plugins/base/src/test/kotlin/multiplatform/BasicMultiplatformTest.kt deleted file mode 100644 index 5412113e..00000000 --- a/plugins/base/src/test/kotlin/multiplatform/BasicMultiplatformTest.kt +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package multiplatform - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import kotlin.test.Test -import kotlin.test.assertEquals - -class BasicMultiplatformTest : BaseAbstractTest() { - - @Test - fun dataTestExample() { - val testDataDir = getTestDataDir("multiplatform/basicMultiplatformTest").toAbsolutePath() - - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("$testDataDir/jvmMain/") - } - } - } - - testFromData(configuration) { - pagesTransformationStage = { - assertEquals(7, it.children.firstOrNull()?.children?.count() ?: 0) - } - } - } - - @Test - fun inlineTestExample() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin/multiplatform/Test.kt") - } - } - } - - testInline( - """ - |/src/main/kotlin/multiplatform/Test.kt - |package multiplatform - | - |object Test { - | fun test2(str: String): Unit {println(str)} - |} - """.trimMargin(), - configuration - ) { - pagesGenerationStage = { - assertEquals(3, it.parentMap.size) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/packageList/PackageListTest.kt b/plugins/base/src/test/kotlin/packageList/PackageListTest.kt deleted file mode 100644 index d6033433..00000000 --- a/plugins/base/src/test/kotlin/packageList/PackageListTest.kt +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package packageList - -import org.jetbrains.dokka.base.renderers.PackageListService -import org.jetbrains.dokka.base.resolvers.shared.RecognizedLinkFormat -import kotlin.test.Test -import kotlin.test.assertEquals - -class PackageListTest { - @Test - fun `one module package list is created correctly`() { - val nonStandardLocations = mapOf("//longArrayWithFun/#kotlin.Int#kotlin.Function1[kotlin.Int,kotlin.Long]/PointingToDeclaration/" to "[JS root]/long-array-with-fun.html") - val modules = mapOf("" to setOf("foo", "bar", "baz")) - val format = RecognizedLinkFormat.DokkaHtml - val output = PackageListService.renderPackageList(nonStandardLocations, modules, format.formatName, format.linkExtension) - val expected = """ - |${'$'}dokka.format:html-v1 - |${'$'}dokka.linkExtension:html - |${'$'}dokka.location://longArrayWithFun/#kotlin.Int#kotlin.Function1[kotlin.Int,kotlin.Long]/PointingToDeclaration/[JS root]/long-array-with-fun.html - |bar - |baz - |foo - |""".trimMargin() - assertEquals(expected, output) - } - - @Test - fun `multi-module package list is created correctly`() { - val nonStandardLocations = mapOf("//longArrayWithFun/#kotlin.Int#kotlin.Function1[kotlin.Int,kotlin.Long]/PointingToDeclaration/" to "[JS root]/long-array-with-fun.html") - val modules = mapOf("moduleA" to setOf("foo", "bar"), "moduleB" to setOf("baz"), "moduleC" to setOf("qux")) - val format = RecognizedLinkFormat.DokkaHtml - val output = PackageListService.renderPackageList(nonStandardLocations, modules, format.formatName, format.linkExtension) - val expected = """ - |${'$'}dokka.format:html-v1 - |${'$'}dokka.linkExtension:html - |${'$'}dokka.location://longArrayWithFun/#kotlin.Int#kotlin.Function1[kotlin.Int,kotlin.Long]/PointingToDeclaration/[JS root]/long-array-with-fun.html - |module:moduleA - |bar - |foo - |module:moduleB - |baz - |module:moduleC - |qux - |""".trimMargin() - assertEquals(expected, output) - } - - @Test - fun `empty package set in module`() { - val nonStandardLocations = emptyMap<String, String>() - val modules = mapOf("moduleA" to setOf("foo", "bar"), "moduleB" to emptySet(), "moduleC" to setOf("qux")) - val format = RecognizedLinkFormat.DokkaHtml - val output = PackageListService.renderPackageList(nonStandardLocations, modules, format.formatName, format.linkExtension) - val expected = """ - |${'$'}dokka.format:html-v1 - |${'$'}dokka.linkExtension:html - | - |module:moduleA - |bar - |foo - |module:moduleC - |qux - |""".trimMargin() - assertEquals(expected, output) - } -} diff --git a/plugins/base/src/test/kotlin/pageMerger/PageNodeMergerTest.kt b/plugins/base/src/test/kotlin/pageMerger/PageNodeMergerTest.kt deleted file mode 100644 index 983f73ff..00000000 --- a/plugins/base/src/test/kotlin/pageMerger/PageNodeMergerTest.kt +++ /dev/null @@ -1,465 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package pageMerger - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.model.dfs -import org.jetbrains.dokka.model.withDescendants -import org.jetbrains.dokka.pages.* -import org.junit.jupiter.api.RepeatedTest -import kotlin.test.Ignore -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertTrue - -class PageNodeMergerTest : BaseAbstractTest() { - - private val defaultConfiguration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin") - } - } - } - - @Test - fun sameNameStrategyTest() { - testInline( - """ - |/src/main/kotlin/pageMerger/Test.kt - |package pageMerger - | - |fun testT(): Int = 1 - |fun testT(i: Int): Int = i - | - |object Test { - | fun test(): String = "" - | fun test(str: String): String = str - |} - """.trimMargin(), - defaultConfiguration - ) { - pagesTransformationStage = { - val allChildren = it.childrenRec().filterIsInstance<ContentPage>() - val testT = allChildren.filter { it.name == "testT" } - val test = allChildren.filter { it.name == "test" } - - assertTrue(testT.size == 1, "There can be only one testT page") - assertTrue(testT.first().dri.size == 2, "testT page should have 2 DRI, but has ${testT.first().dri.size}") - - assertTrue(test.size == 1, "There can be only one test page") - assertTrue(test.first().dri.size == 2, "test page should have 2 DRI, but has ${test.first().dri.size}") - } - } - } - - @Ignore("TODO: reenable when we have infrastructure for turning off extensions") - @Test - fun defaultStrategyTest() { - val strList: MutableList<String> = mutableListOf() - - testInline( - """ - |/src/main/kotlin/pageMerger/Test.kt - |package pageMerger - | - |fun testT(): Int = 1 - |fun testT(i: Int): Int = i - | - |object Test { - | fun test(): String = "" - | fun test(str: String): String = str - |} - """.trimMargin(), - defaultConfiguration - ) { - pagesTransformationStage = { root -> - val allChildren = root.childrenRec().filterIsInstance<ContentPage>() - val testT = allChildren.filter { it.name == "testT" } - val test = allChildren.filter { it.name == "test" } - - assertTrue(testT.size == 1, "There can be only one testT page") - assertTrue(testT.first().dri.size == 1, "testT page should have single DRI, but has ${testT.first().dri.size}") - - assertTrue(test.size == 1, "There can be only one test page") - assertTrue(test.first().dri.size == 1, "test page should have single DRI, but has ${test.first().dri.size}") - - assertTrue(strList.count() == 2, "Expected 2 warnings, got ${strList.count()}") - } - } - } - - fun PageNode.childrenRec(): List<PageNode> = listOf(this) + children.flatMap { it.childrenRec() } - - - @Test - fun `should not be merged`() { - - val configuration = dokkaConfiguration { - moduleName = "example" - sourceSets { - val common = sourceSet { - name = "common" - displayName = "common" - analysisPlatform = "common" - sourceRoots = listOf("src/commonMain/kotlin/pageMerger/Test.kt") - } - sourceSet { - name = "js" - displayName = "js" - analysisPlatform = "js" - dependentSourceSets = setOf(common.value.sourceSetID) - sourceRoots = listOf("src/jsMain/kotlin/pageMerger/Test.kt") - } - sourceSet { - name = "jvm" - displayName = "jvm" - analysisPlatform = "jvm" - dependentSourceSets = setOf(common.value.sourceSetID) - sourceRoots = listOf("src/jvmMain/kotlin/pageMerger/Test.kt") - } - } - } - - testInline( - """ - |/src/commonMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |/src/jsMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |annotation class DoNotMerge - | - |/src/jvmMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |annotation class DoNotMerge - """.trimMargin(), - configuration - ) { - pagesTransformationStage = { - println(it) - val allChildren = it.childrenRec().filterIsInstance<ClasslikePageNode>() - val jvmClass = allChildren.filter { it.name == "[jvm]DoNotMerge" } - val jsClass = allChildren.filter { it.name == "[js]DoNotMerge" } - val noClass = allChildren.filter { it.name == "DoNotMerge" } - assertTrue(jvmClass.size == 1, "There can be only one DoNotMerge(jvm) page") - assertTrue( - jvmClass.first().documentables.firstOrNull()?.sourceSets?.single()?.analysisPlatform?.key == "jvm", - "[jvm]DoNotMerge should have only jvm sources" - ) - - assertTrue(jsClass.size == 1, "There can be only one DoNotMerge(js) page") - assertTrue( - jsClass.first().documentables.firstOrNull()?.sourceSets?.single()?.analysisPlatform?.key == "js", - "[js]DoNotMerge should have only js sources" - ) - - assertTrue(noClass.isEmpty(), "There can't be any DoNotMerge page") - } - } - } - - @RepeatedTest(3) - fun `should deterministically render same name property extensions`() { - testInline( - """ - |/src/main/kotlin/test/Test.kt - |package test - | - |class ExtensionReceiver - | - |/** - | * Top level val extension - | */ - |val ExtensionReceiver.foo: String get() = "bar" - | - |class Obj { - | companion object { - | /** - | * Companion val extension - | */ - | val ExtensionReceiver.foo: String get() = "bar" - | } - |} - | - |/src/main/kotlin/test/nestedpackage/Pckg.kt - |package test.nestedpackage - | - |import test.ExtensionReceiver - | - |/** - | * From nested package int val extension - | */ - |val ExtensionReceiver.foo: Int get() = 42 - """.trimMargin(), - defaultConfiguration - ) { - renderingStage = { rootPageNode, _ -> - val extensions = rootPageNode.findDivergencesOfClass("ExtensionReceiver", ContentKind.Extensions) - - extensions.assertContainsKDocsInOrder( - "Top level val extension", - "Companion val extension", - "From nested package int val extension" - ) - } - } - } - - @RepeatedTest(3) - fun `should deterministically render parameterless same name function extensions`() { - testInline( - """ - |/src/main/kotlin/test/Test.kt - |package test - | - |class ExtensionReceiver - | - |/** - | * Top level fun extension - | */ - |fun ExtensionReceiver.bar(): String = "bar" - | - |class Obj { - | - | companion object { - | /** - | * Companion fun extension - | */ - | fun ExtensionReceiver.bar(): String = "bar" - | } - |} - | - |/src/main/kotlin/test/nestedpackage/Pckg.kt - |package test.nestedpackage - | - |import test.ExtensionReceiver - | - |/** - | * From nested package fun extension - | */ - |fun ExtensionReceiver.bar(): String = "bar" - """.trimMargin(), - defaultConfiguration - ) { - renderingStage = { rootPageNode, _ -> - val extensions = rootPageNode.findDivergencesOfClass("ExtensionReceiver", ContentKind.Extensions) - extensions.assertContainsKDocsInOrder( - "Top level fun extension", - "Companion fun extension", - "From nested package fun extension" - ) - } - } - } - - @RepeatedTest(3) - fun `should deterministically render same name function extensions with parameters`() { - testInline( - """ - |/src/main/kotlin/test/Test.kt - |package test - | - |class ExtensionReceiver - | - |/** - | * Top level fun extension with one string param - | */ - |fun ExtensionReceiver.bar(one: String): String = "bar" - | - |/** - | * Top level fun extension with one int param - | */ - |fun ExtensionReceiver.bar(one: Int): Int = 42 - | - |class Obj { - | - | companion object { - | /** - | * Companion fun extension with two params - | */ - | fun ExtensionReceiver.bar(one: String, two: String): String = "bar" - | } - |} - | - |/src/main/kotlin/test/nestedpackage/Pckg.kt - |package test.nestedpackage - | - |import test.ExtensionReceiver - | - |/** - | * From nested package fun extension with two params - | */ - |fun ExtensionReceiver.bar(one: String, two: String): String = "bar" - | - |/** - | * From nested package fun extension with three params - | */ - |fun ExtensionReceiver.bar(one: String, two: String, three: String): String = "bar" - | - |/** - | * From nested package fun extension with four params - | */ - |fun ExtensionReceiver.bar(one: String, two: String, three: String, four: String): String = "bar" - """.trimMargin(), - defaultConfiguration - ) { - renderingStage = { rootPageNode, _ -> - val extensions = rootPageNode.findDivergencesOfClass("ExtensionReceiver", ContentKind.Extensions) - extensions.assertContainsKDocsInOrder( - "Top level fun extension with one int param", - "Top level fun extension with one string param", - "Companion fun extension with two params", - "From nested package fun extension with two params", - "From nested package fun extension with three params", - "From nested package fun extension with four params" - ) - } - } - } - - @RepeatedTest(3) - fun `should deterministically render same name function extensions with different receiver and return type`() { - testInline( - """ - |/src/main/kotlin/test/Test.kt - |package test - | - |/** - | * Top level fun extension string - | */ - |fun Int.bar(): String = "bar" - | - |/** - | * Top level fun extension int - | */ - |fun String.bar(): Int = 42 - """.trimMargin(), - defaultConfiguration - ) { - renderingStage = { rootPageNode, _ -> - val packageFunctionBlocks = rootPageNode.findPackageFunctionBlocks(packageName = "test") - assertEquals(1, packageFunctionBlocks.size, "Expected to find only one group for the functions") - - val functionsBlock = packageFunctionBlocks[0] - functionsBlock.assertContainsKDocsInOrder( - "Top level fun extension string", - "Top level fun extension int" - ) - } - } - } - - @Test - fun `should not ignore case when grouping by name`() { - testInline( - """ - |/src/main/kotlin/test/Test.kt - |package test - | - |/** - | * Top level fun bAr - | */ - |fun Int.bAr(): String = "bar" - | - |/** - | * Top level fun BaR - | */ - |fun String.BaR(): Int = 42 - """.trimMargin(), - defaultConfiguration - ) { - renderingStage = { rootPageNode, _ -> - val packageFunctionBlocks = rootPageNode.findPackageFunctionBlocks(packageName = "test") - assertEquals(2, packageFunctionBlocks.size, "Expected two separate function groups") - - val firstGroup = packageFunctionBlocks[0] - firstGroup.assertContainsKDocsInOrder( - "Top level fun BaR", - ) - - val secondGroup = packageFunctionBlocks[1] - secondGroup.assertContainsKDocsInOrder( - "Top level fun bAr", - ) - } - } - } - - @Test - fun `should sort groups alphabetically ignoring case`() { - testInline( - """ - |/src/main/kotlin/test/Test.kt - |package test - | - |/** Sequence builder */ - |fun <T> sequence(): Sequence<T> - | - |/** Sequence SAM constructor */ - |fun <T> Sequence(): Sequence<T> - | - |/** Sequence.any() */ - |fun <T> Sequence<T>.any() {} - | - |/** Sequence interface */ - |interface Sequence<T> - """.trimMargin(), - defaultConfiguration - ) { - renderingStage = { rootPageNode, _ -> - val packageFunctionBlocks = rootPageNode.findPackageFunctionBlocks(packageName = "test") - assertEquals(3, packageFunctionBlocks.size, "Expected 3 separate function groups") - - packageFunctionBlocks[0].assertContainsKDocsInOrder( - "Sequence.any()", - ) - - packageFunctionBlocks[1].assertContainsKDocsInOrder( - "Sequence SAM constructor", - ) - - packageFunctionBlocks[2].assertContainsKDocsInOrder( - "Sequence builder", - ) - } - } - } - - private fun RootPageNode.findDivergencesOfClass(className: String, kind: ContentKind): ContentDivergentGroup { - val extensionReceiverPage = this.dfs { it is ClasslikePageNode && it.name == className } as ClasslikePageNode - return extensionReceiverPage.content - .dfs { it is ContentDivergentGroup && it.dci.kind == kind } as ContentDivergentGroup - } - - private fun RootPageNode.findPackageFunctionBlocks(packageName: String): List<ContentDivergentGroup> { - val packagePage = this.dfs { it is PackagePage && it.name == packageName } as PackagePage - val packageFunctionTable = packagePage.content.dfs { - it is ContentTable && it.dci.kind == ContentKind.Functions - } as ContentTable - - return packageFunctionTable.children.map { packageGroup -> - packageGroup.dfs { it is ContentDivergentGroup } as ContentDivergentGroup - } - } - - private fun ContentDivergentGroup.assertContainsKDocsInOrder(vararg expectedKDocs: String) { - expectedKDocs.forEachIndexed { index, expectedKDoc -> - assertEquals(expectedKDoc, this.getElementKDocText(index)) - } - } - - private fun ContentDivergentGroup.getElementKDocText(index: Int): String { - val element = this.children.getOrNull(index) ?: throw IllegalArgumentException("No element with index $index") - val commentNode = element.after - ?.withDescendants() - ?.singleOrNull { it is ContentText && it.dci.kind == ContentKind.Comment } - ?: throw IllegalStateException("Expected the element to contain a single paragraph of text / comment") - - return (commentNode as ContentText).text - } -} diff --git a/plugins/base/src/test/kotlin/parsers/JavadocParserTest.kt b/plugins/base/src/test/kotlin/parsers/JavadocParserTest.kt deleted file mode 100644 index b56edc97..00000000 --- a/plugins/base/src/test/kotlin/parsers/JavadocParserTest.kt +++ /dev/null @@ -1,618 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package parsers - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.links.Callable -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.links.JavaClassReference -import org.jetbrains.dokka.model.DEnum -import org.jetbrains.dokka.model.DModule -import org.jetbrains.dokka.model.doc.* -import org.jetbrains.dokka.utilities.firstIsInstanceOrNull -import utils.docs -import utils.text -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertNotNull - -class JavadocParserTest : BaseAbstractTest() { - - private val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - analysisPlatform = "jvm" - } - } - } - - private fun performJavadocTest(testOperation: (DModule) -> Unit) { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/java") - } - } - } - - testInline( - """ - |/src/main/java/sample/Date2.java - | - |package docs - |/** - | * class level docs - | */ - |public enum AnEnumType { - | /** - | * content being refreshed, which can be a result of - | * invalidation, refresh that may contain content updates, or the initial load. - | */ - | REFRESH - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = testOperation - } - } - - @Test - fun `correctly parsed list`() { - performJavadocTest { module -> - val docs = - (module.packages.single().classlikes.single() as DEnum).entries.single().documentation.values.single().children.single().root.text() - assertEquals( - "content being refreshed, which can be a result of invalidation, refresh that may contain content updates, or the initial load.", - docs.trimEnd() - ) - } - } - - @Test - fun `code tag`() { - val source = """ - |/src/main/kotlin/test/Test.java - |package example - | - | /** - | * Identifies calls to {@code assertThat}. - | * - | * {@code - | * Set<String> s; - | * System.out.println("s1 = " + s); - | * } - | * <pre>{@code - | * Set<String> s2; - | * System.out - | * .println("s2 = " + s2); - | * }</pre> - | * - | */ - | public class Test {} - """.trimIndent() - testInline( - source, - configuration, - ) { - documentablesCreationStage = { modules -> - val docs = modules.first().packages.first().classlikes.single().documentation.values.first() - val root = docs.children.first().root - - kotlin.test.assertEquals( - listOf( - Text(body = "Identifies calls to "), - CodeInline(children = listOf(Text(body = "assertThat"))), - Text(body = ". "), - CodeInline(children = listOf(Text(body = "\nSet<String> s;\nSystem.out.println(\"s1 = \" + s);\n"))) - ), - root.children[0].children - ) - kotlin.test.assertEquals( - CodeBlock(children = listOf(Text(body = "\nSet<String> s2;\nSystem.out\n .println(\"s2 = \" + s2);\n"))), - root.children[1] - ) - } - } - } - - @Test - fun `literal tag`() { - val source = """ - |/src/main/kotlin/test/Test.java - |package example - | - | /** - | * An example of using the literal tag - | * {@literal @}Entity - | * public class User {} - | */ - | public class Test {} - """.trimIndent() - testInline( - source, - configuration, - ) { - documentablesCreationStage = { modules -> - val docs = modules.first().packages.first().classlikes.single().documentation.values.first() - val root = docs.children.first().root - - kotlin.test.assertEquals( - listOf( - Text(body = "An example of using the literal tag "), - Text(body = "@"), - Text(body = "Entity public class User {}"), - ), - root.children.first().children - ) - } - } - } - - @Test - fun `literal tag nested under pre tag`() { - val source = """ - |/src/main/kotlin/test/Test.java - |package example - | - | /** - | * An example of using the literal tag - | * <pre> - | * {@literal @}Entity - | * public class User {} - | * </pre> - | */ - | public class Test {} - """.trimIndent() - testInline( - source, - configuration, - ) { - documentablesCreationStage = { modules -> - val docs = modules.first().packages.first().classlikes.single().documentation.values.first() - val root = docs.children.first().root - - kotlin.test.assertEquals( - listOf( - P(children = listOf(Text(body = "An example of using the literal tag "))), - Pre( - children = - listOf( - Text(body = "@"), - Text(body = "Entity\npublic class User {}\n") - ) - ) - ), - root.children - ) - } - } - } - - @Test - fun `literal tag containing angle brackets`() { - val source = """ - |/src/main/kotlin/test/Test.java - |package example - | - | /** - | * An example of using the literal tag - | * {@literal a<B>c} - | */ - | public class Test {} - """.trimIndent() - testInline( - source, - configuration, - ) { - documentablesCreationStage = { modules -> - val docs = modules.first().packages.first().classlikes.single().documentation.values.first() - val root = docs.children.first().root - - kotlin.test.assertEquals( - listOf( - P( - children = listOf( - Text(body = "An example of using the literal tag "), - Text(body = "a<B>c") - ) - ), - ), - root.children - ) - } - } - } - - @Test - fun `html img tag`() { - val source = """ - |/src/main/kotlin/test/Test.java - |package example - | - | /** - | * <img src="/path/to/img.jpg" alt="Alt text"/> - | */ - | public class Test {} - """.trimIndent() - testInline( - source, - configuration, - ) { - documentablesCreationStage = { modules -> - val docs = modules.first().packages.first().classlikes.single().documentation.values.first() - val root = docs.children.first().root - - kotlin.test.assertEquals( - listOf( - P( - children = listOf( - Img( - params = mapOf( - "href" to "/path/to/img.jpg", - "alt" to "Alt text" - ) - ) - ) - ) - ), - root.children - ) - } - } - } - - @Test - fun `description list tag`() { - val source = """ - |/src/main/kotlin/test/Test.java - |package example - | - | /** - | * <dl> - | * <dt> - | * <code>name="<i>name</i>"</code> - | * </dt> - | * <dd> - | * A URI path segment. The subdirectory name for this value is contained in the - | * <code>path</code> attribute. - | * </dd> - | * <dt> - | * <code>path="<i>path</i>"</code> - | * </dt> - | * <dd> - | * The subdirectory you're sharing. While the <i>name</i> attribute is a URI path - | * segment, the <i>path</i> value is an actual subdirectory name. - | * </dd> - | * </dl> - | */ - | public class Test {} - """.trimIndent() - - val expected = listOf( - Dl( - listOf( - Dt( - listOf( - CodeInline( - listOf( - Text("name=\""), - I( - listOf( - Text("name") - ) - ), - Text("\"") - ) - ), - ) - ), - Dd( - listOf( - Text(" A URI path segment. The subdirectory name for this value is contained in the "), - CodeInline( - listOf( - Text("path") - ) - ), - Text(" attribute. ") - ) - ), - - Dt( - listOf( - CodeInline( - listOf( - Text("path=\""), - I( - listOf( - Text("path") - ) - ), - Text("\"") - ) - ) - ) - ), - Dd( - listOf( - Text(" The subdirectory you're sharing. While the "), - I( - listOf( - Text("name") - ) - ), - Text(" attribute is a URI path segment, the "), - I( - listOf( - Text("path") - ) - ), - Text(" value is an actual subdirectory name. ") - ) - ) - ) - ) - ) - - testInline(source, configuration) { - documentablesCreationStage = { modules -> - val docs = modules.first().packages.first().classlikes.single().documentation.values.first() - assertEquals(expected, docs.children.first().root.children) - } - } - } - - @Test - fun `header tags are handled properly`() { - val source = """ - |/src/main/kotlin/test/Test.java - |package example - | - | /** - | * An example of using the header tags - | * <h1>A header</h1> - | * <h2>A second level header</h2> - | * <h3>A third level header</h3> - | */ - | public class Test {} - """.trimIndent() - testInline( - source, - configuration, - ) { - documentablesCreationStage = { modules -> - val docs = modules.first().packages.first().classlikes.single().documentation.values.first() - val root = docs.children.first().root - - kotlin.test.assertEquals( - listOf( - P(children = listOf(Text("An example of using the header tags "))), - H1( - listOf( - Text("A header") - ) - ), - H2( - listOf( - Text("A second level header") - ) - ), - H3( - listOf( - Text("A third level header") - ) - ) - ), - root.children - ) - } - } - } - - @Test - fun `var tag is handled properly`() { - val source = """ - |/src/main/kotlin/test/Test.java - |package example - | - | /** - | * An example of using var tag: <var>variable</var> - | */ - | public class Test {} - """.trimIndent() - testInline( - source, - configuration, - ) { - documentablesCreationStage = { modules -> - val docs = modules.first().packages.first().classlikes.single().documentation.values.first() - val root = docs.children.first().root - - kotlin.test.assertEquals( - listOf( - P( - children = listOf( - Text("An example of using var tag: "), - Var(children = listOf(Text("variable"))), - ) - ), - ), - root.children - ) - } - } - } - - @Test - fun `u tag is handled properly`() { - val source = """ - |/src/main/kotlin/test/Test.java - |package example - | - | /** - | * An example of using u tag: <u>underlined</u> - | */ - | public class Test {} - """.trimIndent() - testInline( - source, - configuration, - ) { - documentablesCreationStage = { modules -> - val docs = modules.first().packages.first().classlikes.single().documentation.values.first() - val root = docs.children.first().root - - assertEquals( - listOf( - P( - children = listOf( - Text("An example of using u tag: "), - U(children = listOf(Text("underlined"))), - ) - ), - ), - root.children - ) - } - } - } - - @Test - fun `undocumented see also from java`() { - testInline( - """ - |/src/main/java/example/Source.java - |package example; - | - |public interface Source { - | String getProperty(String k, String v); - | - | /** - | * @see #getProperty(String, String) - | */ - | String getProperty(String k); - |} - """.trimIndent(), configuration - ) { - documentablesTransformationStage = { module -> - val functionWithSeeTag = module.packages.flatMap { it.classlikes }.flatMap { it.functions } - .find { it.name == "getProperty" && it.parameters.count() == 1 } - val seeTag = functionWithSeeTag?.docs()?.firstIsInstanceOrNull<See>() - val expectedLinkDestinationDRI = DRI( - packageName = "example", - classNames = "Source", - callable = Callable( - name = "getProperty", - params = listOf(JavaClassReference("java.lang.String"), JavaClassReference("java.lang.String")) - ) - ) - - assertNotNull(seeTag) - assertEquals("getProperty(String, String)", seeTag.name) - assertEquals(expectedLinkDestinationDRI, seeTag.address) - assertEquals(emptyList<DocTag>(), seeTag.children) - } - } - } - - @Test - fun `documented see also from java`() { - testInline( - """ - |/src/main/java/example/Source.java - |package example; - | - |public interface Source { - | String getProperty(String k, String v); - | - | /** - | * @see #getProperty(String, String) this is a reference to a method that is present on the same class. - | */ - | String getProperty(String k); - |} - """.trimIndent(), configuration - ) { - documentablesTransformationStage = { module -> - val functionWithSeeTag = module.packages.flatMap { it.classlikes }.flatMap { it.functions } - .find { it.name == "getProperty" && it.parameters.size == 1 } - val seeTag = functionWithSeeTag?.docs()?.firstIsInstanceOrNull<See>() - val expectedLinkDestinationDRI = DRI( - packageName = "example", - classNames = "Source", - callable = Callable( - name = "getProperty", - params = listOf(JavaClassReference("java.lang.String"), JavaClassReference("java.lang.String")) - ) - ) - - assertNotNull(seeTag) - assertEquals("getProperty(String, String)", seeTag.name) - assertEquals(expectedLinkDestinationDRI, seeTag.address) - assertEquals( - "this is a reference to a method that is present on the same class.", - seeTag.children.first().text().trim() - ) - assertEquals(1, seeTag.children.size) - } - } - } - - @Test - fun `tags are case-sensitive`() { - val source = """ - |/src/main/kotlin/test/Test.java - |package example - | - | /** - | * Java's tag with wrong case - | * {@liTeRal @}Entity - | * public class User {} - | */ - | public class Test {} - """.trimIndent() - testInline( - source, - configuration, - ) { - documentablesCreationStage = { modules -> - val docs = modules.first().packages.first().classlikes.single().documentation.values.first() - val root = docs.children.first().root - - kotlin.test.assertEquals( - listOf( - Text(body = "Java's tag with wrong case {@liTeRal @}Entity public class User {}"), - ), - root.children.first().children - ) - } - } - } - - // TODO [beresnev] move to java-analysis -// @Test -// fun `test isolated parsing is case sensitive`() { -// // Ensure that it won't accidentally break -// val values = JavadocTag.values().map { it.toString().toLowerCase() } -// val withRandomizedCapitalization = values.map { -// val result = buildString { -// for (char in it) { -// if (Random.nextBoolean()) { -// append(char) -// } else { -// append(char.toLowerCase()) -// } -// } -// } -// if (result == it) result.toUpperCase() else result -// } -// -// for ((index, value) in JavadocTag.values().withIndex()) { -// assertEquals(value, JavadocTag.lowercaseValueOfOrNull(values[index])) -// assertNull(JavadocTag.lowercaseValueOfOrNull(withRandomizedCapitalization[index])) -// } -// } -} diff --git a/plugins/base/src/test/kotlin/renderers/html/BasicTest.kt b/plugins/base/src/test/kotlin/renderers/html/BasicTest.kt deleted file mode 100644 index 9653b7bb..00000000 --- a/plugins/base/src/test/kotlin/renderers/html/BasicTest.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 renderers.html - -import org.jetbrains.dokka.base.renderers.html.HtmlRenderer -import org.jetbrains.dokka.links.DRI -import renderers.testPage -import utils.Span -import utils.match -import kotlin.test.Test - -class BasicTest : HtmlRenderingOnlyTestBase() { - @Test - fun `unresolved DRI link should render as text`() { - val page = testPage { - link("linkText", DRI("nonexistentPackage", "nonexistentClass")) - } - - HtmlRenderer(context).render(page) - renderedContent.match(Span("linkText")) - } -} diff --git a/plugins/base/src/test/kotlin/renderers/html/BreadcrumbsTest.kt b/plugins/base/src/test/kotlin/renderers/html/BreadcrumbsTest.kt deleted file mode 100644 index 4bb0d41f..00000000 --- a/plugins/base/src/test/kotlin/renderers/html/BreadcrumbsTest.kt +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package renderers.html - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jsoup.nodes.Element -import signatures.renderedContent -import utils.* -import kotlin.test.Test - -class BreadcrumbsTest : BaseAbstractTest() { - - private val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - } - } - } - - @Test - fun `should add breadcrumbs with current element`() { - val writerPlugin = TestOutputWriterPlugin() - testInline( - """ - |/src/main/kotlin/basic/TestClass.kt - |package testpackage - | - |class TestClass { - | fun foo() {} - |} - """.trimMargin(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/testpackage/-test-class/foo.html").selectBreadcrumbs().match( - link("root"), - delimiter(), - link("testpackage"), - delimiter(), - link("TestClass"), - delimiter(), - current("foo"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `should mark only one element as current even if more elements have the same name`() { - val writerPlugin = TestOutputWriterPlugin() - testInline( - """ - |/src/main/kotlin/basic/TestClass.kt - |package testpackage - | - |class testname { - | val testname: String = "" - |} - """.trimMargin(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/testpackage/testname/testname.html").selectBreadcrumbs().match( - link("root"), - delimiter(), - link("testpackage"), - delimiter(), - link("testname"), - delimiter(), - current("testname"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - private fun Element.selectBreadcrumbs() = this.select("div.breadcrumbs").single() - - private fun link(text: String): Tag = A(text) - private fun delimiter(): Tag = Span().withClasses("delimiter") - private fun current(text: String): Tag = Span(text).withClasses("current") -} diff --git a/plugins/base/src/test/kotlin/renderers/html/CoverPageTest.kt b/plugins/base/src/test/kotlin/renderers/html/CoverPageTest.kt deleted file mode 100644 index 6b3ce2eb..00000000 --- a/plugins/base/src/test/kotlin/renderers/html/CoverPageTest.kt +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package renderers.html - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import signatures.renderedContent -import utils.TestOutputWriterPlugin -import kotlin.test.Test -import kotlin.test.assertEquals - -class CoverPageTest : BaseAbstractTest() { - - private val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - classpath = listOf(commonStdlibPath!!) - externalDocumentationLinks = listOf(stdlibExternalDocumentationLink) - } - } - } - - @Test - fun `names of nested inheritors`() { - val source = """ - |/src/main/kotlin/test/Test.kt - |package example - | - | sealed class Result{ - | class Success(): Result() - | class Failed(): Result() - | } - """ - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val content = writerPlugin.writer.renderedContent("root/example/-result/index.html") - val tableInheritors = content.select("div.table").single { it.previousElementSibling()?.text() == "Inheritors" && it.childrenSize() == 2 } - assertEquals(tableInheritors.getElementsContainingOwnText("Failed").singleOrNull()?.tagName(), "a") - assertEquals(tableInheritors.getElementsContainingOwnText("Success").singleOrNull()?.tagName(), "a") - } - } - } -} diff --git a/plugins/base/src/test/kotlin/renderers/html/CustomFooterTest.kt b/plugins/base/src/test/kotlin/renderers/html/CustomFooterTest.kt deleted file mode 100644 index ff562c38..00000000 --- a/plugins/base/src/test/kotlin/renderers/html/CustomFooterTest.kt +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package renderers.html - -import org.jetbrains.dokka.DokkaConfiguration -import org.jetbrains.dokka.DokkaConfigurationImpl -import org.jetbrains.dokka.PluginConfigurationImpl -import org.jetbrains.dokka.base.DokkaBase -import org.jetbrains.dokka.base.DokkaBaseConfiguration -import org.jetbrains.dokka.base.renderers.html.HtmlRenderer -import org.jetbrains.dokka.base.templating.toJsonString -import org.jsoup.Jsoup -import org.jsoup.nodes.Element -import renderers.testPage -import utils.A -import utils.Div -import utils.Span -import utils.match -import kotlin.test.Test - -class CustomFooterTest : HtmlRenderingOnlyTestBase() { - @Test - fun `should include message from custom footer`() { - val page = testPage { } - HtmlRenderer(context).render(page) - renderedContent.match( - Span(A()), - Span(Div("Custom message")), - Span(Span("Generated by "), A(Span("dokka"), Span())) - ) - } - - override val configuration: DokkaConfigurationImpl - get() = super.configuration.copy( - pluginsConfiguration = listOf( - PluginConfigurationImpl( - DokkaBase::class.java.canonicalName, - DokkaConfiguration.SerializationFormat.JSON, - toJsonString(DokkaBaseConfiguration(footerMessage = """<div style="color: red">Custom message</div>""")) - ) - ) - ) - - override val renderedContent: Element - get() = files.contents.getValue("test-page.html").let { Jsoup.parse(it) }.select(".footer").single() -} diff --git a/plugins/base/src/test/kotlin/renderers/html/DivergentTest.kt b/plugins/base/src/test/kotlin/renderers/html/DivergentTest.kt deleted file mode 100644 index ccc43f12..00000000 --- a/plugins/base/src/test/kotlin/renderers/html/DivergentTest.kt +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package renderers.html - -import org.jetbrains.dokka.base.renderers.html.HtmlRenderer -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.pages.ContentDivergentGroup -import renderers.testPage -import utils.Br -import utils.match -import kotlin.test.Test -import kotlin.test.assertEquals - -class DivergentTest : HtmlRenderingOnlyTestBase() { - - @Test - fun simpleWrappingCase() { - val page = testPage { - divergentGroup(ContentDivergentGroup.GroupID("test")) { - instance(setOf(DRI("test", "Test")), setOf(js)) { - divergent { - text("a") - } - } - } - } - HtmlRenderer(context).render(page) - renderedContent.select("[data-togglable=DEFAULT/js]").single().match("a") - } - - @Test - fun noPlatformHintCase() { - val page = testPage { - divergentGroup(ContentDivergentGroup.GroupID("test"), implicitlySourceSetHinted = false) { - instance(setOf(DRI("test", "Test")), setOf(js)) { - divergent { - text("a") - } - } - } - } - HtmlRenderer(context).render(page) - renderedContent.match("a") - } - - @Test - fun divergentBetweenSourceSets() { - val page = testPage { - divergentGroup(ContentDivergentGroup.GroupID("test")) { - instance(setOf(DRI("test", "Test")), setOf(js)) { - divergent { - text("a") - } - } - instance(setOf(DRI("test", "Test")), setOf(jvm)) { - divergent { - text("b") - } - } - instance(setOf(DRI("test", "Test")), setOf(native)) { - divergent { - text("c") - } - } - } - } - - HtmlRenderer(context).render(page) - val content = renderedContent - content.select("[data-togglable=DEFAULT/js]").single().match("a") - content.select("[data-togglable=DEFAULT/jvm]").single().match("b") - content.select("[data-togglable=DEFAULT/native]").single().match("c") - } - - @Test - fun divergentInOneSourceSet() { - val page = testPage { - divergentGroup(ContentDivergentGroup.GroupID("test")) { - instance(setOf(DRI("test", "Test")), setOf(js)) { - divergent { - text("a") - } - } - instance(setOf(DRI("test", "Test2")), setOf(js)) { - divergent { - text("b") - } - } - instance(setOf(DRI("test", "Test3")), setOf(js)) { - divergent { - text("c") - } - } - } - } - - HtmlRenderer(context).render(page) - renderedContent.select("[data-togglable=DEFAULT/js]").single().match("abc") - } - - @Test - fun divergentInAndBetweenSourceSets() { - val page = testPage { - divergentGroup(ContentDivergentGroup.GroupID("test")) { - instance(setOf(DRI("test", "Test")), setOf(native)) { - divergent { - text("a") - } - } - instance(setOf(DRI("test", "Test")), setOf(js)) { - divergent { - text("b") - } - } - instance(setOf(DRI("test", "Test")), setOf(jvm)) { - divergent { - text("c") - } - } - instance(setOf(DRI("test", "Test2")), setOf(js)) { - divergent { - text("d") - } - } - instance(setOf(DRI("test", "Test3")), setOf(native)) { - divergent { - text("e") - } - } - } - } - - HtmlRenderer(context).render(page) - val content = renderedContent - val orderOfTabs = content.select(".platform-bookmarks-row").single().children().map { it.attr("data-toggle") } - - assertEquals(listOf("DEFAULT/js", "DEFAULT/jvm", "DEFAULT/native"), orderOfTabs) - - content.select("[data-togglable=DEFAULT/native]").single().match("ae") - content.select("[data-togglable=DEFAULT/js]").single().match("bd") - content.select("[data-togglable=DEFAULT/jvm]").single().match("c") - } - - @Test - fun divergentInAndBetweenSourceSetsWithGrouping() { - val page = testPage { - divergentGroup(ContentDivergentGroup.GroupID("test")) { - instance(setOf(DRI("test", "Test")), setOf(native)) { - divergent { - text("a") - } - after { - text("a+") - } - } - instance(setOf(DRI("test", "Test")), setOf(js)) { - divergent { - text("b") - } - after { - text("bd+") - } - } - instance(setOf(DRI("test", "Test")), setOf(jvm)) { - divergent { - text("c") - } - } - instance(setOf(DRI("test", "Test2")), setOf(js)) { - divergent { - text("d") - } - after { - text("bd+") - } - } - instance(setOf(DRI("test", "Test3")), setOf(native)) { - divergent { - text("e") - } - after { - text("e+") - } - } - } - } - - HtmlRenderer(context).render(page) - val content = renderedContent - content.select("[data-togglable=DEFAULT/native]").single().match("aa+", Br, "ee+") - content.select("[data-togglable=DEFAULT/js]").single().match("bdbd+") - content.select("[data-togglable=DEFAULT/jvm]").single().match("c") - } - - @Test - fun divergentSameBefore() { - val page = testPage { - divergentGroup(ContentDivergentGroup.GroupID("test")) { - instance(setOf(DRI("test", "Test")), setOf(native)) { - before { - text("ab-") - } - divergent { - text("a") - } - } - instance(setOf(DRI("test", "Test2")), setOf(native)) { - before { - text("ab-") - } - divergent { - text("b") - } - } - } - } - - HtmlRenderer(context).render(page) - renderedContent.select("[data-togglable=DEFAULT/native]").single().match("ab-ab") - } - - @Test - fun divergentSameAfter() { - val page = testPage { - divergentGroup(ContentDivergentGroup.GroupID("test")) { - instance(setOf(DRI("test", "Test")), setOf(native)) { - divergent { - text("a") - } - after { - text("ab+") - } - } - instance(setOf(DRI("test", "Test2")), setOf(native)) { - divergent { - text("b") - } - after { - text("ab+") - } - } - } - } - - HtmlRenderer(context).render(page) - renderedContent.select("[data-togglable=DEFAULT/native]").single().match("abab+") - } - - @Test - fun divergentGroupedByBeforeAndAfter() { - val page = testPage { - divergentGroup(ContentDivergentGroup.GroupID("test")) { - instance(setOf(DRI("test", "Test")), setOf(native)) { - before { - text("ab-") - } - divergent { - text("a") - } - after { - text("ab+") - } - } - instance(setOf(DRI("test", "Test2")), setOf(native)) { - before { - text("ab-") - } - divergent { - text("b") - } - after { - text("ab+") - } - } - } - } - - HtmlRenderer(context).render(page) - renderedContent.select("[data-togglable=DEFAULT/native]").single().match("ab-abab+") - } - - @Test - fun divergentDifferentBeforeAndAfter() { - val page = testPage { - divergentGroup(ContentDivergentGroup.GroupID("test")) { - instance(setOf(DRI("test", "Test")), setOf(native)) { - before { - text("a-") - } - divergent { - text("a") - } - after { - text("ab+") - } - } - instance(setOf(DRI("test", "Test2")), setOf(native)) { - before { - text("b-") - } - divergent { - text("b") - } - after { - text("ab+") - } - } - } - } - - HtmlRenderer(context).render(page) - renderedContent.select("[data-togglable=DEFAULT/native]").single().match("a-aab+", Br, "b-bab+") - } -} diff --git a/plugins/base/src/test/kotlin/renderers/html/FooterMessageTest.kt b/plugins/base/src/test/kotlin/renderers/html/FooterMessageTest.kt deleted file mode 100644 index 149f970c..00000000 --- a/plugins/base/src/test/kotlin/renderers/html/FooterMessageTest.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 renderers.html - -import org.jetbrains.dokka.base.DokkaBaseConfiguration.Companion.defaultFooterMessage -import org.jetbrains.dokka.base.renderers.html.HtmlRenderer -import org.jsoup.Jsoup -import org.jsoup.nodes.Element -import renderers.testPage -import utils.A -import utils.Span -import utils.match -import kotlin.test.Test - -class FooterMessageTest : HtmlRenderingOnlyTestBase() { - @Test - fun `should include defaultFooter`() { - val page = testPage { } - HtmlRenderer(context).render(page) - renderedContent.match( - Span(A()), - Span(defaultFooterMessage), - Span(Span("Generated by "), A(Span("dokka"), Span())) - ) - } - - override val renderedContent: Element - get() = files.contents.getValue("test-page.html").let { Jsoup.parse(it) }.select(".footer").single() -} diff --git a/plugins/base/src/test/kotlin/renderers/html/FormattingUtilsTest.kt b/plugins/base/src/test/kotlin/renderers/html/FormattingUtilsTest.kt deleted file mode 100644 index 028ffa77..00000000 --- a/plugins/base/src/test/kotlin/renderers/html/FormattingUtilsTest.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 renderers.html - -import kotlinx.html.body -import kotlinx.html.html -import kotlinx.html.stream.createHTML -import org.jetbrains.dokka.base.renderers.html.buildBreakableText -import kotlin.test.Test -import kotlin.test.assertEquals - -class FormattingUtilsTest { - @Test - fun `should build breakable text`(){ - val testedText = "kotlinx.collections.immutable" - val expectedHtml = """ - <html> - <body><span>kotlinx.</span><wbr></wbr><span>collections.</span><wbr></wbr><span>immutable</span></body> - </html> - """.trimIndent() - - val html = createHTML(prettyPrint = true).html { - body { - buildBreakableText(testedText) - } - } - - assertEquals(expectedHtml.trim(), html.trim()) - } - - @Test - fun `should build breakable text without empty spans`(){ - val testedText = "Package org.jetbrains.dokka.it.moduleC" - val expectedHtml = """ - <html> - <body><span><span>Package</span></span> <span>org.</span><wbr></wbr><span>jetbrains.</span><wbr></wbr><span>dokka.</span><wbr></wbr><span>it.</span><wbr></wbr><span>moduleC</span></body> - </html> - """.trimIndent() - - val html = createHTML(prettyPrint = true).html { - body { - buildBreakableText(testedText) - } - } - - assertEquals(expectedHtml.trim(), html.trim()) - } - - @Test - fun `should build breakable text for text with braces`(){ - val testedText = "[Common]kotlinx.collections.immutable" - val expectedHtml = """ - <html> - <body><span>[Common]kotlinx.</span><wbr></wbr><span>collections.</span><wbr></wbr><span>immutable</span></body> - </html> - """.trimIndent() - - val html = createHTML(prettyPrint = true).html { - body { - buildBreakableText(testedText) - } - } - - assertEquals(expectedHtml.trim(), html.trim()) - } - - @Test - fun `should build breakable text for camel case notation`(){ - val testedText = "DokkkkkkkaIsTheBest" - val expectedHtml = """ - <html> - <body><span>Dokkkkkkka</span><wbr></wbr><span>Is</span><wbr></wbr><span>The</span><wbr></wbr><span><span>Best</span></span></body> - </html> - """.trimIndent() - - val html = createHTML(prettyPrint = true).html { - body { - buildBreakableText(testedText) - } - } - - assertEquals(expectedHtml.trim(), html.trim()) - } -} diff --git a/plugins/base/src/test/kotlin/renderers/html/GroupWrappingTest.kt b/plugins/base/src/test/kotlin/renderers/html/GroupWrappingTest.kt deleted file mode 100644 index cc9b763d..00000000 --- a/plugins/base/src/test/kotlin/renderers/html/GroupWrappingTest.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 renderers.html - -import org.jetbrains.dokka.base.renderers.html.HtmlRenderer -import org.jetbrains.dokka.pages.TextStyle -import renderers.testPage -import utils.Div -import utils.P -import utils.match -import kotlin.test.Test - -class GroupWrappingTest : HtmlRenderingOnlyTestBase() { - - @Test - fun notWrapped() { - val page = testPage { - group { - text("a") - text("b") - } - text("c") - } - - HtmlRenderer(context).render(page) - - renderedContent.match("abc") - } - - @Test - fun paragraphWrapped() { - val page = testPage { - group(styles = setOf(TextStyle.Paragraph)) { - text("a") - text("b") - } - text("c") - } - - HtmlRenderer(context).render(page) - - renderedContent.match(P("ab"), "c") - } - - @Test - fun blockWrapped() { - val page = testPage { - group(styles = setOf(TextStyle.Block)) { - text("a") - text("b") - } - text("c") - } - - HtmlRenderer(context).render(page) - - renderedContent.match(Div("ab"), "c") - } - - @Test - fun nested() { - val page = testPage { - group(styles = setOf(TextStyle.Block)) { - text("a") - group(styles = setOf(TextStyle.Block)) { - group(styles = setOf(TextStyle.Block)) { - text("b") - text("c") - } - } - text("d") - } - } - - HtmlRenderer(context).render(page) - - renderedContent.match(Div("a", Div(Div("bc")), "d")) - } - -} diff --git a/plugins/base/src/test/kotlin/renderers/html/HeaderTest.kt b/plugins/base/src/test/kotlin/renderers/html/HeaderTest.kt deleted file mode 100644 index c19f965f..00000000 --- a/plugins/base/src/test/kotlin/renderers/html/HeaderTest.kt +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package renderers.html - -import org.jetbrains.dokka.DokkaConfiguration -import org.jetbrains.dokka.DokkaConfigurationImpl -import org.jetbrains.dokka.PluginConfigurationImpl -import org.jetbrains.dokka.base.DokkaBase -import org.jetbrains.dokka.base.DokkaBaseConfiguration -import org.jetbrains.dokka.base.templating.toJsonString -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.pages.RootPageNode -import org.jetbrains.dokka.plugability.DokkaContext -import org.jsoup.Jsoup -import utils.TestOutputWriter -import utils.TestOutputWriterPlugin -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertNotNull -import kotlin.test.assertNull - -class HeaderTest : BaseAbstractTest() { - private val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - name = "jvm" - sourceRoots = listOf("src/jvm") - } - sourceSet { - name = "js" - sourceRoots = listOf("src/js") - } - } - } - - @Test - fun `should include homepage link if homepageLink is provided`() { - testRendering( - DokkaBaseConfiguration(homepageLink = "https://github.com/Kotlin/dokka/") - ) { _, _, writer -> - val renderedContent = navigationElement(writer) - - val sourceLinkElement = - assertNotNull(renderedContent.getElementById("homepage-link"), "Source link element not found") - val aElement = assertNotNull(sourceLinkElement.selectFirst("a")) - assertEquals("https://github.com/Kotlin/dokka/", aElement.attr("href")) - } - } - - @Test - fun `should not include homepage link by default`() { - testRendering(null) { _, _, writer -> - val renderedContent = navigationElement(writer) - assertNull(renderedContent.getElementById("homepage-link"), "Source link element found") - } - } - - private fun testRendering( - baseConfiguration: DokkaBaseConfiguration?, - block: (RootPageNode, DokkaContext, writer: TestOutputWriter) -> Unit - ) { - fun configuration(): DokkaConfigurationImpl { - baseConfiguration ?: return configuration - return configuration.copy( - pluginsConfiguration = listOf( - PluginConfigurationImpl( - DokkaBase::class.java.canonicalName, - DokkaConfiguration.SerializationFormat.JSON, - toJsonString(baseConfiguration) - ) - ) - ) - } - - val writerPlugin = TestOutputWriterPlugin() - testInline( - """ - |/src/jvm/Test.kt - |fun test() {} - |/src/js/Test.kt - |fun test() {} - """, - configuration(), - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { node, context -> - block(node, context, writerPlugin.writer) - } - } - } - - private fun navigationElement(writer: TestOutputWriter) = - writer - .contents - .getValue("index.html") - .let(Jsoup::parse) - .select(".navigation") - .single() - -} diff --git a/plugins/base/src/test/kotlin/renderers/html/HtmlRenderingOnlyTestBase.kt b/plugins/base/src/test/kotlin/renderers/html/HtmlRenderingOnlyTestBase.kt deleted file mode 100644 index 4e098371..00000000 --- a/plugins/base/src/test/kotlin/renderers/html/HtmlRenderingOnlyTestBase.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 renderers.html - -import org.jetbrains.dokka.DokkaConfigurationImpl -import org.jetbrains.dokka.Platform -import org.jetbrains.dokka.base.DokkaBase -import org.jetbrains.dokka.base.renderers.RootCreator -import org.jetbrains.dokka.base.resolvers.external.DefaultExternalLocationProviderFactory -import org.jetbrains.dokka.base.resolvers.external.javadoc.JavadocExternalLocationProviderFactory -import org.jetbrains.dokka.base.resolvers.local.DokkaLocationProviderFactory -import org.jetbrains.dokka.testApi.context.MockContext -import org.jsoup.Jsoup -import org.jsoup.nodes.Element -import renderers.RenderingOnlyTestBase -import testApi.testRunner.defaultSourceSet -import utils.TestOutputWriter -import java.io.File - -abstract class HtmlRenderingOnlyTestBase : RenderingOnlyTestBase<Element>() { - - protected val js = defaultSourceSet.copy( - "JS", - defaultSourceSet.sourceSetID.copy(sourceSetName = "js"), - analysisPlatform = Platform.js, - sourceRoots = setOf(File("pl1")) - ) - protected val jvm = defaultSourceSet.copy( - "JVM", - defaultSourceSet.sourceSetID.copy(sourceSetName = "jvm"), - - analysisPlatform = Platform.jvm, - sourceRoots = setOf(File("pl1")) - ) - protected val native = defaultSourceSet.copy( - "NATIVE", - defaultSourceSet.sourceSetID.copy(sourceSetName = "native"), - analysisPlatform = Platform.native, - sourceRoots = setOf(File("pl1")) - ) - - val files = TestOutputWriter() - - open val configuration = DokkaConfigurationImpl( - sourceSets = listOf(js, jvm, native), - finalizeCoroutines = false - ) - - override val context = MockContext( - DokkaBase().outputWriter to { files }, - DokkaBase().locationProviderFactory to ::DokkaLocationProviderFactory, - DokkaBase().htmlPreprocessors to { RootCreator }, - DokkaBase().externalLocationProviderFactory to ::JavadocExternalLocationProviderFactory, - DokkaBase().externalLocationProviderFactory to ::DefaultExternalLocationProviderFactory, - testConfiguration = configuration - ) - - override val renderedContent: Element by lazy { - files.contents.getValue("test-page.html").let { Jsoup.parse(it) }.select("#content").single() - } - - protected fun linesAfterContentTag() = - files.contents.getValue("test-page.html").lines() - .dropWhile { !it.contains("""<div id="content">""") } - .joinToString(separator = "") { it.trim() } -} diff --git a/plugins/base/src/test/kotlin/renderers/html/ListStylesTest.kt b/plugins/base/src/test/kotlin/renderers/html/ListStylesTest.kt deleted file mode 100644 index f8afb54c..00000000 --- a/plugins/base/src/test/kotlin/renderers/html/ListStylesTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package renderers.html - -import org.jetbrains.dokka.base.renderers.html.HtmlRenderer -import org.jetbrains.dokka.pages.ListStyle -import renderers.testPage -import utils.Dd -import utils.Dl -import utils.Dt -import utils.match -import kotlin.test.Test - - -class ListStylesTest : HtmlRenderingOnlyTestBase() { - - @Test - fun `description list render`() { - val page = testPage { - descriptionList { - item(styles = setOf(ListStyle.DescriptionTerm)) { - text("Description term #1") - } - item(styles = setOf(ListStyle.DescriptionTerm)) { - text("Description term #2") - } - item(styles = setOf(ListStyle.DescriptionDetails)) { - text("Description details describing terms #1 and #2") - } - } - } - - - HtmlRenderer(context).render(page) - renderedContent.match( - Dl( - Dt("Description term #1"), - Dt("Description term #2"), - Dd("Description details describing terms #1 and #2") - ) - ) - } -} diff --git a/plugins/base/src/test/kotlin/renderers/html/NavigationIconTest.kt b/plugins/base/src/test/kotlin/renderers/html/NavigationIconTest.kt deleted file mode 100644 index d57f84df..00000000 --- a/plugins/base/src/test/kotlin/renderers/html/NavigationIconTest.kt +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package renderers.html - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import utils.TestOutputWriterPlugin -import utils.navigationHtml -import utils.selectNavigationGrid -import kotlin.test.Test -import kotlin.test.assertEquals - -class NavigationIconTest : BaseAbstractTest() { - - private val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - } - } - } - - @Test - fun `should include all navigation icons`() { - val source = """ - |/src/main/kotlin/com/example/Empty.kt - |package com.example - | - |class Empty {} - """ - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val navIconAssets = writerPlugin.writer.contents - .filterKeys { it.startsWith("images/nav-icons") } - .keys.sorted() - - assertEquals(16, navIconAssets.size) - assertEquals("images/nav-icons/abstract-class-kotlin.svg", navIconAssets[0]) - assertEquals("images/nav-icons/abstract-class.svg", navIconAssets[1]) - assertEquals("images/nav-icons/annotation-kotlin.svg", navIconAssets[2]) - assertEquals("images/nav-icons/annotation.svg", navIconAssets[3]) - assertEquals("images/nav-icons/class-kotlin.svg", navIconAssets[4]) - assertEquals("images/nav-icons/class.svg", navIconAssets[5]) - assertEquals("images/nav-icons/enum-kotlin.svg", navIconAssets[6]) - assertEquals("images/nav-icons/enum.svg", navIconAssets[7]) - assertEquals("images/nav-icons/exception-class.svg", navIconAssets[8]) - assertEquals("images/nav-icons/field-value.svg", navIconAssets[9]) - assertEquals("images/nav-icons/field-variable.svg", navIconAssets[10]) - assertEquals("images/nav-icons/function.svg", navIconAssets[11]) - assertEquals("images/nav-icons/interface-kotlin.svg", navIconAssets[12]) - assertEquals("images/nav-icons/interface.svg", navIconAssets[13]) - assertEquals("images/nav-icons/object.svg", navIconAssets[14]) - assertEquals("images/nav-icons/typealias-kotlin.svg", navIconAssets[15]) - } - } - } - - @Test - fun `should add icon styles to kotlin class navigation item`() { - assertNavigationIcon( - source = kotlinSource("class Clazz {}"), - expectedIconClass = "class-kt", - expectedNavLinkText = "Clazz" - ) - } - - @Test - fun `should add icon styles to java class navigation item`() { - assertNavigationIcon( - source = javaSource( - className = "JavaClazz", - source = "public class JavaClazz {}" - ), - expectedIconClass = "class", - expectedNavLinkText = "JavaClazz" - ) - } - - @Test - fun `should add icon styles to kotlin abstract class navigation item`() { - assertNavigationIcon( - source = kotlinSource("abstract class AbstractClazz {}"), - expectedIconClass = "abstract-class-kt", - expectedNavLinkText = "AbstractClazz" - ) - } - - @Test - fun `should add icon styles to java abstract class navigation item`() { - assertNavigationIcon( - source = javaSource( - className = "AbstractJavaClazz", - source = "public abstract class AbstractJavaClazz {}" - ), - expectedIconClass = "abstract-class", - expectedNavLinkText = "AbstractJavaClazz" - ) - } - - @Test - fun `should add icon styles to kotlin typealias navigation item`() { - assertNavigationIcon( - source = kotlinSource("typealias KotlinTypealias = String"), - expectedIconClass = "typealias-kt", - expectedNavLinkText = "KotlinTypealias" - ) - } - - @Test - fun `should add icon styles to kotlin enum navigation item`() { - assertNavigationIcon( - source = kotlinSource("enum class KotlinEnum {}"), - expectedIconClass = "enum-class-kt", - expectedNavLinkText = "KotlinEnum" - ) - } - - @Test - fun `should add icon styles to java enum class navigation item`() { - assertNavigationIcon( - source = javaSource( - className = "JavaEnum", - source = "public enum JavaEnum {}" - ), - expectedIconClass = "enum-class", - expectedNavLinkText = "JavaEnum" - ) - } - - @Test - fun `should add icon styles to kotlin annotation navigation item`() { - assertNavigationIcon( - source = kotlinSource("annotation class KotlinAnnotation"), - expectedIconClass = "annotation-class-kt", - expectedNavLinkText = "KotlinAnnotation" - ) - } - - @Test - fun `should add icon styles to java annotation navigation item`() { - assertNavigationIcon( - source = javaSource( - className = "JavaAnnotation", - source = "public @interface JavaAnnotation {}" - ), - expectedIconClass = "annotation-class", - expectedNavLinkText = "JavaAnnotation" - ) - } - - - @Test - fun `should add icon styles to kotlin interface navigation item`() { - assertNavigationIcon( - source = kotlinSource("interface KotlinInterface"), - expectedIconClass = "interface-kt", - expectedNavLinkText = "KotlinInterface" - ) - } - - @Test - fun `should add icon styles to java interface navigation item`() { - assertNavigationIcon( - source = javaSource( - className = "JavaInterface", - source = "public interface JavaInterface {}" - ), - expectedIconClass = "interface", - expectedNavLinkText = "JavaInterface" - ) - } - - @Test - fun `should add icon styles to kotlin function navigation item`() { - assertNavigationIcon( - source = kotlinSource("fun ktFunction() {}"), - expectedIconClass = "function", - expectedNavLinkText = "ktFunction()" - ) - } - - @Test - fun `should add icon styles to kotlin exception class navigation item`() { - assertNavigationIcon( - source = kotlinSource("class KotlinException : Exception() {}"), - expectedIconClass = "exception-class", - expectedNavLinkText = "KotlinException" - ) - } - - @Test - fun `should add icon styles to kotlin object navigation item`() { - assertNavigationIcon( - source = kotlinSource("object KotlinObject {}"), - expectedIconClass = "object", - expectedNavLinkText = "KotlinObject" - ) - } - - @Test - fun `should add icon styles to kotlin val navigation item`() { - assertNavigationIcon( - source = kotlinSource("val value: String? = null"), - expectedIconClass = "val", - expectedNavLinkText = "value" - ) - } - - @Test - fun `should add icon styles to kotlin var navigation item`() { - assertNavigationIcon( - source = kotlinSource("var variable: String? = null"), - expectedIconClass = "var", - expectedNavLinkText = "variable" - ) - } - - private fun kotlinSource(source: String): String { - return """ - |/src/main/kotlin/com/example/Example.kt - |package com.example - | - |$source - """.trimIndent() - } - - private fun javaSource(className: String, source: String): String { - return """ - |/src/main/java/com/example/$className.java - |package com.example; - | - |$source - """.trimIndent() - } - - private fun assertNavigationIcon(source: String, expectedIconClass: String, expectedNavLinkText: String) { - val writerPlugin = TestOutputWriterPlugin() - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val content = writerPlugin.writer.navigationHtml().select("div.sideMenuPart") - val navigationGrid = content.selectNavigationGrid() - - val classNames = navigationGrid.child(0).classNames().toList() - assertEquals("nav-link-child", classNames[0]) - assertEquals("nav-icon", classNames[1]) - assertEquals(expectedIconClass, classNames[2]) - - val navLinkText = navigationGrid.child(1).text() - assertEquals(expectedNavLinkText, navLinkText) - } - } - } - - @Test - fun `should not generate nav link grids or icons for packages and modules`() { - val writerPlugin = TestOutputWriterPlugin() - testInline( - """ - |/src/main/kotlin/com/example/Example.kt - |package com.example - | - |class Example {} - """.trimIndent(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val content = writerPlugin.writer.navigationHtml().select("div.sideMenuPart") - - assertEquals(3, content.size) - assertEquals("root-nav-submenu", content[0].id()) - assertEquals("root-nav-submenu-0", content[1].id()) - assertEquals("root-nav-submenu-0-0", content[2].id()) - - // there's 3 nav items, but only one icon - val navLinkGrids = content.select("span.nav-icon") - assertEquals(1, navLinkGrids.size) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/renderers/html/NavigationTest.kt b/plugins/base/src/test/kotlin/renderers/html/NavigationTest.kt deleted file mode 100644 index 02074810..00000000 --- a/plugins/base/src/test/kotlin/renderers/html/NavigationTest.kt +++ /dev/null @@ -1,414 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package renderers.html - -import org.jetbrains.dokka.base.renderers.html.NavigationNodeIcon -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jsoup.nodes.Element -import utils.TestOutputWriterPlugin -import utils.navigationHtml -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertNotNull -import kotlin.test.assertNull - -class NavigationTest : BaseAbstractTest() { - - private val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - } - } - } - - @Test - fun `should sort alphabetically ignoring case`() { - val writerPlugin = TestOutputWriterPlugin() - testInline( - """ - |/src/main/kotlin/com/example/Sequences.kt - |package com.example - | - |fun <T> sequence(): Sequence<T> - | - |fun <T> Sequence(): Sequence<T> - | - |fun <T> Sequence<T>.any() {} - | - |interface Sequence<T> - """.trimMargin(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val content = writerPlugin.writer.navigationHtml().select("div.sideMenuPart") - assertEquals(6, content.size) - - // Navigation menu should be the following: - // - root - // - com.example - // - any() - // - Sequence interface - // - Sequence() - // - sequence() - - content[0].assertNavigationLink( - id = "root-nav-submenu", - text = "root", - address = "index.html", - ) - - content[1].assertNavigationLink( - id = "root-nav-submenu-0", - text = "com.example", - address = "root/com.example/index.html", - ) - - content[2].assertNavigationLink( - id = "root-nav-submenu-0-0", - text = "any()", - address = "root/com.example/any.html", - icon = NavigationNodeIcon.FUNCTION - ) - - content[3].assertNavigationLink( - id = "root-nav-submenu-0-1", - text = "Sequence", - address = "root/com.example/-sequence/index.html", - icon = NavigationNodeIcon.INTERFACE_KT - ) - - content[4].assertNavigationLink( - id = "root-nav-submenu-0-2", - text = "Sequence()", - address = "root/com.example/-sequence.html", - icon = NavigationNodeIcon.FUNCTION - ) - - content[5].assertNavigationLink( - id = "root-nav-submenu-0-3", - text = "sequence()", - address = "root/com.example/sequence.html", - icon = NavigationNodeIcon.FUNCTION - ) - } - } - } - - @Test - fun `should strike deprecated class link`() { - val writerPlugin = TestOutputWriterPlugin() - testInline( - """ - |/src/main/kotlin/com/example/SimpleDeprecatedClass.kt - |package com.example - | - |@Deprecated("reason") - |class SimpleDeprecatedClass {} - """.trimIndent(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val content = writerPlugin.writer.navigationHtml().select("div.sideMenuPart") - assertEquals(3, content.size) - - // Navigation menu should be the following: - // - root - // - com.example - // - SimpleDeprecatedClass - - content[0].assertNavigationLink( - id = "root-nav-submenu", - text = "root", - address = "index.html", - ) - - content[1].assertNavigationLink( - id = "root-nav-submenu-0", - text = "com.example", - address = "root/com.example/index.html", - ) - - content[2].assertNavigationLink( - id = "root-nav-submenu-0-0", - text = "SimpleDeprecatedClass", - address = "root/com.example/-simple-deprecated-class/index.html", - icon = NavigationNodeIcon.CLASS_KT, - isStrikethrough = true - ) - } - } - } - - @Test - fun `should not strike pages where only one of N documentables is deprecated`() { - val writerPlugin = TestOutputWriterPlugin() - testInline( - """ - |/src/main/kotlin/com/example/File.kt - |package com.example - | - |/** - | * First - | */ - |@Deprecated("reason") - |fun functionWithCommonName() - | - |/** - | * Second - | */ - |fun functionWithCommonName() - """.trimIndent(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val content = writerPlugin.writer.navigationHtml().select("div.sideMenuPart") - assertEquals(3, content.size) - - // Navigation menu should be the following: - // - root - // - com.example - // - functionWithCommonName - - content[0].assertNavigationLink( - id = "root-nav-submenu", - text = "root", - address = "index.html", - ) - - content[1].assertNavigationLink( - id = "root-nav-submenu-0", - text = "com.example", - address = "root/com.example/index.html", - ) - - content[2].assertNavigationLink( - id = "root-nav-submenu-0-0", - text = "functionWithCommonName()", - address = "root/com.example/function-with-common-name.html", - icon = NavigationNodeIcon.FUNCTION, - isStrikethrough = false - ) - } - } - } - - @Test - fun `should have expandable classlikes`() { - val writerPlugin = TestOutputWriterPlugin() - testInline( - """ - |/src/main/kotlin/com/example/WithInner.kt - |package com.example - | - |class WithInner { - | // in-class functions should not be in navigation - | fun a() {} - | fun b() {} - | fun c() {} - | - | class InnerClass {} - | interface InnerInterface {} - | enum class InnerEnum {} - | object InnerObject {} - | annotation class InnerAnnotation {} - | companion object CompanionObject {} - |} - """.trimIndent(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val content = writerPlugin.writer.navigationHtml().select("div.sideMenuPart") - assertEquals(9, content.size) - - // Navigation menu should be the following, sorted by name: - // - root - // - com.example - // - WithInner - // - CompanionObject - // - InnerAnnotation - // - InnerClass - // - InnerEnum - // - InnerInterface - // - InnerObject - - content[0].assertNavigationLink( - id = "root-nav-submenu", - text = "root", - address = "index.html", - ) - - content[1].assertNavigationLink( - id = "root-nav-submenu-0", - text = "com.example", - address = "root/com.example/index.html", - ) - - content[2].assertNavigationLink( - id = "root-nav-submenu-0-0", - text = "WithInner", - address = "root/com.example/-with-inner/index.html", - icon = NavigationNodeIcon.CLASS_KT - ) - - content[3].assertNavigationLink( - id = "root-nav-submenu-0-0-0", - text = "CompanionObject", - address = "root/com.example/-with-inner/-companion-object/index.html", - icon = NavigationNodeIcon.OBJECT - ) - - content[4].assertNavigationLink( - id = "root-nav-submenu-0-0-1", - text = "InnerAnnotation", - address = "root/com.example/-with-inner/-inner-annotation/index.html", - icon = NavigationNodeIcon.ANNOTATION_CLASS_KT - ) - - content[5].assertNavigationLink( - id = "root-nav-submenu-0-0-2", - text = "InnerClass", - address = "root/com.example/-with-inner/-inner-class/index.html", - icon = NavigationNodeIcon.CLASS_KT - ) - - content[6].assertNavigationLink( - id = "root-nav-submenu-0-0-3", - text = "InnerEnum", - address = "root/com.example/-with-inner/-inner-enum/index.html", - icon = NavigationNodeIcon.ENUM_CLASS_KT - ) - - content[7].assertNavigationLink( - id = "root-nav-submenu-0-0-4", - text = "InnerInterface", - address = "root/com.example/-with-inner/-inner-interface/index.html", - icon = NavigationNodeIcon.INTERFACE_KT - ) - - content[8].assertNavigationLink( - id = "root-nav-submenu-0-0-5", - text = "InnerObject", - address = "root/com.example/-with-inner/-inner-object/index.html", - icon = NavigationNodeIcon.OBJECT - ) - } - } - } - - @Test - fun `should be able to have deeply nested classlikes`() { - val writerPlugin = TestOutputWriterPlugin() - testInline( - """ - |/src/main/kotlin/com/example/DeeplyNested.kt - |package com.example - | - |class DeeplyNested { - | class FirstLevelClass { - | interface SecondLevelInterface { - | object ThirdLevelObject { - | annotation class FourthLevelAnnotation {} - | } - | } - | } - |} - """.trimIndent(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val content = writerPlugin.writer.navigationHtml().select("div.sideMenuPart") - assertEquals(7, content.size) - - // Navigation menu should be the following - // - root - // - com.example - // - DeeplyNested - // - FirstLevelClass - // - SecondLevelInterface - // - ThirdLevelObject - // - FourthLevelAnnotation - - content[0].assertNavigationLink( - id = "root-nav-submenu", - text = "root", - address = "index.html", - ) - - content[1].assertNavigationLink( - id = "root-nav-submenu-0", - text = "com.example", - address = "root/com.example/index.html", - ) - - content[2].assertNavigationLink( - id = "root-nav-submenu-0-0", - text = "DeeplyNested", - address = "root/com.example/-deeply-nested/index.html", - icon = NavigationNodeIcon.CLASS_KT - ) - - content[3].assertNavigationLink( - id = "root-nav-submenu-0-0-0", - text = "FirstLevelClass", - address = "root/com.example/-deeply-nested/-first-level-class/index.html", - icon = NavigationNodeIcon.CLASS_KT - ) - - content[4].assertNavigationLink( - id = "root-nav-submenu-0-0-0-0", - text = "SecondLevelInterface", - address = "root/com.example/-deeply-nested/-first-level-class/-second-level-interface/index.html", - icon = NavigationNodeIcon.INTERFACE_KT - ) - - content[5].assertNavigationLink( - id = "root-nav-submenu-0-0-0-0-0", - text = "ThirdLevelObject", - address = "root/com.example/-deeply-nested/-first-level-class/-second-level-interface/" + - "-third-level-object/index.html", - icon = NavigationNodeIcon.OBJECT - ) - - content[6].assertNavigationLink( - id = "root-nav-submenu-0-0-0-0-0-0", - text = "FourthLevelAnnotation", - address = "root/com.example/-deeply-nested/-first-level-class/-second-level-interface/" + - "-third-level-object/-fourth-level-annotation/index.html", - icon = NavigationNodeIcon.ANNOTATION_CLASS_KT - ) - } - } - } - - private fun Element.assertNavigationLink( - id: String, text: String, address: String, icon: NavigationNodeIcon? = null, isStrikethrough: Boolean = false - ) { - assertEquals(id, this.id()) - - val link = this.selectFirst("a") - assertNotNull(link) - assertEquals(text, link.text()) - assertEquals(address, link.attr("href")) - if (icon != null) { - val iconStyles = - this.selectFirst("div.overview span.nav-link-grid")?.child(0)?.classNames()?.toList() ?: emptyList() - assertEquals(3, iconStyles.size) - assertEquals("nav-link-child", iconStyles[0]) - assertEquals(icon.style(), "${iconStyles[1]} ${iconStyles[2]}") - } - if (isStrikethrough) { - val textInsideStrikethrough = link.selectFirst("strike")?.text() - assertEquals(text, textInsideStrikethrough) - } else { - assertNull(link.selectFirst("strike")) - } - } -} diff --git a/plugins/base/src/test/kotlin/renderers/html/SearchbarDataInstallerTest.kt b/plugins/base/src/test/kotlin/renderers/html/SearchbarDataInstallerTest.kt deleted file mode 100644 index a5f5feb5..00000000 --- a/plugins/base/src/test/kotlin/renderers/html/SearchbarDataInstallerTest.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. - */ - -package renderers.html - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import utils.TestOutputWriterPlugin -import utils.pagesJson -import kotlin.test.Test -import kotlin.test.assertEquals - -class SearchbarDataInstallerTest: BaseAbstractTest() { - - @Test // see #2289 - fun `should display description of root declarations without a leading dot`() { - val configuration = dokkaConfiguration { - moduleName = "Dokka Module" - - sourceSets { - sourceSet { - sourceRoots = listOf("src/kotlin/Test.kt") - } - } - } - - val source = """ - |/src/kotlin/Test.kt - | - |class Test - | - """.trimIndent() - - val writerPlugin = TestOutputWriterPlugin() - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val searchRecords = writerPlugin.writer.pagesJson() - - assertEquals( - "Test", - searchRecords.find { record -> record.name == "class Test" }?.description ?: "" - ) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/renderers/html/SourceSetDependentHintTest.kt b/plugins/base/src/test/kotlin/renderers/html/SourceSetDependentHintTest.kt deleted file mode 100644 index e3c28984..00000000 --- a/plugins/base/src/test/kotlin/renderers/html/SourceSetDependentHintTest.kt +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package renderers.html - -import org.jetbrains.dokka.Platform -import org.jetbrains.dokka.base.renderers.html.HtmlRenderer -import org.jetbrains.dokka.pages.TextStyle -import renderers.testPage -import testApi.testRunner.defaultSourceSet -import utils.Div -import utils.match -import java.io.File -import kotlin.test.Test - -class SourceSetDependentHintTest : HtmlRenderingOnlyTestBase() { - - private val pl1 = defaultSourceSet.copy( - "pl1", - defaultSourceSet.sourceSetID.copy(sourceSetName = "pl1"), - analysisPlatform = Platform.js, - sourceRoots = setOf(File("pl1")) - ) - private val pl2 = defaultSourceSet.copy( - "pl2", - defaultSourceSet.sourceSetID.copy(sourceSetName = "pl2"), - analysisPlatform = Platform.jvm, - sourceRoots = setOf(File("pl1")) - ) - private val pl3 = defaultSourceSet.copy( - "pl3", - defaultSourceSet.sourceSetID.copy(sourceSetName = "pl3"), - analysisPlatform = Platform.native, - sourceRoots = setOf(File("pl1")) - ) - - @Test - fun platformIndependentCase() { - val page = testPage { - sourceSetDependentHint(sourceSets = setOf(pl1, pl2, pl3), styles = setOf(TextStyle.Block)) { - text("a") - text("b") - text("c") - } - } - - HtmlRenderer(context).render(page) - renderedContent.match(Div(Div(Div("abc")))) - } - - @Test - fun completelyDivergentCase() { - val page = testPage { - sourceSetDependentHint(sourceSets = setOf(pl1, pl2, pl3), styles = setOf(TextStyle.Block)) { - text("a", sourceSets = setOf(pl1)) - text("b", sourceSets = setOf(pl2)) - text("c", sourceSets = setOf(pl3)) - } - } - - HtmlRenderer(context).render(page) - renderedContent.match(Div(Div(Div("a")), Div(Div("b")), Div(Div("c")))) - } - - @Test - fun overlappingCase() { - val page = testPage { - sourceSetDependentHint(sourceSets = setOf(pl1, pl2), styles = setOf(TextStyle.Block)) { - text("a", sourceSets = setOf(pl1)) - text("b", sourceSets = setOf(pl1, pl2)) - text("c", sourceSets = setOf(pl2)) - } - } - - HtmlRenderer(context).render(page) - renderedContent.match(Div(Div(Div("ab")), Div(Div("bc")))) - } - - @Test - fun caseThatCanBeSimplified() { - val page = testPage { - sourceSetDependentHint(sourceSets = setOf(pl1, pl2), styles = setOf(TextStyle.Block)) { - text("a", sourceSets = setOf(pl1, pl2)) - text("b", sourceSets = setOf(pl1)) - text("b", sourceSets = setOf(pl2)) - } - } - - HtmlRenderer(context).render(page) - renderedContent.match(Div(Div(Div("ab")))) - } - - @Test - fun caseWithGroupBreakingSimplification() { - val page = testPage { - sourceSetDependentHint(sourceSets = setOf(pl1, pl2), styles = setOf(TextStyle.Block)) { - group(styles = setOf(TextStyle.Block)) { - text("a", sourceSets = setOf(pl1, pl2)) - text("b", sourceSets = setOf(pl1)) - } - text("b", sourceSets = setOf(pl2)) - } - } - - HtmlRenderer(context).render(page) - renderedContent.match(Div(Div(Div(Div("ab"))), Div(Div(Div("a"), "b")))) - } - - @Test - fun caseWithGroupNotBreakingSimplification() { - val page = testPage { - sourceSetDependentHint(sourceSets = setOf(pl1, pl2)) { - group { - text("a", sourceSets = setOf(pl1, pl2)) - text("b", sourceSets = setOf(pl1)) - } - text("b", sourceSets = setOf(pl2)) - } - } - - HtmlRenderer(context).render(page) - renderedContent.match(Div(Div("ab"))) - } - - @Test - fun partiallyUnifiedCase() { - val page = testPage { - sourceSetDependentHint(sourceSets = setOf(pl1, pl2, pl3), styles = setOf(TextStyle.Block)) { - text("a", sourceSets = setOf(pl1)) - text("a", sourceSets = setOf(pl2)) - text("b", sourceSets = setOf(pl3)) - } - } - - HtmlRenderer(context).render(page) - renderedContent.match(Div(Div(Div("a")), Div(Div("b")))) - } -} diff --git a/plugins/base/src/test/kotlin/renderers/html/SourceSetFilterTest.kt b/plugins/base/src/test/kotlin/renderers/html/SourceSetFilterTest.kt deleted file mode 100644 index b461bfcd..00000000 --- a/plugins/base/src/test/kotlin/renderers/html/SourceSetFilterTest.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 renderers.html - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import signatures.renderedContent -import utils.TestOutputWriterPlugin -import kotlin.test.Test -import kotlin.test.assertEquals - -class SourceSetFilterTest : BaseAbstractTest() { - - @Test // see #3011 - fun `should separate multiple data-filterable attribute values with comma`() { - val configuration = dokkaConfiguration { - moduleName = "Dokka Module" - - sourceSets { - val common = sourceSet { - name = "common" - displayName = "common" - analysisPlatform = "common" - sourceRoots = listOf("src/commonMain/kotlin/testing/Test.kt") - } - sourceSet { - name = "jvm" - displayName = "jvm" - analysisPlatform = "jvm" - dependentSourceSets = setOf(common.value.sourceSetID) - sourceRoots = listOf("src/jvmMain/kotlin/testing/Test.kt") - } - } - } - - val source = """ - |/src/commonMain/kotlin/testing/Test.kt - |package testing - | - |expect open class Test - | - |/src/jvmMain/kotlin/testing/Test.kt - |package testing - | - |actual open class Test - """.trimIndent() - - val writerPlugin = TestOutputWriterPlugin() - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val packagePage = writerPlugin.writer.renderedContent("-dokka -module/testing/index.html") - - val testClassRow = packagePage - .select("div[data-togglable=TYPE]") - .select("div[class=table-row]") - .single() - - assertEquals("Dokka Module/common,Dokka Module/jvm", testClassRow.attr("data-filterable-current")) - assertEquals("Dokka Module/common,Dokka Module/jvm", testClassRow.attr("data-filterable-set")) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/renderers/html/TabbedContentTest.kt b/plugins/base/src/test/kotlin/renderers/html/TabbedContentTest.kt deleted file mode 100644 index 090127fd..00000000 --- a/plugins/base/src/test/kotlin/renderers/html/TabbedContentTest.kt +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package renderers.html - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jsoup.nodes.Element -import signatures.renderedContent -import utils.TestOutputWriterPlugin -import kotlin.test.Test -import kotlin.test.assertEquals - -class TabbedContentTest : BaseAbstractTest() { - - private val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - classpath = listOf(commonStdlibPath!!) - externalDocumentationLinks = listOf(stdlibExternalDocumentationLink) - } - } - } - - private fun Element.getTabbedRow(type: String) = select(".table-row[data-togglable=$type]") - private fun Element.getTabbedTable(type: String) = select("div[data-togglable=$type] .table") - private fun Element.getMainContentDataType() = selectFirst(".main-content")?.attr("data-page-type") - - @Test - fun `should have correct tabbed content type`() { - val source = """ - |/src/main/kotlin/test/Test.kt - |package example - | - |val p = 0 - |fun foo() = 0 - | - | class A(val d: Int = 0) { - | class Success(): Result() - | class Failed(): Result() - | - | fun fn() = 0 - | } - | - | fun A.fn() = 0 - | fun A.fn2() = 0 - | fun A.fn3() = 0 - | val A.p = 0 - | val A.p2 = 0 - """ - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val classContent = writerPlugin.writer.renderedContent("root/example/-a/index.html") - assertEquals(1, classContent.getTabbedTable("CONSTRUCTOR").size) - assertEquals(1, classContent.getTabbedTable("PROPERTY").size) - assertEquals(1, classContent.getTabbedTable("CONSTRUCTOR").size) - assertEquals(1, classContent.getTabbedTable("FUNCTION").size) - assertEquals(1, classContent.getTabbedTable("TYPE").size) - assertEquals(3, classContent.getTabbedRow("EXTENSION_FUNCTION").size) - assertEquals(2, classContent.getTabbedRow("EXTENSION_PROPERTY").size) - assertEquals("classlike", classContent.getMainContentDataType()) - - val packagePage = writerPlugin.writer.renderedContent("root/example/index.html") - assertEquals(1, packagePage.getTabbedTable("TYPE").size) - assertEquals(1, packagePage.getTabbedTable("PROPERTY").size) - assertEquals(1, packagePage.getTabbedTable("FUNCTION").size) - assertEquals(3, packagePage.getTabbedRow("EXTENSION_FUNCTION").size) - assertEquals(2, packagePage.getTabbedRow("EXTENSION_PROPERTY").size) - assertEquals("package", packagePage.getMainContentDataType()) - } - } - } - - @Test - fun `should not have Types-tab where there are not types`() { - val source = """ - |/src/main/kotlin/test/Test.kt - |package example - | - |val p = 0 - |fun foo() = 0 - | - |/src/main/kotlin/test/PackageTwo.kt - |package example2 - | - |class A - """ - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val packagePage = writerPlugin.writer.renderedContent("root/example/index.html") - assertEquals(0, packagePage.select("*[data-togglable=TYPE]").size) - assertEquals(1, packagePage.getTabbedTable("PROPERTY").size) - assertEquals(1, packagePage.getTabbedTable("FUNCTION").size) - - val packagePage2 = writerPlugin.writer.renderedContent("root/example2/index.html") - assertEquals(2, packagePage2.select("*[data-togglable=TYPE]").size) - assertEquals(0, packagePage2.getTabbedTable("PROPERTY").size) - assertEquals(0, packagePage2.getTabbedTable("FUNCTION").size) - } - } - } - - @Test - fun `should have correct order of members and extensions`() { - val source = """ - |/src/main/kotlin/test/Test.kt - |package example - | - |val p = 0 - |fun foo() = 0 - | - |class A(val d: Int = 0) { - | fun fn() = 0 - | fun a() = 0 - | fun g() = 0 - |} - | - | fun A.fn() = 0 - """ - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val classContent = writerPlugin.writer.renderedContent("root/example/-a/index.html") - val funTable = classContent.select("div[data-togglable=FUNCTION] .table") - val orders = - funTable.select(".table-row").map { it.attr("data-togglable") } - assertEquals(listOf("", "", "EXTENSION_FUNCTION", ""), orders) - val names = - funTable.select(".main-subrow .inline-flex a").map { it.text() } - assertEquals(listOf("a", "fn", "fn", "g"), names) - } - } - } - - @Test - fun `should have expected order of content types within a members tab`() { - val source = """ - |/src/main/kotlin/test/Result.kt - |package example - | - |class Result(val d: Int = 0) { - | class Success(): Result() - | - | val isFailed = false - | fun reset() = 0 - | fun String.extension() = 0 - |} - """ - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val classContent = writerPlugin.writer.renderedContent("root/example/-result/index.html") - val tabSectionNames = classContent.select("div .tabs-section-body > div[data-togglable]") - .map { it.attr("data-togglable") } - - val expectedOrder = listOf("CONSTRUCTOR", "TYPE", "PROPERTY", "FUNCTION") - - assertEquals(expectedOrder.size, tabSectionNames.size) - expectedOrder.forEachIndexed { index, element -> - assertEquals(element, tabSectionNames[index]) - } - } - } - } -} diff --git a/plugins/base/src/test/kotlin/renderers/html/TextStylesTest.kt b/plugins/base/src/test/kotlin/renderers/html/TextStylesTest.kt deleted file mode 100644 index 0ca4e245..00000000 --- a/plugins/base/src/test/kotlin/renderers/html/TextStylesTest.kt +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package renderers.html - -import org.jetbrains.dokka.base.renderers.html.HtmlRenderer -import org.jetbrains.dokka.pages.TextStyle -import org.jetbrains.dokka.pages.TokenStyle -import org.jsoup.Jsoup -import org.jsoup.nodes.Element -import renderers.testPage -import utils.* -import kotlin.test.Test -import kotlin.test.assertEquals - -class TextStylesTest : HtmlRenderingOnlyTestBase() { - @Test - fun `should include bold`(){ - val page = testPage { - text("bold text", styles = setOf(TextStyle.Bold)) - } - HtmlRenderer(context).render(page) - renderedContent.match(B("bold text")) - } - - @Test - fun `should include italics`(){ - val page = testPage { - text("italics text", styles = setOf(TextStyle.Italic)) - } - HtmlRenderer(context).render(page) - renderedContent.match(I("italics text")) - } - - @Test - fun `should include strikethrought`(){ - val page = testPage { - text("strike text", styles = setOf(TextStyle.Strikethrough)) - } - HtmlRenderer(context).render(page) - renderedContent.match(STRIKE("strike text")) - } - - @Test - fun `should include token styles`(){ - val page = testPage { - text("keyword", styles = setOf(TokenStyle.Keyword)) - } - HtmlRenderer(context).render(page) - renderedContent.match(Span("keyword")) - val lastChild = renderedContent.children().last() ?: throw IllegalStateException("No element found") - assertEquals(lastChild.attr("class"), "token keyword") - } - - @Test - fun `should include multiple styles at one`(){ - val page = testPage { - text( - "styled text", - styles = setOf( - TextStyle.Strikethrough, - TextStyle.Bold, - TextStyle.Indented, - TextStyle.UnderCoverText, - TextStyle.BreakableAfter - ) - ) - } - HtmlRenderer(context).render(page) - renderedContent.match(STRIKE(B("styled text"))) - //Our dsl swallows nbsp so i manually check for it - files.contents.getValue("test-page.html").contains(" <strike><b>styled text</b></strike>") - } - - @Test - fun `should include blockquote`() { - val page = testPage { - group(styles = setOf(TextStyle.Quotation)) { - text("blockquote text") - } - } - HtmlRenderer(context).render(page) - renderedContent.match(BlockQuote("blockquote text")) - } - - @Test - fun `should include var`() { - val page = testPage { - group(styles = setOf(TextStyle.Var)) { - text("variable") - } - } - HtmlRenderer(context).render(page) - println(renderedContent) - renderedContent.match(Var("variable")) - } - - @Test - fun `should include underlined text`() { - val page = testPage { - group(styles = setOf(TextStyle.Underlined)) { - text("underlined text") - } - } - HtmlRenderer(context).render(page) - println(renderedContent) - renderedContent.match(U("underlined text")) - } - - override val renderedContent: Element - get() = files.contents.getValue("test-page.html").let { Jsoup.parse(it) }.select("#content").single() -} diff --git a/plugins/base/src/test/kotlin/resourceLinks/ResourceLinksTest.kt b/plugins/base/src/test/kotlin/resourceLinks/ResourceLinksTest.kt deleted file mode 100644 index c3302f70..00000000 --- a/plugins/base/src/test/kotlin/resourceLinks/ResourceLinksTest.kt +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package resourceLinks - -import org.jetbrains.dokka.DokkaConfiguration -import org.jetbrains.dokka.PluginConfigurationImpl -import org.jetbrains.dokka.base.DokkaBase -import org.jetbrains.dokka.base.DokkaBaseConfiguration -import org.jetbrains.dokka.base.renderers.html.TEMPLATE_REPLACEMENT -import org.jetbrains.dokka.base.templating.toJsonString -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.pages.RootPageNode -import org.jetbrains.dokka.plugability.DokkaPlugin -import org.jetbrains.dokka.plugability.DokkaPluginApiPreview -import org.jetbrains.dokka.plugability.PluginApiPreviewAcknowledgement -import org.jetbrains.dokka.transformers.pages.PageTransformer -import org.jsoup.Jsoup -import org.jsoup.nodes.TextNode -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.ValueSource -import utils.TestOutputWriterPlugin -import utils.assertContains -import java.io.File -import kotlin.test.Test -import kotlin.test.assertNotNull -import kotlin.test.assertNull -import kotlin.test.assertTrue - -class ResourceLinksTest : BaseAbstractTest() { - class TestResourcesAppenderPlugin(val resources: List<String>) : DokkaPlugin() { - class TestResourcesAppender(val resources: List<String>) : PageTransformer { - override fun invoke(input: RootPageNode) = input.transformContentPagesTree { - it.modified( - embeddedResources = it.embeddedResources + resources - ) - } - } - - val appender by extending { - plugin<DokkaBase>().htmlPreprocessors with TestResourcesAppender(resources) - } - - @OptIn(DokkaPluginApiPreview::class) - override fun pluginApiPreviewAcknowledgement(): PluginApiPreviewAcknowledgement = - PluginApiPreviewAcknowledgement - } - - @Test - fun resourceLinksTest() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin/test/Test.kt") - } - } - } - val absoluteResources = listOf( - "https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css", - "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js" - ) - val relativeResources = listOf( - "test/relativePath.js", - "test/relativePath.css" - ) - - val source = - """ - |/src/main/kotlin/test/Test.kt - |package example - """.trimIndent() - val writerPlugin = TestOutputWriterPlugin() - testInline( - source, - configuration, - pluginOverrides = listOf(TestResourcesAppenderPlugin(absoluteResources + relativeResources), writerPlugin) - ) { - renderingStage = { _, _ -> - Jsoup - .parse(writerPlugin.writer.contents.getValue("root/example.html")) - .head() - .select("link, script") - .let { - absoluteResources.forEach { r -> - assertTrue(it.`is`("[href=$r], [src=$r]")) - } - relativeResources.forEach { r -> - assertTrue(it.`is`("[href=../$r] , [src=../$r]")) - } - } - } - } - } - - @ParameterizedTest - @ValueSource(booleans = [true, false]) - fun resourceCustomPreprocessorTest(isMultiModule: Boolean) { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin/test/Test.kt") - } - } - delayTemplateSubstitution = isMultiModule - pluginsConfigurations = mutableListOf( - PluginConfigurationImpl( - DokkaBase::class.java.canonicalName, - DokkaConfiguration.SerializationFormat.JSON, - toJsonString( - DokkaBaseConfiguration( - customStyleSheets = listOf(File("test/customStyle.css")), - customAssets = listOf(File("test/customImage.svg")) - ) - ) - ) - ) - } - val source = - """ - |/src/main/kotlin/test/Test.kt - |package example - """.trimIndent() - val writerPlugin = TestOutputWriterPlugin() - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - run { - if (isMultiModule) { - assertNull(writerPlugin.writer.contents["images/customImage.svg"]) - assertNull(writerPlugin.writer.contents["styles/customStyle.css"]) - } else { - assertNotNull(writerPlugin.writer.contents["images/customImage.svg"]) - assertNotNull(writerPlugin.writer.contents["styles/customStyle.css"]) - } - if (isMultiModule) { - Jsoup - .parse(writerPlugin.writer.contents.getValue("example.html")) - .head() - .select("link, script") - .let { - listOf("styles/customStyle.css").forEach { r -> - assertTrue(it.`is`("[href=$TEMPLATE_REPLACEMENT$r]")) - } - } - } else { - Jsoup - .parse(writerPlugin.writer.contents.getValue("root/example.html")) - .head() - .select("link, script") - .let { - listOf("styles/customStyle.css").forEach { r -> - assertTrue(it.`is`("[href=../$r], [src=../$r]")) - } - } - } - } - } - } - } - - @Test - fun resourceMultiModuleLinksTest() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin/test/Test.kt") - } - } - delayTemplateSubstitution = false - } - val absoluteResources = listOf( - "https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css", - "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js" - ) - val relativeResources = listOf( - "test/relativePath.js", - "test/relativePath.css" - ) - - val source = - """ - |/src/main/kotlin/test/Test.kt - |package example - """.trimIndent() - val writerPlugin = TestOutputWriterPlugin() - testInline( - source, - configuration, - pluginOverrides = listOf(TestResourcesAppenderPlugin(absoluteResources + relativeResources), writerPlugin) - ) { - renderingStage = { _, _ -> - run { - assertNull(writerPlugin.writer.contents["scripts/relativePath.js"]) - assertNull(writerPlugin.writer.contents["styles/relativePath.js"]) - Jsoup - .parse(writerPlugin.writer.contents.getValue("root/example.html")) - .head() - .select("link, script") - .let { - absoluteResources.forEach { r -> - assertTrue(it.`is`("[href=$r], [src=$r]")) - } - relativeResources.forEach { r -> - assertTrue(it.`is`("[href=../$r] , [src=../$r]")) - } - } - } - } - } - } - - @Test // see #3040; plain text added to <head> can be rendered by engines inside <body> as well - fun `should not add unknown resources as text to the head or body section`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin") - } - } - - pluginsConfigurations = mutableListOf( - PluginConfigurationImpl( - DokkaBase::class.java.canonicalName, - DokkaConfiguration.SerializationFormat.JSON, - toJsonString( - DokkaBaseConfiguration( - customAssets = listOf(File("test/unknown-file.ext")) - ) - ) - ) - ) - } - - val writerPlugin = TestOutputWriterPlugin() - testInline( - """ - |/src/main/kotlin/test/Test.kt - |package test - | - |class Test - """.trimMargin(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val testClassPage = writerPlugin.writer.contents - .getValue("root/test/-test/-test.html") - .let { Jsoup.parse(it) } - - val headChildNodes = testClassPage.head().childNodes() - assertTrue("<head> section should not contain non-blank text nodes") { - headChildNodes.all { it !is TextNode || it.isBlank } - } - - val bodyChildNodes = testClassPage.body().childNodes() - assertTrue("<body> section should not contain non-blank text nodes. Something leaked from head?") { - bodyChildNodes.all { it !is TextNode || it.isBlank } - } - } - } - } - - @Test - fun `should load script as defer if name ending in _deferred`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin") - } - } - } - - val writerPlugin = TestOutputWriterPlugin() - testInline( - """ - |/src/main/kotlin/test/Test.kt - |package test - | - |class Test - """.trimMargin(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val generatedFiles = writerPlugin.writer.contents - - assertContains(generatedFiles.keys, "scripts/symbol-parameters-wrapper_deferred.js") - - val scripts = generatedFiles.getValue("root/test/-test/-test.html").let { Jsoup.parse(it) }.select("script") - val deferredScriptSources = scripts.filter { element -> element.hasAttr("defer") }.map { it.attr("src") } - - // important to check symbol-parameters-wrapper_deferred specifically since it might break some features - assertContains(deferredScriptSources, "../../../scripts/symbol-parameters-wrapper_deferred.js") - } - } - } -} diff --git a/plugins/base/src/test/kotlin/signatures/AbstractRenderingTest.kt b/plugins/base/src/test/kotlin/signatures/AbstractRenderingTest.kt deleted file mode 100644 index 4c4bbc4c..00000000 --- a/plugins/base/src/test/kotlin/signatures/AbstractRenderingTest.kt +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package signatures - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jsoup.Jsoup -import org.jsoup.nodes.Element -import org.jsoup.select.Elements -import utils.TestOutputWriterPlugin -import java.nio.file.Path -import java.nio.file.Paths - -abstract class AbstractRenderingTest : BaseAbstractTest() { - val testDataDir: Path = getTestDataDir("multiplatform/basicMultiplatformTest").toAbsolutePath() - - val configuration = dokkaConfiguration { - moduleName = "example" - sourceSets { - val common = sourceSet { - name = "common" - displayName = "common" - analysisPlatform = "common" - sourceRoots = listOf(Paths.get("$testDataDir/commonMain/kotlin").toString()) - } - val jvmAndJsSecondCommonMain = sourceSet { - name = "jvmAndJsSecondCommonMain" - displayName = "jvmAndJsSecondCommonMain" - analysisPlatform = "common" - dependentSourceSets = setOf(common.value.sourceSetID) - sourceRoots = listOf(Paths.get("$testDataDir/jvmAndJsSecondCommonMain/kotlin").toString()) - } - sourceSet { - name = "js" - displayName = "js" - analysisPlatform = "js" - dependentSourceSets = setOf(common.value.sourceSetID, jvmAndJsSecondCommonMain.value.sourceSetID) - sourceRoots = listOf(Paths.get("$testDataDir/jsMain/kotlin").toString()) - } - sourceSet { - name = "jvm" - displayName = "jvm" - analysisPlatform = "jvm" - dependentSourceSets = setOf(common.value.sourceSetID, jvmAndJsSecondCommonMain.value.sourceSetID) - sourceRoots = listOf(Paths.get("$testDataDir/jvmMain/kotlin").toString()) - } - } - } - - fun TestOutputWriterPlugin.renderedContent(path: String): Element = writer.contents.getValue(path) - .let { Jsoup.parse(it) }.select("#content").single() - - fun TestOutputWriterPlugin.renderedDivergentContent(path: String): Elements = - renderedContent(path).select("div.divergent-group") - - fun TestOutputWriterPlugin.renderedSourceDependentContent(path: String): Elements = - renderedContent(path).select("div.sourceset-dependent-content") - - val Element.brief: String - get() = children().select("p").text() - - val Element.rawBrief: String - get() = children().select("p").html() -} diff --git a/plugins/base/src/test/kotlin/signatures/DivergentSignatureTest.kt b/plugins/base/src/test/kotlin/signatures/DivergentSignatureTest.kt deleted file mode 100644 index 509dd6e7..00000000 --- a/plugins/base/src/test/kotlin/signatures/DivergentSignatureTest.kt +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package signatures - -import utils.TestOutputWriterPlugin -import kotlin.test.Test -import kotlin.test.assertEquals - - -class DivergentSignatureTest : AbstractRenderingTest() { - - @Test - fun `group { common + jvm + js }`() { - - val writerPlugin = TestOutputWriterPlugin() - - testFromData( - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val content = writerPlugin.renderedSourceDependentContent("example/example/-clock/get-time.html") - - assertEquals(3, content.count()) - val sourceSets = listOf("example/common", "example/js", "example/jvm") - sourceSets.forEach { - assertEquals("", content.select("[data-togglable=$it]").single().brief) - } - } - } - } - - @Test - fun `group { common + jvm }, group { js }`() { - - val writerPlugin = TestOutputWriterPlugin() - - testFromData( - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val content = writerPlugin.renderedSourceDependentContent("example/example/-clock/get-times-in-millis.html") - - assertEquals(3, content.count()) - assertEquals("Time in minis", content.select("[data-togglable=example/common]").single().brief) - assertEquals("Time in minis", content.select("[data-togglable=example/jvm]").single().brief) - assertEquals("JS implementation of getTimeInMillis", content.select("[data-togglable=example/js]").single().brief) - } - } - } - - @Test - fun `group { js }, group { jvm }, group { js }`() { - - val writerPlugin = TestOutputWriterPlugin() - - testFromData( - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val content = writerPlugin.renderedSourceDependentContent("example/example/-clock/get-year.html") - assertEquals(3, content.count()) - assertEquals("JVM custom kdoc", content.select("[data-togglable=example/jvm]").single().brief) - assertEquals("JS custom kdoc", content.select("[data-togglable=example/js]").single().brief) - assertEquals("", content.select("[data-togglable=example/common]").single().brief) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/signatures/FunctionalTypeConstructorsSignatureTest.kt b/plugins/base/src/test/kotlin/signatures/FunctionalTypeConstructorsSignatureTest.kt deleted file mode 100644 index 13d1947f..00000000 --- a/plugins/base/src/test/kotlin/signatures/FunctionalTypeConstructorsSignatureTest.kt +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package signatures - -import org.jetbrains.dokka.DokkaConfiguration -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.jdk -import utils.A -import utils.Span -import utils.TestOutputWriterPlugin -import utils.match -import kotlin.test.Ignore -import kotlin.test.Test - -class FunctionalTypeConstructorsSignatureTest : BaseAbstractTest() { - private val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - classpath = listOf(commonStdlibPath!!, jvmStdlibPath!!) - externalDocumentationLinks = listOf( - stdlibExternalDocumentationLink, - DokkaConfiguration.ExternalDocumentationLink.Companion.jdk(8) - ) - } - } - } - - private val jvmConfiguration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - classpath = listOf(jvmStdlibPath ?: throw IllegalStateException("JVM stdlib is not found")) - externalDocumentationLinks = listOf( - stdlibExternalDocumentationLink, - DokkaConfiguration.ExternalDocumentationLink.Companion.jdk(8) - ) - } - } - } - - fun source(signature: String) = - """ - |/src/main/kotlin/test/Test.kt - |package example - | - | $signature - """.trimIndent() - - @Test - fun `kotlin normal function`() { - val source = source("val nF: Function1<Int, String> = { _ -> \"\" }") - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match( - "val ", A("nF"), ": (", A("Int"), ") -> ", A("String"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `kotlin syntactic sugar function`() { - val source = source("val nF: (Int) -> String = { _ -> \"\" }") - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match( - "val ", A("nF"), ": (", A("Int"), ") -> ", A("String"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `kotlin syntactic sugar extension function`() { - val source = source("val nF: Boolean.(Int) -> String = { _ -> \"\" }") - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match( - "val ", A("nF"), ": ", A("Boolean"), ".(", A("Int"), ") -> ", A("String"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `kotlin syntactic sugar function with param name`() { - val source = source("val nF: (param: Int) -> String = { _ -> \"\" }") - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match( - "val ", A("nF"), ": (param: ", A("Int"), ") -> ", A("String"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `kotlin syntactic sugar function with param name of generic and functional type`() { - val source = source(""" - | @Target(AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.TYPE) - | @MustBeDocumented - | annotation class Fancy - | - | fun <T> f(): (param1: T, param2: @Fancy ()->Unit) -> String " - """.trimIndent()) - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, configuration, pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/index.html").lastSignature().match( - "fun <", A("T"), "> ", - A("f"), "(): (param1:", A("T"), - ", param2: ", Span("@", A("Fancy")), " () -> ", A("Unit"), - ") -> ", A("String"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - @Ignore // Add coroutines on classpath and get proper import - @Test - fun `kotlin normal suspendable function`() { - val source = source("val nF: SuspendFunction1<Int, String> = { _ -> \"\" }") - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match( - "val ", A("nF"), ": suspend (", A("Int"), ") -> ", A("String"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `kotlin syntactic sugar suspendable function`() { - val source = source("val nF: suspend (Int) -> String = { _ -> \"\" }") - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match( - "val ", A("nF"), ": suspend (", A("Int"), ") -> ", A("String"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `kotlin syntactic sugar suspendable extension function`() { - val source = source("val nF: suspend Boolean.(Int) -> String = { _ -> \"\" }") - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match( - "val ", A("nF"), ": suspend ", A("Boolean"), ".(", A("Int"), ") -> ", A("String"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `kotlin syntactic sugar suspendable function with param name`() { - val source = source("val nF: suspend (param: Int) -> String = { _ -> \"\" }") - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match( - "val ", A("nF"), ": suspend (param: ", A("Int"), ") -> ", A("String"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `kotlin syntactic sugar suspendable fancy function with param name`() { - val source = - source("val nF: suspend (param1: suspend Boolean.(param2: List<Int>) -> Boolean) -> String = { _ -> \"\" }") - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match( - "val ", - A("nF"), - ": suspend (param1: suspend", - A("Boolean"), - ".(param2: ", - A("List"), - "<", - A("Int"), - ">) -> ", - A("Boolean"), - ") -> ", - A("String"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `java with java function`() { - val source = """ - |/src/main/kotlin/test/JavaClass.java - |package example - | - |public class JavaClass { - | public java.util.function.Function<Integer, String> javaFunction = null; - |} - """.trimIndent() - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/-java-class/index.html").lastSignature().match( - "open var ", A("javaFunction"), ": (", A("Integer"), ") -> ", A("String"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `java with kotlin function`() { - val source = """ - |/src/main/kotlin/test/JavaClass.java - |package example - | - |public class JavaClass { - | public kotlin.jvm.functions.Function1<Integer, String> kotlinFunction = null; - |} - """.trimIndent() - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - jvmConfiguration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/-java-class/index.html").lastSignature().match( - "open var ", A("kotlinFunction"), ": (", A("Integer"), ") -> ", A("String"), - ignoreSpanWithTokenStyle = true - ) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/signatures/InheritedAccessorsSignatureTest.kt b/plugins/base/src/test/kotlin/signatures/InheritedAccessorsSignatureTest.kt deleted file mode 100644 index b5e2a9c3..00000000 --- a/plugins/base/src/test/kotlin/signatures/InheritedAccessorsSignatureTest.kt +++ /dev/null @@ -1,461 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package signatures - -import org.jetbrains.dokka.DokkaConfiguration -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import utils.A -import utils.Span -import utils.TestOutputWriterPlugin -import utils.match -import utils.OnlyDescriptors -import kotlin.test.Test -import kotlin.test.assertEquals - -class InheritedAccessorsSignatureTest : BaseAbstractTest() { - - private val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - classpath = listOf( - commonStdlibPath ?: throw IllegalStateException("Common stdlib is not found"), - jvmStdlibPath ?: throw IllegalStateException("JVM stdlib is not found") - ) - externalDocumentationLinks = listOf(stdlibExternalDocumentationLink) - } - } - } - - @OnlyDescriptors("'var' expected but found: 'open var'") - @Test - fun `should collapse accessor functions inherited from java into the property`() { - val writerPlugin = TestOutputWriterPlugin() - testInline( - """ - |/src/test/A.java - |package test; - |public class A { - | private int a = 1; - | public int getA() { return a; } - | public void setA(int a) { this.a = a; } - |} - | - |/src/test/B.kt - |package test - |class B : A {} - """.trimIndent(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/test/-b/index.html").let { kotlinClassContent -> - val signatures = kotlinClassContent.signature().toList() - assertEquals( - 3, signatures.size, - "Expected 3 signatures: class signature, constructor and property" - ) - - val property = signatures[2] - property.match( - "var ", A("a"), ":", A("Int"), - ignoreSpanWithTokenStyle = true - ) - } - - writerPlugin.writer.renderedContent("root/test/-a/index.html").let { javaClassContent -> - val signatures = javaClassContent.signature().toList() - assertEquals( - 3, signatures.size, - "Expected 3 signatures: class signature, default constructor and property" - ) - - val property = signatures[2] - property.match( - "open var ", A("a"), ":", A("Int"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - } - - @OnlyDescriptors("'var' expected but found: 'open var'") - @Test - fun `should render as val if inherited java property has no setter`() { - val writerPlugin = TestOutputWriterPlugin() - testInline( - """ - |/src/test/A.java - |package test; - |public class A { - | private int a = 1; - | public int getA() { return a; } - |} - | - |/src/test/B.kt - |package test - |class B : A {} - """.trimIndent(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/test/-b/index.html").let { kotlinClassContent -> - val signatures = kotlinClassContent.signature().toList() - assertEquals(3, signatures.size, "Expected 3 signatures: class signature, constructor and property") - - val property = signatures[2] - property.match( - "val ", A("a"), ":", A("Int"), - ignoreSpanWithTokenStyle = true - ) - } - - writerPlugin.writer.renderedContent("root/test/-a/index.html").let { javaClassContent -> - val signatures = javaClassContent.signature().toList() - assertEquals( - 3, - signatures.size, - "Expected 3 signatures: class signature, default constructor and property" - ) - - val property = signatures[2] - property.match( - "open val ", A("a"), ":", A("Int"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - } - - @Test - fun `should keep inherited java setter as a regular function due to inaccessible property`() { - val writerPlugin = TestOutputWriterPlugin() - testInline( - """ - |/src/test/A.java - |package test; - |public class A { - | private int a = 1; - | public void setA(int a) { this.a = a; } - |} - | - |/src/test/B.kt - |package test - |class B : A {} - """.trimIndent(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/test/-b/index.html").let { kotlinClassContent -> - val signatures = kotlinClassContent.signature().toList() - assertEquals(3, signatures.size, "Expected 3 signatures: class signature, constructor and setter") - - val setterFunction = signatures[2] - setterFunction.match( - "open fun ", A("setA"), "(", Parameters( - Parameter("a: ", A("Int")) - ), ")", - ignoreSpanWithTokenStyle = true - ) - } - - writerPlugin.writer.renderedContent("root/test/-a/index.html").let { javaClassContent -> - val signatures = javaClassContent.signature().toList() - assertEquals( - 3, - signatures.size, - "Expected 3 signatures: class signature, default constructor and setter" - ) - - val setterFunction = signatures[2] - setterFunction.match( - "open fun ", A("setA"), "(", Parameters( - Parameter("a: ", A("Int")) - ), ")", - ignoreSpanWithTokenStyle = true - ) - } - } - } - } - - @OnlyDescriptors("'var' expected but found: 'open var'") - @Test - fun `should keep inherited java accessor lookalikes if underlying function is public`() { - val writerPlugin = TestOutputWriterPlugin() - testInline( - """ - |/src/test/A.java - |package test; - |public class A { - | public int a = 1; - | public int getA() { return a; } - | public void setA(int a) { this.a = a; } - |} - | - |/src/test/B.kt - |package test - |class B : A {} - """.trimIndent(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val signatures = writerPlugin.writer.renderedContent("root/test/-b/index.html").signature().toList() - assertEquals( - 5, signatures.size, - "Expected 5 signatures: class signature, constructor, property and two accessor lookalikes" - ) - - val getterLookalikeFunction = signatures[3] - getterLookalikeFunction.match( - "open fun ", A("getA"), "():", A("Int"), - ignoreSpanWithTokenStyle = true - ) - - val setterLookalikeFunction = signatures[4] - setterLookalikeFunction.match( - "open fun ", A("setA"), "(", Parameters( - Parameter("a: ", A("Int")) - ), ")", - ignoreSpanWithTokenStyle = true - ) - - val property = signatures[2] - property.match( - "var ", A("a"), ":", A("Int"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `should keep kotlin property with no accessors when java inherits kotlin a var`() { - val writerPlugin = TestOutputWriterPlugin() - testInline( - """ - |/src/test/JavaClass.java - |package test; - |public class JavaClass extends KotlinClass {} - | - |/src/test/KotlinClass.kt - |package test - |open class KotlinClass { - | var variable: String = "s" - |} - """.trimIndent(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/test/-java-class/index.html").let { kotlinClassContent -> - val signatures = kotlinClassContent.signature().toList() - assertEquals( - 3, - signatures.size, - "Expected to find 3 signatures: class, default constructor and property" - ) - - val property = signatures[2] - property.match( - "open var ", A("variable"), ": ", Span("String"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - } - - @Test - fun `kotlin property with compute get and set`() { - val writerPlugin = TestOutputWriterPlugin() - testInline( - """ - |/src/test/JavaClass.java - |package test; - |public class JavaClass extends KotlinClass {} - | - |/src/test/KotlinClass.kt - |package test - |open class KotlinClass { - | var variable: String - | get() = "asd" - | set(value) {} - |} - """.trimIndent(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/test/-kotlin-class/index.html").let { kotlinClassContent -> - val signatures = kotlinClassContent.signature().toList() - assertEquals(3, signatures.size, "Expected to find 3 signatures: class, constructor and property") - - val property = signatures[2] - property.match( - "var ", A("variable"), ": ", A("String"), - ignoreSpanWithTokenStyle = true - ) - } - - // it's actually unclear how it should react in this situation. It should most likely not - // break the abstraction and display it as a simple variable just like can be seen from Kotlin, - // test added to control changes - writerPlugin.writer.renderedContent("root/test/-java-class/index.html").let { javaClassContent -> - val signatures = javaClassContent.signature().toList() - assertEquals( - 4, - signatures.size, - "Expected to find 4 signatures: class, default constructor and two accessors" - ) - - val getter = signatures[2] - getter.match( - "fun ", A("getVariable"), "(): ", Span("String"), - ignoreSpanWithTokenStyle = true - ) - - val setter = signatures[3] - setter.match( - "fun ", A("setVariable"), "(", Parameters( - Parameter("value: ", Span("String")) - ), ")", - ignoreSpanWithTokenStyle = true - ) - } - } - } - } - - @OnlyDescriptors("'var' expected but found: 'open var'") - @Test - fun `inherited property should inherit getter's visibility`() { - val configWithProtectedVisibility = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - classpath = listOf( - commonStdlibPath ?: throw IllegalStateException("Common stdlib is not found"), - jvmStdlibPath ?: throw IllegalStateException("JVM stdlib is not found") - ) - externalDocumentationLinks = listOf(stdlibExternalDocumentationLink) - documentedVisibilities = setOf( - DokkaConfiguration.Visibility.PUBLIC, - DokkaConfiguration.Visibility.PROTECTED - ) - } - } - } - - val writerPlugin = TestOutputWriterPlugin() - testInline( - """ - |/src/test/JavaClass.java - |package test; - |public class JavaClass { - | private int protectedGetterAndProtectedSetter = 0; - | - | protected int getProtectedGetterAndProtectedSetter() { - | return protectedGetterAndProtectedSetter; - | } - | - | protected void setProtectedGetterAndProtectedSetter(int protectedGetterAndProtectedSetter) { - | this.protectedGetterAndProtectedSetter = protectedGetterAndProtectedSetter; - | } - |} - | - |/src/test/KotlinClass.kt - |package test - |open class KotlinClass : JavaClass() { } - """.trimIndent(), - configWithProtectedVisibility, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/test/-kotlin-class/index.html").let { kotlinClassContent -> - val signatures = kotlinClassContent.signature().toList() - assertEquals(3, signatures.size, "Expected 3 signatures: class signature, constructor and property") - - val property = signatures[2] - property.match( - "protected var ", A("protectedGetterAndProtectedSetter"), ":", A("Int"), - ignoreSpanWithTokenStyle = true - ) - } - - writerPlugin.writer.renderedContent("root/test/-java-class/index.html").let { javaClassContent -> - val signatures = javaClassContent.signature().toList() - assertEquals( - 3, - signatures.size, - "Expected 3 signatures: class signature, default constructor and property" - ) - - val property = signatures[2] - property.match( - "protected open var ", A("protectedGetterAndProtectedSetter"), ":", A("Int"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - } - - @OnlyDescriptors("'var' expected but found: 'open var'") - @Test - fun `should resolve protected java property as protected`() { - val configWithProtectedVisibility = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - classpath = listOf( - commonStdlibPath ?: throw IllegalStateException("Common stdlib is not found"), - jvmStdlibPath ?: throw IllegalStateException("JVM stdlib is not found") - ) - externalDocumentationLinks = listOf(stdlibExternalDocumentationLink) - documentedVisibilities = setOf( - DokkaConfiguration.Visibility.PUBLIC, - DokkaConfiguration.Visibility.PROTECTED - ) - } - } - } - - val writerPlugin = TestOutputWriterPlugin() - testInline( - """ - |/src/test/JavaClass.java - |package test; - |public class JavaClass { - | protected int protectedProperty = 0; - |} - | - |/src/test/KotlinClass.kt - |package test - |open class KotlinClass : JavaClass() { } - """.trimIndent(), - configWithProtectedVisibility, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/test/-kotlin-class/index.html").let { kotlinClassContent -> - val signatures = kotlinClassContent.signature().toList() - assertEquals(3, signatures.size, "Expected 2 signatures: class signature, constructor and property") - - val property = signatures[2] - property.match( - "protected var ", A("protectedProperty"), ":", A("Int"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - } -} diff --git a/plugins/base/src/test/kotlin/signatures/ObviousTypeSkippingTest.kt b/plugins/base/src/test/kotlin/signatures/ObviousTypeSkippingTest.kt deleted file mode 100644 index 71a0851b..00000000 --- a/plugins/base/src/test/kotlin/signatures/ObviousTypeSkippingTest.kt +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package signatures - -import matchers.content.assertNode -import matchers.content.hasExactText -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.model.firstMemberOfType -import org.jetbrains.dokka.pages.* -import org.jetbrains.dokka.testApi.logger.TestLogger -import org.jetbrains.dokka.utilities.DokkaConsoleLogger -import org.jetbrains.dokka.utilities.LoggingLevel -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.MethodSource -import kotlin.reflect.KClass - -class ObviousTypeSkippingTest : BaseAbstractTest( - logger = TestLogger(DokkaConsoleLogger(LoggingLevel.WARN)) -) { - - private fun source(signature: String) = - """ - |/src/test.kt - |package example - | - | $signature - """.trimIndent() - - private val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src") - classpath = listOfNotNull(jvmStdlibPath) - } - } - } - - companion object TestDataSources { - @JvmStatic - fun `run tests for obvious types omitting`() = listOf( - forFunction("fun underTest(): Int = 5", "fun underTest(): Int"), - forFunction("fun underTest() = 5", "fun underTest(): Int"), - forFunction("fun underTest() {}", "fun underTest()"), - forFunction("fun underTest() = println(6)", "fun underTest()"), - forFunction("fun underTest(): Unit = println(6)", "fun underTest()"), - forFunction("fun underTest(): Unit? = if (true) println(6) else null", "fun underTest(): Unit?"), - forFunction("fun underTest() = if (true) println(6) else null", "fun underTest(): Unit?"), - forFunction("fun underTest(): Any = if (true) 7 else true", "fun underTest(): Any"), - forFunction("fun underTest() = if (true) 7 else true", "fun underTest(): Any"), - forFunction("fun underTest(): Any? = if (true) 7 else (null as String?)", "fun underTest(): Any?"), - forFunction("fun underTest() = if (true) 7 else (null as String?)", "fun underTest(): Any?"), - forFunction("fun underTest(arg: Int) {}", "fun underTest(arg: Int)"), - forFunction("fun underTest(arg: Unit) {}", "fun underTest(arg: Unit)"), - forFunction("fun <T: Iterable<Any>> underTest(arg: T) {}", "fun <T : Iterable<Any>> underTest(arg: T)"), - forFunction("fun <T: Iterable<Any?>> underTest(arg: T) {}", "fun <T : Iterable<Any?>> underTest(arg: T)"), - forFunction("fun <T> underTest(arg: T) {}", "fun <T> underTest(arg: T)"), - forFunction("fun <T: Any> underTest(arg: T) {}", "fun <T : Any> underTest(arg: T)"), - forFunction("fun <T: Any?> underTest(arg: T) {}", "fun <T> underTest(arg: T)"), - forProperty("val underTest: Int = 5", "val underTest: Int = 5"), - forProperty("val underTest = 5", "val underTest: Int = 5"), - forProperty("val underTest: Unit = println(5)", "val underTest: Unit"), - forProperty("val underTest = println(5)", "val underTest: Unit"), - forProperty("val underTest: Unit? = if (true) println(5) else null", "val underTest: Unit?"), - forProperty("val underTest = if (true) println(5) else null", "val underTest: Unit?"), - forProperty("val underTest: Any = if (true) println(5) else 5", "val underTest: Any"), - forProperty("val underTest = if (true) println(5) else 5", "val underTest: Any"), - forExtension("fun <T: Iterable<Any>> T.underTest() {}", "fun <T : Iterable<Any>> T.underTest()"), - forExtension("fun <T: Iterable<Any?>> T.underTest() {}", "fun <T : Iterable<Any?>> T.underTest()"), - forExtension("fun <T: Iterable<Any?>?> T.underTest() {}", "fun <T : Iterable<Any?>?> T.underTest()"), - forExtension("fun <T: Any> T.underTest() {}", "fun <T : Any> T.underTest()"), - forExtension("fun <T: Any?> T.underTest() {}", "fun <T> T.underTest()"), - forExtension("fun <T> T.underTest() {}", "fun <T> T.underTest()"), - forClass("class Testable<T: Any>", "class Testable<T : Any>"), - forClass("class Testable<T: Any?>", "class Testable<T>"), - forClass("class Testable<T: Any?>(t: T)", "class Testable<T>(t: T)"), - forClass("class Testable<T>", "class Testable<T>"), - forClass("class Testable(butWhy: Unit)", "class Testable(butWhy: Unit)"), - forMethod("class Testable { fun underTest(): Int = 5 }", "fun underTest(): Int"), - forMethod("class Testable { fun underTest() = 5 }", "fun underTest(): Int"), - forMethod("class Testable { fun underTest() {} }", "fun underTest()"), - forMethod("class Testable { fun underTest() = println(6) }", "fun underTest()"), - forMethod("class Testable { fun underTest(): Unit = println(6) }", "fun underTest()"), - forMethod( - "class Testable { fun underTest(): Unit? = if (true) println(6) else null }", - "fun underTest(): Unit?" - ), - forClassProperty("class Testable { val underTest: Unit = println(5) }", "val underTest: Unit"), - forClassProperty("class Testable { val underTest = println(5) }", "val underTest: Unit"), - forClassProperty( - "class Testable { val underTest: Unit? = if (true) println(5) else null }", - "val underTest: Unit?" - ), - forClassProperty( - "class Testable { val underTest = if (true) println(5) else null }", - "val underTest: Unit?" - ), - forClassProperty( - "class Testable { val underTest: Any = if (true) println(5) else 5 }", - "val underTest: Any" - ), - forClassProperty("class Testable { val underTest = if (true) println(5) else 5 }", "val underTest: Any"), - ) - } - - @ParameterizedTest(name = "{0}") - @MethodSource - fun `run tests for obvious types omitting`(testData: TestData) { - val (codeFragment, expectedSignature, placesToTest) = testData - testInline( - query = source(codeFragment), - configuration = configuration - ) { - pagesTransformationStage = { root -> - placesToTest.forEach { place -> - try { - when (place) { - is OnOwnPage -> - root.firstMemberOfType<ContentPage> { it.name == place.name }.content - .firstMemberOfType<ContentGroup> { it.dci.kind == ContentKind.Symbol } - .assertNode { hasExactText(expectedSignature) } - is OnParentPage -> - root.firstMemberOfType<ContentPage> { - place.pageType.isInstance(it) && (place.parentName.isNullOrBlank() || place.parentName == it.name) - } - .content - .firstMemberOfType<ContentGroup> { - it.dci.kind == place.section && (place.selfName.isNullOrBlank() || - it.dci.dri.toString().contains(place.selfName)) - } - .firstMemberOfType<ContentGroup> { it.dci.kind == ContentKind.Symbol } - .assertNode { hasExactText(expectedSignature) } - } - } catch (e: Throwable) { - logger.warn("$testData") // Because gradle has serious problem rendering custom test names - throw e - } - } - } - } - } - -} - -sealed class Place -data class OnOwnPage(val name: String) : Place() -data class OnParentPage( - val pageType: KClass<out ContentPage>, - val section: Kind, - val parentName: String? = null, - val selfName: String? = null -) : Place() - -data class TestData( - val codeFragment: String, - val expectedSignature: String, - val placesToTest: Iterable<Place> -) { - constructor(codeFragment: String, expectedSignature: String, vararg placesToTest: Place) - : this(codeFragment, expectedSignature, placesToTest.asIterable()) - - override fun toString() = "[code = \"$codeFragment\"]" -} - -private fun forFunction(codeFragment: String, expectedSignature: String, functionName: String = "underTest") = - TestData( - codeFragment, - expectedSignature, - OnParentPage(PackagePageNode::class, ContentKind.Functions), - OnOwnPage(functionName) - ) - -private fun forExtension(codeFragment: String, expectedSignature: String, functionName: String = "underTest") = - TestData( - codeFragment, - expectedSignature, - OnParentPage(PackagePageNode::class, ContentKind.Extensions), - OnOwnPage(functionName) - ) -private fun forMethod( - codeFragment: String, - expectedSignature: String, - functionName: String = "underTest", - className: String = "Testable" -) = - TestData( - codeFragment, - expectedSignature, - OnParentPage(ClasslikePageNode::class, ContentKind.Functions, className, functionName), - OnOwnPage(functionName) - ) - -private fun forProperty(codeFragment: String, expectedSignature: String) = - TestData(codeFragment, expectedSignature, OnParentPage(PackagePageNode::class, ContentKind.Properties)) - -private fun forClassProperty(codeFragment: String, expectedSignature: String, className: String = "Testable") = - TestData(codeFragment, expectedSignature, OnParentPage(ClasslikePageNode::class, ContentKind.Properties, className)) - -private fun forClass(codeFragment: String, expectedSignature: String, className: String = "Testable") = - TestData( - codeFragment, - expectedSignature, - OnParentPage(PackagePageNode::class, ContentKind.Classlikes), - OnOwnPage(className) - ) diff --git a/plugins/base/src/test/kotlin/signatures/RawHtmlRenderingTest.kt b/plugins/base/src/test/kotlin/signatures/RawHtmlRenderingTest.kt deleted file mode 100644 index c79d70fd..00000000 --- a/plugins/base/src/test/kotlin/signatures/RawHtmlRenderingTest.kt +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package signatures - -import org.jsoup.Jsoup -import utils.TestOutputWriterPlugin -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertTrue - -class RawHtmlRenderingTest: AbstractRenderingTest() { - @Test - fun `work with raw html with inline comment`() { - val writerPlugin = TestOutputWriterPlugin() - - testFromData( - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val content = writerPlugin.renderedSourceDependentContent("example/example/-html-test/test.html") - assertEquals(1, content.count()) - assertEquals(content.select("[data-togglable=example/jvm]").single().rawBrief,"This is an example <!-- not visible --> of html") - - val indexContent = writerPlugin.writer.contents.getValue("example/example/-html-test/index.html") - .let { Jsoup.parse(it) } - assertTrue(indexContent.select("div.brief").any { it.html().contains("This is an example <!-- not visible --> of html")}) - } - } - } - - @Test - fun `work with raw html`() { - val writerPlugin = TestOutputWriterPlugin() - - testFromData( - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - //Module page - val content = writerPlugin.renderedContent("example/example/index.html").select("div.brief") - assertTrue(content.size > 0) - assertTrue(content.any { it.html().contains("<!-- this shouldn't be visible -->")}) - } - } - } - - @Test - fun `work with raw, visible html`() { - val writerPlugin = TestOutputWriterPlugin() - - testFromData( - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val content = writerPlugin.renderedSourceDependentContent("example/example/-html-test/test-p.html") - assertEquals(1, content.count()) - assertEquals(content.select("[data-togglable=example/jvm]").single().rawBrief, "This is an <b> documentation </b>") - - val indexContent = writerPlugin.writer.contents.getValue("example/example/-html-test/index.html") - .let { Jsoup.parse(it) } - assertTrue(indexContent.select("div.brief").any { it.html().contains("This is an <b> documentation </b>")}) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/signatures/SignatureTest.kt b/plugins/base/src/test/kotlin/signatures/SignatureTest.kt deleted file mode 100644 index 80a043fe..00000000 --- a/plugins/base/src/test/kotlin/signatures/SignatureTest.kt +++ /dev/null @@ -1,1035 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package signatures - -import org.jetbrains.dokka.DokkaSourceSetID -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.model.DFunction -import org.jetbrains.dokka.model.DefinitelyNonNullable -import org.jetbrains.dokka.model.dfs -import utils.* -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertTrue - -class SignatureTest : BaseAbstractTest() { - private val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - classpath = listOf( - commonStdlibPath ?: throw IllegalStateException("Common stdlib is not found"), - jvmStdlibPath ?: throw IllegalStateException("JVM stdlib is not found") - ) - externalDocumentationLinks = listOf(stdlibExternalDocumentationLink) - } - } - } - - private val mppConfiguration = dokkaConfiguration { - moduleName = "test" - sourceSets { - sourceSet { - name = "common" - sourceRoots = listOf("src/main/kotlin/common/Test.kt") - classpath = listOf(commonStdlibPath!!) - externalDocumentationLinks = listOf(stdlibExternalDocumentationLink) - } - sourceSet { - name = "jvm" - dependentSourceSets = setOf(DokkaSourceSetID("test", "common")) - sourceRoots = listOf("src/main/kotlin/jvm/Test.kt") - classpath = listOf( - commonStdlibPath ?: throw IllegalStateException("Common stdlib is not found"),) - externalDocumentationLinks = listOf(stdlibExternalDocumentationLink) - } - } - } - - fun source(signature: String) = - """ - |/src/main/kotlin/test/Test.kt - |package example - | - | $signature - """.trimIndent() - - @Test - fun `fun`() { - val source = source("fun simpleFun(): String = \"Celebrimbor\"") - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/simple-fun.html").firstSignature().match( - "fun ", A("simpleFun"), "(): ", A("String"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `open fun`() { - val source = source("open fun simpleFun(): String = \"Celebrimbor\"") - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/simple-fun.html").firstSignature().match( - "open fun ", A("simpleFun"), "(): ", A("String"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `open suspend fun`() { - val source = source("open suspend fun simpleFun(): String = \"Celebrimbor\"") - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/simple-fun.html").firstSignature().match( - "open suspend fun ", A("simpleFun"), "(): ", A("String"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `fun with params`() { - val source = source("fun simpleFun(a: Int, b: Boolean, c: Any): String = \"Celebrimbor\"") - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/simple-fun.html").firstSignature().match( - "fun ", A("simpleFun"), "(", Parameters( - Parameter("a: ", A("Int"), ","), - Parameter("b: ", A("Boolean"), ","), - Parameter("c: ", A("Any")), - ), "): ", A("String"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `fun with function param`() { - val source = source("fun simpleFun(a: (Int) -> String): String = \"Celebrimbor\"") - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/simple-fun.html").firstSignature().match( - "fun ", A("simpleFun"), "(", Parameters( - Parameter("a: (", A("Int"), ") -> ", A("String")), - ),"): ", A("String"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `fun with generic param`() { - val source = source("fun <T> simpleFun(): T = \"Celebrimbor\" as T") - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/simple-fun.html").firstSignature().match( - "fun <", A("T"), "> ", A("simpleFun"), "(): ", - A("T"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `fun with generic bounded param`() { - val source = source("fun <T : String> simpleFun(): T = \"Celebrimbor\" as T") - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/simple-fun.html").firstSignature().match( - "fun <", A("T"), " : ", A("String"), "> ", A("simpleFun"), - "(): ", A("T"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `fun with definitely non-nullable types`() { - val source = source("fun <T> elvisLike(x: T, y: T & Any): T & Any = x ?: y") - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - documentablesTransformationStage = { - val fn = (it.dfs { it.name == "elvisLike" } as? DFunction).assertNotNull("Function elvisLike") - - assertTrue(fn.type is DefinitelyNonNullable) - assertTrue(fn.parameters[1].type is DefinitelyNonNullable) - } - renderingStage = { _, _ -> - val signature = writerPlugin.writer.renderedContent("root/example/elvis-like.html") - assertEquals(2, signature.select("a[href=\"https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-any/index.html\"]").size) - signature.firstSignature().match( - "fun <", A("T"), "> ", A("elvisLike"), - "(", - Span( - Span("x: ", A("T"), ", "), - Span("y: ", A("T"), " & ", A("Any")) - ), - "): ", A("T"), " & ", A("Any"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `fun with keywords, params and generic bound`() { - val source = source("inline suspend fun <T : String> simpleFun(a: Int, b: String): T = \"Celebrimbor\" as T") - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/simple-fun.html").firstSignature().match( - "inline suspend fun <", A("T"), " : ", A("String"), "> ", A("simpleFun"), "(", Parameters( - Parameter("a: ", A("Int"), ","), - Parameter("b: ", A("String")), - ), "): ", A("T"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `fun with vararg`() { - val source = source("fun simpleFun(vararg params: Int): Unit") - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/simple-fun.html").firstSignature().match( - "fun ", A("simpleFun"), "(", Parameters( - Parameter("vararg params: ", A("Int")), - ), ")", - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `class with no supertype`() { - val source = source("class SimpleClass") - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/-simple-class/index.html").firstSignature().match( - "class ", A("SimpleClass"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `class with generic supertype`() { - val source = source("class InheritingClassFromGenericType<T : Number, R : CharSequence> : Comparable<T>, Collection<R>") - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/-inheriting-class-from-generic-type/index.html").firstSignature().match( - "class ", A("InheritingClassFromGenericType"), " <", A("T"), " : ", A("Number"), ", ", A("R"), " : ", A("CharSequence"), - "> : ", A("Comparable"), "<", A("T"), "> , ", A("Collection"), "<", A("R"), ">", - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `functional interface`() { - val source = source("fun interface KRunnable") - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/-k-runnable/index.html").firstSignature().match( - "fun interface ", A("KRunnable"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `fun with annotation`() { - val source = """ - |/src/main/kotlin/test/Test.kt - |package example - | - | @MustBeDocumented() - | @Target(AnnotationTarget.FUNCTION) - | annotation class Marking - | - | @Marking() - | fun simpleFun(): String = "Celebrimbor" - """.trimIndent() - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/simple-fun.html").firstSignature().match( - Div( - Div("@", A("Marking")) - ), - "fun ", A("simpleFun"), - "(): ", A("String"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `property with annotation`() { - val source = """ - |/src/main/kotlin/test/Test.kt - |package example - | - | @MustBeDocumented() - | @Target(AnnotationTarget.FUNCTION) - | annotation class Marking - | - | @get:Marking() - | @set:Marking() - | var str: String - """.trimIndent() - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/str.html").firstSignature().match( - Div( - Div("@get:", A("Marking")), - Div("@set:", A("Marking")) - ), - "var ", A("str"), - ": ", A("String"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `fun with two annotations`() { - val source = """ - |/src/main/kotlin/test/Test.kt - |package example - | - | @MustBeDocumented() - | @Target(AnnotationTarget.FUNCTION) - | annotation class Marking(val msg: String) - | - | @MustBeDocumented() - | @Target(AnnotationTarget.FUNCTION) - | annotation class Marking2(val int: Int) - | - | @Marking("Nenya") - | @Marking2(1) - | fun simpleFun(): String = "Celebrimbor" - """.trimIndent() - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/simple-fun.html") - .firstSignature() - .match( - Div( - Div("@", A("Marking"), "(", Span("msg = ", Span("\"Nenya\"")), Wbr, ")"), - Div("@", A("Marking2"), "(", Span("int = ", Span("1")), Wbr, ")") - ), - "fun ", A("simpleFun"), - "(): ", A("String"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `fun with annotation with array`() { - val source = """ - |/src/main/kotlin/test/Test.kt - |package example - | - | @MustBeDocumented() - | @Target(AnnotationTarget.FUNCTION) - | annotation class Marking(val msg: Array<String>) - | - | @Marking(["Nenya", "Vilya", "Narya"]) - | @Marking2(1) - | fun simpleFun(): String = "Celebrimbor" - """.trimIndent() - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/simple-fun.html").firstSignature().match( - Div( - Div( - "@", A("Marking"), "(", Span( - "msg = [", - Span(Span("\"Nenya\""), ", "), Wbr, - Span(Span("\"Vilya\""), ", "), Wbr, - Span(Span("\"Narya\"")), Wbr, "]" - ), Wbr, ")" - ) - ), - "fun ", A("simpleFun"), - "(): ", A("String"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `actual fun`() { - val writerPlugin = TestOutputWriterPlugin() - - testInline( - """ - |/src/main/kotlin/common/Test.kt - |package example - | - |expect fun simpleFun(): String - | - |/src/main/kotlin/jvm/Test.kt - |package example - | - |actual fun simpleFun(): String = "Celebrimbor" - | - """.trimMargin(), - mppConfiguration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val signatures = writerPlugin.writer.renderedContent("test/example/simple-fun.html").signature().toList() - - signatures[0].match( - "expect fun ", A("simpleFun"), - "(): ", A("String"), - ignoreSpanWithTokenStyle = true - ) - signatures[1].match( - "actual fun ", A("simpleFun"), - "(): ", A("String"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `actual property with a default value`() { - val writerPlugin = TestOutputWriterPlugin() - - testInline( - """ - |/src/main/kotlin/common/Test.kt - |package example - | - |expect val prop: Int - | - |/src/main/kotlin/jvm/Test.kt - |package example - | - |actual val prop: Int = 2 - | - """.trimMargin(), - mppConfiguration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val signatures = writerPlugin.writer.renderedContent("test/example/prop.html").signature().toList() - - signatures[0].match( - "expect val ", A("prop"), - ": ", A("Int"), - ignoreSpanWithTokenStyle = true - ) - signatures[1].match( - "actual val ", A("prop"), - ": ", A("Int"), - " = 2", - ignoreSpanWithTokenStyle = true - ) - } - } - } - @Test - fun `actual typealias should have generic parameters and fully qualified name of the expansion type`() { - val writerPlugin = TestOutputWriterPlugin() - - testInline( - """ - |/src/main/kotlin/common/Test.kt - |package example - | - |expect class Array<T> - | - |/src/main/kotlin/jvm/Test.kt - |package example - | - |actual typealias Array<T> = kotlin.Array<T> - """.trimMargin(), - mppConfiguration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val signatures = writerPlugin.writer.renderedContent("test/example/-array/index.html").signature().toList() - - signatures[0].match( - "expect class ", A("Array"), "<", A("T"), ">", - ignoreSpanWithTokenStyle = true - ) - signatures[1].match( - "actual typealias ", A("Array"), "<", A("T"), "> = ", A("kotlin.Array"), "<", A("T"), ">", - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `type with an actual typealias`() { - val writerPlugin = TestOutputWriterPlugin() - - testInline( - """ - |/src/main/kotlin/common/Test.kt - |package example - | - |expect class Foo - | - |/src/main/kotlin/jvm/Test.kt - |package example - | - |class Bar - |actual typealias Foo = Bar - | - """.trimMargin(), - mppConfiguration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val signatures = writerPlugin.writer.renderedContent("test/example/-foo/index.html").signature().toList() - - signatures[0].match( - "expect class ", A("Foo"), - ignoreSpanWithTokenStyle = true - ) - signatures[1].match( - "actual typealias ", A("Foo"), " = ", A("Bar"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `plain typealias of plain class`() { - - val writerPlugin = TestOutputWriterPlugin() - - testInline( - """ - |/src/main/kotlin/common/Test.kt - |package example - | - |typealias PlainTypealias = Int - | - """.trimMargin(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match( - "typealias ", A("PlainTypealias"), " = ", A("Int"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `plain typealias of plain class with annotation`() { - - val writerPlugin = TestOutputWriterPlugin() - - testInline( - """ - |/src/main/kotlin/common/Test.kt - |package example - | - |@MustBeDocumented - |@Target(AnnotationTarget.TYPEALIAS) - |annotation class SomeAnnotation - | - |@SomeAnnotation - |typealias PlainTypealias = Int - | - """.trimMargin(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match( - Div( - Div( - "@", A("SomeAnnotation") - ) - ), - "typealias ", A("PlainTypealias"), " = ", A("Int"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `plain typealias of generic class`() { - - val writerPlugin = TestOutputWriterPlugin() - - testInline( - """ - |/src/main/kotlin/common/Test.kt - |package example - | - |typealias PlainTypealias = Comparable<Int> - | - """.trimMargin(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match( - "typealias ", A("PlainTypealias"), " = ", A("Comparable"), - "<", A("Int"), ">", - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `typealias with generics params`() { - - - val writerPlugin = TestOutputWriterPlugin() - - testInline( - """ - |/src/main/kotlin/common/Test.kt - |package example - | - |typealias GenericTypealias<T> = Comparable<T> - | - """.trimMargin(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match( - "typealias ", A("GenericTypealias"), "<", A("T"), "> = ", A("Comparable"), - "<", A("T"), ">", - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `typealias with generic params swapped`() { - - val writerPlugin = TestOutputWriterPlugin() - - testInline( - """ - |/src/main/kotlin/kotlinAsJavaPlugin/Test.kt - |package kotlinAsJavaPlugin - | - |typealias XD<B, A> = Map<A, B> - | - |class ABC { - | fun someFun(xd: XD<Int, String>) = 1 - |} - """.trimMargin(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/kotlinAsJavaPlugin/-a-b-c/some-fun.html").firstSignature() - .match( - "fun ", A("someFun"), "(", Parameters( - Parameter("xd: ", A("XD"), "<", A("Int"), ", ", A("String"), ">"), - ), "):", A("Int"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @OnlyDescriptors("Order of constructors is different in K2") - @Test - fun `generic constructor params`() { - val writerPlugin = TestOutputWriterPlugin() - - testInline( - """ - |/src/main/kotlin/common/Test.kt - |package example - | - |class GenericClass<T>(val x: Int) { - | constructor(x: T) : this(1) - | - | constructor(x: Int, y: String) : this(1) - | - | constructor(x: Int, y: List<T>) : this(1) - | - | constructor(x: Boolean, y: Int, z: String) : this(1) - | - | constructor(x: List<Comparable<Lazy<T>>>?) : this(1) - |} - | - """.trimMargin(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/-generic-class/-generic-class.html").signature().zip( - listOf( - arrayOf( - "constructor(", - Parameters( - Parameter("x: ", A("T")) - ), - ")", - ), - arrayOf( - "constructor(", - Parameters( - Parameter("x: ", A("Int"), ", "), - Parameter("y: ", A("String")) - ), - ")", - ), - arrayOf( - "constructor(", - Parameters( - Parameter("x: ", A("Int"), ", "), - Parameter("y: ", A("List"), "<", A("T"), ">") - ), - ")", - ), - arrayOf( - "constructor(", - Parameters( - Parameter("x: ", A("Boolean"), ", "), - Parameter("y: ", A("Int"), ", "), - Parameter("z:", A("String")) - ), - ")", - ), - arrayOf( - "constructor(", - Parameters( - Parameter("x: ", A("List"), "<", A("Comparable"), "<", A("Lazy"), "<", A("T"), ">>>?") - ), - ")", - ), - arrayOf( - "constructor(", - Parameters( - Parameter("x: ", A("Int")) - ), - ")", - ), - ) - ).forEach { - it.first.match(*it.second, ignoreSpanWithTokenStyle = true) - } - } - } - } - - @Test - fun `constructor has its own custom signature keyword in Constructor tab`() { - val writerPlugin = TestOutputWriterPlugin() - - testInline( - """ - |/src/main/kotlin/common/Test.kt - |package example - | - |class PrimaryConstructorClass(x: String) { } - """.trimMargin(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val constructorTabFirstElement = - writerPlugin.writer.renderedContent("root/example/-primary-constructor-class/index.html") - .tab("CONSTRUCTOR") - .first() ?: throw NoSuchElementException("No Constructors tab found or it is empty") - - constructorTabFirstElement.firstSignature().match( - "constructor(", Parameters(Parameter("x: ", A("String"))), ")", - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `primary constructor with properties check for all tokens`() { - val writerPlugin = TestOutputWriterPlugin() - - testInline( - """ - |/src/main/kotlin/common/Test.kt - |package example - | - |class PrimaryConstructorClass<T>(val x: Int, var s: String) { } - """.trimMargin(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/-primary-constructor-class/index.html").firstSignature().match( - // In `<T>` expression, an empty `<span class="token keyword"></span>` is present for some reason - Span("class "), A("PrimaryConstructorClass"), Span("<"), Span(), A("T"), Span(">"), Span("("), Parameters( - Parameter(Span("val "), "x", Span(": "), A("Int"), Span(",")), - Parameter(Span("var "), "s", Span(": "), A("String")) - ), Span(")"), - ) - } - } - } - - @Test - fun `fun with default values`() { - val source = source("fun simpleFun(int: Int = 1, string: String = \"string\"): String = \"\"") - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/simple-fun.html").firstSignature().match( - "fun", A("simpleFun"), "(", Parameters( - Parameter("int: ", A("Int"), " = 1,"), - Parameter("string: ", A("String"), " = \"string\"") - ), "): ", A("String"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `const val with default values`() { - val source = source("const val simpleVal = 1") - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/index.html").firstSignature().match( - "const val ", A("simpleVal"), ": ", A("Int"), " = 1", - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `should not expose enum constructor entry arguments`() { - val writerPlugin = TestOutputWriterPlugin() - - testInline( - """ - |/src/main/kotlin/common/EnumClass.kt - |package example - | - |enum class EnumClass(param: String = "Default") { - | EMPTY, - | WITH_ARG("arg") - |} - """.trimMargin(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val enumEntrySignatures = writerPlugin.writer.renderedContent("root/example/-enum-class/index.html") - .select("div[data-togglable=ENTRY] .table") - .single() - .signature() - .select("div.block") - - enumEntrySignatures[0].match( - A("EMPTY"), - ignoreSpanWithTokenStyle = true - ) - - enumEntrySignatures[1].match( - A("WITH_ARG"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @OnlyDescriptors("'var' expected but found: 'open var'") - @Test - fun `java property without accessors should be var`() { - val writerPlugin = TestOutputWriterPlugin() - testInline( - """ - |/src/test/JavaClass.java - |package test; - |public class JavaClass { - | public int property = 0; - |} - | - |/src/test/KotlinClass.kt - |package test - |open class KotlinClass : JavaClass() { } - """.trimIndent(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/test/-kotlin-class/index.html").let { kotlinClassContent -> - val signatures = kotlinClassContent.signature().toList() - assertEquals(3, signatures.size, "Expected 2 signatures: class signature, constructor and property") - - val property = signatures[2] - property.match( - "var ", A("property"), ":", A("Int"), - ignoreSpanWithTokenStyle = true - ) - } - - writerPlugin.writer.renderedContent("root/test/-java-class/index.html").let { kotlinClassContent -> - val signatures = kotlinClassContent.signature().toList() - assertEquals( - 3, - signatures.size, - "Expected 3 signatures: class signature, default constructor and property" - ) - - val property = signatures[2] - property.match( - "open var ", A("property"), ":", A("Int"), - ignoreSpanWithTokenStyle = true - ) - } - } - } - } -} diff --git a/plugins/base/src/test/kotlin/signatures/VarianceSignatureTest.kt b/plugins/base/src/test/kotlin/signatures/VarianceSignatureTest.kt deleted file mode 100644 index 0e8a8845..00000000 --- a/plugins/base/src/test/kotlin/signatures/VarianceSignatureTest.kt +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package signatures - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import utils.A -import utils.TestOutputWriterPlugin -import utils.match -import kotlin.test.Test - -class VarianceSignatureTest : BaseAbstractTest() { - private val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - classpath = listOf(commonStdlibPath!!) - externalDocumentationLinks = listOf(stdlibExternalDocumentationLink) - } - } - } - - fun source(signature: String) = - """ - |/src/main/kotlin/test/Test.kt - |package example - | - | $signature - """.trimIndent() - - @Test - fun `simple contravariance`() { - val source = source("class Generic<in T>") - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/-generic/index.html").firstSignature().match( - "class ", A("Generic"), "<in ", A("T"), ">", - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `simple covariance`() { - val source = source("class Generic<out T>") - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/-generic/index.html").firstSignature().match( - "class ", A("Generic"), "<out ", A("T"), ">", - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `simple invariance`() { - val source = source("class Generic<T>") - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/-generic/index.html").firstSignature().match( - "class ", A("Generic"), "<", A("T"), ">", - ignoreSpanWithTokenStyle = true - ) - } - } - } - - @Test - fun `covariance and bound`() { - val source = source("class Generic<out T : List<CharSequence>>") - val writerPlugin = TestOutputWriterPlugin() - - testInline( - source, - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/example/-generic/index.html").firstSignature().match( - "class ", A("Generic"), "<out ", A("T"), ":", A("List"), "<", A("CharSequence"), ">>", - ignoreSpanWithTokenStyle = true - ) - } - } - } -} - diff --git a/plugins/base/src/test/kotlin/superFields/DescriptorSuperPropertiesTest.kt b/plugins/base/src/test/kotlin/superFields/DescriptorSuperPropertiesTest.kt deleted file mode 100644 index 8f984485..00000000 --- a/plugins/base/src/test/kotlin/superFields/DescriptorSuperPropertiesTest.kt +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package superFields - -import org.jetbrains.dokka.DokkaConfiguration -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.model.InheritedMember -import org.jetbrains.dokka.model.IsVar -import org.jetbrains.dokka.model.KotlinVisibility -import utils.OnlyDescriptors -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertNotNull -import kotlin.test.assertNull - -class DescriptorSuperPropertiesTest : BaseAbstractTest() { - - private val commonTestConfiguration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - analysisPlatform = "jvm" - name = "jvm" - } - } - } - - @Test - fun `kotlin inheriting java should append only getter`() { - testInline( - """ - |/src/test/A.java - |package test; - |public class A { - | private int a = 1; - | public int getA() { return a; } - |} - | - |/src/test/B.kt - |package test - |class B : A {} - """.trimIndent(), - commonTestConfiguration - ) { - this.documentablesTransformationStage = { module -> - val kotlinProperties = module.packages.single().classlikes.single { it.name == "B" }.properties - - val property = kotlinProperties.single { it.name == "a" } - val propertyInheritedFrom = property.extra[InheritedMember]?.inheritedFrom?.values?.single() - assertEquals(DRI(packageName = "test", classNames = "A"), propertyInheritedFrom) - - assertNull(property.setter) - assertNotNull(property.getter) - - val getterInheritedFrom = property.getter?.extra?.get(InheritedMember)?.inheritedFrom?.values?.single() - assertEquals(DRI(packageName = "test", classNames = "A"), getterInheritedFrom) - - assertNull(property.extra[IsVar]) - } - } - } - - - @Test - fun `kotlin inheriting java should ignore setter lookalike for non accessible field`() { - testInline( - """ - |/src/test/A.java - |package test; - |public class A { - | private int a = 1; - | - | public void setA(int a) { this.a = a; } - |} - | - |/src/test/B.kt - |package test - |class B : A {} - """.trimIndent(), - commonTestConfiguration - ) { - documentablesMergingStage = { module -> - val testedClass = module.packages.single().classlikes.single { it.name == "B" } - - val property = testedClass.properties.firstOrNull { it.name == "a" } - assertNull(property, "Inherited property `a` should not be visible as it's not accessible") - - val setterLookalike = testedClass.functions.firstOrNull { it.name == "setA" } - assertNotNull(setterLookalike) { - "Expected setA to be a regular function because field `a` is neither var nor val from Kotlin's " + - "interop perspective, it's not accessible." - } - } - } - } - - - @Test - fun `kotlin inheriting java should append getter and setter`() { - testInline( - """ - |/src/test/A.java - |package test; - |public class A { - | private int a = 1; - | public int getA() { return a; } - | public void setA(int a) { this.a = a; } - |} - | - |/src/test/B.kt - |package test - |class B : A {} - """.trimIndent(), - commonTestConfiguration - ) { - documentablesMergingStage = { module -> - val kotlinProperties = module.packages.single().classlikes.single { it.name == "B" }.properties - val property = kotlinProperties.single { it.name == "a" } - property.extra[InheritedMember]?.inheritedFrom?.values?.single()?.run { - assertEquals( - DRI(packageName = "test", classNames = "A"), - this - ) - } - - val getter = property.getter - assertNotNull(getter) - assertEquals("getA", getter.name) - val getterInheritedFrom = getter.extra[InheritedMember]?.inheritedFrom?.values?.single() - assertEquals(DRI(packageName = "test", classNames = "A"), getterInheritedFrom) - - val setter = property.setter - assertNotNull(setter) - assertEquals("setA", setter.name) - val setterInheritedFrom = setter.extra[InheritedMember]?.inheritedFrom?.values?.single() - assertEquals(DRI(packageName = "test", classNames = "A"), setterInheritedFrom) - - assertNotNull(property.extra[IsVar]) - } - } - } - - @Test - @OnlyDescriptors("Incorrect test, see https://github.com/Kotlin/dokka/issues/3128") - fun `should have special getter and setter names for boolean property inherited from java`() { - testInline( - """ - |/src/test/A.java - |package test; - |public class A { - | private boolean bool = true; - | public boolean isBool() { return bool; } - | public void setBool(boolean bool) { this.bool = bool; } - |} - | - |/src/test/B.kt - |package test - |class B : A {} - """.trimIndent(), - commonTestConfiguration - ) { - documentablesMergingStage = { module -> - val kotlinProperties = module.packages.single().classlikes.single { it.name == "B" }.properties - val boolProperty = kotlinProperties.single { it.name == "bool" } - - val getter = boolProperty.getter - assertNotNull(getter) - assertEquals("isBool", getter.name) - - val setter = boolProperty.setter - assertNotNull(setter) - assertEquals("setBool", setter.name) - - assertNotNull(boolProperty.extra[IsVar]) - } - } - } - - @OnlyDescriptors("Incorrect test, see https://github.com/Kotlin/dokka/issues/3128") - @Test - fun `kotlin inheriting java should not append anything since field is public api`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - analysisPlatform = "jvm" - name = "jvm" - documentedVisibilities = setOf( - DokkaConfiguration.Visibility.PUBLIC, - DokkaConfiguration.Visibility.PROTECTED - ) - } - } - } - - testInline( - """ - |/src/test/A.java - |package test; - |public class A { - | protected int a = 1; - | public int getA() { return a; } - | public void setA(int a) { this.a = a; } - |} - | - |/src/test/B.kt - |package test - |class B : A {} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testedClass = module.packages.single().classlikes.single { it.name == "B" } - val property = testedClass.properties.single { it.name == "a" } - - assertNull(property.getter) - assertNull(property.setter) - assertEquals(2, testedClass.functions.size) - - assertEquals("getA", testedClass.functions[0].name) - assertEquals("setA", testedClass.functions[1].name) - - val inheritedFrom = property.extra[InheritedMember]?.inheritedFrom?.values?.single() - assertEquals(DRI(packageName = "test", classNames = "A"), inheritedFrom) - - assertNotNull(property.extra[IsVar]) - } - } - } - - @Test - fun `should inherit property visibility from getter`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - analysisPlatform = "jvm" - name = "jvm" - documentedVisibilities = setOf( - DokkaConfiguration.Visibility.PUBLIC, - DokkaConfiguration.Visibility.PROTECTED - ) - } - } - } - - testInline( - """ - |/src/test/A.java - |package test; - |public class A { - | private int a = 1; - | protected int getA() { return a; } - | protected void setA(int a) { this.a = a; } - |} - | - |/src/test/B.kt - |package test - |class B : A {} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testedClass = module.packages.single().classlikes.single { it.name == "B" } - assertEquals(0, testedClass.functions.size) - - val property = testedClass.properties.single { it.name == "a" } - - assertNotNull(property.getter) - assertNotNull(property.setter) - - val propertyVisibility = property.visibility.values.single() - assertEquals(KotlinVisibility.Protected, propertyVisibility) - - val getterVisibility = property.getter?.visibility?.values?.single() - assertEquals(KotlinVisibility.Protected, getterVisibility) - - val setterVisibility = property.setter?.visibility?.values?.single() - assertEquals(KotlinVisibility.Protected, setterVisibility) - - val inheritedFrom = property.extra[InheritedMember]?.inheritedFrom?.values?.single() - assertEquals(DRI(packageName = "test", classNames = "A"), inheritedFrom) - - assertNotNull(property.extra[IsVar]) - } - } - } - - @Test // checking for mapping between kotlin and java visibility - fun `should resolve inherited java protected field as protected`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - analysisPlatform = "jvm" - name = "jvm" - documentedVisibilities = setOf( - DokkaConfiguration.Visibility.PUBLIC, - DokkaConfiguration.Visibility.PROTECTED - ) - } - } - } - - testInline( - """ - |/src/test/A.java - |package test; - |public class A { - | protected int protectedProperty = 0; - |} - | - |/src/test/B.kt - |package test - |class B : A {} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testedClass = module.packages.single().classlikes.single { it.name == "B" } - assertEquals(0, testedClass.functions.size) - - val property = testedClass.properties.single { it.name == "protectedProperty" } - - assertNull(property.getter) - assertNull(property.setter) - - val propertyVisibility = property.visibility.values.single() - assertEquals(KotlinVisibility.Protected, propertyVisibility) - - val inheritedFrom = property.extra[InheritedMember]?.inheritedFrom?.values?.single() - assertEquals(DRI(packageName = "test", classNames = "A"), inheritedFrom) - - assertNotNull(property.extra[IsVar]) - } - } - } - - @Test - fun `should mark final property inherited from java as val`() { - testInline( - """ - |/src/test/A.java - |package test; - |public class A { - | public final int a = 1; - |} - | - |/src/test/B.kt - |package test - |class B : A {} - """.trimIndent(), - commonTestConfiguration - ) { - documentablesMergingStage = { module -> - val kotlinProperties = module.packages.single().classlikes.single { it.name == "B" }.properties - val property = kotlinProperties.single { it.name == "a" } - - assertNull(property.extra[IsVar]) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/superFields/PsiSuperFieldsTest.kt b/plugins/base/src/test/kotlin/superFields/PsiSuperFieldsTest.kt deleted file mode 100644 index 38f263a6..00000000 --- a/plugins/base/src/test/kotlin/superFields/PsiSuperFieldsTest.kt +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package superFields - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.model.Annotations -import org.jetbrains.dokka.model.InheritedMember -import org.jetbrains.dokka.model.IsVar -import org.jetbrains.dokka.model.isJvmField -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertNotNull -import kotlin.test.assertNull - -class PsiSuperFieldsTest : BaseAbstractTest() { - - private val commonTestConfiguration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - analysisPlatform = "jvm" - name = "jvm" - } - } - } - - @Test - fun `java inheriting java`() { - testInline( - """ - |/src/test/A.java - |package test; - |public class A { - | public int a = 1; - |} - | - |/src/test/B.java - |package test; - |public class B extends A {} - """.trimIndent(), - commonTestConfiguration - ) { - documentablesMergingStage = { module -> - val inheritorProperties = module.packages.single().classlikes.single { it.name == "B" }.properties - val property = inheritorProperties.single { it.name == "a" } - - val inheritedFrom = property.extra[InheritedMember]?.inheritedFrom?.values?.single() - assertEquals(DRI(packageName = "test", classNames = "A"), inheritedFrom) - } - } - } - - @Test - fun `java inheriting kotlin common case`() { - testInline( - """ - |/src/test/A.kt - |package test - |open class A { - | var a: Int = 1 - | val b: Int = 2 - |} - | - |/src/test/B.java - |package test; - |public class B extends A {} - """.trimIndent(), - commonTestConfiguration - ) { - documentablesMergingStage = { module -> - val inheritorProperties = module.packages.single().classlikes.single { it.name == "B" }.properties - inheritorProperties.single { it.name == "a" }.let { mutableProperty -> - assertNotNull(mutableProperty.getter) - assertNotNull(mutableProperty.setter) - - val inheritedFrom = mutableProperty.extra[InheritedMember]?.inheritedFrom?.values?.single() - assertEquals(DRI(packageName = "test", classNames = "A"), inheritedFrom) - - assertNotNull(mutableProperty.extra[IsVar]) - } - - inheritorProperties.single { it.name == "b" }.let { immutableProperty -> - assertNotNull(immutableProperty.getter) - assertNull(immutableProperty.setter) - - val inheritedFrom = immutableProperty.extra[InheritedMember]?.inheritedFrom?.values?.single() - assertEquals(DRI(packageName = "test", classNames = "A"), inheritedFrom) - - assertNull(immutableProperty.extra[IsVar]) - } - } - } - } - - @Test - fun `java inheriting kotlin with boolean property`() { - testInline( - """ - |/src/test/A.kt - |package test - |open class A { - | var isActive: Boolean = true - |} - | - |/src/test/B.java - |package test; - |public class B extends A {} - """.trimIndent(), - commonTestConfiguration - ) { - documentablesMergingStage = { module -> - val inheritorProperties = module.packages.single().classlikes.single { it.name == "B" }.properties - val property = inheritorProperties.single { it.name == "isActive" } - - assertNotNull(property.getter) - assertEquals("isActive", property.getter?.name) - - assertNotNull(property.setter) - assertEquals("setActive", property.setter?.name) - - val inheritedFrom = property.extra[InheritedMember]?.inheritedFrom?.values?.single() - assertEquals(DRI(packageName = "test", classNames = "A"), inheritedFrom) - - assertNotNull(property.extra[IsVar]) - } - } - } - - @Test - fun `java inheriting kotlin with @JvmField should not inherit accessors`() { - testInline( - """ - |/src/test/A.kt - |package test - |open class A { - | @kotlin.jvm.JvmField - | var a: Int = 1 - |} - | - |/src/test/B.java - |package test; - |public class B extends A {} - """.trimIndent(), - dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - analysisPlatform = "jvm" - name = "jvm" - classpath += jvmStdlibPath!! // needed for JvmField - } - } - } - ) { - documentablesMergingStage = { module -> - val inheritorProperties = module.packages.single().classlikes.single { it.name == "B" }.properties - val property = inheritorProperties.single { it.name == "a" } - - assertNull(property.getter) - assertNull(property.setter) - - val jvmFieldAnnotation = property.extra[Annotations]?.directAnnotations?.values?.single()?.find { - it.isJvmField() - } - assertNotNull(jvmFieldAnnotation) - - val inheritedFrom = property.extra[InheritedMember]?.inheritedFrom?.values?.single() - assertEquals(DRI(packageName = "test", classNames = "A"), inheritedFrom) - - assertNotNull(property.extra[IsVar]) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/transformerBuilders/PageTransformerBuilderTest.kt b/plugins/base/src/test/kotlin/transformerBuilders/PageTransformerBuilderTest.kt deleted file mode 100644 index 7ee67228..00000000 --- a/plugins/base/src/test/kotlin/transformerBuilders/PageTransformerBuilderTest.kt +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package transformerBuilders - -import org.jetbrains.dokka.CoreExtensions -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.model.dfs -import org.jetbrains.dokka.pages.* -import org.jetbrains.dokka.plugability.DokkaPlugin -import org.jetbrains.dokka.plugability.DokkaPluginApiPreview -import org.jetbrains.dokka.plugability.PluginApiPreviewAcknowledgement -import org.jetbrains.dokka.transformers.pages.PageTransformer -import org.jetbrains.dokka.transformers.pages.pageMapper -import org.jetbrains.dokka.transformers.pages.pageScanner -import org.jetbrains.dokka.transformers.pages.pageStructureTransformer -import utils.assertNotNull -import kotlin.test.Test -import kotlin.test.assertEquals - -class PageTransformerBuilderTest : BaseAbstractTest() { - - class ProxyPlugin(transformer: PageTransformer) : DokkaPlugin() { - val pageTransformer by extending { CoreExtensions.pageTransformer with transformer } - - @OptIn(DokkaPluginApiPreview::class) - override fun pluginApiPreviewAcknowledgement(): PluginApiPreviewAcknowledgement = - PluginApiPreviewAcknowledgement - } - - @Test - fun scannerTest() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin/transformerBuilder/Test.kt") - } - } - } - val list = mutableListOf<String>() - - var orig: PageNode? = null - - testInline( - """ - |/src/main/kotlin/transformerBuilder/Test.kt - |package transformerBuilder - | - |object Test { - | fun test2(str: String): Unit {println(str)} - |} - """.trimMargin(), - configuration, - pluginOverrides = listOf(ProxyPlugin(pageScanner { - list += name - })) - ) { - pagesGenerationStage = { - orig = it - } - pagesTransformationStage = { root -> - list.assertCount(4, "Page list: ") - orig?.let { root.assertTransform(it) } - } - } - } - - @Test - fun mapperTest() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin/transformerBuilder/Test.kt") - } - } - } - - var orig: PageNode? = null - - testInline( - """ - |/src/main/kotlin/transformerBuilder/Test.kt - |package transformerBuilder - | - |object Test { - | fun test2(str: String): Unit {println(str)} - |} - """.trimMargin(), - configuration, - pluginOverrides = listOf(ProxyPlugin(pageMapper { - modified(name = name + "2") - })) - ) { - pagesGenerationStage = { - orig = it - } - pagesTransformationStage = { - it.let { root -> - root.name.assertEqual("root2", "Root name: ") - orig?.let { - root.assertTransform(it) { node -> node.modified(name = node.name + "2") } - } - } - } - } - } - - @Test - fun structureTransformerTest() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin/transformerBuilder/Test.kt") - } - } - } - - testInline( - """ - |/src/main/kotlin/transformerBuilder/Test.kt - |package transformerBuilder - | - |object Test { - | fun test2(str: String): Unit {println(str)} - |} - """.trimMargin(), - configuration, - pluginOverrides = listOf(ProxyPlugin(pageStructureTransformer { - val ch = children.first() - modified( - children = listOf( - ch, - RendererSpecificResourcePage("test", emptyList(), RenderingStrategy.DoNothing) - ) - ) - })) - ) { - pagesTransformationStage = { root -> - root.children.assertCount(2, "Root children: ") - root.children.first().name.assertEqual("transformerBuilder") - root.children[1].name.assertEqual("test") - } - } - } - - @Test - fun `kotlin constructors tab should exist even though there is primary constructor only`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - } - } - } - testInline( - """ - |/src/main/kotlin/kotlinAsJavaPlugin/Test.kt - |package kotlinAsJavaPlugin - | - |class Test(val xd: Int) - """.trimMargin(), - configuration - ) { - pagesGenerationStage = { root -> - val content = root.children - .flatMap { it.children<ContentPage>() } - .map { it.content }.single().children - .filterIsInstance<ContentGroup>() - .single { it.dci.kind == ContentKind.Main }.children - - val contentWithConstructorsHeader = content.find { tabContent -> tabContent.dfs { it is ContentText && (it as? ContentText)?.text == "Constructors"} != null } - - contentWithConstructorsHeader.assertNotNull("contentWithConstructorsHeader") - - contentWithConstructorsHeader?.dfs { it.dci.kind == ContentKind.Constructors && it is ContentGroup } - .assertNotNull("constructor group") - } - } - } - - private fun <T> Collection<T>.assertCount(n: Int, prefix: String = "") = - assertEquals(n, count(), "${prefix}Expected $n, got ${count()}") - - private fun <T> T.assertEqual(expected: T, prefix: String = "") = - assertEquals(expected, this, "${prefix}Expected $expected, got $this") - - private fun PageNode.assertTransform(expected: PageNode, block: (PageNode) -> PageNode = { it }): Unit = this.let { - it.name.assertEqual(block(expected).name) - it.children.zip(expected.children).forEach { (g, e) -> - g.name.assertEqual(block(e).name) - g.assertTransform(e, block) - } - } -} diff --git a/plugins/base/src/test/kotlin/transformers/AbstractContextModuleAndPackageDocumentationReaderTest.kt b/plugins/base/src/test/kotlin/transformers/AbstractContextModuleAndPackageDocumentationReaderTest.kt deleted file mode 100644 index 8ce9360f..00000000 --- a/plugins/base/src/test/kotlin/transformers/AbstractContextModuleAndPackageDocumentationReaderTest.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 transformers - -import org.jetbrains.dokka.model.SourceSetDependent -import org.jetbrains.dokka.model.doc.DocumentationNode -import org.jetbrains.dokka.model.doc.Text -import org.jetbrains.dokka.model.withDescendants -import org.junit.jupiter.api.io.TempDir -import java.nio.file.Path - -abstract class AbstractContextModuleAndPackageDocumentationReaderTest { - @TempDir - protected lateinit var temporaryDirectory: Path - - - companion object { - val SourceSetDependent<DocumentationNode>.texts: List<String> - get() = values.flatMap { it.withDescendants() } - .flatMap { it.children } - .flatMap { it.children } - .mapNotNull { it as? Text } - .map { it.body } - } -} diff --git a/plugins/base/src/test/kotlin/transformers/CommentsToContentConverterTest.kt b/plugins/base/src/test/kotlin/transformers/CommentsToContentConverterTest.kt deleted file mode 100644 index 1387c0e0..00000000 --- a/plugins/base/src/test/kotlin/transformers/CommentsToContentConverterTest.kt +++ /dev/null @@ -1,484 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package transformers - -import matchers.content.* -import org.jetbrains.dokka.base.transformers.pages.comments.DocTagToContentConverter -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.model.doc.* -import org.jetbrains.dokka.pages.* -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertTrue - -class CommentsToContentConverterTest { - private val converter = DocTagToContentConverter() - - private fun executeTest( - docTag: DocTag, - match: ContentMatcherBuilder<ContentComposite>.() -> Unit, - ) { - val dci = DCI( - setOf( - DRI("kotlin", "Any") - ), - ContentKind.Comment - ) - converter.buildContent( - Li( - listOf( - docTag - ) - ), - dci, - emptySet() - ).single().assertNode(match) - } - - @Test - fun `simple text`() { - val docTag = P(listOf(Text("This is simple test of string Next line"))) - executeTest(docTag) { - group { +"This is simple test of string Next line" } - } - } - - @Test - fun `simple text with new line`() { - val docTag = P( - listOf( - Text("This is simple test of string"), - Br, - Text("Next line") - ) - ) - executeTest(docTag) { - group { - +"This is simple test of string" - node<ContentBreakLine>() - +"Next line" - } - } - } - - @Test - fun `paragraphs`() { - val docTag = P( - listOf( - P(listOf(Text("Paragraph number one"))), - P(listOf(Text("Paragraph"), Br, Text("number two"))) - ) - ) - executeTest(docTag) { - group { - group { +"Paragraph number one" } - group { - +"Paragraph" - node<ContentBreakLine>() - +"number two" - } - } - } - } - - @Test - fun `unordered list with empty lines`() { - val docTag = Ul( - listOf( - Li(listOf(P(listOf(Text("list item 1 continue 1"))))), - Li(listOf(P(listOf(Text("list item 2"), Br, Text("continue 2"))))) - ) - ) - executeTest(docTag) { - node<ContentList> { - group { - +"list item 1 continue 1" - } - group { - +"list item 2" - node<ContentBreakLine>() - +"continue 2" - } - } - } - } - - @Test - fun `nested list`() { - val docTag = P( - listOf( - Ul( - listOf( - Li(listOf(P(listOf(Text("Outer first Outer next line"))))), - Li(listOf(P(listOf(Text("Outer second"))))), - Ul( - listOf( - Li(listOf(P(listOf(Text("Middle first Middle next line"))))), - Li(listOf(P(listOf(Text("Middle second"))))), - Ul( - listOf( - Li(listOf(P(listOf(Text("Inner first Inner next line"))))) - ) - ), - Li(listOf(P(listOf(Text("Middle third"))))) - ) - ), - Li(listOf(P(listOf(Text("Outer third"))))) - ) - ), - P(listOf(Text("New paragraph"))) - ) - ) - executeTest(docTag) { - group { - node<ContentList> { - group { +"Outer first Outer next line" } - group { +"Outer second" } - node<ContentList> { - group { +"Middle first Middle next line" } - group { +"Middle second" } - node<ContentList> { - group { +"Inner first Inner next line" } - } - group { +"Middle third" } - } - group { +"Outer third" } - } - group { +"New paragraph" } - } - } - } - - @Test - fun `header and paragraphs`() { - val docTag = P( - listOf( - H1(listOf(Text("Header 1"))), - P(listOf(Text("Following text"))), - P(listOf(Text("New paragraph"))) - ) - ) - executeTest(docTag) { - group { - header(1) { +"Header 1" } - group { +"Following text" } - group { +"New paragraph" } - } - } - } - - @Test - fun `header levels`() { - val docTag = P( - listOf( - H1(listOf(Text("Header 1"))), - P(listOf(Text("Text 1"))), - H2(listOf(Text("Header 2"))), - P(listOf(Text("Text 2"))), - H3(listOf(Text("Header 3"))), - P(listOf(Text("Text 3"))), - H4(listOf(Text("Header 4"))), - P(listOf(Text("Text 4"))), - H5(listOf(Text("Header 5"))), - P(listOf(Text("Text 5"))), - H6(listOf(Text("Header 6"))), - P(listOf(Text("Text 6"))) - ) - ) - executeTest(docTag) { - group { - header(1) { +"Header 1" } - group { +"Text 1" } - header(2) { +"Header 2" } - group { +"Text 2" } - header(3) { +"Header 3" } - group { +"Text 3" } - header(4) { +"Header 4" } - group { +"Text 4" } - header(5) { +"Header 5" } - group { +"Text 5" } - header(6) { +"Header 6" } - group { +"Text 6" } - } - } - } - - @Test - fun `block quotes`() { - val docTag = P( - listOf( - BlockQuote( - listOf( - P( - listOf( - Text("Blockquotes are very handy in email to emulate reply text. This line is part of the same quote.") - ) - ) - ) - ), - P(listOf(Text("Quote break."))), - BlockQuote( - listOf( - P(listOf(Text("Quote"))) - ) - ) - ) - ) - executeTest(docTag) { - group { - group { - group { - +"Blockquotes are very handy in email to emulate reply text. This line is part of the same quote." - } - } - group { +"Quote break." } - group { - group { - +"Quote" - } - } - } - } - } - - @Test - fun `nested block quotes`() { - val docTag = P( - listOf( - BlockQuote( - listOf( - P(listOf(Text("text 1 text 2"))), - BlockQuote( - listOf( - P(listOf(Text("text 3 text 4"))) - ) - ), - P(listOf(Text("text 5"))) - ) - ), - P(listOf(Text("Quote break."))), - BlockQuote( - listOf( - P(listOf(Text("Quote"))) - ) - ) - ) - ) - executeTest(docTag) { - group { - group { - group { +"text 1 text 2" } - group { - group { +"text 3 text 4" } - } - group { +"text 5" } - } - group { +"Quote break." } - group { - group { +"Quote" } - } - } - } - } - - @Test - fun `multiline code`() { - val docTag = P( - listOf( - CodeBlock( - listOf( - Text("val x: Int = 0"), Br, - Text("val y: String = \"Text\""), Br, Br, - Text(" val z: Boolean = true"), Br, - Text("for(i in 0..10) {"), Br, - Text(" println(i)"), Br, - Text("}") - ), - mapOf("lang" to "kotlin") - ), - P(listOf(Text("Sample text"))) - ) - ) - executeTest(docTag) { - group { - node<ContentCodeBlock> { - +"val x: Int = 0" - node<ContentBreakLine>() - +"val y: String = \"Text\"" - node<ContentBreakLine>() - node<ContentBreakLine>() - +" val z: Boolean = true" - node<ContentBreakLine>() - +"for(i in 0..10) {" - node<ContentBreakLine>() - +" println(i)" - node<ContentBreakLine>() - +"}" - } - group { +"Sample text" } - } - } - } - - @Test - fun `inline link`() { - val docTag = P( - listOf( - A( - listOf(Text("I'm an inline-style link")), - mapOf("href" to "https://www.google.com") - ) - ) - ) - executeTest(docTag) { - group { - link { - +"I'm an inline-style link" - check { - assertEquals( - (this as? ContentResolvedLink)?.address ?: error("Link should be resolved"), - "https://www.google.com" - ) - } - } - } - } - } - - - @Test - fun `ordered list`() { - val docTag = - Ol( - listOf( - Li( - listOf( - P(listOf(Text("test1"))), - P(listOf(Text("test2"))), - ) - ), - Li( - listOf( - P(listOf(Text("test3"))), - P(listOf(Text("test4"))), - ) - ) - ) - ) - executeTest(docTag) { - node<ContentList> { - group { - +"test1" - +"test2" - } - group { - +"test3" - +"test4" - } - } - } - } - - @Test - fun `nested ordered list`() { - val docTag = P( - listOf( - Ol( - listOf( - Li(listOf(P(listOf(Text("Outer first Outer next line"))))), - Li(listOf(P(listOf(Text("Outer second"))))), - Ol( - listOf( - Li(listOf(P(listOf(Text("Middle first Middle next line"))))), - Li(listOf(P(listOf(Text("Middle second"))))), - Ol( - listOf( - Li(listOf(P(listOf(Text("Inner first Inner next line"))))) - ), - mapOf("start" to "1") - ), - Li(listOf(P(listOf(Text("Middle third"))))) - ), - mapOf("start" to "1") - ), - Li(listOf(P(listOf(Text("Outer third"))))) - ), - mapOf("start" to "1") - ), - P(listOf(Text("New paragraph"))) - ) - ) - executeTest(docTag) { - group { - node<ContentList> { - group { +"Outer first Outer next line" } - group { +"Outer second" } - node<ContentList> { - group { +"Middle first Middle next line" } - group { +"Middle second" } - node<ContentList> { - +"Inner first Inner next line" - } - group { +"Middle third" } - } - group { +"Outer third" } - } - group { - +"New paragraph" - } - } - } - } - - @Test - fun `description list`() { - val docTag = - Dl( - listOf( - Dt( - listOf( - Text("description list can have...") - ) - ), - Dt( - listOf( - Text("... two consecutive description terms") - ) - ), - Dd( - listOf( - Text("and usually has some sort of a description, like this one") - ) - ) - ) - ) - - executeTest(docTag) { - composite<ContentList> { - check { - assertTrue(style.contains(ListStyle.DescriptionList), "Expected DL style") - } - group { - check { - assertTrue(style.contains(ListStyle.DescriptionTerm), "Expected DT style") - } - +"description list can have..." - } - group { - check { - assertTrue(style.contains(ListStyle.DescriptionTerm), "Expected DT style") - } - +"... two consecutive description terms" - } - group { - check { - assertTrue(style.contains(ListStyle.DescriptionDetails), "Expected DD style") - } - +"and usually has some sort of a description, like this one" - } - } - } - } -} diff --git a/plugins/base/src/test/kotlin/transformers/ContextModuleAndPackageDocumentationReaderTest1.kt b/plugins/base/src/test/kotlin/transformers/ContextModuleAndPackageDocumentationReaderTest1.kt deleted file mode 100644 index dfb3eff1..00000000 --- a/plugins/base/src/test/kotlin/transformers/ContextModuleAndPackageDocumentationReaderTest1.kt +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package transformers - -import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet -import org.jetbrains.dokka.analysis.kotlin.internal.InternalKotlinAnalysisPlugin -import org.jetbrains.dokka.links.DRI -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.testApi.logger.TestLogger -import org.jetbrains.dokka.utilities.DokkaConsoleLogger -import org.jetbrains.dokka.utilities.LoggingLevel -import testApi.testRunner.TestDokkaConfigurationBuilder -import testApi.testRunner.dModule -import testApi.testRunner.dPackage -import kotlin.test.BeforeTest -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertFailsWith - -class ContextModuleAndPackageDocumentationReaderTest1 : AbstractContextModuleAndPackageDocumentationReaderTest() { - - - private val includeSourceSetA by lazy { temporaryDirectory.resolve("includeA.md").toFile() } - private val includeSourceSetB by lazy { temporaryDirectory.resolve("includeB.md").toFile() } - - @BeforeTest - fun materializeIncludes() { - includeSourceSetA.writeText( - """ - # Module moduleA - This is moduleA - - # Package sample.a - This is package sample.a\r\n - - # Package noise.b - This will just add some noise - """.trimIndent().replace("\n", "\r\n") - ) - - includeSourceSetB.writeText( - """ - # Module moduleB - This is moduleB - - # Package sample.b - This is package sample.b - - # Package noise.b - This will just add some more noise - """.trimIndent() - ) - } - - private val configurationBuilder = TestDokkaConfigurationBuilder().apply { - moduleName = "moduleA" - } - - private val sourceSetA by configurationBuilder.sourceSet { - name = "sourceSetA" - includes = listOf(includeSourceSetA.canonicalPath) - } - - - private val sourceSetB by configurationBuilder.sourceSet { - name = "sourceSetB" - includes = listOf(includeSourceSetB.canonicalPath) - } - - - private val sourceSetB2 by configurationBuilder.sourceSet { - name = "sourceSetB2" - includes = emptyList() - } - - - private val context by lazy { - DokkaContext.create( - configuration = configurationBuilder.build(), - logger = TestLogger(DokkaConsoleLogger(LoggingLevel.DEBUG)), - pluginOverrides = emptyList() - ) - } - - private val reader by lazy { context.plugin<InternalKotlinAnalysisPlugin>().querySingle { moduleAndPackageDocumentationReader } } - - @Test - fun `assert moduleA with sourceSetA`() { - val documentation = reader.read(dModule(name = "moduleA", sourceSets = setOf(sourceSetA))) - assertEquals( - 1, documentation.keys.size, - "Expected moduleA only containing documentation in a single source set" - ) - assertEquals( - "sourceSetA", documentation.keys.single().sourceSetID.sourceSetName, - "Expected moduleA documentation coming from sourceSetA" - ) - - assertEquals( - "This is moduleA", documentation.texts.single(), - "Expected moduleA documentation being present" - ) - } - - @Test - fun `assert moduleA with no source sets`() { - val documentation = reader.read(dModule("moduleA")) - assertEquals( - emptyMap(), documentation, - "Expected no documentation received for module not declaring a matching sourceSet" - ) - } - - @Test - fun `assert moduleA with unknown source set`() { - assertFailsWith<IllegalStateException>( - "Expected no documentation received for module with unknown sourceSet" - ) { - reader.read( - dModule("moduleA", sourceSets = setOf(configurationBuilder.unattachedSourceSet { name = "unknown" })) - ) - } - } - - @Test - fun `assert moduleA with all sourceSets`() { - val documentation = reader.read(dModule("moduleA", sourceSets = setOf(sourceSetA, sourceSetB, sourceSetB2))) - assertEquals(1, documentation.entries.size, "Expected only one entry from sourceSetA") - assertEquals(sourceSetA, documentation.keys.single(), "Expected only one entry from sourceSetA") - assertEquals("This is moduleA", documentation.texts.single()) - } - - @Test - fun `assert moduleB with sourceSetB and sourceSetB2`() { - val documentation = reader.read(dModule("moduleB", sourceSets = setOf(sourceSetB, sourceSetB2))) - assertEquals(1, documentation.keys.size, "Expected only one entry from sourceSetB") - assertEquals(sourceSetB, documentation.keys.single(), "Expected only one entry from sourceSetB") - assertEquals("This is moduleB", documentation.texts.single()) - } - - @Test - fun `assert sample_A in sourceSetA`() { - val documentation = reader.read(dPackage(DRI("sample.a"), sourceSets = setOf(sourceSetA))) - assertEquals(1, documentation.keys.size, "Expected only one entry from sourceSetA") - assertEquals(sourceSetA, documentation.keys.single(), "Expected only one entry from sourceSetA") - assertEquals("This is package sample.a\\r\\n", documentation.texts.single()) - } - - @Test - fun `assert sample_a_sub in sourceSetA`() { - val documentation = reader.read(dPackage(DRI("sample.a.sub"), sourceSets = setOf(sourceSetA))) - assertEquals( - emptyMap<DokkaSourceSet, DocumentationNode>(), documentation, - "Expected no documentation found for different package" - ) - } - - @Test - fun `assert sample_a in sourceSetB`() { - val documentation = reader.read(dPackage(DRI("sample.a"), sourceSets = setOf(sourceSetB))) - assertEquals( - emptyMap<DokkaSourceSet, DocumentationNode>(), documentation, - "Expected no documentation found for different sourceSet" - ) - } - - @Test - fun `assert sample_b in sourceSetB`() { - val documentation = reader.read(dPackage(DRI("sample.b"), sourceSets = setOf(sourceSetB))) - assertEquals(1, documentation.keys.size, "Expected only one entry from sourceSetB") - assertEquals(sourceSetB, documentation.keys.single(), "Expected only one entry from sourceSetB") - assertEquals("This is package sample.b", documentation.texts.single()) - } - - @Test - fun `assert sample_b in sourceSetB and sourceSetB2`() { - val documentation = reader.read(dPackage(DRI("sample.b"), sourceSets = setOf(sourceSetB, sourceSetB2))) - assertEquals(1, documentation.keys.size, "Expected only one entry from sourceSetB") - assertEquals(sourceSetB, documentation.keys.single(), "Expected only one entry from sourceSetB") - assertEquals("This is package sample.b", documentation.texts.single()) - } -} diff --git a/plugins/base/src/test/kotlin/transformers/ContextModuleAndPackageDocumentationReaderTest3.kt b/plugins/base/src/test/kotlin/transformers/ContextModuleAndPackageDocumentationReaderTest3.kt deleted file mode 100644 index ebd5b7eb..00000000 --- a/plugins/base/src/test/kotlin/transformers/ContextModuleAndPackageDocumentationReaderTest3.kt +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package transformers - -import org.jetbrains.dokka.analysis.kotlin.internal.InternalKotlinAnalysisPlugin -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.plugability.DokkaContext -import org.jetbrains.dokka.plugability.plugin -import org.jetbrains.dokka.plugability.querySingle -import org.jetbrains.dokka.utilities.DokkaConsoleLogger -import org.jetbrains.dokka.utilities.LoggingLevel -import testApi.testRunner.TestDokkaConfigurationBuilder -import testApi.testRunner.dPackage -import kotlin.test.BeforeTest -import kotlin.test.Test -import kotlin.test.assertEquals - -class ContextModuleAndPackageDocumentationReaderTest3 : AbstractContextModuleAndPackageDocumentationReaderTest() { - - private val include by lazy { temporaryDirectory.resolve("include.md").toFile() } - - @BeforeTest - fun materializeInclude() { - include.writeText( - """ - # Package - This is the root package - - # Package [root] - This is also the root package - """.trimIndent() - ) - } - - private val configurationBuilder = TestDokkaConfigurationBuilder() - - private val sourceSet by configurationBuilder.sourceSet { - includes = listOf(include.canonicalPath) - } - - private val context by lazy { - DokkaContext.create( - configuration = configurationBuilder.build(), - logger = DokkaConsoleLogger(LoggingLevel.DEBUG), - pluginOverrides = emptyList() - ) - } - - private val reader by lazy { context.plugin<InternalKotlinAnalysisPlugin>().querySingle { moduleAndPackageDocumentationReader } } - - - @Test - fun `root package is matched by empty string and the root keyword`() { - val documentation = reader.read(dPackage(DRI(""), sourceSets = setOf(sourceSet))) - assertEquals( - listOf("This is the root package", "This is also the root package"), documentation.texts - ) - } -} diff --git a/plugins/base/src/test/kotlin/transformers/DivisionSwitchTest.kt b/plugins/base/src/test/kotlin/transformers/DivisionSwitchTest.kt deleted file mode 100644 index fec5fc47..00000000 --- a/plugins/base/src/test/kotlin/transformers/DivisionSwitchTest.kt +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package transformers - -import org.jetbrains.dokka.DokkaConfiguration -import org.jetbrains.dokka.PluginConfigurationImpl -import org.jetbrains.dokka.base.DokkaBase -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.model.dfs -import org.jetbrains.dokka.pages.ClasslikePageNode -import org.jetbrains.dokka.pages.ContentHeader -import org.jetbrains.dokka.pages.ContentNode -import org.jetbrains.dokka.pages.ContentText -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertNotNull - -class DivisionSwitchTest : BaseAbstractTest() { - - private val query = """ - |/src/source0.kt - package package0 - /** - * Documentation for ClassA - */ - class ClassA { - val A: String = "A" - fun a() {} - fun b() {} - } - - /src/source1.kt - package package0 - /** - * Documentation for ClassB - */ - class ClassB : ClassA() { - val B: String = "B" - fun d() {} - fun e() {} - } - """.trimMargin() - - private fun configuration(switchOn: Boolean) = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - } - } - suppressObviousFunctions = false - pluginsConfigurations.add( - PluginConfigurationImpl( - DokkaBase::class.qualifiedName!!, - DokkaConfiguration.SerializationFormat.JSON, - """{ "separateInheritedMembers": $switchOn }""", - ) - ) - } - - private fun testClassB(switchOn: Boolean, operation: (ClasslikePageNode) -> Unit) { - testInline( - query, - configuration(switchOn), - cleanupOutput = true - ) { - pagesTransformationStage = { root -> - val classB = root.dfs { it.name == "ClassB" } as? ClasslikePageNode - assertNotNull(classB, "Tested class not found!") - operation(classB) - } - } - } - - private fun ClasslikePageNode.findSectionWithName(name: String) : ContentNode? { - var sectionHeader: ContentHeader? = null - return content.dfs { node -> - node.children.filterIsInstance<ContentHeader>().any { header -> - header.children.firstOrNull { it is ContentText && it.text == name }?.also { sectionHeader = header } != null - } - }?.children?.dropWhile { child -> child != sectionHeader }?.drop(1)?.firstOrNull() - } - - @Test - fun `should not split inherited and regular methods`() { - testClassB(false) { classB -> - val functions = classB.findSectionWithName("Functions") - assertNotNull(functions, "Functions not found!") - assertEquals(7, functions.children.size, "Incorrect number of functions found") - } - } - - @Test - fun `should not split inherited and regular properties`() { - testClassB(false) { classB -> - val properties = classB.findSectionWithName("Properties") - assertNotNull(properties, "Properties not found!") - assertEquals(2, properties.children.size, "Incorrect number of properties found") - } - } - - @Test - fun `should split inherited and regular methods`() { - testClassB(true) { classB -> - val functions = classB.findSectionWithName("Functions") - val inheritedFunctions = classB.findSectionWithName("Inherited functions") - assertNotNull(functions, "Functions not found!") - assertEquals(2, functions.children.size, "Incorrect number of functions found") - assertNotNull(inheritedFunctions, "Inherited functions not found!") - assertEquals(5, inheritedFunctions.children.size, "Incorrect number of inherited functions found") - } - } - - @Test - fun `should split inherited and regular properties`() { - testClassB(true) { classB -> - val properties = classB.findSectionWithName("Properties") - assertNotNull(properties, "Properties not found!") - assertEquals(1, properties.children.size, "Incorrect number of properties found") - val inheritedProperties = classB.findSectionWithName("Inherited properties") - assertNotNull(inheritedProperties, "Inherited properties not found!") - assertEquals(1, inheritedProperties.children.size, "Incorrect number of inherited properties found") - } - } -} diff --git a/plugins/base/src/test/kotlin/transformers/InheritedEntriesDocumentableFilterTransfromerTest.kt b/plugins/base/src/test/kotlin/transformers/InheritedEntriesDocumentableFilterTransfromerTest.kt deleted file mode 100644 index c07dd5b8..00000000 --- a/plugins/base/src/test/kotlin/transformers/InheritedEntriesDocumentableFilterTransfromerTest.kt +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package transformers - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.model.DEnum -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertTrue - -class InheritedEntriesDocumentableFilterTransformerTest : BaseAbstractTest() { - val suppressingInheritedConfiguration = dokkaConfiguration { - suppressInheritedMembers = true - suppressObviousFunctions = false - sourceSets { - sourceSet { - sourceRoots = listOf("src") - } - } - } - - val nonSuppressingInheritedConfiguration = dokkaConfiguration { - suppressObviousFunctions = false - suppressInheritedMembers = false - sourceSets { - sourceSet { - sourceRoots = listOf("src") - } - } - } - - - @Test - fun `should suppress toString, equals and hashcode but keep custom ones`() { - testInline( - """ - /src/suppressed/Suppressed.kt - package suppressed - data class Suppressed(val x: String) { - override fun toString(): String { - return "custom" - } - } - """.trimIndent(), - suppressingInheritedConfiguration - ) { - preMergeDocumentablesTransformationStage = { modules -> - val functions = modules.flatMap { it.packages }.flatMap { it.classlikes }.flatMap { it.functions } - assertEquals(listOf("toString", "copy", "component1").sorted(), functions.map { it.name }.sorted()) - } - } - } - - @Test - fun `should suppress toString, equals and hashcode`() { - testInline( - """ - /src/suppressed/Suppressed.kt - package suppressed - data class Suppressed(val x: String) - """.trimIndent(), - suppressingInheritedConfiguration - ) { - preMergeDocumentablesTransformationStage = { modules -> - val functions = modules.flatMap { it.packages }.flatMap { it.classlikes }.flatMap { it.functions } - assertEquals(listOf("copy", "component1").sorted(), functions.map { it.name }.sorted()) - } - } - } - - @Test - fun `should also suppress properites`(){ - testInline( - """ - /src/suppressed/Suppressed.kt - package suppressed - open class Parent { - val parentValue = "String" - } - - class Child : Parent { - - } - """.trimIndent(), - suppressingInheritedConfiguration - ) { - preMergeDocumentablesTransformationStage = { modules -> - val properties = modules.flatMap { it.packages }.flatMap { it.classlikes }.first { it.name == "Child" }.properties - assertEquals(0, properties.size) - } - } - } - - @Test - fun `should not suppress properites if config says so`(){ - testInline( - """ - /src/suppressed/Suppressed.kt - package suppressed - open class Parent { - val parentValue = "String" - } - - class Child : Parent { - - } - """.trimIndent(), - nonSuppressingInheritedConfiguration - ) { - preMergeDocumentablesTransformationStage = { modules -> - val properties = modules.flatMap { it.packages }.flatMap { it.classlikes }.first { it.name == "Child" }.properties - assertEquals(listOf("parentValue"), properties.map { it.name }) - } - } - } - - @Test - fun `should work with enum entries`(){ - testInline( - """ - /src/suppressed/Suppressed.kt - package suppressed - enum class Suppressed { - ENTRY_SUPPRESSED - } - """.trimIndent(), - suppressingInheritedConfiguration - ) { - preMergeDocumentablesTransformationStage = { modules -> - val entry = (modules.flatMap { it.packages }.flatMap { it.classlikes }.first { it.name == "Suppressed" } as DEnum).entries.first() - assertEquals(emptyList(), entry.properties) - assertEquals(emptyList(), entry.functions) - assertEquals(emptyList(), entry.classlikes) - } - } - } - - @Test - fun `should work with enum entries when not suppressing`(){ - testInline( - """ - /src/suppressed/Suppressed.kt - package suppressed - enum class Suppressed { - ENTRY_SUPPRESSED; - class A - } - """.trimIndent(), - nonSuppressingInheritedConfiguration - ) { - preMergeDocumentablesTransformationStage = { modules -> - val entry = (modules.flatMap { it.packages }.flatMap { it.classlikes }.first { it.name == "Suppressed" } as DEnum).entries.first() - assertEquals(listOf("name", "ordinal"), entry.properties.map { it.name }) - assertTrue(entry.functions.map { it.name }.containsAll(listOf("compareTo", "equals", "hashCode", "toString"))) - assertEquals(emptyList(), entry.classlikes) - } - } - } -} - diff --git a/plugins/base/src/test/kotlin/transformers/InvalidContentModuleAndPackageDocumentationReaderTest.kt b/plugins/base/src/test/kotlin/transformers/InvalidContentModuleAndPackageDocumentationReaderTest.kt deleted file mode 100644 index ca7536d4..00000000 --- a/plugins/base/src/test/kotlin/transformers/InvalidContentModuleAndPackageDocumentationReaderTest.kt +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package transformers - -import org.jetbrains.dokka.analysis.kotlin.internal.InternalKotlinAnalysisPlugin -import org.jetbrains.dokka.plugability.DokkaContext -import org.jetbrains.dokka.plugability.plugin -import org.jetbrains.dokka.plugability.querySingle -import org.jetbrains.dokka.utilities.DokkaConsoleLogger -import org.jetbrains.dokka.utilities.LoggingLevel -import testApi.testRunner.TestDokkaConfigurationBuilder -import testApi.testRunner.dModule -import kotlin.test.BeforeTest -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertTrue - - -class InvalidContentModuleAndPackageDocumentationReaderTest : AbstractContextModuleAndPackageDocumentationReaderTest() { - - private val includeA by lazy { temporaryDirectory.resolve("includeA.md").toFile() } - private val includeB by lazy { temporaryDirectory.resolve("includeB.md").toFile() } - - @BeforeTest - fun materializeInclude() { - includeA.writeText( - """ - Invalid random stuff - - # Module moduleA - Simple stuff - """.trimIndent() - ) - includeB.writeText( - """ - # Module moduleB - ### - """.trimIndent() - ) - } - - private val configurationBuilderA = TestDokkaConfigurationBuilder().apply { - moduleName = "moduleA" - } - private val configurationBuilderB = TestDokkaConfigurationBuilder().apply { - moduleName = "moduleB" - } - - private val sourceSetA by configurationBuilderA.sourceSet { - includes = listOf(includeA.canonicalPath) - } - - private val sourceSetB by configurationBuilderB.sourceSet { - includes = listOf(includeB.canonicalPath) - } - - private val contextA by lazy { - DokkaContext.create( - configuration = configurationBuilderA.build(), - logger = DokkaConsoleLogger(LoggingLevel.DEBUG), - pluginOverrides = emptyList() - ) - } - private val contextB by lazy { - DokkaContext.create( - configuration = configurationBuilderB.build(), - logger = DokkaConsoleLogger(LoggingLevel.DEBUG), - pluginOverrides = emptyList() - ) - } - - private val readerA by lazy { contextA.plugin<InternalKotlinAnalysisPlugin>().querySingle { moduleAndPackageDocumentationReader } } - private val readerB by lazy { contextB.plugin<InternalKotlinAnalysisPlugin>().querySingle { moduleAndPackageDocumentationReader } } - - - @Test - fun `parsing should fail with a message when documentation is in not proper format`() { - val exception = - runCatching { readerA.read(dModule(name = "moduleA", sourceSets = setOf(sourceSetA))) }.exceptionOrNull() - assertEquals( - "Unexpected classifier: \"Invalid\", expected either \"Module\" or \"Package\". \n" + - "For more information consult the specification: https://kotlinlang.org/docs/dokka-module-and-package-docs.html", - exception?.message - ) - } - - @Test - fun `parsing should fail with a message where it encountered error and why`() { - val exception = - runCatching { readerB.read(dModule(name = "moduleB", sourceSets = setOf(sourceSetB))) }.exceptionOrNull()?.message!! - - //I don't want to assert whole message since it contains a path to a temporary folder - assertTrue(exception.contains("Wrong AST Tree. Header does not contain expected content in ")) - assertTrue(exception.contains("includeB.md")) - assertTrue(exception.contains("element starts from offset 0 and ends 3: ###")) - } -} - diff --git a/plugins/base/src/test/kotlin/transformers/MergeImplicitExpectActualDeclarationsTest.kt b/plugins/base/src/test/kotlin/transformers/MergeImplicitExpectActualDeclarationsTest.kt deleted file mode 100644 index 18e42e47..00000000 --- a/plugins/base/src/test/kotlin/transformers/MergeImplicitExpectActualDeclarationsTest.kt +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package transformers - -import org.jetbrains.dokka.DokkaConfiguration -import org.jetbrains.dokka.PluginConfigurationImpl -import org.jetbrains.dokka.base.DokkaBase -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.model.childrenOfType -import org.jetbrains.dokka.model.dfs -import org.jetbrains.dokka.model.firstChildOfType -import org.jetbrains.dokka.pages.* -import utils.assertNotNull -import utils.findSectionWithName -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertNotNull - -class MergeImplicitExpectActualDeclarationsTest : BaseAbstractTest() { - - @Suppress("UNUSED_VARIABLE") - private fun configuration(switchOn: Boolean) = dokkaConfiguration { - sourceSets { - val common = sourceSet { - name = "common" - displayName = "common" - analysisPlatform = "common" - sourceRoots = listOf("src/commonMain/kotlin/pageMerger/Test.kt") - } - val js = sourceSet { - name = "js" - displayName = "js" - analysisPlatform = "js" - dependentSourceSets = setOf(common.value.sourceSetID) - sourceRoots = listOf("src/jsMain/kotlin/pageMerger/Test.kt") - } - val jvm = sourceSet { - name = "jvm" - displayName = "jvm" - analysisPlatform = "jvm" - sourceRoots = listOf("src/jvmMain/kotlin/pageMerger/Test.kt") - } - } - pluginsConfigurations.add( - PluginConfigurationImpl( - DokkaBase::class.qualifiedName!!, - DokkaConfiguration.SerializationFormat.JSON, - """{ "mergeImplicitExpectActualDeclarations": $switchOn }""", - ) - ) - } - - private fun ContentNode.findTabWithType(type: TabbedContentType): ContentNode? = dfs { node -> - node.children.filterIsInstance<ContentGroup>().any { gr -> - gr.extra[TabbedContentTypeExtra]?.value == type - } - } - - @Test - fun `should merge fun`() { - testInline( - """ - - |/src/jvmMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |class classA { - | fun method1(): String - |} - | - |/src/jsMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |class classA { - | fun method1(): Int - |} - | - """.trimMargin(), - configuration(true), - cleanupOutput = true - ) { - pagesTransformationStage = { root -> - val classPage = root.dfs { it.name == "classA" } as? ClasslikePageNode - assertNotNull(classPage, "Tested class not found!") - - val functions = classPage.findSectionWithName("Functions").assertNotNull("Functions") - val method1 = functions.children.singleOrNull().assertNotNull("method1") - - assertEquals( - 2, - method1.firstChildOfType<ContentDivergentGroup>().childrenOfType<ContentDivergentInstance>().size, - "Incorrect number of divergent instances found" - ) - - val methodPage = root.dfs { it.name == "method1" } as? MemberPageNode - assertNotNull(methodPage, "Tested method not found!") - - val divergentGroup = methodPage.content.dfs { it is ContentDivergentGroup } as? ContentDivergentGroup - - assertEquals( - 2, - divergentGroup?.childrenOfType<ContentDivergentInstance>()?.size, - "Incorrect number of divergent instances found in method page" - ) - } - } - } - - @Test - fun `should merge class and typealias`() { - testInline( - """ - |/src/jvmMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |class A { - | fun method1(): String - |} - | - |/src/jsMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |typealias A = String - | - """.trimMargin(), - configuration(true), - cleanupOutput = true - ) { - pagesTransformationStage = { root -> - val classPage = root.dfs { it.name == "A" } as? ClasslikePageNode - assertNotNull(classPage, "Tested class not found!") - - val platformHintedContent = classPage.content.dfs { it is PlatformHintedContent }.assertNotNull("platformHintedContent") - assertEquals(2, platformHintedContent.sourceSets.size) - - platformHintedContent.dfs { it is ContentText && it.text == "class " }.assertNotNull("class keyword") - platformHintedContent.dfs { it is ContentText && it.text == "typealias " }.assertNotNull("typealias keyword") - } - } - } - @Test - fun `should merge method and prop`() { - testInline( - """ - |/src/jvmMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |class classA { - | fun method1(): String - |} - | - |/src/jsMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |class classA { - | val prop1: Int - |} - | - """.trimMargin(), - configuration(true), - cleanupOutput = true - ) { - pagesTransformationStage = { root -> - val classPage = root.dfs { it.name == "classA" } as? ClasslikePageNode - assertNotNull(classPage, "Tested class not found!") - - val props = classPage.findSectionWithName("Properties").assertNotNull("Properties") - props.children.singleOrNull().assertNotNull("prop1") - - val functions = classPage.findSectionWithName("Functions").assertNotNull("Functions") - functions.children.singleOrNull().assertNotNull("method1") - } - } - } - - @Test - fun `should merge prop`() { - testInline( - """ - |/src/jvmMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |class classA { - | val prop1: String - |} - | - |/src/jsMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |class classA { - | val prop1: Int - |} - | - """.trimMargin(), - configuration(true), - cleanupOutput = true - ) { - pagesTransformationStage = { root -> - val classPage = root.dfs { it.name == "classA" } as? ClasslikePageNode - assertNotNull(classPage, "Tested class not found!") - - val props = classPage.findSectionWithName("Properties").assertNotNull("Properties") - val prop1 = props.children.singleOrNull().assertNotNull("prop1") - - assertEquals( - 2, - prop1.firstChildOfType<ContentDivergentGroup>().children.size, - "Incorrect number of divergent instances found" - ) - - val propPage = root.dfs { it.name == "prop1" } as? MemberPageNode - assertNotNull(propPage, "Tested method not found!") - - val divergentGroup = propPage.content.dfs { it is ContentDivergentGroup } as? ContentDivergentGroup - - assertEquals( - 2, - divergentGroup?.childrenOfType<ContentDivergentInstance>()?.size, - "Incorrect number of divergent instances found in method page" - ) - } - } - } - - @Test - fun `should merge enum and class`() { - testInline( - """ - |/src/jvmMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |class classA { - | val prop1: String - |} - | - |/src/jsMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |enum class classA { - | ENTRY - |} - | - """.trimMargin(), - configuration(true), - cleanupOutput = true - ) { - pagesTransformationStage = { root -> - val classPage = root.dfs { it.name == "classA" } as? ClasslikePageNode - assertNotNull(classPage, "Tested class not found!") - - val entries = classPage.content.findTabWithType(BasicTabbedContentType.ENTRY).assertNotNull("Entries") - entries.children.singleOrNull().assertNotNull("ENTRY") - - val props = classPage.findSectionWithName("Properties").assertNotNull("Properties") - assertEquals( - 3, - props.children.size, - "Incorrect number of properties found in method page" - ) - } - } - } - - fun PageNode.childrenRec(): List<PageNode> = listOf(this) + children.flatMap { it.childrenRec() } - - @Test - fun `should merge enum entries`() { - testInline( - """ - |/src/jvmMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |enum class classA { - | SMTH; - | fun method1(): Int - |} - | - |/src/jsMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |enum class classA { - | SMTH; - | fun method1(): Int - |} - | - """.trimMargin(), - configuration(true), - cleanupOutput = true - ) { - pagesTransformationStage = { root -> - val classPage = root.dfs { it.name == "SMTH" } as? ClasslikePageNode - assertNotNull(classPage, "Tested class not found!") - - val functions = classPage.findSectionWithName("Functions").assertNotNull("Functions") - val method1 = functions.children.single { it.sourceSets.size == 2 && it.dci.dri.singleOrNull()?.callable?.name == "method1" } - .assertNotNull("method1") - - assertEquals( - 2, - method1.firstChildOfType<ContentDivergentGroup>().childrenOfType<ContentDivergentInstance>().size, - "Incorrect number of divergent instances found" - ) - } - } - } - - /** - * There is a case when a property and fun from different source sets - * have the same name so pages have the same urls respectively. - */ - @Test - fun `should no merge prop and method with the same name`() { - testInline( - """ - |/src/jvmMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |class classA { - | fun merged():String - |} - | - |/src/jsMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |class classA { - | val merged:String - |} - | - """.trimMargin(), - configuration(true), - cleanupOutput = true - ) { - pagesTransformationStage = { root -> - val allChildren = root.childrenRec().filterIsInstance<MemberPageNode>() - - assertEquals( - 1, - allChildren.filter { it.name == "merged" }.size, - "Incorrect number of fun pages" - ) - } - } - } - - @Test - fun `should always merge constructor`() { - testInline( - """ - |/src/commonMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |expect class classA(a: Int) - | - |/src/jsMain/kotlin/pageMerger/Test.kt - |package pageMerger - | - |actual class classA(a: Int) - """.trimMargin(), - configuration(false), - cleanupOutput = true - ) { - pagesTransformationStage = { root -> - val classPage = root.dfs { it.name == "classA" } as? ClasslikePageNode - assertNotNull(classPage, "Tested class not found!") - - val constructors = classPage.findSectionWithName("Constructors").assertNotNull("Constructors") - - assertEquals( - 1, - constructors.children.size, - "Incorrect number of constructors" - ) - - val platformHinted = constructors.dfs { it is PlatformHintedContent } as? PlatformHintedContent - - assertEquals( - 2, - platformHinted?.sourceSets?.size, - "Incorrect number of source sets" - ) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/transformers/ModuleAndPackageDocumentationTransformerFunctionalTest.kt b/plugins/base/src/test/kotlin/transformers/ModuleAndPackageDocumentationTransformerFunctionalTest.kt deleted file mode 100644 index 54f0120a..00000000 --- a/plugins/base/src/test/kotlin/transformers/ModuleAndPackageDocumentationTransformerFunctionalTest.kt +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package transformers - -import org.jetbrains.dokka.DokkaSourceSetID -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.junit.jupiter.api.io.TempDir -import transformers.AbstractContextModuleAndPackageDocumentationReaderTest.Companion.texts -import utils.OnlyDescriptorsMPP -import java.nio.file.Path -import kotlin.test.Test -import kotlin.test.assertEquals - -class ModuleAndPackageDocumentationTransformerFunctionalTest : BaseAbstractTest() { - - @OnlyDescriptorsMPP("#3238") - @Test - fun `multiplatform project`(@TempDir tempDir: Path) { - val include = tempDir.resolve("include.md").toFile() - include.writeText( - """ - # Module moduleA - This is moduleA - - # Package - This is the root package - - # Package [root] - This is also the root package - - # Package common - This is the common package - - # Package jvm - This is the jvm package - - # Package js - This is the js package - """.trimIndent() - ) - val configuration = dokkaConfiguration { - moduleName = "moduleA" - sourceSets { - sourceSet { - name = "commonMain" - displayName = "common" - analysisPlatform = "common" - sourceRoots = listOf("src/commonMain/kotlin") - includes = listOf(include.canonicalPath) - } - sourceSet { - name = "jsMain" - displayName = "js" - analysisPlatform = "js" - sourceRoots = listOf("src/jsMain/kotlin") - dependentSourceSets = setOf(DokkaSourceSetID("moduleA", "commonMain")) - includes = listOf(include.canonicalPath) - } - sourceSet { - name = "jvmMain" - displayName = "jvm" - analysisPlatform = "jvm" - sourceRoots = listOf("src/jvmMain/kotlin") - dependentSourceSets = setOf(DokkaSourceSetID("moduleA", "commonMain")) - includes = listOf(include.canonicalPath) - } - } - } - - testInline( - """ - /src/commonMain/kotlin/common/CommonApi.kt - package common - val commonApi = "common" - - /src/jsMain/kotlin/js/JsApi.kt - package js - val jsApi = "js" - - /src/jvmMain/kotlin/jvm/JvmApi.kt - package jvm - val jvmApi = "jvm" - - /src/commonMain/kotlin/CommonRoot.kt - val commonRoot = "commonRoot" - - /src/jsMain/kotlin/JsRoot.kt - val jsRoot = "jsRoot" - - /src/jvmMain/kotlin/JvmRoot.kt - val jvmRoot = "jvmRoot" - """.trimIndent(), - configuration - ) { - this.documentablesMergingStage = { module -> - val packageNames = module.packages.map { it.dri.packageName ?: "NULL" } - assertEquals( - listOf("", "common", "js", "jvm").sorted(), packageNames.sorted(), - "Expected all packages to be present" - ) - - /* Assert module documentation */ - assertEquals(3, module.documentation.keys.size, "Expected all three source sets") - assertEquals("This is moduleA", module.documentation.texts.distinct().joinToString()) - - /* Assert root package */ - val rootPackage = module.packages.single { it.dri.packageName == "" } - assertEquals(3, rootPackage.documentation.keys.size, "Expected all three source sets") - assertEquals( - listOf("This is the root package", "This is also the root package"), - rootPackage.documentation.texts.distinct() - ) - - /* Assert common package */ - val commonPackage = module.packages.single { it.dri.packageName == "common" } - assertEquals(3, commonPackage.documentation.keys.size, "Expected all three source sets") - assertEquals("This is the common package", commonPackage.documentation.texts.distinct().joinToString()) - - /* Assert js package */ - val jsPackage = module.packages.single { it.dri.packageName == "js" } - assertEquals( - "This is the js package", - jsPackage.documentation.texts.joinToString() - ) - - /* Assert the jvm package */ - val jvmPackage = module.packages.single { it.dri.packageName == "jvm" } - assertEquals( - "This is the jvm package", - jvmPackage.documentation.texts.joinToString() - ) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/transformers/ModuleAndPackageDocumentationTransformerUnitTest.kt b/plugins/base/src/test/kotlin/transformers/ModuleAndPackageDocumentationTransformerUnitTest.kt deleted file mode 100644 index a54b6c68..00000000 --- a/plugins/base/src/test/kotlin/transformers/ModuleAndPackageDocumentationTransformerUnitTest.kt +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package transformers - - -import org.jetbrains.dokka.DokkaConfiguration -import org.jetbrains.dokka.analysis.kotlin.internal.ModuleAndPackageDocumentationReader -import org.jetbrains.dokka.analysis.markdown.jb.MARKDOWN_ELEMENT_FILE_NAME -import org.jetbrains.dokka.base.transformers.documentables.ModuleAndPackageDocumentationTransformer -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.model.DModule -import org.jetbrains.dokka.model.DPackage -import org.jetbrains.dokka.model.SourceSetDependent -import org.jetbrains.dokka.model.doc.CustomDocTag -import org.jetbrains.dokka.model.doc.Description -import org.jetbrains.dokka.model.doc.DocumentationNode -import org.jetbrains.dokka.model.doc.Text -import testApi.testRunner.dPackage -import testApi.testRunner.sourceSet -import kotlin.test.Test -import kotlin.test.assertEquals - - -class ModuleAndPackageDocumentationTransformerUnitTest { - - @Test - fun `empty list of modules`() { - val transformer = ModuleAndPackageDocumentationTransformer( - object : ModuleAndPackageDocumentationReader { - override fun read(module: DModule): SourceSetDependent<DocumentationNode> = throw NotImplementedError() - override fun read(pkg: DPackage): SourceSetDependent<DocumentationNode> = throw NotImplementedError() - override fun read(module: DokkaConfiguration.DokkaModuleDescription): DocumentationNode = throw NotImplementedError() - } - ) - - assertEquals( - emptyList<DModule>(), transformer(emptyList()), - ) - } - - @Test - fun `single module documentation`() { - val transformer = ModuleAndPackageDocumentationTransformer( - object : ModuleAndPackageDocumentationReader { - override fun read(pkg: DPackage): SourceSetDependent<DocumentationNode> = throw NotImplementedError() - override fun read(module: DModule): SourceSetDependent<DocumentationNode> { - return module.sourceSets.associateWith { sourceSet -> - documentationNode("doc" + sourceSet.displayName) - } - } - override fun read(module: DokkaConfiguration.DokkaModuleDescription): DocumentationNode = throw NotImplementedError() - } - ) - - val result = transformer( - listOf( - DModule( - "ModuleName", - documentation = emptyMap(), - packages = emptyList(), - sourceSets = setOf( - sourceSet("A"), - sourceSet("B") - ) - ) - ) - ) - - assertEquals( - DModule( - "ModuleName", - documentation = mapOf( - sourceSet("A") to documentationNode("docA"), - sourceSet("B") to documentationNode("docB") - ), - sourceSets = setOf(sourceSet("A"), sourceSet("B")), - packages = emptyList() - ), - result.single() - ) - - } - - @Test - fun `merges with already existing module documentation`() { - val transformer = ModuleAndPackageDocumentationTransformer( - object : ModuleAndPackageDocumentationReader { - override fun read(pkg: DPackage): SourceSetDependent<DocumentationNode> = throw NotImplementedError() - override fun read(module: DModule): SourceSetDependent<DocumentationNode> { - /* Only add documentation for first source set */ - return module.sourceSets.take(1).associateWith { sourceSet -> - documentationNode("doc" + sourceSet.displayName) - } - } - override fun read(module: DokkaConfiguration.DokkaModuleDescription): DocumentationNode = throw NotImplementedError() - } - ) - - val result = transformer( - listOf( - DModule( - "MyModule", - documentation = mapOf( - sourceSet("A") to documentationNode("pre-existing:A"), - sourceSet("B") to documentationNode("pre-existing:B") - ), - sourceSets = setOf(sourceSet("A"), sourceSet("B")), - packages = emptyList() - ) - ) - ) - - assertEquals( - DModule( - "MyModule", - documentation = mapOf( - /* Expect previous documentation and newly attached one */ - sourceSet("A") to documentationNode("pre-existing:A", "docA"), - /* Only first source set will get documentation attached */ - sourceSet("B") to documentationNode("pre-existing:B") - ), - sourceSets = setOf(sourceSet("A"), sourceSet("B")), - packages = emptyList() - ), - result.single() - ) - } - - @Test - fun `package documentation`() { - val transformer = ModuleAndPackageDocumentationTransformer( - object : ModuleAndPackageDocumentationReader { - override fun read(module: DModule): SourceSetDependent<DocumentationNode> = emptyMap() - override fun read(pkg: DPackage): SourceSetDependent<DocumentationNode> { - /* Only attach documentation to packages with 'attach' */ - if ("attach" !in pkg.dri.packageName.orEmpty()) return emptyMap() - /* Only attach documentation to two source sets */ - return pkg.sourceSets.take(2).associateWith { sourceSet -> - documentationNode("doc:${sourceSet.displayName}:${pkg.dri.packageName}") - } - } - override fun read(module: DokkaConfiguration.DokkaModuleDescription): DocumentationNode = throw NotImplementedError() - } - ) - - val result = transformer( - listOf( - DModule( - "MyModule", - documentation = emptyMap(), - sourceSets = emptySet(), - packages = listOf( - dPackage( - dri = DRI("com.sample"), - documentation = mapOf( - sourceSet("A") to documentationNode("pre-existing:A:com.sample") - ), - sourceSets = setOf(sourceSet("A"), sourceSet("B"), sourceSet("C")), - ), - dPackage( - dri = DRI("com.attach"), - documentation = mapOf( - sourceSet("A") to documentationNode("pre-existing:A:com.attach") - ), - sourceSets = setOf(sourceSet("A"), sourceSet("B"), sourceSet("C")) - ), - dPackage( - dri = DRI("com.attach.sub"), - documentation = mapOf( - sourceSet("A") to documentationNode("pre-existing:A:com.attach.sub"), - sourceSet("B") to documentationNode("pre-existing:B:com.attach.sub"), - sourceSet("C") to documentationNode("pre-existing:C:com.attach.sub") - ), - sourceSets = setOf(sourceSet("A"), sourceSet("B"), sourceSet("C")), - ) - ) - ) - ) - ) - - result.single().packages.forEach { pkg -> - assertEquals( - setOf(sourceSet("A"), sourceSet("B"), sourceSet("C")), pkg.sourceSets, - "Expected source sets A, B, C for package ${pkg.dri.packageName}" - ) - } - - val comSample = result.single().packages.single { it.dri.packageName == "com.sample" } - assertEquals( - mapOf(sourceSet("A") to documentationNode("pre-existing:A:com.sample")), - comSample.documentation, - "Expected no documentation added to package 'com.sample' because of wrong package" - ) - - val comAttach = result.single().packages.single { it.dri.packageName == "com.attach" } - assertEquals( - mapOf( - sourceSet("A") to documentationNode("pre-existing:A:com.attach", "doc:A:com.attach"), - sourceSet("B") to documentationNode("doc:B:com.attach") - ), - comAttach.documentation, - "Expected documentation added to source sets A and B" - ) - - assertEquals( - DModule( - "MyModule", - documentation = emptyMap(), - sourceSets = emptySet(), - packages = listOf( - dPackage( - dri = DRI("com.sample"), - documentation = mapOf( - /* No documentation added, since in wrong package */ - sourceSet("A") to documentationNode("pre-existing:A:com.sample") - ), - sourceSets = setOf(sourceSet("A"), sourceSet("B"), sourceSet("C")), - - ), - dPackage( - dri = DRI("com.attach"), - documentation = mapOf( - /* Documentation added */ - sourceSet("A") to documentationNode("pre-existing:A:com.attach", "doc:A:com.attach"), - sourceSet("B") to documentationNode("doc:B:com.attach") - ), - sourceSets = setOf(sourceSet("A"), sourceSet("B"), sourceSet("C")), - ), - dPackage( - dri = DRI("com.attach.sub"), - documentation = mapOf( - /* Documentation added */ - sourceSet("A") to documentationNode( - "pre-existing:A:com.attach.sub", - "doc:A:com.attach.sub" - ), - /* Documentation added */ - sourceSet("B") to documentationNode( - "pre-existing:B:com.attach.sub", - "doc:B:com.attach.sub" - ), - /* No documentation added, since in wrong source set */ - sourceSet("C") to documentationNode("pre-existing:C:com.attach.sub") - ), - sourceSets = setOf(sourceSet("A"), sourceSet("B"), sourceSet("C")), - ) - ) - ), result.single() - ) - } - - - private fun documentationNode(vararg texts: String): DocumentationNode { - return DocumentationNode( - texts.toList() - .map { Description(CustomDocTag(listOf(Text(it)), name = MARKDOWN_ELEMENT_FILE_NAME)) }) - } -} diff --git a/plugins/base/src/test/kotlin/transformers/ObviousAndInheritedFunctionsDocumentableFilterTest.kt b/plugins/base/src/test/kotlin/transformers/ObviousAndInheritedFunctionsDocumentableFilterTest.kt deleted file mode 100644 index d035948f..00000000 --- a/plugins/base/src/test/kotlin/transformers/ObviousAndInheritedFunctionsDocumentableFilterTest.kt +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package transformers - -import org.jetbrains.dokka.DokkaConfigurationImpl -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.MethodSource -import testApi.testRunner.dokkaConfiguration -import kotlin.test.assertEquals - -class ObviousAndInheritedFunctionsDocumentableFilterTest : BaseAbstractTest() { - companion object { - @JvmStatic - fun suppressingObviousConfiguration() = listOf(dokkaConfiguration { - suppressInheritedMembers = false - suppressObviousFunctions = true - sourceSets { - sourceSet { - sourceRoots = listOf("src") - } - } - }) - - @JvmStatic - fun nonSuppressingObviousConfiguration() = listOf(dokkaConfiguration { - suppressObviousFunctions = false - suppressInheritedMembers = false - sourceSets { - sourceSet { - sourceRoots = listOf("src") - } - } - }) - - @JvmStatic - fun suppressingInheritedConfiguration() = listOf(dokkaConfiguration { - suppressInheritedMembers = true - suppressObviousFunctions = false - sourceSets { - sourceSet { - sourceRoots = listOf("src") - } - } - }) - - @JvmStatic - fun nonSuppressingInheritedConfiguration() = listOf(dokkaConfiguration { - suppressObviousFunctions = false - suppressInheritedMembers = false - sourceSets { - sourceSet { - sourceRoots = listOf("src") - } - } - }) - } - - - @ParameterizedTest - @MethodSource(value = ["suppressingObviousConfiguration"]) - fun `should suppress toString, equals and hashcode`(suppressingConfiguration: DokkaConfigurationImpl) { - testInline( - """ - /src/suppressed/Suppressed.kt - package suppressed - data class Suppressed(val x: String) - """.trimIndent(), - suppressingConfiguration - ) { - preMergeDocumentablesTransformationStage = { modules -> - val functions = modules.flatMap { it.packages }.flatMap { it.classlikes }.flatMap { it.functions } - assertEquals(0, functions.size) - } - } - } - - @ParameterizedTest - @MethodSource(value = ["suppressingObviousConfiguration", "suppressingInheritedConfiguration"]) - fun `should suppress toString, equals and hashcode for interface`(suppressingConfiguration: DokkaConfigurationImpl) { - testInline( - """ - /src/suppressed/Suppressed.kt - package suppressed - interface Suppressed - """.trimIndent(), - suppressingConfiguration - ) { - preMergeDocumentablesTransformationStage = { modules -> - val functions = modules.flatMap { it.packages }.flatMap { it.classlikes }.flatMap { it.functions } - assertEquals(0, functions.size) - } - } - } - - @ParameterizedTest - @MethodSource(value = ["suppressingObviousConfiguration", "suppressingInheritedConfiguration"]) - fun `should suppress toString, equals and hashcode in Java`(suppressingConfiguration: DokkaConfigurationImpl) { - testInline( - """ - /src/suppressed/Suppressed.java - package suppressed; - public class Suppressed { - } - """.trimIndent(), - suppressingConfiguration - ) { - preMergeDocumentablesTransformationStage = { modules -> - val functions = modules.flatMap { it.packages }.flatMap { it.classlikes }.flatMap { it.functions } - assertEquals(0, functions.size) - } - } - } - - @ParameterizedTest - @MethodSource(value = ["suppressingObviousConfiguration"]) - fun `should suppress toString, equals and hashcode but keep custom ones`(suppressingConfiguration: DokkaConfigurationImpl) { - testInline( - """ - /src/suppressed/Suppressed.kt - package suppressed - data class Suppressed(val x: String) { - override fun toString(): String { - return "custom" - } - } - """.trimIndent(), - suppressingConfiguration - ) { - preMergeDocumentablesTransformationStage = { modules -> - val functions = modules.flatMap { it.packages }.flatMap { it.classlikes }.flatMap { it.functions } - assertEquals(listOf("toString"), functions.map { it.name }) - } - } - } - - @ParameterizedTest - @MethodSource(value = ["suppressingObviousConfiguration", "suppressingInheritedConfiguration"]) - fun `should suppress toString, equals and hashcode but keep custom ones in Java`(suppressingConfiguration: DokkaConfigurationImpl) { - testInline( - """ - /src/suppressed/Suppressed.java - package suppressed; - public class Suppressed { - @Override - public String toString() { - return ""; - } - } - """.trimIndent(), - suppressingConfiguration - ) { - preMergeDocumentablesTransformationStage = { modules -> - val functions = modules.flatMap { it.packages }.flatMap { it.classlikes }.flatMap { it.functions } - assertEquals(listOf("toString"), functions.map { it.name }) - } - } - } - - @ParameterizedTest - @MethodSource(value = ["nonSuppressingObviousConfiguration", "nonSuppressingInheritedConfiguration"]) - fun `should not suppress toString, equals and hashcode if custom config is provided`(nonSuppressingConfiguration: DokkaConfigurationImpl) { - testInline( - """ - /src/suppressed/Suppressed.kt - package suppressed - data class Suppressed(val x: String) - """.trimIndent(), - nonSuppressingConfiguration - ) { - preMergeDocumentablesTransformationStage = { modules -> - val functions = modules.flatMap { it.packages }.flatMap { it.classlikes }.flatMap { it.functions } - assertEquals( - listOf("copy", "equals", "toString", "component1", "hashCode").sorted(), - functions.map { it.name }.sorted() - ) - } - } - } - - @ParameterizedTest - @MethodSource(value = ["nonSuppressingObviousConfiguration", "nonSuppressingInheritedConfiguration"]) - fun `not should suppress toString, equals and hashcode for interface if custom config is provided`(nonSuppressingConfiguration: DokkaConfigurationImpl) { - testInline( - """ - /src/suppressed/Suppressed.kt - package suppressed - interface Suppressed - """.trimIndent(), - nonSuppressingConfiguration - ) { - preMergeDocumentablesTransformationStage = { modules -> - val functions = modules.flatMap { it.packages }.flatMap { it.classlikes }.flatMap { it.functions } - assertEquals(listOf("equals", "hashCode", "toString").sorted(), functions.map { it.name }.sorted()) - } - } - } - - @ParameterizedTest - @MethodSource(value = ["nonSuppressingObviousConfiguration", "nonSuppressingInheritedConfiguration"]) - fun `should not suppress toString, equals and hashcode if custom config is provided in Java`(nonSuppressingConfiguration: DokkaConfigurationImpl) { - testInline( - """ - /src/suppressed/Suppressed.java - package suppressed; - public class Suppressed { - } - """.trimIndent(), - nonSuppressingConfiguration - ) { - preMergeDocumentablesTransformationStage = { modules -> - val functions = modules.flatMap { it.packages }.flatMap { it.classlikes }.flatMap { it.functions } - //I would normally just assert names but this would make it JDK dependent, so this is better - assertEquals( - 5, - setOf( - "equals", - "hashCode", - "toString", - "notify", - "notifyAll" - ).intersect(functions.map { it.name }).size - ) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/transformers/ReportUndocumentedTransformerTest.kt b/plugins/base/src/test/kotlin/transformers/ReportUndocumentedTransformerTest.kt deleted file mode 100644 index c824e690..00000000 --- a/plugins/base/src/test/kotlin/transformers/ReportUndocumentedTransformerTest.kt +++ /dev/null @@ -1,927 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package transformers - -import org.jetbrains.dokka.DokkaConfiguration -import org.jetbrains.dokka.DokkaDefaults -import org.jetbrains.dokka.PackageOptionsImpl -import org.jetbrains.dokka.Platform -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import kotlin.test.Ignore -import kotlin.test.Test -import kotlin.test.assertEquals - - -class ReportUndocumentedTransformerTest : BaseAbstractTest() { - @Test - fun `undocumented class gets reported`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - reportUndocumented = true - sourceRoots = listOf("src/main/kotlin/Test.kt") - } - } - } - - testInline( - """ - |/src/main/kotlin/Test.kt - |package sample - | - |class X - """.trimMargin(), - configuration - ) { - pagesTransformationStage = { - assertNoUndocumentedReport(Regex("init")) - assertSingleUndocumentedReport(Regex("""sample/X/""")) - } - } - } - - @Test - fun `undocumented non-public class does not get reported`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - reportUndocumented = true - sourceRoots = listOf("src/main/kotlin/Test.kt") - } - } - } - - testInline( - """ - |/src/main/kotlin/Test.kt - |package sample - | - |internal class X - """.trimMargin(), - configuration - ) { - pagesTransformationStage = { - assertNoUndocumentedReport() - } - } - } - - @Test - fun `undocumented function gets reported`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - reportUndocumented = true - sourceRoots = listOf("src/main/kotlin/Test.kt") - } - } - } - - testInline( - """ - |/src/main/kotlin/Test.kt - |package sample - | - |/** Documented */ - |class X { - | fun x() - |} - """.trimMargin(), - configuration - ) { - pagesTransformationStage = { - assertSingleUndocumentedReport(Regex("X")) - assertSingleUndocumentedReport(Regex("X/x")) - } - } - } - - @Test - fun `undocumented property gets reported`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - reportUndocumented = true - sourceRoots = listOf("src/main/kotlin/Test.kt") - } - } - } - - testInline( - """ - |/src/main/kotlin/Test.kt - |package sample - | - |/** Documented */ - |class X { - | val x: Int = 0 - |} - """.trimMargin(), - configuration - ) { - pagesTransformationStage = { - assertSingleUndocumentedReport(Regex("X")) - assertSingleUndocumentedReport(Regex("X/x")) - } - } - } - - @Test - fun `undocumented primary constructor does not get reported`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - reportUndocumented = true - sourceRoots = listOf("src/main/kotlin/Test.kt") - } - } - } - - testInline( - """ - |/src/main/kotlin/Test.kt - |package sample - | - |/** Documented */ - |class X(private val x: Int) { - |} - """.trimMargin(), - configuration - ) { - pagesTransformationStage = { - assertNoUndocumentedReport() - } - } - } - - @Test - fun `data class component functions do not get reported`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - reportUndocumented = true - sourceRoots = listOf("src/main/kotlin") - } - } - } - - testInline( - """ - |/src/main/kotlin/Test.kt - |package sample - | - |/** Documented */ - |data class X(val x: Int) { - |} - """.trimMargin(), - configuration - ) { - pagesTransformationStage = { - assertNoUndocumentedReport(Regex("component")) - assertNumberOfUndocumentedReports(1) - } - } - } - - @Ignore - @Test - fun `undocumented secondary constructor gets reported`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - reportUndocumented = true - sourceRoots = listOf("src/main/kotlin/Test.kt") - } - } - } - - testInline( - """ - |/src/main/kotlin/Test.kt - |package sample - | - |/** Documented */ - |class X { - | constructor(unit: Unit) : this() - |} - """.trimMargin(), - configuration - ) { - pagesTransformationStage = { - assertSingleUndocumentedReport(Regex("X")) - assertSingleUndocumentedReport(Regex("X.*init.*Unit")) - } - } - } - - @Test - fun `undocumented inherited function does not get reported`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - reportUndocumented = true - sourceRoots = listOf("src/main/kotlin/Test.kt") - } - } - } - - testInline( - """ - |/src/main/kotlin/Test.kt - |package sample - | - |/** Documented */ - |open class A { - | fun a() = Unit - |} - | - |/** Documented */ - |class B : A() - """.trimMargin(), - configuration - ) { - pagesTransformationStage = { - assertNoUndocumentedReport(Regex("B")) - assertSingleUndocumentedReport(Regex("A.*a")) - } - } - } - - @Test - fun `undocumented inherited property does not get reported`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - reportUndocumented = true - sourceRoots = listOf("src/main/kotlin/Test.kt") - } - } - } - - testInline( - """ - |/src/main/kotlin/Test.kt - |package sample - | - |/** Documented */ - |open class A { - | val a = Unit - |} - | - |/** Documented */ - |class B : A() - """.trimMargin(), - configuration - ) { - pagesTransformationStage = { - assertNoUndocumentedReport(Regex("B")) - assertSingleUndocumentedReport(Regex("A.*a")) - } - } - } - - @Test - fun `overridden function does not get reported when super is documented`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - reportUndocumented = true - sourceRoots = listOf("src/main/kotlin/Test.kt") - } - } - } - - testInline( - """ - |/src/main/kotlin/Test.kt - |package sample - |import kotlin.Exception - | - |/** Documented */ - |open class A { - | /** Documented */ - | fun a() = Unit - |} - | - |/** Documented */ - |class B : A() { - | override fun a() = throw Exception() - |} - """.trimMargin(), - configuration - ) { - pagesTransformationStage = { - assertNoUndocumentedReport() - } - } - } - - @Test - fun `overridden property does not get reported when super is documented`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - reportUndocumented = true - sourceRoots = listOf("src/main/kotlin/Test.kt") - } - } - } - - testInline( - """ - |/src/main/kotlin/Test.kt - |package sample - |import kotlin.Exception - | - |/** Documented */ - |open class A { - | /** Documented */ - | open val a = 0 - |} - | - |/** Documented */ - |class B : A() { - | override val a = 1 - |} - """.trimMargin(), - configuration - ) { - pagesTransformationStage = { - assertNoUndocumentedReport() - } - } - } - - @Test - fun `report disabled by source set`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - reportUndocumented = false - sourceRoots = listOf("src/main/kotlin/Test.kt") - } - } - } - - testInline( - """ - |/src/main/kotlin/Test.kt - |package sample - | - |class X - """.trimMargin(), - configuration - ) { - pagesTransformationStage = { - assertNoUndocumentedReport() - } - } - } - - @Test - fun `report enabled by package configuration`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - perPackageOptions += packageOptions( - matchingRegex = "sample.*", - reportUndocumented = true, - ) - reportUndocumented = false - sourceRoots = listOf("src/main/kotlin/Test.kt") - } - } - } - - testInline( - """ - |/src/main/kotlin/Test.kt - |package sample - | - |class X - """.trimMargin(), - configuration - ) { - pagesTransformationStage = { - assertSingleUndocumentedReport(Regex("X")) - } - } - } - - @Test - fun `report enabled by more specific package configuration`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - perPackageOptions += packageOptions( - matchingRegex = "sample.*", - reportUndocumented = false, - ) - perPackageOptions += packageOptions( - matchingRegex = "sample.enabled.*", - reportUndocumented = true, - ) - reportUndocumented = false - sourceRoots = listOf("src/main/kotlin/") - } - } - } - - testInline( - """ - |/src/main/kotlin/sample/disabled/Disabled.kt - |package sample.disabled - |class Disabled - | - |/src/main/kotlin/sample/enabled/Enabled.kt - |package sample.enabled - |class Enabled - """.trimMargin(), - configuration - ) { - pagesTransformationStage = { - assertSingleUndocumentedReport(Regex("Enabled")) - assertNumberOfUndocumentedReports(1) - } - } - } - - @Test - fun `report disabled by more specific package configuration`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - perPackageOptions += packageOptions( - matchingRegex = "sample.*", - reportUndocumented = true, - ) - perPackageOptions += packageOptions( - matchingRegex = "sample.disabled.*", - reportUndocumented = false, - ) - reportUndocumented = true - sourceRoots = listOf("src/main/kotlin/") - } - } - } - - testInline( - """ - |/src/main/kotlin/sample/disabled/Disabled.kt - |package sample.disabled - |class Disabled - | - |/src/main/kotlin/sample/enabled/Enabled.kt - |package sample.enabled - |class Enabled - """.trimMargin(), - configuration - ) { - pagesTransformationStage = { - assertSingleUndocumentedReport(Regex("Enabled")) - assertNumberOfUndocumentedReports(1) - } - } - } - - @Test - fun `multiplatform undocumented class gets reported`() { - val configuration = dokkaConfiguration { - sourceSets { - val commonMain by sourceSet { - reportUndocumented = true - analysisPlatform = Platform.common.toString() - name = "commonMain" - displayName = "commonMain" - sourceRoots = listOf("src/commonMain/kotlin") - } - - sourceSet { - reportUndocumented = true - analysisPlatform = Platform.jvm.toString() - name = "jvmMain" - displayName = "jvmMain" - sourceRoots = listOf("src/jvmMain/kotlin") - dependentSourceSets = setOf(commonMain.sourceSetID) - } - } - } - - testInline( - """ - |/src/commonMain/kotlin/sample/Common.kt - |package sample - |expect class X - | - |/src/jvmMain/kotlin/sample/JvmMain.kt - |package sample - |actual class X - """.trimMargin(), - configuration - ) { - pagesTransformationStage = { - assertNumberOfUndocumentedReports(2, Regex("X")) - assertSingleUndocumentedReport(Regex("X.*jvmMain")) - assertSingleUndocumentedReport(Regex("X.*commonMain")) - } - } - } - - @Test - fun `multiplatform undocumented class does not get reported if expect is documented`() { - val configuration = dokkaConfiguration { - sourceSets { - val commonMain by sourceSet { - reportUndocumented = true - analysisPlatform = Platform.common.toString() - name = "commonMain" - displayName = "commonMain" - sourceRoots = listOf("src/commonMain/kotlin") - } - - sourceSet { - reportUndocumented = true - analysisPlatform = Platform.jvm.toString() - name = "jvmMain" - displayName = "jvmMain" - sourceRoots = listOf("src/jvmMain/kotlin") - dependentSourceSets = setOf(commonMain.sourceSetID) - } - } - } - - testInline( - """ - |/src/commonMain/kotlin/sample/Common.kt - |package sample - |/** Documented */ - |expect class X - | - |/src/jvmMain/kotlin/sample/JvmMain.kt - |package sample - |actual class X - """.trimMargin(), - configuration - ) { - pagesTransformationStage = { - assertNumberOfUndocumentedReports(0) - } - } - } - - @Test - fun `multiplatform undocumented function gets reported`() { - val configuration = dokkaConfiguration { - sourceSets { - val commonMain by sourceSet { - reportUndocumented = true - analysisPlatform = Platform.common.toString() - name = "commonMain" - displayName = "commonMain" - sourceRoots = listOf("src/commonMain/kotlin") - } - - sourceSet { - reportUndocumented = true - analysisPlatform = Platform.jvm.toString() - name = "jvmMain" - displayName = "jvmMain" - sourceRoots = listOf("src/jvmMain/kotlin") - dependentSourceSets = setOf(commonMain.sourceSetID) - } - - sourceSet { - reportUndocumented = true - analysisPlatform = Platform.native.toString() - name = "macosMain" - displayName = "macosMain" - sourceRoots = listOf("src/macosMain/kotlin") - dependentSourceSets = setOf(commonMain.sourceSetID) - } - } - } - - testInline( - """ - |/src/commonMain/kotlin/sample/Common.kt - |package sample - |expect fun x() - | - |/src/macosMain/kotlin/sample/MacosMain.kt - |package sample - |/** Documented */ - |actual fun x() = Unit - | - |/src/jvmMain/kotlin/sample/JvmMain.kt - |package sample - |actual fun x() = Unit - """.trimMargin(), - configuration - ) { - pagesTransformationStage = { - assertNumberOfUndocumentedReports(2) - assertSingleUndocumentedReport(Regex("x.*commonMain")) - assertSingleUndocumentedReport(Regex("x.*jvmMain")) - } - } - } - - @Test - fun `java undocumented class gets reported`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - reportUndocumented = true - sourceRoots = listOf("src/main/java") - } - } - } - - testInline( - """ - |/src/main/java/sample/Test.java - |package sample - |public class Test { } - """.trimMargin(), - configuration - ) { - pagesTransformationStage = { - assertNoUndocumentedReport(Regex("init")) - assertSingleUndocumentedReport(Regex("""Test""")) - assertNumberOfUndocumentedReports(1) - } - } - } - - @Test - fun `java undocumented non-public class does not get reported`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - reportUndocumented = true - sourceRoots = listOf("src/main/java") - } - } - } - - testInline( - """ - |/src/main/java/sample/Test.java - |package sample - |class Test { } - """.trimMargin(), - configuration - ) { - pagesTransformationStage = { - assertNoUndocumentedReport() - } - } - } - - @Test - fun `java undocumented constructor does not get reported`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - reportUndocumented = true - sourceRoots = listOf("src/main/java") - } - } - } - - testInline( - """ - |/src/main/java/sample/Test.java - |package sample - |/** Documented */ - |public class Test { - | public Test() { - | } - |} - """.trimMargin(), - configuration - ) { - pagesTransformationStage = { - assertNoUndocumentedReport() - } - } - } - - @Test - fun `java undocumented method gets reported`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - reportUndocumented = true - sourceRoots = listOf("src/main/java") - } - } - } - - testInline( - """ - |/src/main/java/sample/X.java - |package sample - |/** Documented */ - |public class X { - | public void x { } - |} - """.trimMargin(), - configuration - ) { - pagesTransformationStage = { - assertSingleUndocumentedReport(Regex("X")) - assertSingleUndocumentedReport(Regex("X.*x")) - assertNumberOfUndocumentedReports(1) - } - } - } - - @Test - fun `java undocumented property gets reported`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - reportUndocumented = true - sourceRoots = listOf("src/main/java") - } - } - } - - testInline( - """ - |/src/main/java/sample/X.java - |package sample - |/** Documented */ - |public class X { - | public int x = 0; - |} - """.trimMargin(), - configuration - ) { - pagesTransformationStage = { - assertSingleUndocumentedReport(Regex("X")) - assertSingleUndocumentedReport(Regex("X.*x")) - assertNumberOfUndocumentedReports(1) - } - } - } - - @Test - fun `java undocumented inherited method gets reported`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - reportUndocumented = true - sourceRoots = listOf("src/main/java") - } - } - } - - testInline( - """ - |/src/main/java/sample/Super.java - |package sample - |/** Documented */ - |public class Super { - | public void x() {} - |} - | - |/src/main/java/sample/X.java - |package sample - |/** Documented */ - |public class X extends Super { - | public void x() {} - |} - | - """.trimMargin(), - configuration - ) { - pagesTransformationStage = { - assertSingleUndocumentedReport(Regex("X")) - assertSingleUndocumentedReport(Regex("X.*x")) - assertSingleUndocumentedReport(Regex("Super.*x")) - assertNumberOfUndocumentedReports(2) - } - } - } - - @Test - fun `java documented inherited method does not get reported`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - reportUndocumented = true - sourceRoots = listOf("src/main/java") - } - } - } - - testInline( - """ - |/src/main/java/sample/Super.java - |package sample - |/** Documented */ - |public class Super { - | /** Documented */ - | public void x() {} - |} - | - |/src/main/java/sample/X.java - |package sample - |/** Documented */ - |public class X extends Super { - | - |} - | - """.trimMargin(), - configuration - ) { - pagesTransformationStage = { - assertNoUndocumentedReport() - } - } - } - - @Test - fun `java overridden function does not get reported when super is documented`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - reportUndocumented = true - sourceRoots = listOf("src/main/java") - } - } - } - - testInline( - """ - |/src/main/java/sample/Super.java - |package sample - |/** Documented */ - |public class Super { - | /** Documented */ - | public void x() {} - |} - | - |/src/main/java/sample/X.java - |package sample - |/** Documented */ - |public class X extends Super { - | @Override - | public void x() {} - |} - | - """.trimMargin(), - configuration - ) { - pagesTransformationStage = { - assertNoUndocumentedReport() - } - } - } - - private fun assertNumberOfUndocumentedReports(expectedReports: Int, regex: Regex = Regex(".")) { - val reports = logger.warnMessages - .filter { it.startsWith("Undocumented:") } - val matchingReports = reports - .filter { it.contains(regex) } - - assertEquals( - expectedReports, matchingReports.size, - "Expected $expectedReports report of documented code ($regex).\n" + - "Found matching reports: $matchingReports\n" + - "Found reports: $reports" - ) - } - - private fun assertSingleUndocumentedReport(regex: Regex) { - assertNumberOfUndocumentedReports(1, regex) - } - - private fun assertNoUndocumentedReport(regex: Regex) { - assertNumberOfUndocumentedReports(0, regex) - } - - private fun assertNoUndocumentedReport() { - assertNoUndocumentedReport(Regex(".")) - } - - private fun packageOptions( - matchingRegex: String, - reportUndocumented: Boolean?, - includeNonPublic: Boolean = true, - skipDeprecated: Boolean = false, - suppress: Boolean = false, - documentedVisibilities: Set<DokkaConfiguration.Visibility> = DokkaDefaults.documentedVisibilities - ) = PackageOptionsImpl( - matchingRegex = matchingRegex, - reportUndocumented = reportUndocumented, - includeNonPublic = includeNonPublic, - documentedVisibilities = documentedVisibilities, - skipDeprecated = skipDeprecated, - suppress = suppress - ) -} diff --git a/plugins/base/src/test/kotlin/transformers/SourceLinkTransformerTest.kt b/plugins/base/src/test/kotlin/transformers/SourceLinkTransformerTest.kt deleted file mode 100644 index 87424120..00000000 --- a/plugins/base/src/test/kotlin/transformers/SourceLinkTransformerTest.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 transformers - -import org.jetbrains.dokka.DokkaSourceSetID -import org.jetbrains.dokka.SourceLinkDefinitionImpl -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jsoup.nodes.Element -import signatures.renderedContent -import utils.TestOutputWriterPlugin -import java.net.URL -import kotlin.test.Test -import kotlin.test.assertEquals - -class SourceLinkTransformerTest : BaseAbstractTest() { - - private fun Element.getSourceLink() = select(".symbol .floating-right") - .select("a[href]") - .attr("href") - - @Test - fun `source link should lead to name`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - sourceLinks = listOf( - SourceLinkDefinitionImpl( - localDirectory = "src/main/kotlin", - remoteUrl = URL("https://github.com/user/repo/tree/master/src/main/kotlin"), - remoteLineSuffix = "#L" - ) - ) - } - } - } - - val writerPlugin = TestOutputWriterPlugin() - - testInline( - """ - |/src/main/kotlin/basic/Deprecated.kt - |package testpackage - | - |/** - |* Marks the annotated declaration as deprecated. ... - |*/ - |@Target(CLASS, FUNCTION, PROPERTY, ANNOTATION_CLASS, CONSTRUCTOR, PROPERTY_SETTER, PROPERTY_GETTER, TYPEALIAS) - |@MustBeDocumented - |public annotation class Deprecated( - | val message: String, - | val replaceWith: ReplaceWith = ReplaceWith(""), - | val level: DeprecationLevel = DeprecationLevel.WARNING - |) - """.trimMargin(), - configuration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val page = writerPlugin.writer.renderedContent("root/testpackage/-deprecated/index.html") - val sourceLink = page.getSourceLink() - - assertEquals( - "https://github.com/user/repo/tree/master/src/main/kotlin/basic/Deprecated.kt#L8", - sourceLink - ) - } - } - } - - @Test - fun `source link should be for actual typealias`() { - val mppConfiguration = dokkaConfiguration { - moduleName = "test" - sourceSets { - sourceSet { - name = "common" - sourceRoots = listOf("src/main/kotlin/common/Test.kt") - classpath = listOf(commonStdlibPath!!) - externalDocumentationLinks = listOf(stdlibExternalDocumentationLink) - } - sourceSet { - name = "jvm" - dependentSourceSets = setOf(DokkaSourceSetID("test", "common")) - sourceRoots = listOf("src/main/kotlin/jvm/Test.kt") - classpath = listOf(commonStdlibPath!!) - externalDocumentationLinks = listOf(stdlibExternalDocumentationLink) - sourceLinks = listOf( - SourceLinkDefinitionImpl( - localDirectory = "src/main/kotlin", - remoteUrl = URL("https://github.com/user/repo/tree/master/src/main/kotlin"), - remoteLineSuffix = "#L" - ) - ) - } - } - } - - val writerPlugin = TestOutputWriterPlugin() - - testInline( - """ - |/src/main/kotlin/common/Test.kt - |package example - | - |expect class Foo - | - |/src/main/kotlin/jvm/Test.kt - |package example - | - |class Bar - |actual typealias Foo = Bar - | - """.trimMargin(), - mppConfiguration, - pluginOverrides = listOf(writerPlugin) - ) { - renderingStage = { _, _ -> - val page = writerPlugin.writer.renderedContent("test/example/-foo/index.html") - val sourceLink = page.getSourceLink() - - assertEquals( - "https://github.com/user/repo/tree/master/src/main/kotlin/jvm/Test.kt#L4", - sourceLink - ) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/transformers/SuppressTagFilterTest.kt b/plugins/base/src/test/kotlin/transformers/SuppressTagFilterTest.kt deleted file mode 100644 index 5392a028..00000000 --- a/plugins/base/src/test/kotlin/transformers/SuppressTagFilterTest.kt +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package transformers - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.model.DEnum -import org.jetbrains.dokka.model.WithCompanion -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertNotNull -import kotlin.test.assertNull - -class SuppressTagFilterTest : BaseAbstractTest() { - private val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src") - } - } - } - - @Test - fun `should filter classes with suppress tag`() { - testInline( - """ - |/src/suppressed/NotSuppressed.kt - |/** - | * sample docs - |*/ - |class NotSuppressed - |/src/suppressed/Suppressed.kt - |/** - | * sample docs - | * @suppress - |*/ - |class Suppressed - """.trimIndent(), configuration - ) { - preMergeDocumentablesTransformationStage = { modules -> - assertEquals( - "NotSuppressed", - modules.flatMap { it.packages }.flatMap { it.classlikes }.singleOrNull()?.name - ) - } - } - } - - @Test - fun `should filter functions with suppress tag`() { - testInline( - """ - |/src/suppressed/Suppressed.kt - |class Suppressed { - | /** - | * sample docs - | * @suppress - | */ - | fun suppressedFun(){ } - |} - """.trimIndent(), configuration - ) { - preMergeDocumentablesTransformationStage = { modules -> - assertNull(modules.flatMap { it.packages }.flatMap { it.classlikes }.flatMap { it.functions } - .firstOrNull { it.name == "suppressedFun" }) - } - } - } - - @Test - fun `should filter top level functions`() { - testInline( - """ - |/src/suppressed/Suppressed.kt - |/** - | * sample docs - | * @suppress - | */ - |fun suppressedFun(){ } - | - |/** - | * Sample - | */ - |fun notSuppressedFun() { } - """.trimIndent(), configuration - ) { - preMergeDocumentablesTransformationStage = { modules -> - assertNull(modules.flatMap { it.packages }.flatMap { it.functions } - .firstOrNull { it.name == "suppressedFun" }) - } - } - } - - @Test - fun `should filter setter`() { - testInline( - """ - |/src/suppressed/Suppressed.kt - |var property: Int - |/** @suppress */ - |private set - """.trimIndent(), configuration - ) { - preMergeDocumentablesTransformationStage = { modules -> - val prop = modules.flatMap { it.packages }.flatMap { it.properties } - .find { it.name == "property" } - assertNotNull(prop) - assertNotNull(prop.getter) - assertNull(prop.setter) - } - } - } - - @Test - fun `should filter top level type aliases`() { - testInline( - """ - |/src/suppressed/suppressed.kt - |/** - | * sample docs - | * @suppress - | */ - |typealias suppressedTypeAlias = String - | - |/** - | * Sample - | */ - |typealias notSuppressedTypeAlias = String - """.trimIndent(), configuration - ) { - preMergeDocumentablesTransformationStage = { modules -> - assertNull(modules.flatMap { it.packages }.flatMap { it.typealiases } - .firstOrNull { it.name == "suppressedTypeAlias" }) - assertNotNull(modules.flatMap { it.packages }.flatMap { it.typealiases } - .firstOrNull { it.name == "notSuppressedTypeAlias" }) - } - } - } - - @Test - fun `should filter companion object`() { - testInline( - """ - |/src/suppressed/Suppressed.kt - |class Suppressed { - |/** - | * @suppress - | */ - |companion object { - | val x = 1 - |} - |} - """.trimIndent(), configuration - ) { - preMergeDocumentablesTransformationStage = { modules -> - assertNull((modules.flatMap { it.packages }.flatMap { it.classlikes } - .firstOrNull { it.name == "Suppressed" } as? WithCompanion)?.companion) - } - } - } - - @Test - fun `should suppress inner classlike`() { - testInline( - """ - |/src/suppressed/Testing.kt - |class Testing { - | /** - | * Sample - | * @suppress - | */ - | inner class Suppressed { - | val x = 1 - | } - |} - """.trimIndent(), configuration - ) { - preMergeDocumentablesTransformationStage = { modules -> - val testingClass = modules.flatMap { it.packages }.flatMap { it.classlikes }.single() - assertNull(testingClass.classlikes.firstOrNull()) - } - } - } - - @Test - fun `should suppress enum entry`() { - testInline( - """ - |/src/suppressed/Testing.kt - |enum class Testing { - | /** - | * Sample - | * @suppress - | */ - | SUPPRESSED, - | - | /** - | * Not suppressed - | */ - | NOT_SUPPRESSED - |} - """.trimIndent(), configuration - ) { - preMergeDocumentablesTransformationStage = { modules -> - val testingClass = modules.flatMap { it.packages }.flatMap { it.classlikes }.single() as DEnum - assertEquals(listOf("NOT_SUPPRESSED"), testingClass.entries.map { it.name }) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/transformers/SuppressedByConfigurationDocumentableFilterTransformerTest.kt b/plugins/base/src/test/kotlin/transformers/SuppressedByConfigurationDocumentableFilterTransformerTest.kt deleted file mode 100644 index f946a885..00000000 --- a/plugins/base/src/test/kotlin/transformers/SuppressedByConfigurationDocumentableFilterTransformerTest.kt +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package transformers - -import org.jetbrains.dokka.DokkaDefaults -import org.jetbrains.dokka.PackageOptionsImpl -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.links.DRI -import kotlin.test.Test -import kotlin.test.assertEquals - -class SuppressedByConfigurationDocumentableFilterTransformerTest : BaseAbstractTest() { - - @Test - fun `class filtered by package options`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src") - perPackageOptions = listOf( - packageOptions(matchingRegex = "suppressed.*", suppress = true), - packageOptions(matchingRegex = "default.*", suppress = false) - ) - } - } - } - - testInline( - """ - /src/suppressed/Suppressed.kt - package suppressed - class Suppressed - - /src/default/Default.kt - package default - class Default.kt - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - assertEquals(1, module.children.size, "Expected just a single package in module") - assertEquals(1, module.packages.size, "Expected just a single package in module") - - val pkg = module.packages.single() - assertEquals("default", pkg.dri.packageName, "Expected 'default' package in module") - assertEquals(1, pkg.children.size, "Expected just a single child in 'default' package") - assertEquals(1, pkg.classlikes.size, "Expected just a single child in 'default' package") - - val classlike = pkg.classlikes.single() - assertEquals(DRI("default", "Default"), classlike.dri, "Expected 'Default' class in 'default' package") - } - } - } - - @Test - fun `class filtered by more specific package options`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src") - perPackageOptions = listOf( - packageOptions(matchingRegex = "parent.some.*", suppress = false), - packageOptions(matchingRegex = "parent.some.suppressed.*", suppress = true), - - packageOptions(matchingRegex = "parent.other.*", suppress = true), - packageOptions(matchingRegex = "parent.other.default.*", suppress = false) - ) - } - } - } - - testInline( - """ - /src/parent/some/Some.kt - package parent.some - class Some - - /src/parent/some/suppressed/Suppressed.kt - package parent.some.suppressed - class Suppressed - - /src/parent/other/Other.kt - package parent.other - class Other - - /src/parent/other/default/Default.kt - package parent.other.default - class Default - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - assertEquals(2, module.packages.size, "Expected two packages in module") - assertEquals( - listOf(DRI("parent.some"), DRI("parent.other.default")).sortedBy { it.packageName }, - module.packages.map { it.dri }.sortedBy { it.packageName }, - "Expected 'parent.some' and 'parent.other.default' packages to be not suppressed" - ) - } - } - } - - @Test - fun `class filtered by parent file path`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src") - suppressedFiles = listOf("src/suppressed") - } - } - } - - testInline( - """ - /src/suppressed/Suppressed.kt - package suppressed - class Suppressed - - /src/default/Default.kt - package default - class Default.kt - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - assertEquals(1, module.children.size, "Expected just a single package in module") - assertEquals(1, module.packages.size, "Expected just a single package in module") - - val pkg = module.packages.single() - assertEquals("default", pkg.dri.packageName, "Expected 'default' package in module") - assertEquals(1, pkg.children.size, "Expected just a single child in 'default' package") - assertEquals(1, pkg.classlikes.size, "Expected just a single child in 'default' package") - - val classlike = pkg.classlikes.single() - assertEquals(DRI("default", "Default"), classlike.dri, "Expected 'Default' class in 'default' package") - } - } - } - - @Test - fun `class filtered by exact file path`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src") - suppressedFiles = listOf("src/suppressed/Suppressed.kt") - } - } - } - - testInline( - """ - /src/suppressed/Suppressed.kt - package suppressed - class Suppressed - - /src/default/Default.kt - package default - class Default.kt - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - assertEquals(1, module.children.size, "Expected just a single package in module") - assertEquals(1, module.packages.size, "Expected just a single package in module") - - val pkg = module.packages.single() - assertEquals("default", pkg.dri.packageName, "Expected 'default' package in module") - assertEquals(1, pkg.children.size, "Expected just a single child in 'default' package") - assertEquals(1, pkg.classlikes.size, "Expected just a single child in 'default' package") - - val classlike = pkg.classlikes.single() - assertEquals(DRI("default", "Default"), classlike.dri, "Expected 'Default' class in 'default' package") - } - } - } - - private fun packageOptions( - matchingRegex: String, - suppress: Boolean - ) = PackageOptionsImpl( - matchingRegex = matchingRegex, - suppress = suppress, - includeNonPublic = true, - documentedVisibilities = DokkaDefaults.documentedVisibilities, - reportUndocumented = false, - skipDeprecated = false - ) - -} diff --git a/plugins/base/src/test/kotlin/transformers/isExceptionTest.kt b/plugins/base/src/test/kotlin/transformers/isExceptionTest.kt deleted file mode 100644 index a387c60d..00000000 --- a/plugins/base/src/test/kotlin/transformers/isExceptionTest.kt +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package transformers - -import org.jetbrains.dokka.base.transformers.documentables.isException -import org.jetbrains.dokka.model.DClass -import org.jetbrains.dokka.model.DTypeAlias -import utils.AbstractModelTest -import kotlin.test.Test - -class IsExceptionKotlinTest : AbstractModelTest("/src/main/kotlin/classes/Test.kt", "classes") { - @Test - fun `isException should work for kotlin exception`(){ - inlineModelTest( - """ - |class ExampleException(): Exception()""" - ) { - with((this / "classes" / "ExampleException").cast<DClass>()) { - name equals "ExampleException" - isException equals true - } - } - } - - @Test - fun `isException should work for java exceptions`(){ - inlineModelTest( - """ - |class ExampleException(): java.lang.Exception()""" - ) { - with((this / "classes" / "ExampleException").cast<DClass>()) { - name equals "ExampleException" - isException equals true - } - } - } - - @Test - fun `isException should work for RuntimeException`(){ - inlineModelTest( - """ - |class ExampleException(reason: String): RuntimeException(reason)""" - ) { - with((this / "classes" / "ExampleException").cast<DClass>()) { - name equals "ExampleException" - isException equals true - } - } - } - - @Test - fun `isException should work if exception is typealiased`(){ - inlineModelTest( - """ - |typealias ExampleException = java.lang.Exception""" - ) { - with((this / "classes" / "ExampleException").cast<DTypeAlias>()) { - name equals "ExampleException" - isException equals true - } - } - } - - @Test - fun `isException should work if exception is extending a typaliased class`(){ - inlineModelTest( - """ - |class ExampleException(): Exception() - |typealias ExampleExceptionAlias = ExampleException""" - ) { - with((this / "classes" / "ExampleExceptionAlias").cast<DTypeAlias>()) { - name equals "ExampleExceptionAlias" - isException equals true - } - } - } - - @Test - fun `isException should return false for a basic class`(){ - inlineModelTest( - """ - |class NotAnException(): Serializable""" - ) { - with((this / "classes" / "NotAnException").cast<DClass>()) { - name equals "NotAnException" - isException equals false - } - } - } - - @Test - fun `isException should return false for a typealias`(){ - inlineModelTest( - """ - |typealias NotAnException = Serializable""" - ) { - with((this / "classes" / "NotAnException").cast<DTypeAlias>()) { - name equals "NotAnException" - isException equals false - } - } - } -} - -class IsExceptionJavaTest: AbstractModelTest("/src/main/kotlin/java/Test.java", "java") { - @Test - fun `isException should work for java exceptions`(){ - inlineModelTest( - """ - |public class ExampleException extends java.lang.Exception { }""" - ) { - with((this / "java" / "ExampleException").cast<DClass>()) { - name equals "ExampleException" - isException equals true - } - } - } - - @Test - fun `isException should work for RuntimeException`(){ - inlineModelTest( - """ - |public class ExampleException extends java.lang.RuntimeException""" - ) { - with((this / "java" / "ExampleException").cast<DClass>()) { - name equals "ExampleException" - isException equals true - } - } - } - - @Test - fun `isException should return false for a basic class`(){ - inlineModelTest( - """ - |public class NotAnException extends Serializable""" - ) { - with((this / "java" / "NotAnException").cast<DClass>()) { - name equals "NotAnException" - isException equals false - } - } - } -} - diff --git a/plugins/base/src/test/kotlin/translators/AccessorMethodNamingTest.kt b/plugins/base/src/test/kotlin/translators/AccessorMethodNamingTest.kt deleted file mode 100644 index ff36337a..00000000 --- a/plugins/base/src/test/kotlin/translators/AccessorMethodNamingTest.kt +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package translators - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.model.DProperty -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertTrue - -/** - * https://kotlinlang.org/docs/java-to-kotlin-interop.html#properties - * https://kotlinlang.org/docs/java-interop.html#getters-and-setters - */ -class AccessorMethodNamingTest : BaseAbstractTest() { - - @Test - fun `standard property`() { - testAccessors("data class TestCase(var standardString: String, var standardBoolean: Boolean)") { - doTest("standardString", "getStandardString", "setStandardString") - doTest("standardBoolean", "getStandardBoolean", "setStandardBoolean") - } - } - - @Test - fun `properties that start with the word 'is' use the special is rules`() { - testAccessors("data class TestCase(var isFoo: String, var isBar: Boolean)") { - doTest("isFoo", "isFoo", "setFoo") - doTest("isBar", "isBar", "setBar") - } - } - - @Test - fun `properties that start with a word that starts with 'is' use get and set`() { - testAccessors("data class TestCase(var issuesFetched: Int, var issuesWereDisplayed: Boolean)") { - doTest("issuesFetched", "getIssuesFetched", "setIssuesFetched") - doTest("issuesWereDisplayed", "getIssuesWereDisplayed", "setIssuesWereDisplayed") - } - } - - @Test - fun `properties that start with the word 'is' followed by underscore use the special is rules`() { - testAccessors("data class TestCase(var is_foo: String, var is_bar: Boolean)") { - doTest("is_foo", "is_foo", "set_foo") - doTest("is_bar", "is_bar", "set_bar") - } - } - - @Test - fun `properties that start with the word 'is' followed by a number use the special is rules`() { - testAccessors("data class TestCase(var is1of: String, var is2of: Boolean)") { - doTest("is1of", "is1of", "set1of") - doTest("is2of", "is2of", "set2of") - } - } - - @Test - fun `sanity check short names`() { - testAccessors( - """ - data class TestCase( - var i: Boolean, - var `is`: Boolean, - var isz: Boolean, - var isA: Int, - var isB: Boolean, - ) - """.trimIndent() - ) { - doTest("i", "getI", "setI") - doTest("is", "getIs", "setIs") - doTest("isz", "getIsz", "setIsz") - doTest("isA", "isA", "setA") - doTest("isB", "isB", "setB") - } - } - - private fun testAccessors(code: String, block: PropertyTestCase.() -> Unit) { - val configuration = dokkaConfiguration { - suppressObviousFunctions = false - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin") - } - } - } - - testInline(""" - /src/main/kotlin/sample/TestCase.kt - package sample - - $code - """.trimIndent(), - configuration) { - documentablesMergingStage = { module -> - val properties = module.packages.single().classlikes.first().properties - PropertyTestCase(properties).apply { - block() - finish() - } - } - } - } - - private class PropertyTestCase(private val properties: List<DProperty>) { - private var testsDone: Int = 0 - - fun doTest(kotlinName: String, getter: String? = null, setter: String? = null) { - properties.first { it.name == kotlinName }.let { - assertEquals(getter, it.getter?.name) - assertEquals(setter, it.setter?.name) - } - testsDone += 1 - } - - fun finish() { - assertTrue(testsDone > 0, "No tests in TestCase") - assertEquals(testsDone, properties.size) - } - } -} diff --git a/plugins/base/src/test/kotlin/translators/Bug1341.kt b/plugins/base/src/test/kotlin/translators/Bug1341.kt deleted file mode 100644 index 6a7bfc97..00000000 --- a/plugins/base/src/test/kotlin/translators/Bug1341.kt +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package translators - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.links.DRI -import kotlin.test.Test -import kotlin.test.assertEquals - -class Bug1341 : BaseAbstractTest() { - @Test - fun `reproduce bug #1341`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src") - analysisPlatform = "jvm" - } - } - } - - testInline( - """ - /src/com/sample/OtherClass.kt - package com.sample - class OtherClass internal constructor() { - internal annotation class CustomAnnotation - } - - /src/com/sample/ClassUsingAnnotation.java - package com.sample - public class ClassUsingAnnotation { - @OtherClass.CustomAnnotation - public int doSomething() { - return 1; - } - } - """.trimIndent(), - configuration - ) { - this.documentablesMergingStage = { module -> - assertEquals(DRI("com.sample"), module.packages.single().dri) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/translators/DefaultDescriptorToDocumentableTranslatorTest.kt b/plugins/base/src/test/kotlin/translators/DefaultDescriptorToDocumentableTranslatorTest.kt deleted file mode 100644 index 6812f0b4..00000000 --- a/plugins/base/src/test/kotlin/translators/DefaultDescriptorToDocumentableTranslatorTest.kt +++ /dev/null @@ -1,1107 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package translators - -import org.jetbrains.dokka.DokkaConfiguration -import org.jetbrains.dokka.base.signatures.KotlinSignatureUtils.modifiers -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.links.PointingToDeclaration -import org.jetbrains.dokka.model.* -import org.jetbrains.dokka.model.doc.* -import utils.text -import kotlin.test.* -import utils.OnlyDescriptors - -class DefaultDescriptorToDocumentableTranslatorTest : BaseAbstractTest() { - val configuration = dokkaConfiguration { - suppressObviousFunctions = false - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin") - classpath = listOf(commonStdlibPath!!, jvmStdlibPath!!) - } - } - } - - @Suppress("DEPRECATION") // for includeNonPublic - val javaConfiguration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/java") - includeNonPublic = true - } - } - } - - @Test - fun `data class kdocs over generated methods`() { - testInline( - """ - |/src/main/kotlin/sample/XD.kt - |package sample - |/** - | * But the fat Hobbit, he knows. Eyes always watching. - | */ - |data class XD(val xd: String) { - | /** - | * But the fat Hobbit, he knows. Eyes always watching. - | */ - | fun custom(): String = "" - | - | /** - | * Memory is not what the heart desires. That is only a mirror. - | */ - | override fun equals(other: Any?): Boolean = true - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - assertEquals("", module.documentationOf("XD", "copy")) - assertEquals( - "Memory is not what the heart desires. That is only a mirror.", - module.documentationOf( - "XD", - "equals" - ) - ) - assertEquals("", module.documentationOf("XD", "hashCode")) - assertEquals("", module.documentationOf("XD", "toString")) - assertEquals("But the fat Hobbit, he knows. Eyes always watching.", module.documentationOf("XD", "custom")) - } - } - } - - @Test - fun `simple class kdocs`() { - testInline( - """ - |/src/main/kotlin/sample/XD.kt - |package sample - |/** - | * But the fat Hobbit, he knows. Eyes always watching. - | */ - |class XD(val xd: String) { - | /** - | * But the fat Hobbit, he knows. Eyes always watching. - | */ - | fun custom(): String = "" - | - | /** - | * Memory is not what the heart desires. That is only a mirror. - | */ - | override fun equals(other: Any?): Boolean = true - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - assertEquals("But the fat Hobbit, he knows. Eyes always watching.", module.documentationOf("XD", "custom")) - assertEquals( - "Memory is not what the heart desires. That is only a mirror.", - module.documentationOf( - "XD", - "equals" - ) - ) - } - } - } - - @Test - fun `kdocs with code block`() { - testInline( - """ - |/src/main/kotlin/sample/TestForCodeInDocs.kt - |package sample - |/** - | * Utility for building a String that represents an XML document. - | * The XmlBlob object is immutable and the passed values are copied where it makes sense. - | * - | * Note the XML Declaration is not output as part of the XmlBlob - | * - | * - | * val soapAttrs = attrs("soap-env" to "http://www.w3.org/2001/12/soap-envelope", - | * "soap-env:encodingStyle" to "http://www.w3.org/2001/12/soap-encoding") - | * val soapXml = node("soap-env:Envelope", soapAttrs, - | * node("soap-env:Body", attrs("xmlns:m" to "http://example"), - | * node("m:GetExample", - | * node("m:GetExampleName", "BasePair") - | * ) - | * ) - | * ) - | * - | * - | */ - |class TestForCodeInDocs { - |} - """.trimIndent(), configuration - ) { - documentablesMergingStage = { module -> - val description = module.descriptionOf("TestForCodeInDocs") - val expected = listOf( - P( - children = listOf(Text("Utility for building a String that represents an XML document. The XmlBlob object is immutable and the passed values are copied where it makes sense.")) - ), - P( - children = listOf(Text("Note the XML Declaration is not output as part of the XmlBlob")) - ), - CodeBlock( - children = listOf( - Text( - """val soapAttrs = attrs("soap-env" to "http://www.w3.org/2001/12/soap-envelope", - "soap-env:encodingStyle" to "http://www.w3.org/2001/12/soap-encoding") -val soapXml = node("soap-env:Envelope", soapAttrs, - node("soap-env:Body", attrs("xmlns:m" to "http://example"), - node("m:GetExample", - node("m:GetExampleName", "BasePair") - ) - ) -)""" - ) - ) - ) - ) - assertEquals(expected, description?.root?.children) - } - } - } - - private fun runTestSuitesAgainstGivenClasses(classlikes: List<DClasslike>, testSuites: List<List<TestSuite>>) { - classlikes.zip(testSuites).forEach { (classlike, testSuites) -> - testSuites.forEach { testSuite -> - when (testSuite) { - is TestSuite.PropertyDoesntExist -> assertEquals( - null, - classlike.properties.firstOrNull { it.name == testSuite.propertyName }, - "Test for class ${classlike.name} failed" - ) - is TestSuite.PropertyExists -> classlike.properties.single { it.name == testSuite.propertyName } - .run { - assertEquals( - testSuite.modifier, - modifier.values.single(), - "Test for class ${classlike.name} with property $name failed" - ) - assertEquals( - testSuite.visibility, - visibility.values.single(), - "Test for class ${classlike.name} with property $name failed" - ) - assertEquals( - testSuite.additionalModifiers, - extra[AdditionalModifiers]?.content?.values?.single() ?: emptySet<ExtraModifiers>(), - "Test for class ${classlike.name} with property $name failed" - ) - } - is TestSuite.FunctionDoesntExist -> assertEquals( - null, - classlike.functions.firstOrNull { it.name == testSuite.propertyName }, - "Test for class ${classlike.name} failed" - ) - is TestSuite.FunctionExists -> classlike.functions.single { it.name == testSuite.propertyName } - .run { - assertEquals( - testSuite.modifier, - modifier.values.single(), - "Test for class ${classlike.name} with function $name failed" - ) - assertEquals( - testSuite.visibility, - visibility.values.single(), - "Test for class ${classlike.name} with function $name failed" - ) - assertEquals( - testSuite.additionalModifiers, - extra[AdditionalModifiers]?.content?.values?.single() ?: emptySet<ExtraModifiers>(), - "Test for class ${classlike.name} with function $name failed" - ) - } - } - } - } - } - - @Test - fun `derived properties with non-public code included`() { - - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin") - documentedVisibilities = setOf( - DokkaConfiguration.Visibility.PUBLIC, - DokkaConfiguration.Visibility.PRIVATE, - DokkaConfiguration.Visibility.PROTECTED, - DokkaConfiguration.Visibility.INTERNAL, - ) - } - } - } - - testInline( - """ - |/src/main/kotlin/sample/XD.kt - |package sample - | - |open class A { - | private val privateProperty: Int = 1 - | protected val protectedProperty: Int = 2 - | internal val internalProperty: Int = 3 - | val publicProperty: Int = 4 - | open val propertyToOverride: Int = 5 - | - | private fun privateFun(): Int = 6 - | protected fun protectedFun(): Int = 7 - | internal fun internalFun(): Int = 8 - | fun publicFun(): Int = 9 - | open fun funToOverride(): Int = 10 - |} - | - |open class B : A() { - | override val propertyToOverride: Int = 11 - | - | override fun funToOverride(): Int = 12 - |} - |class C : B() - """.trimIndent(), - configuration - ) { - - documentablesMergingStage = { module -> - val classes = module.packages.single().classlikes.sortedBy { it.name } - - val testSuites: List<List<TestSuite>> = listOf( - listOf( - TestSuite.PropertyExists( - "privateProperty", - KotlinModifier.Final, - KotlinVisibility.Private, - emptySet() - ), - TestSuite.PropertyExists( - "protectedProperty", - KotlinModifier.Final, - KotlinVisibility.Protected, - emptySet() - ), - TestSuite.PropertyExists( - "internalProperty", - KotlinModifier.Final, - KotlinVisibility.Internal, - emptySet() - ), - TestSuite.PropertyExists( - "publicProperty", - KotlinModifier.Final, - KotlinVisibility.Public, - emptySet() - ), - TestSuite.PropertyExists( - "propertyToOverride", - KotlinModifier.Open, - KotlinVisibility.Public, - emptySet() - ), - TestSuite.FunctionExists( - "privateFun", - KotlinModifier.Final, - KotlinVisibility.Private, - emptySet() - ), - TestSuite.FunctionExists( - "protectedFun", - KotlinModifier.Final, - KotlinVisibility.Protected, - emptySet() - ), - TestSuite.FunctionExists( - "internalFun", - KotlinModifier.Final, - KotlinVisibility.Internal, - emptySet() - ), - TestSuite.FunctionExists( - "publicFun", - KotlinModifier.Final, - KotlinVisibility.Public, - emptySet() - ), - TestSuite.FunctionExists( - "funToOverride", - KotlinModifier.Open, - KotlinVisibility.Public, - emptySet() - ) - ), - listOf( - TestSuite.PropertyExists( - "privateProperty", - KotlinModifier.Final, - KotlinVisibility.Private, - emptySet() - ), - TestSuite.PropertyExists( - "protectedProperty", - KotlinModifier.Final, - KotlinVisibility.Protected, - emptySet() - ), - TestSuite.PropertyExists( - "internalProperty", - KotlinModifier.Final, - KotlinVisibility.Internal, - emptySet() - ), - TestSuite.PropertyExists( - "publicProperty", - KotlinModifier.Final, - KotlinVisibility.Public, - emptySet() - ), - TestSuite.PropertyExists( - "propertyToOverride", - KotlinModifier.Open, - KotlinVisibility.Public, - setOf(ExtraModifiers.KotlinOnlyModifiers.Override) - ), - TestSuite.FunctionExists( - "privateFun", - KotlinModifier.Final, - KotlinVisibility.Private, - emptySet() - ), - TestSuite.FunctionExists( - "protectedFun", - KotlinModifier.Final, - KotlinVisibility.Protected, - emptySet() - ), - TestSuite.FunctionExists( - "internalFun", - KotlinModifier.Final, - KotlinVisibility.Internal, - emptySet() - ), - TestSuite.FunctionExists( - "publicFun", - KotlinModifier.Final, - KotlinVisibility.Public, - emptySet() - ), - TestSuite.FunctionExists( - "funToOverride", - KotlinModifier.Open, - KotlinVisibility.Public, - setOf(ExtraModifiers.KotlinOnlyModifiers.Override) - ) - ), - listOf( - TestSuite.PropertyExists( - "privateProperty", - KotlinModifier.Final, - KotlinVisibility.Private, - emptySet() - ), - TestSuite.PropertyExists( - "protectedProperty", - KotlinModifier.Final, - KotlinVisibility.Protected, - emptySet() - ), - TestSuite.PropertyExists( - "internalProperty", - KotlinModifier.Final, - KotlinVisibility.Internal, - emptySet() - ), - TestSuite.PropertyExists( - "publicProperty", - KotlinModifier.Final, - KotlinVisibility.Public, - emptySet() - ), - TestSuite.PropertyExists( - "propertyToOverride", - KotlinModifier.Open, - KotlinVisibility.Public, - setOf(ExtraModifiers.KotlinOnlyModifiers.Override) - ), - TestSuite.FunctionExists( - "privateFun", - KotlinModifier.Final, - KotlinVisibility.Private, - emptySet() - ), - TestSuite.FunctionExists( - "protectedFun", - KotlinModifier.Final, - KotlinVisibility.Protected, - emptySet() - ), - TestSuite.FunctionExists( - "internalFun", - KotlinModifier.Final, - KotlinVisibility.Internal, - emptySet() - ), - TestSuite.FunctionExists( - "publicFun", - KotlinModifier.Final, - KotlinVisibility.Public, - emptySet() - ), - TestSuite.FunctionExists( - "funToOverride", - KotlinModifier.Open, - KotlinVisibility.Public, - setOf(ExtraModifiers.KotlinOnlyModifiers.Override) - ) - ) - ) - - runTestSuitesAgainstGivenClasses(classes, testSuites) - } - } - } - - - @Test - fun `derived properties with only public code`() { - - @Suppress("DEPRECATION") // for includeNonPublic - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/kotlin") - includeNonPublic = false - } - } - } - - testInline( - """ - |/src/main/kotlin/sample/XD.kt - |package sample - | - |open class A { - | private val privateProperty: Int = 1 - | protected val protectedProperty: Int = 2 - | internal val internalProperty: Int = 3 - | val publicProperty: Int = 4 - | open val propertyToOverride: Int = 5 - | open val propertyToOverrideButCloseMeanwhile: Int = 6 - | - | private fun privateFun(): Int = 7 - | protected fun protectedFun(): Int = 8 - | internal fun internalFun(): Int = 9 - | fun publicFun(): Int = 10 - | open fun funToOverride(): Int = 11 - | open fun funToOverrideButCloseMeanwhile(): Int = 12 - |} - | - |open class B : A() { - | override val propertyToOverride: Int = 13 - | final override val propertyToOverrideButCloseMeanwhile: Int = 14 - | - | override fun funToOverride(): Int = 15 - | final override fun funToOverrideButCloseMeanwhile(): Int = 16 - |} - |class C : B() - """.trimIndent(), - configuration - ) { - - documentablesMergingStage = { module -> - val classes = module.packages.single().classlikes.sortedBy { it.name } - - val testSuites: List<List<TestSuite>> = listOf( - listOf( - TestSuite.PropertyDoesntExist("privateProperty"), - TestSuite.PropertyDoesntExist("protectedProperty"), - TestSuite.PropertyDoesntExist("internalProperty"), - TestSuite.PropertyExists( - "publicProperty", - KotlinModifier.Final, - KotlinVisibility.Public, - emptySet() - ), - TestSuite.PropertyExists( - "propertyToOverride", - KotlinModifier.Open, - KotlinVisibility.Public, - emptySet() - ), - TestSuite.PropertyExists( - "propertyToOverrideButCloseMeanwhile", - KotlinModifier.Open, - KotlinVisibility.Public, - emptySet() - ), - TestSuite.FunctionDoesntExist("privateFun"), - TestSuite.FunctionDoesntExist("protectedFun"), - TestSuite.FunctionDoesntExist("internalFun"), - TestSuite.FunctionExists( - "publicFun", - KotlinModifier.Final, - KotlinVisibility.Public, - emptySet() - ), - TestSuite.FunctionExists( - "funToOverride", - KotlinModifier.Open, - KotlinVisibility.Public, - emptySet() - ), - TestSuite.FunctionExists( - "funToOverrideButCloseMeanwhile", - KotlinModifier.Open, - KotlinVisibility.Public, - emptySet() - ) - ), - listOf( - TestSuite.PropertyDoesntExist("privateProperty"), - TestSuite.PropertyDoesntExist("protectedProperty"), - TestSuite.PropertyDoesntExist("internalProperty"), - TestSuite.PropertyExists( - "publicProperty", - KotlinModifier.Final, - KotlinVisibility.Public, - emptySet() - ), - TestSuite.PropertyExists( - "propertyToOverride", - KotlinModifier.Open, - KotlinVisibility.Public, - setOf(ExtraModifiers.KotlinOnlyModifiers.Override) - ), - TestSuite.PropertyExists( - "propertyToOverrideButCloseMeanwhile", - KotlinModifier.Final, - KotlinVisibility.Public, - setOf(ExtraModifiers.KotlinOnlyModifiers.Override) - ), - TestSuite.FunctionDoesntExist("privateFun"), - TestSuite.FunctionDoesntExist("protectedFun"), - TestSuite.FunctionDoesntExist("internalFun"), - TestSuite.FunctionExists( - "publicFun", - KotlinModifier.Final, - KotlinVisibility.Public, - emptySet() - ), - TestSuite.FunctionExists( - "funToOverride", - KotlinModifier.Open, - KotlinVisibility.Public, - setOf(ExtraModifiers.KotlinOnlyModifiers.Override) - ), - TestSuite.FunctionExists( - "funToOverrideButCloseMeanwhile", - KotlinModifier.Final, - KotlinVisibility.Public, - setOf(ExtraModifiers.KotlinOnlyModifiers.Override) - ) - ), - listOf( - TestSuite.PropertyDoesntExist("privateProperty"), - TestSuite.PropertyDoesntExist("protectedProperty"), - TestSuite.PropertyDoesntExist("internalProperty"), - TestSuite.PropertyExists( - "publicProperty", - KotlinModifier.Final, - KotlinVisibility.Public, - emptySet() - ), - TestSuite.PropertyExists( - "propertyToOverride", - KotlinModifier.Open, - KotlinVisibility.Public, - setOf(ExtraModifiers.KotlinOnlyModifiers.Override) - ), - TestSuite.PropertyExists( - "propertyToOverrideButCloseMeanwhile", - KotlinModifier.Final, - KotlinVisibility.Public, - setOf(ExtraModifiers.KotlinOnlyModifiers.Override) - ), - TestSuite.FunctionDoesntExist("privateFun"), - TestSuite.FunctionDoesntExist("protectedFun"), - TestSuite.FunctionDoesntExist("internalFun"), - TestSuite.FunctionExists( - "publicFun", - KotlinModifier.Final, - KotlinVisibility.Public, - emptySet() - ), - TestSuite.FunctionExists( - "funToOverride", - KotlinModifier.Open, - KotlinVisibility.Public, - setOf(ExtraModifiers.KotlinOnlyModifiers.Override) - ), - TestSuite.FunctionExists( - "funToOverrideButCloseMeanwhile", - KotlinModifier.Final, - KotlinVisibility.Public, - setOf(ExtraModifiers.KotlinOnlyModifiers.Override) - ) - ) - ) - - runTestSuitesAgainstGivenClasses(classes, testSuites) - } - } - } - - @Ignore // The compiler throws away annotations on unresolved types upstream - @Test - fun `Can annotate unresolved type`() { - testInline( - """ - |/src/main/java/sample/FooLibrary.kt - |package sample; - |@MustBeDocumented - |@Target(AnnotationTarget.TYPE) - |annotation class Hello() - |fun bar(): @Hello() TypeThatDoesntResolve - """.trimMargin(), - javaConfiguration - ) { - documentablesMergingStage = { module -> - val type = module.packages.single().functions.single().type as GenericTypeConstructor - assertEquals( - Annotations.Annotation(DRI("sample", "Hello"), emptyMap()), - type.extra[Annotations]?.directAnnotations?.values?.single()?.single() - ) - } - } - } - - /** - * Kotlin Int becomes java int. Java int cannot be annotated in source, but Kotlin Int can be. - * This is paired with KotlinAsJavaPluginTest.`Java primitive annotations work`() - */ - @Test - fun `Java primitive annotations work`() { - testInline( - """ - |/src/main/java/sample/FooLibrary.kt - |package sample; - |@MustBeDocumented - |@Target(AnnotationTarget.TYPE) - |annotation class Hello() - |fun bar(): @Hello() Int - """.trimMargin(), - javaConfiguration - ) { - documentablesMergingStage = { module -> - val type = module.packages.single().functions.single().type as GenericTypeConstructor - assertEquals( - Annotations.Annotation(DRI("sample", "Hello"), emptyMap()), - type.extra[Annotations]?.directAnnotations?.values?.single()?.single() - ) - assertEquals("kotlin/Int///PointingToDeclaration/", type.dri.toString()) - } - } - } - - @Test - fun `should preserve regular functions that look like accessors, but are not accessors`() { - testInline( - """ - |/src/main/kotlin/A.kt - |package test - |class A { - | private var v: Int = 0 - | - | // not accessors because declared separately, just functions - | fun setV(new: Int) { v = new } - | fun getV(): Int = v - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testClass = module.packages.single().classlikes.single { it.name == "A" } - val setterLookalike = testClass.functions.firstOrNull { it.name == "setV" } - assertNotNull(setterLookalike) { - "Expected regular function not found, wrongly categorized as setter?" - } - - val getterLookalike = testClass.functions.firstOrNull { it.name == "getV" } - assertNotNull(getterLookalike) { - "Expected regular function not found, wrongly categorized as getter?" - } - } - } - } - - @Test - fun `should correctly add IsVar extra for properties`() { - testInline( - """ - |/src/main/kotlin/A.kt - |package test - |class A { - | public var mutable: Int = 0 - | public val immutable: Int = 0 - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testClass = module.packages.single().classlikes.single { it.name == "A" } - assertEquals(2, testClass.properties.size) - - val mutable = testClass.properties[0] - assertEquals("mutable", mutable.name) - assertNotNull(mutable.extra[IsVar]) - - val immutable = testClass.properties[1] - assertEquals("immutable", immutable.name) - assertNull(immutable.extra[IsVar]) - } - } - } - - @Test - fun `should correctly parse multiple see tags with static function and property links`() { - testInline( - """ - |/src/main/kotlin/com/example/package/CollectionExtensions.kt - |package com.example.util - | - |object CollectionExtensions { - | val property = "Hi" - | - | fun emptyList() {} - | fun emptyMap() {} - | fun emptySet() {} - |} - | - |/src/main/kotlin/com/example/foo.kt - |package com.example - | - |import com.example.util.CollectionExtensions.emptyMap - |import com.example.util.CollectionExtensions.emptyList - |import com.example.util.CollectionExtensions.emptySet - |import com.example.util.CollectionExtensions.property - | - |/** - | * @see [List] stdlib list - | * @see [Map] stdlib map - | * @see [emptyMap] static emptyMap - | * @see [emptyList] static emptyList - | * @see [emptySet] static emptySet - | * @see [property] static property - | */ - |fun foo() {} - """.trimIndent(), - configuration - ) { - fun assertSeeTag(tag: TagWrapper, expectedName: String, expectedDescription: String) { - assertTrue(tag is See) - assertEquals(expectedName, tag.name) - val description = tag.children.joinToString { it.text().trim() } - assertEquals(expectedDescription, description) - } - - documentablesMergingStage = { module -> - val testFunction = module.packages.find { it.name == "com.example" } - ?.functions - ?.single { it.name == "foo" } - assertNotNull(testFunction) - - val documentationTags = testFunction.documentation.values.single().children - assertEquals(7, documentationTags.size) - - val descriptionTag = documentationTags[0] - assertTrue(descriptionTag is Description, "Expected first tag to be empty description") - assertTrue(descriptionTag.children.isEmpty(), "Expected first tag to be empty description") - - assertSeeTag( - tag = documentationTags[1], - expectedName = "kotlin.collections.List", - expectedDescription = "stdlib list" - ) - assertSeeTag( - tag = documentationTags[2], - expectedName = "kotlin.collections.Map", - expectedDescription = "stdlib map" - ) - assertSeeTag( - tag = documentationTags[3], - expectedName = "com.example.util.CollectionExtensions.emptyMap", - expectedDescription = "static emptyMap" - ) - assertSeeTag( - tag = documentationTags[4], - expectedName = "com.example.util.CollectionExtensions.emptyList", - expectedDescription = "static emptyList" - ) - assertSeeTag( - tag = documentationTags[5], - expectedName = "com.example.util.CollectionExtensions.emptySet", - expectedDescription = "static emptySet" - ) - assertSeeTag( - tag = documentationTags[6], - expectedName = "com.example.util.CollectionExtensions.property", - expectedDescription = "static property" - ) - } - } - } - - @Test - fun `should have documentation for synthetic Enum values functions`() { - testInline( - """ - |/src/main/kotlin/test/KotlinEnum.kt - |package test - | - |enum class KotlinEnum { - | FOO, BAR; - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val kotlinEnum = module.packages.find { it.name == "test" } - ?.classlikes - ?.single { it.name == "KotlinEnum" } - assertNotNull(kotlinEnum) - val valuesFunction = kotlinEnum.functions.single { it.name == "values" } - - val expectedValuesType = GenericTypeConstructor( - dri = DRI( - packageName = "kotlin", - classNames = "Array" - ), - projections = listOf( - Invariance( - GenericTypeConstructor( - dri = DRI( - packageName = "test", - classNames = "KotlinEnum" - ), - projections = emptyList() - ) - ) - ) - ) - assertEquals(expectedValuesType, valuesFunction.type) - - val expectedDocumentation = DocumentationNode(listOf( - Description( - CustomDocTag( - children = listOf( - P(listOf( - Text( - "Returns an array containing the constants of this enum type, in the order " + - "they're declared." - ), - )), - P(listOf( - Text("This method may be used to iterate over the constants.") - )) - ), - name = "MARKDOWN_FILE" - ) - ) - )) - assertEquals(expectedDocumentation, valuesFunction.documentation.values.single()) - } - } - } - - @Test - fun `should have documentation for synthetic Enum entries property`() { - testInline( - """ - |/src/main/kotlin/test/KotlinEnum.kt - |package test - | - |enum class KotlinEnum { - | FOO, BAR; - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val kotlinEnum = module.packages.find { it.name == "test" } - ?.classlikes - ?.single { it.name == "KotlinEnum" } - - assertNotNull(kotlinEnum) - - val entriesProperty = kotlinEnum.properties.single { it.name == "entries" } - val expectedEntriesType = GenericTypeConstructor( - dri = DRI( - packageName = "kotlin.enums", - classNames = "EnumEntries" - ), - projections = listOf( - Invariance( - GenericTypeConstructor( - dri = DRI( - packageName = "test", - classNames = "KotlinEnum" - ), - projections = emptyList() - ) - ) - ) - ) - assertEquals(expectedEntriesType, entriesProperty.type) - - val expectedDocumentation = DocumentationNode(listOf( - Description( - CustomDocTag( - children = listOf( - P(listOf( - Text( - "Returns a representation of an immutable list of all enum entries, " + - "in the order they're declared." - ), - )), - P(listOf( - Text("This method may be used to iterate over the enum entries.") - )) - ), - name = "MARKDOWN_FILE" - ) - ) - )) - assertEquals(expectedDocumentation, entriesProperty.documentation.values.single()) - } - } - } - - @OnlyDescriptors("Fix kdoc link") // TODO - @Test - fun `should have documentation for synthetic Enum valueOf functions`() { - testInline( - """ - |/src/main/kotlin/test/KotlinEnum.kt - |package test - | - |enum class KotlinEnum { - | FOO, BAR; - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val kotlinEnum = module.packages.find { it.name == "test" } - ?.classlikes - ?.single { it.name == "KotlinEnum" } - assertNotNull(kotlinEnum) - - val expectedValueOfType = GenericTypeConstructor( - dri = DRI( - packageName = "test", - classNames = "KotlinEnum" - ), - projections = emptyList() - ) - - val expectedDocumentation = DocumentationNode(listOf( - Description( - CustomDocTag( - children = listOf( - P(listOf( - Text( - "Returns the enum constant of this type with the specified name. " + - "The string must match exactly an identifier used to declare an enum " + - "constant in this type. (Extraneous whitespace characters are not permitted.)" - ) - )) - ), - name = "MARKDOWN_FILE" - ) - ), - Throws( - root = CustomDocTag( - children = listOf( - P(listOf( - Text("if this enum type has no constant with the specified name") - )) - ), - name = "MARKDOWN_FILE" - ), - name = "kotlin.IllegalArgumentException", - exceptionAddress = DRI( - packageName = "kotlin", - classNames = "IllegalArgumentException", - target = PointingToDeclaration - ), - ) - )) - - val valueOfFunction = kotlinEnum.functions.single { it.name == "valueOf" } - assertEquals(expectedDocumentation, valueOfFunction.documentation.values.single()) - assertEquals(expectedValueOfType, valueOfFunction.type) - - val valueOfParamDRI = (valueOfFunction.parameters.single().type as GenericTypeConstructor).dri - assertEquals(DRI(packageName = "kotlin", classNames = "String"), valueOfParamDRI) - } - } - } - - @Test - fun `should add data modifier to data objects`() { - testInline( - """ - |/src/main/kotlin/test/KotlinDataObject.kt - |package test - | - |data object KotlinDataObject {} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val pckg = module.packages.single { it.name == "test" } - - val dataObject = pckg.classlikes.single { it.name == "KotlinDataObject" } - assertTrue(dataObject is DObject) - - val modifiers = dataObject.modifiers().values.flatten() - assertEquals(1, modifiers.size) - assertEquals(ExtraModifiers.KotlinOnlyModifiers.Data, modifiers[0]) - } - } - } -} - -private sealed class TestSuite { - abstract val propertyName: String - - data class PropertyDoesntExist( - override val propertyName: String - ) : TestSuite() - - - data class PropertyExists( - override val propertyName: String, - val modifier: KotlinModifier, - val visibility: KotlinVisibility, - val additionalModifiers: Set<ExtraModifiers.KotlinOnlyModifiers> - ) : TestSuite() - - data class FunctionDoesntExist( - override val propertyName: String, - ) : TestSuite() - - data class FunctionExists( - override val propertyName: String, - val modifier: KotlinModifier, - val visibility: KotlinVisibility, - val additionalModifiers: Set<ExtraModifiers.KotlinOnlyModifiers> - ) : TestSuite() -} diff --git a/plugins/base/src/test/kotlin/translators/DefaultPsiToDocumentableTranslatorTest.kt b/plugins/base/src/test/kotlin/translators/DefaultPsiToDocumentableTranslatorTest.kt deleted file mode 100644 index 7e9bff1e..00000000 --- a/plugins/base/src/test/kotlin/translators/DefaultPsiToDocumentableTranslatorTest.kt +++ /dev/null @@ -1,1027 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package translators - -import org.jetbrains.dokka.DokkaConfiguration -import org.jetbrains.dokka.DokkaConfiguration.Visibility -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.links.PointingToDeclaration -import org.jetbrains.dokka.model.* -import org.jetbrains.dokka.model.doc.* -import kotlin.test.* - -class DefaultPsiToDocumentableTranslatorTest : BaseAbstractTest() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/java") - } - } - } - - @Test - fun `method overriding two documented classes picks closest class documentation`() { - testInline( - """ - |/src/main/java/sample/BaseClass1.java - |package sample; - |public class BaseClass1 { - | /** B1 */ - | public void x() { } - |} - | - |/src/main/java/sample/BaseClass2.java - |package sample; - |public class BaseClass2 extends BaseClass1 { - | /** B2 */ - | public void x() { } - |} - | - |/src/main/java/sample/X.java - |package sample; - |public class X extends BaseClass2 { - | public void x() { } - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val documentationOfFunctionX = module.documentationOf("X", "x") - assertTrue( - "B2" in documentationOfFunctionX, - "Expected nearest super method documentation to be parsed as documentation. " + - "Documentation: $documentationOfFunctionX" - ) - } - } - } - - @Test - fun `method overriding class and interface picks class documentation`() { - testInline( - """ - |/src/main/java/sample/BaseClass1.java - |package sample; - |public class BaseClass1 { - | /** B1 */ - | public void x() { } - |} - | - |/src/main/java/sample/Interface1.java - |package sample; - |public interface Interface1 { - | /** I1 */ - | public void x() {} - |} - | - |/src/main/java/sample/X.java - |package sample; - |public class X extends BaseClass1 implements Interface1 { - | public void x() { } - |} - """.trimMargin(), - configuration - ) { - documentablesMergingStage = { module -> - val documentationOfFunctionX = module.documentationOf("X", "x") - assertTrue( - "B1" in documentationOfFunctionX, - "Expected documentation of superclass being prioritized over interface " + - "Documentation: $documentationOfFunctionX" - ) - } - } - } - - @Test - fun `method overriding two classes picks closest documented class documentation`() { - testInline( - """ - |/src/main/java/sample/BaseClass1.java - |package sample; - |public class BaseClass1 { - | /** B1 */ - | public void x() { } - |} - | - |/src/main/java/sample/BaseClass2.java - |package sample; - |public class BaseClass2 extends BaseClass1 { - | public void x() {} - |} - | - |/src/main/java/sample/X.java - |package sample; - |public class X extends BaseClass2 { - | public void x() { } - |} - """.trimMargin(), - configuration - ) { - documentablesMergingStage = { module -> - val documentationOfFunctionX = module.documentationOf("X", "x") - assertTrue( - "B1" in documentationOfFunctionX, - "Expected Documentation \"B1\", found: \"$documentationOfFunctionX\"" - ) - } - } - } - - @Test - fun `java package-info package description`() { - testInline( - """ - |/src/main/java/sample/BaseClass1.java - |package sample; - |public class BaseClass1 { - | /** B1 */ - | void x() { } - |} - | - |/src/main/java/sample/BaseClass2.java - |package sample; - |public class BaseClass2 extends BaseClass1 { - | void x() {} - |} - | - |/src/main/java/sample/X.java - |package sample; - |public class X extends BaseClass2 { - | void x() { } - |} - | - |/src/main/java/sample/package-info.java - |/** - | * Here comes description from package-info - | */ - |package sample; - """.trimMargin(), - configuration - ) { - documentablesMergingStage = { module -> - val documentationOfPackage = module.packages.single().documentation.values.single().children.single() - .firstMemberOfType<Text>().body - assertEquals( - "Here comes description from package-info", documentationOfPackage - ) - } - } - } - - @Test - fun `java package-info package annotations`() { - testInline( - """ - |/src/main/java/sample/PackageAnnotation.java - |package sample; - |@java.lang.annotation.Target(java.lang.annotation.ElementType.PACKAGE) - |public @interface PackageAnnotation { - |} - | - |/src/main/java/sample/package-info.java - |@PackageAnnotation - |package sample; - """.trimMargin(), - configuration - ) { - documentablesMergingStage = { module -> - assertEquals( - Annotations.Annotation(DRI("sample", "PackageAnnotation"), emptyMap()), - module.packages.single().extra[Annotations]?.directAnnotations?.values?.single()?.single() - ) - } - } - } - - @Test - fun `should add default value to constant properties`() { - testInline( - """ - |/src/main/java/test/JavaConstants.java - |package test; - | - |public class JavaConstants { - | public static final byte BYTE = 1; - | public static final short SHORT = 2; - | public static final int INT = 3; - | public static final long LONG = 4L; - | public static final float FLOAT = 5.0f; - | public static final double DOUBLE = 6.0d; - | public static final String STRING = "Seven"; - | public static final char CHAR = 'E'; - | public static final boolean BOOLEAN = true; - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testedClass = module.packages.single().classlikes.single { it.name == "JavaConstants" } - - val constants = testedClass.properties - assertEquals(9, constants.size) - - val constantsByName = constants.associateBy { it.name } - fun getConstantExpression(name: String): Expression? { - return constantsByName.getValue(name).extra[DefaultValue]?.expression?.values?.first() - } - - assertEquals(IntegerConstant(1), getConstantExpression("BYTE")) - assertEquals(IntegerConstant(2), getConstantExpression("SHORT")) - assertEquals(IntegerConstant(3), getConstantExpression("INT")) - assertEquals(IntegerConstant(4), getConstantExpression("LONG")) - assertEquals(FloatConstant(5.0f), getConstantExpression("FLOAT")) - assertEquals(DoubleConstant(6.0), getConstantExpression("DOUBLE")) - assertEquals(StringConstant("Seven"), getConstantExpression("STRING")) - assertEquals(StringConstant("E"), getConstantExpression("CHAR")) - assertEquals(BooleanConstant(true), getConstantExpression("BOOLEAN")) - } - } - } - - @Test - fun `should resolve static imports used as annotation param values as literal values`() { - testInline( - """ - |/src/main/java/test/JavaClassUsingAnnotation.java - |package test; - | - |import static test.JavaConstants.STRING; - |import static test.JavaConstants.INTEGER; - |import static test.JavaConstants.LONG; - |import static test.JavaConstants.BOOLEAN; - |import static test.JavaConstants.DOUBLE; - |import static test.JavaConstants.FLOAT; - |import static test.JavaConstants.BYTE; - |import static test.JavaConstants.SHORT; - |import static test.JavaConstants.CHAR; - | - |@JavaAnnotation( - | byteValue = BYTE, shortValue = SHORT, intValue = INTEGER, longValue = LONG, booleanValue = BOOLEAN, - | doubleValue = DOUBLE, floatValue = FLOAT, stringValue = STRING, charValue = CHAR - |) - |public class JavaClassUsingAnnotation { - |} - | - |/src/main/java/test/JavaAnnotation.java - |package test; - |@Documented - |public @interface JavaAnnotation { - | byte byteValue(); - | short shortValue(); - | int intValue(); - | long longValue(); - | boolean booleanValue(); - | double doubleValue(); - | float floatValue(); - | String stringValue(); - | char charValue(); - |} - | - |/src/main/java/test/JavaConstants.java - |package test; - |public class JavaConstants { - | public static final byte BYTE = 3; - | public static final short SHORT = 4; - | public static final int INTEGER = 5; - | public static final long LONG = 6L; - | public static final boolean BOOLEAN = true; - | public static final double DOUBLE = 7.0d; - | public static final float FLOAT = 8.0f; - | public static final String STRING = "STRING_CONSTANT_VALUE"; - | public static final char CHAR = 'c'; - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testedClass = module.packages.single().classlikes.single { it.name == "JavaClassUsingAnnotation" } - - val annotation = (testedClass as DClass).extra[Annotations]?.directAnnotations?.values?.single()?.single() - assertNotNull(annotation) - - assertEquals("JavaAnnotation", annotation.dri.classNames) - - assertEquals(IntValue(3), annotation.params["byteValue"]) - assertEquals(IntValue(4), annotation.params["shortValue"]) - assertEquals(IntValue(5), annotation.params["intValue"]) - assertEquals(LongValue(6), annotation.params["longValue"]) - assertEquals(BooleanValue(true), annotation.params["booleanValue"]) - assertEquals(DoubleValue(7.0), annotation.params["doubleValue"]) - assertEquals(FloatValue(8.0f), annotation.params["floatValue"]) - assertEquals(StringValue("STRING_CONSTANT_VALUE"), annotation.params["stringValue"]) - assertEquals(StringValue("c"), annotation.params["charValue"]) - } - } - } - - // TODO [beresnev] fix -// class OnlyPsiPlugin : DokkaPlugin() { -// private val kotlinAnalysisPlugin by lazy { plugin<Kotlin>() } -// -// @Suppress("unused") -// val psiOverrideDescriptorTranslator by extending { -// (plugin<JavaAnalysisPlugin>().psiToDocumentableTranslator -// override kotlinAnalysisPlugin.descriptorToDocumentableTranslator) -// } -// -// @OptIn(DokkaPluginApiPreview::class) -// override fun pluginApiPreviewAcknowledgement(): PluginApiPreviewAcknowledgement = -// PluginApiPreviewAcknowledgement -// } -// -// // for Kotlin classes from DefaultPsiToDocumentableTranslator -// @Test -// fun `should resolve ultralight class`() { -// val configurationWithNoJVM = dokkaConfiguration { -// sourceSets { -// sourceSet { -// sourceRoots = listOf("src/main/java") -// } -// } -// } -// -// testInline( -// """ -// |/src/main/java/example/Test.kt -// |package example -// | -// |open class KotlinSubClass { -// | fun kotlinSubclassFunction(bar: String): String { -// | return "KotlinSubClass" -// | } -// |} -// | -// |/src/main/java/example/JavaLeafClass.java -// |package example; -// | -// |public class JavaLeafClass extends KotlinSubClass { -// | public String javaLeafClassFunction(String baz) { -// | return "JavaLeafClass"; -// | } -// |} -// """.trimMargin(), -// configurationWithNoJVM, -// pluginOverrides = listOf(OnlyPsiPlugin()) // suppress a descriptor translator because of psi and descriptor translators work in parallel -// ) { -// documentablesMergingStage = { module -> -// val kotlinSubclassFunction = -// module.packages.single().classlikes.find { it.name == "JavaLeafClass" }?.functions?.find { it.name == "kotlinSubclassFunction" } -// .assertNotNull("kotlinSubclassFunction ") -// -// assertEquals( -// "String", -// (kotlinSubclassFunction.type as? TypeConstructor)?.dri?.classNames -// ) -// assertEquals( -// "String", -// (kotlinSubclassFunction.parameters.firstOrNull()?.type as? TypeConstructor)?.dri?.classNames -// ) -// } -// } -// } - - @Test - fun `should preserve regular functions that are named like getters, but are not getters`() { - testInline( - """ - |/src/main/java/test/A.java - |package test; - |public class A { - | private int a = 1; - | public String getA() { return "s"; } // wrong return type - | public int getA(String param) { return 123; } // shouldn't have params - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testClass = module.packages.single().classlikes.single { it.name == "A" } - - val getterLookalikes = testClass.functions.filter { it.name == "getA" } - assertEquals(2, getterLookalikes.size, "Not all expected regular functions found, wrongly categorized as getters?") - } - } - } - - @Test - fun `should ignore additional non-accessor setters`() { - testInline( - """ - |/src/main/java/test/A.java - |package test; - |public class A { - | private int a = 1; - | - | public int getA() { return a; } - | - | public void setA(long a) { } - | public void setA(Number a) {} - | - | // the qualifying setter is intentionally in the middle - | // to rule out the order making a difference - | public void setA(int a) { } - | - | public void setA(String a) {} - | public void setA() {} - | - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testClass = module.packages.single().classlikes.single { it.name == "A" } - - val property = testClass.properties.single { it.name == "a" } - assertNotNull(property.getter) - - val setter = property.setter - assertNotNull(setter) - assertEquals(1, setter.parameters.size) - assertEquals(PrimitiveJavaType("int"), setter.parameters[0].type) - - val regularSetterFunctions = testClass.functions.filter { it.name == "setA" } - assertEquals(4, regularSetterFunctions.size) - } - } - } - - @Test - fun `should not qualify methods with subtype parameters as type accessors`() { - testInline( - """ - |/src/main/java/test/Shape.java - |package test; - |public class Shape { } - | - |/src/main/java/test/Triangle.java - |package test; - |public class Triangle extends Shape { } - | - |/src/main/java/test/Square.java - |package test; - |public class Square extends Shape { } - | - |/src/main/java/test/Test.java - |package test; - |public class Test { - | private Shape foo = 1; - | - | public Shape getFoo() { return new Square(); } - | - | public void setFoo(Square foo) { } - | public void setFoo(Triangle foo) { } - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testClass = module.packages.single().classlikes.single { it.name == "Test" } - - val field = testClass.properties.singleOrNull { it.name == "foo" } - assertNotNull(field) { - "Expected the foo property to exist because the field is private with a public getter" - } - assertNull(field.setter) - - val setterMethodsWithSubtypeParams = testClass.functions.filter { it.name == "setFoo" } - assertEquals( - 2, - setterMethodsWithSubtypeParams.size, - "Expected the setter methods to not qualify as accessors because of subtype parameters" - ) - } - } - } - - @Test - fun `should preserve private fields without getters even if they have qualifying setters`() { - testInline( - """ - |/src/main/java/test/A.java - |package test; - |public class A { - | private int a = 1; - | - | public void setA(int a) { } - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val tetClass = module.packages.single().classlikes.single { it.name == "A" } - - val property = tetClass.properties.firstOrNull { it.name == "a" } - assertNull(property, "Expected the property to stay private because there are no getters") - - val regularSetterFunction = tetClass.functions.firstOrNull { it.name == "setA" } - assertNotNull(regularSetterFunction) { - "The qualifying setter function should stay a regular function because the field is inaccessible" - } - } - } - } - - @Test - fun `should not mark a multi-param setter overload as an accessor`() { - testInline( - """ - |/src/main/java/test/A.java - |package test; - |public class A { - | private int field = 1; - | - | public void setField(int a, int b) { } - | public int getField() { return a; } - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testClass = module.packages.single().classlikes.single { it.name == "A" } as DClass - - val property = testClass.properties.single { it.name == "field" } - assertEquals("getField", property.getter?.name) - assertNull(property.setter) - - - // the setField function should not qualify to be an accessor due to the second param - assertEquals(1, testClass.functions.size) - assertEquals("setField", testClass.functions[0].name) - } - } - } - - @Test - fun `should not associate accessors with field because field is public api`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - documentedVisibilities = setOf( - DokkaConfiguration.Visibility.PUBLIC, - DokkaConfiguration.Visibility.PROTECTED - ) - } - } - } - - testInline( - """ - |/src/test/A.java - |package test; - |public class A { - | protected int a = 1; - | public int getA() { return a; } - | public void setA(int a) { this.a = a; } - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testedClass = module.packages.single().classlikes.single { it.name == "A" } - - val property = testedClass.properties.single { it.name == "a" } - assertEquals(JavaVisibility.Protected, property.visibility.values.single()) - assertNull(property.getter) - assertNull(property.setter) - - assertEquals(2, testedClass.functions.size) - - assertEquals("getA", testedClass.functions[0].name) - assertEquals("setA", testedClass.functions[1].name) - } - } - } - - @Test - fun `should add IsVar extra for field with getter and setter`() { - testInline( - """ - |/src/main/java/test/A.java - |package test; - |public class A { - | private int a = 1; - | public int getA() { return a; } - | public void setA(int a) { this.a = a; } - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testedClass = module.packages.single().classlikes.single { it.name == "A" } - - val property = testedClass.properties.single { it.name == "a" } - assertNotNull(property.extra[IsVar]) - } - } - } - - @Test - fun `should not add IsVar extra if field does not have a setter`() { - testInline( - """ - |/src/main/java/test/A.java - |package test; - |public class A { - | private int a = 1; - | public int getA() { return a; } - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testedClass = module.packages.single().classlikes.single { it.name == "A" } - - val property = testedClass.properties.single { it.name == "a" } - assertNull(property.extra[IsVar]) - } - } - } - - @Test - fun `should add IsVar for non-final java field without any accessors`() { - testInline( - """ - |/src/main/java/test/A.java - |package test; - |public class A { - | public int a = 1; - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testedClass = module.packages.single().classlikes.single { it.name == "A" } - - val property = testedClass.properties.single { it.name == "a" } - assertNotNull(property.extra[IsVar]) - } - } - } - - @Test - fun `should not add IsVar for final java field`() { - testInline( - """ - |/src/main/java/test/A.java - |package test; - |public class A { - | public final int a = 2; - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testedClass = module.packages.single().classlikes.single { it.name == "A" } - - val publicFinal = testedClass.properties.single { it.name == "a" } - assertNull(publicFinal.extra[IsVar]) - } - } - } - - @Test // see https://github.com/Kotlin/dokka/issues/2646 - fun `should resolve PsiImmediateClassType as class reference`() { - testInline( - """ - |/src/main/java/test/JavaEnum.java - |package test; - |public enum JavaEnum { - | FOO, BAR - |} - | - |/src/main/java/test/ContainingEnumType.java - |package test; - |public class ContainingEnumType { - | - | public JavaEnum returningEnumType() { - | return null; - | } - | - | public JavaEnum[] returningEnumTypeArray() { - | return null; - | } - | - | public void acceptingEnumType(JavaEnum javaEnum) {} - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val expectedType = GenericTypeConstructor( - dri = DRI(packageName = "test", classNames = "JavaEnum", target = PointingToDeclaration), - projections = emptyList() - ) - val expectedArrayType = GenericTypeConstructor( - dri = DRI("kotlin", "Array", target = PointingToDeclaration), - projections = listOf(expectedType) - ) - - val classWithEnumUsage = module.packages.single().classlikes.single { it.name == "ContainingEnumType" } - - val returningEnum = classWithEnumUsage.functions.single { it.name == "returningEnumType" } - assertEquals(expectedType, returningEnum.type) - - val acceptingEnum = classWithEnumUsage.functions.single { it.name == "acceptingEnumType" } - assertEquals(1, acceptingEnum.parameters.size) - assertEquals(expectedType, acceptingEnum.parameters[0].type) - - val returningArray = classWithEnumUsage.functions.single { it.name == "returningEnumTypeArray" } - assertEquals(expectedArrayType, returningArray.type) - } - } - } - - @Test - fun `should have documentation for synthetic Enum values functions`() { - testInline( - """ - |/src/main/java/test/JavaEnum.java - |package test - | - |public enum JavaEnum { - | FOO, BAR; - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val kotlinEnum = module.packages.find { it.name == "test" } - ?.classlikes - ?.single { it.name == "JavaEnum" } - assertNotNull(kotlinEnum) - - val valuesFunction = kotlinEnum.functions.single { it.name == "values" } - - val expectedDocumentation = DocumentationNode(listOf( - Description( - CustomDocTag( - children = listOf( - P(listOf( - Text( - "Returns an array containing the constants of this enum type, " + - "in the order they're declared. This method may be used to " + - "iterate over the constants." - ), - )) - ), - name = "MARKDOWN_FILE" - ) - ), - Return( - CustomDocTag( - children = listOf( - P(listOf( - Text("an array containing the constants of this enum type, in the order they're declared") - )) - ), - name = "MARKDOWN_FILE" - ) - ) - )) - assertEquals(expectedDocumentation, valuesFunction.documentation.values.single()) - - val expectedValuesType = GenericTypeConstructor( - dri = DRI( - packageName = "kotlin", - classNames = "Array" - ), - projections = listOf( - GenericTypeConstructor( - dri = DRI( - packageName = "test", - classNames = "JavaEnum" - ), - projections = emptyList() - ) - ) - ) - assertEquals(expectedValuesType, valuesFunction.type) - } - } - } - - @Test - fun `should have documentation for synthetic Enum valueOf functions`() { - testInline( - """ - |/src/main/java/test/JavaEnum.java - |package test - | - |public enum JavaEnum { - | FOO, BAR; - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val javaEnum = module.packages.find { it.name == "test" } - ?.classlikes - ?.single { it.name == "JavaEnum" } - assertNotNull(javaEnum) - - val valueOfFunction = javaEnum.functions.single { it.name == "valueOf" } - - val expectedDocumentation = DocumentationNode(listOf( - Description( - CustomDocTag( - children = listOf( - P(listOf( - Text( - "Returns the enum constant of this type with the " + - "specified name. The string must match exactly an identifier used " + - "to declare an enum constant in this type. (Extraneous whitespace " + - "characters are not permitted.)" - ) - )) - ), - name = "MARKDOWN_FILE" - ) - ), - Return( - root = CustomDocTag( - children = listOf( - P(listOf( - Text("the enum constant with the specified name") - )) - ), - name = "MARKDOWN_FILE" - ) - ), - Throws( - name = "java.lang.IllegalArgumentException", - exceptionAddress = DRI( - packageName = "java.lang", - classNames = "IllegalArgumentException", - target = PointingToDeclaration - ), - root = CustomDocTag( - children = listOf( - P(listOf( - Text("if this enum type has no constant with the specified name") - )) - ), - name = "MARKDOWN_FILE" - ) - ), - )) - assertEquals(expectedDocumentation, valueOfFunction.documentation.values.single()) - - val expectedValueOfType = GenericTypeConstructor( - dri = DRI( - packageName = "test", - classNames = "JavaEnum" - ), - projections = emptyList() - ) - assertEquals(expectedValueOfType, valueOfFunction.type) - - val valueOfParamDRI = (valueOfFunction.parameters.single().type as GenericTypeConstructor).dri - assertEquals(DRI(packageName = "java.lang", classNames = "String"), valueOfParamDRI) - } - } - } - - @Test - fun `should have public default constructor in public class`() { - testInline( - """ - |/src/main/java/test/A.java - |package test; - |public class A { - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testedClass = module.findClasslike(packageName = "test", "A") as DClass - - assertEquals(1, testedClass.constructors.size, "Expect 1 default constructor") - assertTrue( - testedClass.constructors.first().parameters.isEmpty(), - "Expect default constructor doesn't have params" - ) - assertEquals(JavaVisibility.Public, testedClass.constructors.first().visibility()) - } - } - } - - @Test - fun `should have package-private default constructor in package-private class`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/java") - documentedVisibilities = setOf(Visibility.PUBLIC, Visibility.PACKAGE) - } - } - } - - testInline( - """ - |/src/main/java/test/A.java - |package test; - |class A { - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testedClass = module.findClasslike(packageName = "test", "A") as DClass - - assertEquals(1, testedClass.constructors.size, "Expect 1 default constructor") - assertEquals(JavaVisibility.Default, testedClass.constructors.first().visibility()) - } - } - } - - @Test - fun `should have private default constructor in private nested class`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/java") - documentedVisibilities = setOf(Visibility.PUBLIC, Visibility.PRIVATE) - } - } - } - - testInline( - """ - |/src/main/java/test/A.java - |package test; - |public class A { - | private static class PrivateNested{} - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val parentClass = module.findClasslike(packageName = "test", "A") as DClass - val testedClass = parentClass.classlikes.single { it.name == "PrivateNested" } as DClass - - assertEquals(1, testedClass.constructors.size, "Expect 1 default constructor") - assertEquals(JavaVisibility.Private, testedClass.constructors.first().visibility()) - } - } - } - - @Test - fun `should not have a default public constructor because have explicit private`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/java") - documentedVisibilities = setOf(Visibility.PUBLIC, Visibility.PRIVATE) - } - } - } - - testInline( - """ - |/src/main/java/test/A.java - |package test; - |public class A { - | private A(){} - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testedClass = module.findClasslike(packageName = "test", "A") as DClass - - assertEquals(1, testedClass.constructors.size, "Expect 1 declared constructor") - assertEquals(JavaVisibility.Private, testedClass.constructors.first().visibility()) - } - } - } - - @Test - fun `default constructor should get the package name`() { - testInline( - """ - |/src/main/java/org/test/A.java - |package org.test; - |public class A { - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = { module -> - val testedClass = module.findClasslike(packageName = "org.test", "A") as DClass - - assertEquals(1, testedClass.constructors.size, "Expect 1 default constructor") - - val constructorDRI = testedClass.constructors.first().dri - assertEquals("org.test", constructorDRI.packageName) - assertEquals("A", constructorDRI.classNames) - } - } - } -} - -private fun DFunction.visibility() = visibility.values.first() diff --git a/plugins/base/src/test/kotlin/translators/ExternalDocumentablesTest.kt b/plugins/base/src/test/kotlin/translators/ExternalDocumentablesTest.kt deleted file mode 100644 index 1879c538..00000000 --- a/plugins/base/src/test/kotlin/translators/ExternalDocumentablesTest.kt +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package translators - -import org.jetbrains.dokka.analysis.kotlin.internal.ExternalDocumentablesProvider -import org.jetbrains.dokka.analysis.kotlin.internal.InternalKotlinAnalysisPlugin -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.model.DClass -import org.jetbrains.dokka.model.DInterface -import org.jetbrains.dokka.plugability.plugin -import org.jetbrains.dokka.plugability.querySingle -import org.jetbrains.dokka.utilities.cast -import kotlin.test.Test -import kotlin.test.assertEquals - -class ExternalDocumentablesTest : BaseAbstractTest() { - @Test - fun `external documentable from java stdlib`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src") - analysisPlatform = "jvm" - classpath += jvmStdlibPath!! - } - } - } - - testInline( - """ - /src/com/sample/MyList.kt - package com.sample - class MyList: ArrayList<Int>() - """.trimIndent(), - configuration - ) { - lateinit var provider: ExternalDocumentablesProvider - pluginsSetupStage = { - provider = it.plugin<InternalKotlinAnalysisPlugin>().querySingle { externalDocumentablesProvider } - } - documentablesTransformationStage = { mod -> - val entry = mod.packages.single().classlikes.single().cast<DClass>().supertypes.entries.single() - val res = provider.findClasslike( - entry.value.single().typeConstructor.dri, - entry.key) - assertEquals("ArrayList", res?.name) - assertEquals("java.util/ArrayList///PointingToDeclaration/", res?.dri?.toString()) - - val supertypes = res?.cast<DClass>()?.supertypes?.values?.single() - ?.map { it.typeConstructor.dri.classNames } - assertEquals( - listOf("AbstractList", "RandomAccess", "Cloneable", "Serializable", "MutableList"), - supertypes - ) - } - } - } - - @Test - fun `external documentable from dependency`() { - val coroutinesPath = - ClassLoader.getSystemResource("kotlinx/coroutines/Job.class") - ?.file - ?.replace("file:", "") - ?.replaceAfter(".jar", "") - - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src") - analysisPlatform = "jvm" - classpath += listOf(jvmStdlibPath!!, coroutinesPath!!) - } - } - } - - testInline( - """ - /src/com/sample/MyJob.kt - package com.sample - import kotlinx.coroutines.Job - abstract class MyJob: Job - """.trimIndent(), - configuration - ) { - lateinit var provider: ExternalDocumentablesProvider - pluginsSetupStage = { - provider = it.plugin<InternalKotlinAnalysisPlugin>().querySingle { externalDocumentablesProvider } - } - documentablesTransformationStage = { mod -> - val entry = mod.packages.single().classlikes.single().cast<DClass>().supertypes.entries.single() - val res = provider.findClasslike( - entry.value.single().typeConstructor.dri, - entry.key) - assertEquals("Job", res?.name) - assertEquals("kotlinx.coroutines/Job///PointingToDeclaration/", res?.dri?.toString()) - - val supertypes = res?.cast<DInterface>()?.supertypes?.values?.single() - ?.map { it.typeConstructor.dri.classNames } - assertEquals( - listOf("CoroutineContext.Element"), - supertypes - ) - } - } - } - - @Test - fun `external documentable for nested class`() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src") - analysisPlatform = "jvm" - classpath += jvmStdlibPath!! - } - } - } - - testInline( - """ - /src/com/sample/MyList.kt - package com.sample - abstract class MyEntry: Map.Entry<Int, String> - """.trimIndent(), - configuration - ) { - lateinit var provider: ExternalDocumentablesProvider - pluginsSetupStage = { - provider = it.plugin<InternalKotlinAnalysisPlugin>().querySingle { externalDocumentablesProvider } - } - documentablesTransformationStage = { mod -> - val entry = mod.packages.single().classlikes.single().cast<DClass>().supertypes.entries.single() - val res = provider.findClasslike( - entry.value.single().typeConstructor.dri, - entry.key) - assertEquals("Entry", res?.name) - assertEquals("kotlin.collections/Map.Entry///PointingToDeclaration/", res?.dri?.toString()) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/translators/JavadocInheritDocsTest.kt b/plugins/base/src/test/kotlin/translators/JavadocInheritDocsTest.kt deleted file mode 100644 index 6413866f..00000000 --- a/plugins/base/src/test/kotlin/translators/JavadocInheritDocsTest.kt +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package translators - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.model.doc.CustomDocTag -import org.jetbrains.dokka.model.doc.Description -import org.jetbrains.dokka.model.doc.P -import org.jetbrains.dokka.model.doc.Text -import kotlin.test.Ignore -import kotlin.test.Test -import kotlin.test.assertEquals - -class JavadocInheritDocsTest : BaseAbstractTest() { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/java") - } - } - } - - @Test - fun `work when whole description is inherited`() { - testInline( - """ - |/src/main/java/sample/Superclass.java - |package sample; - |/** - |* Superclass docs - |*/ - |public class Superclass { } - | - |/src/main/java/sample/Subclass.java - |package sample; - |/** - |* {@inheritDoc} - |*/ - |public class Subclass extends Superclass { } - """.trimIndent(), configuration - ) { - documentablesMergingStage = { module -> - val subclass = module.findClasslike("sample", "Subclass") - val descriptionGot = subclass.documentation.values.first().children.first() - val expectedDescription = Description( - CustomDocTag( - children = listOf( - P( - children = listOf(Text("Superclass docs")) - ) - ), - name = "MARKDOWN_FILE" - ) - ) - - assertEquals(expectedDescription, descriptionGot) - } - } - } - - @Test - fun `work when inherited part is inside description`() { - testInline( - """ - |/src/main/java/sample/Superclass.java - |package sample; - |/** - |* Superclass docs - |*/ - |public class Superclass { } - | - |/src/main/java/sample/Subclass.java - |package sample; - |/** - |* Subclass docs. {@inheritDoc} End of subclass docs - |*/ - |public class Subclass extends Superclass { } - """.trimIndent(), configuration - ) { - documentablesMergingStage = { module -> - val subclass = module.findClasslike("sample", "Subclass") - val descriptionGot = subclass.documentation.values.first().children.first() - val expectedDescription = Description( - CustomDocTag( - children = listOf( - P( - children = listOf(Text("Subclass docs. Superclass docs End of subclass docs")) - ) - ), - name = "MARKDOWN_FILE" - ) - ) - - assertEquals(expectedDescription, descriptionGot) - } - } - } - - @Test - fun `work when inherited part is empty`() { - testInline( - """ - |/src/main/java/sample/Superclass.java - |package sample; - |public class Superclass { } - | - |/src/main/java/sample/Subclass.java - |package sample; - |/** - |* Subclass docs. {@inheritDoc} End of subclass docs - |*/ - |public class Subclass extends Superclass { } - """.trimIndent(), configuration - ) { - documentablesMergingStage = { module -> - val subclass = module.findClasslike("sample", "Subclass") - val descriptionGot = subclass.documentation.values.first().children.first() - val expectedDescription = Description( - CustomDocTag( - children = listOf( - P( - children = listOf(Text("Subclass docs. End of subclass docs")) - ) - ), - name = "MARKDOWN_FILE" - ) - ) - - assertEquals(expectedDescription, descriptionGot) - } - } - } - - @Test - @Ignore // This should be enabled when we have proper tag inheritance in javadoc parser - fun `work when inherited part is empty in supertype but present in its supertype`() { - testInline( - """ - |/src/main/java/sample/SuperSuperclass.java - |package sample; - |/** - |* Super super docs - |*/ - |public class SuperSuperclass { } - |/src/main/java/sample/Superclass.java - |package sample; - |public class Superclass extends SuperSuperClass { } - | - |/src/main/java/sample/Subclass.java - |package sample; - |/** - |* Subclass docs. {@inheritDoc} End of subclass docs - |*/ - |public class Subclass extends Superclass { } - """.trimIndent(), configuration - ) { - documentablesMergingStage = { module -> - val subclass = module.findClasslike("sample", "Subclass") - val descriptionGot = subclass.documentation.values.first().children.first() - val expectedDescription = Description( - CustomDocTag( - children = listOf( - P( - children = listOf(Text("Subclass docs. Super super docs End of subclass docs")) - ) - ), - name = "MARKDOWN_FILE" - ) - ) - - assertEquals(expectedDescription, descriptionGot) - } - } - } - - @Test - //Original javadoc doesn't treat interfaces as valid candidates for inherit doc - fun `work with interfaces`() { - testInline( - """ - |/src/main/java/sample/SuperInterface.java - |package sample; - |/** - |* Super super docs - |*/ - |public interface SuperInterface { } - | - |/src/main/java/sample/Subclass.java - |package sample; - |/** - |* Subclass docs. {@inheritDoc} End of subclass docs - |*/ - |public interface Subclass extends SuperInterface { } - """.trimIndent(), configuration - ) { - documentablesMergingStage = { module -> - val subclass = module.findClasslike("sample", "Subclass") - val descriptionGot = subclass.documentation.values.first().children.first() - val expectedDescription = Description( - CustomDocTag( - children = listOf( - P( - children = listOf(Text("Subclass docs. End of subclass docs")) - ) - ), - name = "MARKDOWN_FILE" - ) - ) - - assertEquals(expectedDescription, descriptionGot) - } - } - } - - - @Test - fun `work with multiple supertypes`() { - testInline( - """ - |/src/main/java/sample/SuperInterface.java - |package sample; - |/** - |* Super interface docs - |*/ - |public interface SuperInterface { } - |/src/main/java/sample/Superclass.java - |package sample; - |/** - |* Super class docs - |*/ - |public class Superclass { } - | - |/src/main/java/sample/Subclass.java - |package sample; - |/** - |* Subclass docs. {@inheritDoc} End of subclass docs - |*/ - |public class Subclass extends Superclass implements SuperInterface { } - """.trimIndent(), configuration - ) { - documentablesMergingStage = { module -> - val subclass = module.findClasslike("sample", "Subclass") - val descriptionGot = subclass.documentation.values.first().children.first() - val expectedDescription = Description( - CustomDocTag( - children = listOf( - P( - children = listOf(Text("Subclass docs. Super class docs End of subclass docs")) - ) - ), - name = "MARKDOWN_FILE" - ) - ) - - assertEquals(expectedDescription, descriptionGot) - } - } - } - - @Test - fun `work with methods`() { - testInline( - """ - |/src/main/java/sample/Superclass.java - |package sample; - |public class Superclass { - |/** - |* Sample super method - |* - |* @return super string - |* @throws RuntimeException super throws - |* @see java.lang.String super see - |* @deprecated super deprecated - |*/ - |public String test() { - | return ""; - |} - |} - |/src/main/java/sample/Subclass.java - |package sample; - |public class Subclass extends Superclass { - | /** - | * Sample sub method. {@inheritDoc} - | */ - | @Override - | public String test() { - | return super.test(); - | } - |} - """.trimIndent(), configuration - ) { - documentablesMergingStage = { module -> - val function = module.findFunction("sample", "Subclass", "test") - val descriptionGot = function.documentation.values.first().children.first() - val expectedDescription = Description( - CustomDocTag( - children = listOf( - P( - children = listOf(Text("Sample sub method. Sample super method")) - ) - ), - name = "MARKDOWN_FILE" - ) - ) - - assertEquals(expectedDescription, descriptionGot) - } - } - } -} diff --git a/plugins/base/src/test/kotlin/translators/JavadocInheritedDocTagsTest.kt b/plugins/base/src/test/kotlin/translators/JavadocInheritedDocTagsTest.kt deleted file mode 100644 index a20db4ca..00000000 --- a/plugins/base/src/test/kotlin/translators/JavadocInheritedDocTagsTest.kt +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package translators - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.links.PointingToDeclaration -import org.jetbrains.dokka.model.DModule -import org.jetbrains.dokka.model.doc.* -import kotlin.test.Test -import kotlin.test.assertEquals -import org.jetbrains.dokka.model.doc.Deprecated as DokkaDeprecatedTag -import org.jetbrains.dokka.model.doc.Throws as DokkaThrowsTag - -class JavadocInheritedDocTagsTest : BaseAbstractTest() { - @Suppress("DEPRECATION") // for includeNonPublic - private val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/java") - includeNonPublic = true - } - } - } - - private fun performTagsTest(test: (DModule) -> Unit) { - testInline( - """ - |/src/main/java/sample/Superclass.java - |package sample; - |/** - |* @author super author - |*/ - |class Superclass { - | /** - | * Sample super method - | * - | * @return super string - | * @throws RuntimeException super throws - | * @see java.lang.String super see - | * @deprecated super deprecated - | */ - | public String test(){ - | return ""; - | } - | - | /** - | * - | * @param xd String superclass - | * @param asd Integer superclass - | */ - | public void test2(String xd, Integer asd){ - | } - |} - |/src/main/java/sample/Subclass.java - |package sample; - |/** - |* @author Ja, {@inheritDoc} - |*/ - |class Subclass extends Superclass { - |/** - | * Sample sub method. {@inheritDoc} - | * - | * @return "sample string". {@inheritDoc} - | * @throws RuntimeException because i can, {@inheritDoc} - | * @throws IllegalStateException this should be it {@inheritDoc} - | * @see java.lang.String string, {@inheritDoc} - | * @deprecated do not use, {@inheritDoc} - | */ - | @Override - | public String test() { - | return super.test(); - | } - | - | /** - | * - | * @param asd2 integer subclass, {@inheritDoc} - | * @param xd2 string subclass, {@inheritDoc} - | */ - | public void test2(String xd2, Integer asd2){ - | } - |} - """.trimIndent(), configuration - ) { - documentablesMergingStage = test - } - } - - @Test - fun `work with return`() { - performTagsTest { module -> - val function = module.findFunction("sample", "Subclass", "test") - val renderedTag = function.documentation.values.first().children.filterIsInstance<Return>().first() - val expectedTag = Return( - CustomDocTag( - children = listOf( - P( - children = listOf(Text("\"sample string\". super string")) - ) - ), - name = "MARKDOWN_FILE" - ) - ) - - assertEquals(expectedTag, renderedTag) - } - } - - @Test - fun `work with throws`() { - performTagsTest { module -> - val function = module.findFunction("sample", "Subclass", "test") - val renderedTag = - function.documentation.values.first().children.first { it is DokkaThrowsTag && it.name == "java.lang.RuntimeException" } - val expectedTag = DokkaThrowsTag( - CustomDocTag( - children = listOf( - P( - children = listOf(Text("because i can, super throws")) - ) - ), - name = "MARKDOWN_FILE" - ), - "java.lang.RuntimeException", - DRI("java.lang", "RuntimeException", target = PointingToDeclaration) - ) - - assertEquals(expectedTag, renderedTag) - } - } - - @Test - fun `work with throws when exceptions are different`() { - performTagsTest { module -> - val function = module.findFunction("sample", "Subclass", "test") - val renderedTag = - function.documentation.values.first().children.first { it is DokkaThrowsTag && it.name == "java.lang.IllegalStateException" } - val expectedTag = DokkaThrowsTag( - CustomDocTag( - children = listOf( - P( - children = listOf(Text("this should be it")) - ) - ), - name = "MARKDOWN_FILE" - ), - "java.lang.IllegalStateException", - DRI("java.lang", "IllegalStateException", target = PointingToDeclaration) - ) - - assertEquals(expectedTag, renderedTag) - } - } - - @Test - fun `work with deprecated`() { - performTagsTest { module -> - val function = module.findFunction("sample", "Subclass", "test") - val renderedTag = function.documentation.values.first().children.filterIsInstance<DokkaDeprecatedTag>().first() - val expectedTag = DokkaDeprecatedTag( - CustomDocTag( - children = listOf( - P( - children = listOf(Text("do not use, Sample super method")) - ) - ), - name = "MARKDOWN_FILE" - ), - ) - - assertEquals(expectedTag, renderedTag) - } - } - - @Test - fun `work with see also`() { - performTagsTest { module -> - val function = module.findFunction("sample", "Subclass", "test") - val renderedTag = function.documentation.values.first().children.filterIsInstance<See>().first() - val expectedTag = See( - CustomDocTag( - children = listOf( - P( - children = listOf(Text("string,")) - ) - ), - name = "MARKDOWN_FILE" - ), - "java.lang.String", - DRI("java.lang", "String") - ) - - assertEquals(expectedTag, renderedTag) - } - } - - @Test - fun `work with author`() { - performTagsTest { module -> - val classlike = module.findClasslike("sample", "Subclass") - val renderedTag = classlike.documentation.values.first().children.filterIsInstance<Author>().first() - val expectedTag = Author( - CustomDocTag( - children = listOf( - P( - children = listOf(Text("Ja, super author")) - ) - ), - name = "MARKDOWN_FILE" - ), - ) - - assertEquals(expectedTag, renderedTag) - } - } - - @Test - fun `work with params`() { - performTagsTest { module -> - val function = module.findFunction("sample", "Subclass", "test2") - val (asdTag, xdTag) = function.documentation.values.first().children.filterIsInstance<Param>() - .sortedBy { it.name } - - val expectedAsdTag = Param( - CustomDocTag( - children = listOf( - P( - children = listOf(Text("integer subclass, Integer superclass")) - ) - ), - name = "MARKDOWN_FILE" - ), - "asd2" - ) - val expectedXdTag = Param( - CustomDocTag( - children = listOf( - P( - children = listOf(Text("string subclass, String superclass")) - ) - ), - name = "MARKDOWN_FILE" - ), - "xd2" - ) - assertEquals(expectedAsdTag, asdTag) - assertEquals(expectedXdTag, xdTag) - } - } -} diff --git a/plugins/base/src/test/kotlin/translators/JavadocParserTest.kt b/plugins/base/src/test/kotlin/translators/JavadocParserTest.kt deleted file mode 100644 index 3f83f462..00000000 --- a/plugins/base/src/test/kotlin/translators/JavadocParserTest.kt +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package translators - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.model.DModule -import org.jetbrains.dokka.model.childrenOfType -import org.jetbrains.dokka.model.doc.* -import org.jetbrains.dokka.model.firstChildOfType -import org.jetbrains.dokka.model.firstMemberOfType -import utils.text -import kotlin.test.Test -import kotlin.test.assertEquals - -class JavadocParserTest : BaseAbstractTest() { - - private fun performJavadocTest(testOperation: (DModule) -> Unit) { - val configuration = dokkaConfiguration { - sourceSets { - sourceSet { - sourceRoots = listOf("src/main/java") - } - } - } - - testInline( - """ - |/src/main/java/sample/Date2.java - |/** - | * The class <code>Date</code> represents a specific instant - | * in time, with millisecond precision. - | * <p> - | * Prior to JDK 1.1, the class <code>Date</code> had two additional - | * functions. It allowed the interpretation of dates as year, month, day, hour, - | * minute, and second values. It also allowed the formatting and parsing - | * of date strings. Unfortunately, the API for these functions was not - | * amenable to internationalization. As of JDK 1.1, the - | * <code>Calendar</code> class should be used to convert between dates and time - | * fields and the <code>DateFormat</code> class should be used to format and - | * parse date strings. - | * The corresponding methods in <code>Date</code> are deprecated. - | * <p> - | * Although the <code>Date</code> class is intended to reflect - | * coordinated universal time (UTC), it may not do so exactly, - | * depending on the host environment of the Java Virtual Machine. - | * Nearly all modern operating systems assume that 1 day = - | * 24 × 60 × 60 = 86400 seconds - | * in all cases. In UTC, however, about once every year or two there - | * is an extra second, called a "leap second." The leap - | * second is always added as the last second of the day, and always - | * on December 31 or June 30. For example, the last minute of the - | * year 1995 was 61 seconds long, thanks to an added leap second. - | * Most computer clocks are not accurate enough to be able to reflect - | * the leap-second distinction. - | * <p> - | * Some computer standards are defined in terms of Greenwich mean - | * time (GMT), which is equivalent to universal time (UT). GMT is - | * the "civil" name for the standard; UT is the - | * "scientific" name for the same standard. The - | * distinction between UTC and UT is that UTC is based on an atomic - | * clock and UT is based on astronomical observations, which for all - | * practical purposes is an invisibly fine hair to split. Because the - | * earth's rotation is not uniform (it slows down and speeds up - | * in complicated ways), UT does not always flow uniformly. Leap - | * seconds are introduced as needed into UTC so as to keep UTC within - | * 0.9 seconds of UT1, which is a version of UT with certain - | * corrections applied. There are other time and date systems as - | * well; for example, the time scale used by the satellite-based - | * global positioning system (GPS) is synchronized to UTC but is - | * <i>not</i> adjusted for leap seconds. An interesting source of - | * further information is the U.S. Naval Observatory, particularly - | * the Directorate of Time at: - | * <blockquote><pre> - | * <a href=http://tycho.usno.navy.mil>http://tycho.usno.navy.mil</a> - | * </pre></blockquote> - | * <p> - | * and their definitions of "Systems of Time" at: - | * <blockquote><pre> - | * <a href=http://tycho.usno.navy.mil/systime.html>http://tycho.usno.navy.mil/systime.html</a> - | * </pre></blockquote> - | * <p> - | * In all methods of class <code>Date</code> that accept or return - | * year, month, date, hours, minutes, and seconds values, the - | * following representations are used: - | * <ul> - | * <li>A year <i>y</i> is represented by the integer - | * <i>y</i> <code>- 1900</code>. - | * <li>A month is represented by an integer from 0 to 11; 0 is January, - | * 1 is February, and so forth; thus 11 is December. - | * <li>A date (day of month) is represented by an integer from 1 to 31 - | * in the usual manner. - | * <li>An hour is represented by an integer from 0 to 23. Thus, the hour - | * from midnight to 1 a.m. is hour 0, and the hour from noon to 1 - | * p.m. is hour 12. - | * <li>A minute is represented by an integer from 0 to 59 in the usual manner. - | * <li>A second is represented by an integer from 0 to 61; the values 60 and - | * 61 occur only for leap seconds and even then only in Java - | * implementations that actually track leap seconds correctly. Because - | * of the manner in which leap seconds are currently introduced, it is - | * extremely unlikely that two leap seconds will occur in the same - | * minute, but this specification follows the date and time conventions - | * for ISO C. - | * </ul> - | * <pre class="prettyprint"> - | * <androidx.fragment.app.FragmentContainerView - | * xmlns:android="http://schemas.android.com/apk/res/android" - | * xmlns:app="http://schemas.android.com/apk/res-auto" - | * android:id="@+id/fragment_container_view" - | * android:layout_width="match_parent" - | * android:layout_height="match_parent"> - | * </androidx.fragment.app.FragmentContainerView> - | * </pre> - | * <p> - | * In all cases, arguments given to methods for these purposes need - | * not fall within the indicated ranges; for example, a date may be - | * specified as January 32 and is interpreted as meaning February 1. - | * - | * <pre class="prettyprint"> - | * class MyFragment extends Fragment { - | * public MyFragment() { - | * super(R.layout.fragment_main); - | * } - | * } - | * </pre> - | - | * @author James Gosling - | * @author Arthur van Hoff - | * @author Alan Liu - | * @see java.text.DateFormat - | * @see java.util.Calendar - | * @since JDK1.0 - | * @apiSince 1 - | */ - |public class Date2 implements java.io.Serializable, java.lang.Cloneable, java.lang.Comparable<java.util.Date> { - | void x() { } - |} - """.trimIndent(), - configuration - ) { - documentablesMergingStage = testOperation - } - } - - @Test - fun `correctly parsed list`() { - performJavadocTest { module -> - val dateDescription = module.descriptionOf("Date2")!! - assertEquals(6, dateDescription.firstChildOfType<Ul>().children.filterIsInstance<Li>().size) - } - } - - @Test - fun `correctly parsed author tags`() { - performJavadocTest { module -> - val authors = module.findClasslike().documentation.values.single().childrenOfType<Author>() - assertEquals(3, authors.size) - assertEquals("James Gosling", authors[0].firstMemberOfType<Text>().text()) - assertEquals("Arthur van Hoff", authors[1].firstMemberOfType<Text>().text()) - assertEquals("Alan Liu", authors[2].firstMemberOfType<Text>().text()) - } - } - - @Test - fun `correctly parsed see tags`() { - performJavadocTest { module -> - val sees = module.findClasslike().documentation.values.single().childrenOfType<See>() - assertEquals(2, sees.size) - assertEquals(DRI("java.text", "DateFormat"), sees[0].address) - assertEquals("java.text.DateFormat", sees[0].name) - assertEquals(DRI("java.util", "Calendar"), sees[1].address) - assertEquals("java.util.Calendar", sees[1].name) - } - } - - @Test - fun `correctly parsed code block`(){ - performJavadocTest { module -> - val dateDescription = module.descriptionOf("Date2")!! - val preTagContent = dateDescription.firstChildOfType<Pre>().firstChildOfType<Text>() - val expectedText = """<androidx.fragment.app.FragmentContainerView - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto" - android:id="@+id/fragment_container_view" - android:layout_width="match_parent" - android:layout_height="match_parent"> -</androidx.fragment.app.FragmentContainerView>""".trimIndent() - assertEquals(expectedText.trim(), preTagContent.body.trim()) - } - } - - @Test - fun `correctly parsed code block with curly braces (which PSI has problem with)`() { - performJavadocTest { module -> - val dateDescription = module.descriptionOf("Date2")!! - val preTagContent = dateDescription.childrenOfType<Pre>()[1].firstChildOfType<Text>() - val expectedText = """class MyFragment extends Fragment { - public MyFragment() { - super(R.layout.fragment_main); - } -}""".trimIndent() - assertEquals(expectedText.trim(), preTagContent.body.trim()) - } - } - -} diff --git a/plugins/base/src/test/kotlin/translators/utils.kt b/plugins/base/src/test/kotlin/translators/utils.kt deleted file mode 100644 index b1979f60..00000000 --- a/plugins/base/src/test/kotlin/translators/utils.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 translators - -import org.jetbrains.dokka.model.* -import org.jetbrains.dokka.model.doc.Description -import org.jetbrains.dokka.model.doc.Text - -fun DModule.documentationOf(className: String, functionName: String? = null): String = - descriptionOf(className, functionName) - ?.firstMemberOfType<Text>() - ?.body.orEmpty() - -fun DModule.descriptionOf(className: String, functionName: String? = null): Description? { - val classlike = packages.single() - .classlikes.single { it.name == className } - val target: Documentable = - if (functionName != null) classlike.functions.single { it.name == functionName } else classlike - return target.documentation.values.singleOrNull() - ?.firstChildOfTypeOrNull<Description>() -} - -fun DModule.findPackage(packageName: String? = null) = - packageName?.let { packages.firstOrNull { pkg -> pkg.packageName == packageName } - ?: throw NoSuchElementException("No packageName with name $packageName") } ?: packages.single() - -fun DModule.findClasslike(packageName: String? = null, className: String? = null): DClasslike { - val pkg = findPackage(packageName) - return className?.let { - pkg.classlikes.firstOrNull { cls -> cls.name == className } - ?: throw NoSuchElementException("No classlike with name $className") - } ?: pkg.classlikes.single() -} - -fun DModule.findFunction(packageName: String? = null, className: String, functionName: String? = null): DFunction { - val classlike = findClasslike(packageName, className) - return functionName?.let { - classlike.functions.firstOrNull { fn -> fn.name == functionName } - ?: throw NoSuchElementException("No classlike with name $functionName") - } ?: classlike.functions.single() -} diff --git a/plugins/base/src/test/kotlin/utils/HtmlUtils.kt b/plugins/base/src/test/kotlin/utils/HtmlUtils.kt deleted file mode 100644 index cb700a94..00000000 --- a/plugins/base/src/test/kotlin/utils/HtmlUtils.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 utils - -import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper -import com.fasterxml.jackson.module.kotlin.readValue -import org.jetbrains.dokka.base.renderers.html.SearchRecord -import org.jsoup.Jsoup -import org.jsoup.nodes.Element -import org.jsoup.select.Elements - -internal fun TestOutputWriter.navigationHtml(): Element = contents.getValue("navigation.html").let { Jsoup.parse(it) } - -internal fun TestOutputWriter.pagesJson(): List<SearchRecord> = jacksonObjectMapper().readValue(contents.getValue("scripts/pages.json")) - -internal fun Elements.selectNavigationGrid(): Element { - return this.select("div.overview").select("span.nav-link-grid").single() -} diff --git a/plugins/base/src/test/kotlin/utils/ModelUtils.kt b/plugins/base/src/test/kotlin/utils/ModelUtils.kt deleted file mode 100644 index fc7e9a2c..00000000 --- a/plugins/base/src/test/kotlin/utils/ModelUtils.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 utils - -import org.jetbrains.dokka.DokkaConfigurationImpl -import org.jetbrains.dokka.model.DModule -import org.jetbrains.dokka.plugability.DokkaPlugin - -abstract class AbstractModelTest(val path: String? = null, val pkg: String) : ModelDSL(), AssertDSL { - - fun inlineModelTest( - query: String, - platform: String = "jvm", - prependPackage: Boolean = true, - cleanupOutput: Boolean = true, - pluginsOverrides: List<DokkaPlugin> = emptyList(), - configuration: DokkaConfigurationImpl? = null, - block: DModule.() -> Unit - ) { - val testConfiguration = configuration ?: dokkaConfiguration { - suppressObviousFunctions = false - sourceSets { - sourceSet { - sourceRoots = listOf("src/") - analysisPlatform = platform - classpath += jvmStdlibPath!! - } - } - } - val prepend = path.let { p -> p?.let { "|$it\n" } ?: "" } + if (prependPackage) "|package $pkg" else "" - - testInline( - query = ("$prepend\n$query").trim().trimIndent(), - configuration = testConfiguration, - cleanupOutput = cleanupOutput, - pluginOverrides = pluginsOverrides - ) { - documentablesTransformationStage = block - } - } -} diff --git a/plugins/base/src/test/kotlin/utils/TagsAnnotations.kt b/plugins/base/src/test/kotlin/utils/TagsAnnotations.kt deleted file mode 100644 index a81b1dae..00000000 --- a/plugins/base/src/test/kotlin/utils/TagsAnnotations.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. - */ - -package utils - -import org.junit.jupiter.api.Tag - - -/** - * Run a test only for descriptors, not symbols. - * - * In theory, these tests can be fixed - */ -@Target( - AnnotationTarget.CLASS, - AnnotationTarget.FUNCTION, - AnnotationTarget.PROPERTY_GETTER, - AnnotationTarget.PROPERTY_SETTER -) -@Retention( - AnnotationRetention.RUNTIME -) -@Tag("onlyDescriptors") -annotation class OnlyDescriptors(val reason: String = "") - -/** - * Run a test only for descriptors, not symbols. - * - * These tests cannot be fixed until Analysis API does not support MPP - */ -@Target( - AnnotationTarget.CLASS, - AnnotationTarget.FUNCTION, - AnnotationTarget.PROPERTY_GETTER, - AnnotationTarget.PROPERTY_SETTER -) -@Retention( - AnnotationRetention.RUNTIME -) -@Tag("onlyDescriptorsMPP") -annotation class OnlyDescriptorsMPP(val reason: String = "") diff --git a/plugins/base/src/test/kotlin/utils/TestUtils.kt b/plugins/base/src/test/kotlin/utils/TestUtils.kt deleted file mode 100644 index 39ac4b23..00000000 --- a/plugins/base/src/test/kotlin/utils/TestUtils.kt +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package utils - -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.dokka.model.* -import org.jetbrains.dokka.model.doc.* -import org.jetbrains.dokka.model.doc.P -import kotlin.collections.orEmpty -import kotlin.test.assertEquals -import kotlin.test.assertTrue -import kotlin.test.asserter -import kotlin.test.fail - -@DslMarker -annotation class TestDSL - -@TestDSL -abstract class ModelDSL : BaseAbstractTest() { - operator fun Documentable?.div(name: String): Documentable? = - this?.children?.find { it.name == name } - - inline fun <reified T : Documentable> Documentable?.cast(): T = - (this as? T).assertNotNull() -} - -@TestDSL -interface AssertDSL { - infix fun Any?.equals(other: Any?) = assertEquals(other, this) - infix fun Collection<Any>?.allEquals(other: Any?) = - this?.onEach { it equals other } ?: run { fail("Collection is empty") } - infix fun <T> Collection<T>?.exists(e: T) { - assertTrue(this.orEmpty().isNotEmpty(), "Collection cannot be null or empty") - assertTrue(this!!.any{it == e}, "Collection doesn't contain $e") - } - - infix fun <T> Collection<T>?.counts(n: Int) = this.orEmpty().assertCount(n) - - infix fun <T> T?.notNull(name: String): T = this.assertNotNull(name) - - fun <T> Collection<T>.assertCount(n: Int, prefix: String = "") = - assertEquals(n, count(), "${prefix}Expected $n, got ${count()}") -} - -/* - * TODO replace with kotlin.test.assertContains after migrating to Kotlin 1.5+ - */ -internal fun <T> assertContains(iterable: Iterable<T>, element: T, ) { - asserter.assertTrue( - { "Expected the collection to contain the element.\nCollection <$iterable>, element <$element>." }, - iterable.contains(element) - ) -} - -inline fun <reified T : Any> Any?.assertIsInstance(name: String): T = - this.let { it as? T } ?: throw AssertionError("$name should not be null") - -fun TagWrapper.text(): String = when (val t = this) { - is NamedTagWrapper -> "${t.name}: [${t.root.text()}]" - else -> t.root.text() -} - -fun DocTag.text(): String = when (val t = this) { - is Text -> t.body - is Code -> t.children.joinToString("\n") { it.text() } - is P -> t.children.joinToString("") { it.text() } + "\n" - else -> t.children.joinToString("") { it.text() } -} - -fun <T : Documentable> T?.comments(): String = docs().map { it.text() } - .joinToString(separator = "\n") { it } - -fun <T> T?.assertNotNull(name: String = ""): T = this ?: throw AssertionError("$name should not be null") - -fun <T : Documentable> T?.docs() = this?.documentation.orEmpty().values.flatMap { it.children } - -val DClass.supers - get() = supertypes.flatMap { it.component2() } - -val Bound.name: String? - get() = when (this) { - is Nullable -> inner.name - is DefinitelyNonNullable -> inner.name - is TypeParameter -> name - is PrimitiveJavaType -> name - is TypeConstructor -> dri.classNames - is JavaObject -> "Object" - is Void -> "void" - is Dynamic -> "dynamic" - is UnresolvedBound -> "<ERROR CLASS>" - is TypeAliased -> typeAlias.name - } diff --git a/plugins/base/src/test/kotlin/utils/contentUtils.kt b/plugins/base/src/test/kotlin/utils/contentUtils.kt deleted file mode 100644 index 3ca0bd2d..00000000 --- a/plugins/base/src/test/kotlin/utils/contentUtils.kt +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package utils - -import matchers.content.* -import org.jetbrains.dokka.model.dfs -import org.jetbrains.dokka.pages.* -import kotlin.test.assertEquals - -//TODO: Try to unify those functions after update to 1.4 -fun ContentMatcherBuilder<*>.functionSignature( - annotations: Map<String, Set<String>>, - visibility: String, - modifier: String, - keywords: Set<String>, - name: String, - returnType: String? = null, - vararg params: Pair<String, ParamAttributes> -) = - platformHinted { - bareSignature(annotations, visibility, modifier, keywords, name, returnType, *params) - } - -fun ContentMatcherBuilder<*>.bareSignature( - annotations: Map<String, Set<String>>, - visibility: String, - modifier: String, - keywords: Set<String>, - name: String, - returnType: String? = null, - vararg params: Pair<String, ParamAttributes> -) = group { - annotations.entries.forEach { - group { - unwrapAnnotation(it) - } - } - if (visibility.isNotBlank()) +"$visibility " - if (modifier.isNotBlank()) +"$modifier " - +("${keywords.joinToString("") { "$it " }}fun ") - link { +name } - +"(" - if (params.isNotEmpty()) { - group { - params.forEachIndexed { id, (n, t) -> - group { - t.annotations.forEach { - unwrapAnnotation(it) - } - t.keywords.forEach { - +it - } - - +"$n: " - group { link { +(t.type) } } - if (id != params.lastIndex) - +", " - } - } - } - } - +")" - if (returnType != null) { - +(": ") - group { - link { - +(returnType) - } - } - } -} - -fun ContentMatcherBuilder<*>.classSignature( - annotations: Map<String, Set<String>>, - visibility: String, - modifier: String, - keywords: Set<String>, - name: String, - vararg params: Pair<String, ParamAttributes>, - parent: String? = null -) = group { - annotations.entries.forEach { - group { - unwrapAnnotation(it) - } - } - if (visibility.isNotBlank()) +"$visibility " - if (modifier.isNotBlank()) +"$modifier " - +("${keywords.joinToString("") { "$it " }}class ") - link { +name } - if (params.isNotEmpty()) { - +"(" - group { - params.forEachIndexed { id, (n, t) -> - group { - t.annotations.forEach { - unwrapAnnotation(it) - } - t.keywords.forEach { - +it - } - - +"$n: " - group { link { +(t.type) } } - if (id != params.lastIndex) - +", " - } - } - } - +")" - } - if (parent != null) { - +(" : ") - link { - +(parent) - } - } -} - -fun ContentMatcherBuilder<*>.functionSignatureWithReceiver( - annotations: Map<String, Set<String>>, - visibility: String?, - modifier: String?, - keywords: Set<String>, - receiver: String, - name: String, - returnType: String? = null, - vararg params: Pair<String, ParamAttributes> -) = - platformHinted { - bareSignatureWithReceiver(annotations, visibility, modifier, keywords, receiver, name, returnType, *params) - } - -fun ContentMatcherBuilder<*>.bareSignatureWithReceiver( - annotations: Map<String, Set<String>>, - visibility: String?, - modifier: String?, - keywords: Set<String>, - receiver: String, - name: String, - returnType: String? = null, - vararg params: Pair<String, ParamAttributes> -) = group { // TODO: remove it when double wrapping for signatures will be resolved - annotations.entries.forEach { - group { - unwrapAnnotation(it) - } - } - if (visibility != null && visibility.isNotBlank()) +"$visibility " - if (modifier != null && modifier.isNotBlank()) +"$modifier " - +("${keywords.joinToString("") { "$it " }}fun ") - group { - link { +receiver } - } - +"." - link { +name } - +"(" - if (params.isNotEmpty()) { - group { - params.forEachIndexed { id, (n, t) -> - group { - t.annotations.forEach { - unwrapAnnotation(it) - } - t.keywords.forEach { - +it - } - - +"$n: " - group { link { +(t.type) } } - if (id != params.lastIndex) - +", " - } - } - } - } - +")" - if (returnType != null) { - +(": ") - group { - link { - +(returnType) - } - } - } -} - -fun ContentMatcherBuilder<*>.propertySignature( - annotations: Map<String, Set<String>>, - visibility: String, - modifier: String, - keywords: Set<String>, - preposition: String, - name: String, - type: String? = null, - value: String? = null -) { - group { - header { +"Package-level declarations" } - skipAllNotMatching() - } - tabbedGroup { - group { - skipAllNotMatching() - tab(BasicTabbedContentType.PROPERTY) { - header{ + "Properties" } - table { - group { - link { +name } - divergentGroup { - divergentInstance { - divergent { - group { - group { - annotations.entries.forEach { - group { - unwrapAnnotation(it) - } - } - if (visibility.isNotBlank()) +"$visibility " - if (modifier.isNotBlank()) +"$modifier " - +("${keywords.joinToString("") { "$it " }}$preposition ") - link { +name } - if (type != null) { - +(": ") - group { - link { - +(type) - } - } - } - if (value != null) { - +(" = $value") - } - } - } - } - } - } - } - } - } - } - } -} - - -fun ContentMatcherBuilder<*>.typealiasSignature(name: String, expressionTarget: String) { - group { - header { +"Package-level declarations" } - skipAllNotMatching() - } - group { - group { - tab(BasicTabbedContentType.TYPE) { - header{ + "Types" } - table { - group { - link { +name } - divergentGroup { - divergentInstance { - group { - group { - group { - group { - +"typealias " - group { - group { - link { +name } - } - skipAllNotMatching() - } - +" = " - group { - link { +expressionTarget } - } - } - } - } - } - } - skipAllNotMatching() - } - } - skipAllNotMatching() - } - skipAllNotMatching() - } - } - } -} - -fun ContentMatcherBuilder<*>.pWrapped(text: String) = - group {// TODO: remove it when double wrapping for descriptions will be resolved - group { +text } - } - -fun ContentMatcherBuilder<*>.unnamedTag(tag: String, content: ContentMatcherBuilder<ContentGroup>.() -> Unit) = - group { - header(4) { +tag } - content() - } - -fun ContentMatcherBuilder<*>.comment(content: ContentMatcherBuilder<ContentGroup>.() -> Unit) = - group { - group { - content() - } - } - -fun ContentMatcherBuilder<*>.unwrapAnnotation(elem: Map.Entry<String, Set<String>>) { - group { - +"@" - link { +elem.key } - if(elem.value.isNotEmpty()) { - +"(" - elem.value.forEach { - group { - +("$it = ") - skipAllNotMatching() - } - } - +")" - } - } -} -inline fun<reified T> PageNode.contentPage(name: String, block: T.() -> Unit) { - (dfs { it.name == name } as? T).assertNotNull("The page `$name` is not found").block() -} - -fun ClasslikePageNode.assertHasFunctions(vararg expectedFunctionName: String) { - val functions = this.findSectionWithName("Functions").assertNotNull("Functions") - val functionsName = functions.children.map { (it.dfs { it is ContentText } as ContentText).text } - assertEquals(expectedFunctionName.toList(), functionsName) -} - -fun ClasslikePageNode.findSectionWithName(name: String) : ContentNode? { - var sectionHeader: ContentHeader? = null - return content.dfs { node -> - node.children.filterIsInstance<ContentHeader>().any { header -> - header.children.firstOrNull { it is ContentText && it.text == name }?.also { sectionHeader = header } != null - } - }?.children?.dropWhile { child -> child != sectionHeader }?.drop(1)?.firstOrNull() -} - -data class ParamAttributes( - val annotations: Map<String, Set<String>>, - val keywords: Set<String>, - val type: String -) - -fun RootPageNode.findTestType(packageName: String, name: String) = - children.single { it.name == packageName }.children.single { it.name == name } as ContentPage diff --git a/plugins/base/src/test/resources/content/samples/samples.kt b/plugins/base/src/test/resources/content/samples/samples.kt deleted file mode 100644 index 4c9f38dc..00000000 --- a/plugins/base/src/test/resources/content/samples/samples.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 test - -fun sampleForClassDescription() { - print("Hello") -} diff --git a/plugins/base/src/test/resources/linkable/includes/include1.md b/plugins/base/src/test/resources/linkable/includes/include1.md deleted file mode 100644 index 09882ec1..00000000 --- a/plugins/base/src/test/resources/linkable/includes/include1.md +++ /dev/null @@ -1,14 +0,0 @@ -# Module example - -This is JVM documentation for module example - -# Package example - -This is JVM documentation for package example - -## Example - -```kotlin -\@SqlTable(People::class) -class Person(val name: String, uuid: UUID = UUID.randomUUID()) : Entity(uuid) -``` diff --git a/plugins/base/src/test/resources/linkable/includes/include11.md b/plugins/base/src/test/resources/linkable/includes/include11.md deleted file mode 100644 index fa27b23d..00000000 --- a/plugins/base/src/test/resources/linkable/includes/include11.md +++ /dev/null @@ -1,3 +0,0 @@ -# Module example - -This is second JVM documentation for module example diff --git a/plugins/base/src/test/resources/linkable/includes/include2.md b/plugins/base/src/test/resources/linkable/includes/include2.md deleted file mode 100644 index 1574003d..00000000 --- a/plugins/base/src/test/resources/linkable/includes/include2.md +++ /dev/null @@ -1,7 +0,0 @@ -# Module example - -This is JS documentation for module example - -# Package greeteer - -This is JS documentation for package greeteer
\ No newline at end of file diff --git a/plugins/base/src/test/resources/linkable/samples/jsMain/kotlin/JsClass.kt b/plugins/base/src/test/resources/linkable/samples/jsMain/kotlin/JsClass.kt deleted file mode 100644 index 62a961c1..00000000 --- a/plugins/base/src/test/resources/linkable/samples/jsMain/kotlin/JsClass.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 p2 - -class JsClass { - - /** - * @sample samples.SamplesJs.exampleUsage - */ - fun printWithExclamation(msg: String) = println("$msg!") -} diff --git a/plugins/base/src/test/resources/linkable/samples/jsMain/resources/Samples.kt b/plugins/base/src/test/resources/linkable/samples/jsMain/resources/Samples.kt deleted file mode 100644 index 5dc791d7..00000000 --- a/plugins/base/src/test/resources/linkable/samples/jsMain/resources/Samples.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 samples - -import p2.JsClass - -class SamplesJs { - - fun exampleUsage() { - JsClass().printWithExclamation("Hi, Js") - } -} diff --git a/plugins/base/src/test/resources/linkable/samples/jvmMain/kotlin/JvmClass.kt b/plugins/base/src/test/resources/linkable/samples/jvmMain/kotlin/JvmClass.kt deleted file mode 100644 index 0014cdb7..00000000 --- a/plugins/base/src/test/resources/linkable/samples/jvmMain/kotlin/JvmClass.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 p2 - -class JvmClass { - - /** - * @sample samples.SamplesJvm.exampleUsage - */ - fun printWithExclamation(msg: String) = println("$msg!") -} diff --git a/plugins/base/src/test/resources/linkable/samples/jvmMain/resources/Samples.kt b/plugins/base/src/test/resources/linkable/samples/jvmMain/resources/Samples.kt deleted file mode 100644 index f32538cc..00000000 --- a/plugins/base/src/test/resources/linkable/samples/jvmMain/resources/Samples.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 samples - -import p2.JvmClass - -class SamplesJvm { - - fun exampleUsage() { - JvmClass().printWithExclamation("Hi, Jvm") - } -} diff --git a/plugins/base/src/test/resources/linkable/sources/jsMain/kotlin/JsClass.kt b/plugins/base/src/test/resources/linkable/sources/jsMain/kotlin/JsClass.kt deleted file mode 100644 index 180d9519..00000000 --- a/plugins/base/src/test/resources/linkable/sources/jsMain/kotlin/JsClass.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 p1 - -class JsClass diff --git a/plugins/base/src/test/resources/linkable/sources/jvmMain/kotlin/JvmClass.kt b/plugins/base/src/test/resources/linkable/sources/jvmMain/kotlin/JvmClass.kt deleted file mode 100644 index 3adf9520..00000000 --- a/plugins/base/src/test/resources/linkable/sources/jvmMain/kotlin/JvmClass.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 p1 - -class JvmClass diff --git a/plugins/base/src/test/resources/linking/jvmMain/kotlin/linking/source/JavaEnum.java b/plugins/base/src/test/resources/linking/jvmMain/kotlin/linking/source/JavaEnum.java deleted file mode 100644 index 016365a7..00000000 --- a/plugins/base/src/test/resources/linking/jvmMain/kotlin/linking/source/JavaEnum.java +++ /dev/null @@ -1,5 +0,0 @@ -package linking.source; - -public enum JavaEnum { - ON_DECEIT, ON_DESTROY; -} diff --git a/plugins/base/src/test/resources/linking/jvmMain/kotlin/linking/source/JavaLinker.java b/plugins/base/src/test/resources/linking/jvmMain/kotlin/linking/source/JavaLinker.java deleted file mode 100644 index ac416530..00000000 --- a/plugins/base/src/test/resources/linking/jvmMain/kotlin/linking/source/JavaLinker.java +++ /dev/null @@ -1,8 +0,0 @@ -package linking.source; - -/** - * Reference link {@link linking.source.KotlinEnum} should resolve <p> - * sjuff sjuff {@link linking.source.KotlinEnum#ON_CREATE} should resolve <p> - * sjujj sjujj {@link linking.source.JavaEnum#ON_DECEIT} should resolve - */ -public class JavaLinker {} diff --git a/plugins/base/src/test/resources/linking/jvmMain/kotlin/linking/source/KotlinEnum.kt b/plugins/base/src/test/resources/linking/jvmMain/kotlin/linking/source/KotlinEnum.kt deleted file mode 100644 index 2d5498c1..00000000 --- a/plugins/base/src/test/resources/linking/jvmMain/kotlin/linking/source/KotlinEnum.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 linking.source - -enum class KotlinEnum { - ON_CREATE, ON_CATASTROPHE -} diff --git a/plugins/base/src/test/resources/linking/jvmMain/kotlin/linking/source/KotlinLinker.kt b/plugins/base/src/test/resources/linking/jvmMain/kotlin/linking/source/KotlinLinker.kt deleted file mode 100644 index ca6e233d..00000000 --- a/plugins/base/src/test/resources/linking/jvmMain/kotlin/linking/source/KotlinLinker.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 linking.source - -/** - * Reference link [KotlinEnum] should resolve <p> - * stuff stuff [KotlinEnum.ON_CREATE] should resolve <p> - * stuff stuff [JavaEnum.ON_DECEIT] should resolve - */ -class KotlinLinker {} diff --git a/plugins/base/src/test/resources/locationProvider/jdk8-package-list b/plugins/base/src/test/resources/locationProvider/jdk8-package-list deleted file mode 100644 index 351c1868..00000000 --- a/plugins/base/src/test/resources/locationProvider/jdk8-package-list +++ /dev/null @@ -1,217 +0,0 @@ -java.applet -java.awt -java.awt.color -java.awt.datatransfer -java.awt.dnd -java.awt.event -java.awt.font -java.awt.geom -java.awt.im -java.awt.im.spi -java.awt.image -java.awt.image.renderable -java.awt.print -java.beans -java.beans.beancontext -java.io -java.lang -java.lang.annotation -java.lang.instrument -java.lang.invoke -java.lang.management -java.lang.ref -java.lang.reflect -java.math -java.net -java.nio -java.nio.channels -java.nio.channels.spi -java.nio.charset -java.nio.charset.spi -java.nio.file -java.nio.file.attribute -java.nio.file.spi -java.rmi -java.rmi.activation -java.rmi.dgc -java.rmi.registry -java.rmi.server -java.security -java.security.acl -java.security.cert -java.security.interfaces -java.security.spec -java.sql -java.text -java.text.spi -java.time -java.time.chrono -java.time.format -java.time.temporal -java.time.zone -java.util -java.util.concurrent -java.util.concurrent.atomic -java.util.concurrent.locks -java.util.function -java.util.jar -java.util.logging -java.util.prefs -java.util.regex -java.util.spi -java.util.stream -java.util.zip -javax.accessibility -javax.activation -javax.activity -javax.annotation -javax.annotation.processing -javax.crypto -javax.crypto.interfaces -javax.crypto.spec -javax.imageio -javax.imageio.event -javax.imageio.metadata -javax.imageio.plugins.bmp -javax.imageio.plugins.jpeg -javax.imageio.spi -javax.imageio.stream -javax.jws -javax.jws.soap -javax.lang.model -javax.lang.model.element -javax.lang.model.type -javax.lang.model.util -javax.management -javax.management.loading -javax.management.modelmbean -javax.management.monitor -javax.management.openmbean -javax.management.relation -javax.management.remote -javax.management.remote.rmi -javax.management.timer -javax.naming -javax.naming.directory -javax.naming.event -javax.naming.ldap -javax.naming.spi -javax.net -javax.net.ssl -javax.print -javax.print.attribute -javax.print.attribute.standard -javax.print.event -javax.rmi -javax.rmi.CORBA -javax.rmi.ssl -javax.script -javax.security.auth -javax.security.auth.callback -javax.security.auth.kerberos -javax.security.auth.login -javax.security.auth.spi -javax.security.auth.x500 -javax.security.cert -javax.security.sasl -javax.sound.midi -javax.sound.midi.spi -javax.sound.sampled -javax.sound.sampled.spi -javax.sql -javax.sql.rowset -javax.sql.rowset.serial -javax.sql.rowset.spi -javax.swing -javax.swing.border -javax.swing.colorchooser -javax.swing.event -javax.swing.filechooser -javax.swing.plaf -javax.swing.plaf.basic -javax.swing.plaf.metal -javax.swing.plaf.multi -javax.swing.plaf.nimbus -javax.swing.plaf.synth -javax.swing.table -javax.swing.text -javax.swing.text.html -javax.swing.text.html.parser -javax.swing.text.rtf -javax.swing.tree -javax.swing.undo -javax.tools -javax.transaction -javax.transaction.xa -javax.xml -javax.xml.bind -javax.xml.bind.annotation -javax.xml.bind.annotation.adapters -javax.xml.bind.attachment -javax.xml.bind.helpers -javax.xml.bind.util -javax.xml.crypto -javax.xml.crypto.dom -javax.xml.crypto.dsig -javax.xml.crypto.dsig.dom -javax.xml.crypto.dsig.keyinfo -javax.xml.crypto.dsig.spec -javax.xml.datatype -javax.xml.namespace -javax.xml.parsers -javax.xml.soap -javax.xml.stream -javax.xml.stream.events -javax.xml.stream.util -javax.xml.transform -javax.xml.transform.dom -javax.xml.transform.sax -javax.xml.transform.stax -javax.xml.transform.stream -javax.xml.validation -javax.xml.ws -javax.xml.ws.handler -javax.xml.ws.handler.soap -javax.xml.ws.http -javax.xml.ws.soap -javax.xml.ws.spi -javax.xml.ws.spi.http -javax.xml.ws.wsaddressing -javax.xml.xpath -org.ietf.jgss -org.omg.CORBA -org.omg.CORBA.DynAnyPackage -org.omg.CORBA.ORBPackage -org.omg.CORBA.TypeCodePackage -org.omg.CORBA.portable -org.omg.CORBA_2_3 -org.omg.CORBA_2_3.portable -org.omg.CosNaming -org.omg.CosNaming.NamingContextExtPackage -org.omg.CosNaming.NamingContextPackage -org.omg.Dynamic -org.omg.DynamicAny -org.omg.DynamicAny.DynAnyFactoryPackage -org.omg.DynamicAny.DynAnyPackage -org.omg.IOP -org.omg.IOP.CodecFactoryPackage -org.omg.IOP.CodecPackage -org.omg.Messaging -org.omg.PortableInterceptor -org.omg.PortableInterceptor.ORBInitInfoPackage -org.omg.PortableServer -org.omg.PortableServer.CurrentPackage -org.omg.PortableServer.POAManagerPackage -org.omg.PortableServer.POAPackage -org.omg.PortableServer.ServantLocatorPackage -org.omg.PortableServer.portable -org.omg.SendingContext -org.omg.stub.java.rmi -org.w3c.dom -org.w3c.dom.bootstrap -org.w3c.dom.events -org.w3c.dom.ls -org.w3c.dom.views -org.xml.sax -org.xml.sax.ext -org.xml.sax.helpers diff --git a/plugins/base/src/test/resources/locationProvider/multi-module-package-list b/plugins/base/src/test/resources/locationProvider/multi-module-package-list deleted file mode 100644 index 03f33d9a..00000000 --- a/plugins/base/src/test/resources/locationProvider/multi-module-package-list +++ /dev/null @@ -1,8 +0,0 @@ -$dokka.format:html-v1 -$dokka.linkExtension:html -$dokka.location:/NoPackageClass///PointingToDeclaration/moduleB/[root]/-no-package-class/index.html -module:moduleA -foo -bar -module:moduleB -baz diff --git a/plugins/base/src/test/resources/locationProvider/old-package-list b/plugins/base/src/test/resources/locationProvider/old-package-list deleted file mode 100644 index d05b4535..00000000 --- a/plugins/base/src/test/resources/locationProvider/old-package-list +++ /dev/null @@ -1,9 +0,0 @@ -$dokka.format:kotlin-website-html -$dokka.linkExtension:html -$dokka.location:kotlin.text.StringBuilderkotlin.relocated.text/-string-builder/index.html -$dokka.location:kotlin$minus(java.math.BigDecimal, java.math.BigDecimal)kotlin/java.math.-big-decimal/minus.html -$dokka.location:kotlin.Int$MAX_VALUE()kotlin/-int/max-value.html -kotlin -kotlin.text -kotlin.reflect - diff --git a/plugins/base/src/test/resources/locationProvider/stdlib-package-list b/plugins/base/src/test/resources/locationProvider/stdlib-package-list deleted file mode 100644 index 298321aa..00000000 --- a/plugins/base/src/test/resources/locationProvider/stdlib-package-list +++ /dev/null @@ -1,67 +0,0 @@ -$dokka.format:html-v1 -$dokka.linkExtension:html -$dokka.location://arrayWithFun/#kotlin.Int#kotlin.Function1[kotlin.Int,TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/kotlin-stdlib/[JS root]/array-with-fun.html -$dokka.location://booleanArray/#kotlin.Int#kotlin.Any/PointingToDeclaration/kotlin-stdlib/[JS root]/boolean-array.html -$dokka.location://booleanArrayWithFun/#kotlin.Int#kotlin.Function1[kotlin.Int,kotlin.Boolean]/PointingToDeclaration/kotlin-stdlib/[JS root]/boolean-array-with-fun.html -$dokka.location://charArray/#kotlin.Int#kotlin.Any/PointingToDeclaration/kotlin-stdlib/[JS root]/char-array.html -$dokka.location://charArrayWithFun/#kotlin.Int#kotlin.Function1[kotlin.Int,kotlin.Char]/PointingToDeclaration/kotlin-stdlib/[JS root]/char-array-with-fun.html -$dokka.location://fillArrayFun/#kotlin.Array[TypeParam(bounds=[kotlin.Any?])]#kotlin.Function1[kotlin.Int,TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/kotlin-stdlib/[JS root]/fill-array-fun.html -$dokka.location://longArray/#kotlin.Int#kotlin.Any/PointingToDeclaration/kotlin-stdlib/[JS root]/long-array.html -$dokka.location://longArrayWithFun/#kotlin.Int#kotlin.Function1[kotlin.Int,kotlin.Long]/PointingToDeclaration/kotlin-stdlib/[JS root]/long-array-with-fun.html -$dokka.location://newArray/#kotlin.Int#TypeParam(bounds=[kotlin.Any?])/PointingToDeclaration/kotlin-stdlib/[JS root]/new-array.html -$dokka.location://untypedCharArrayWithFun/#kotlin.Int#kotlin.Function1[kotlin.Int,kotlin.Char]/PointingToDeclaration/kotlin-stdlib/[JS root]/untyped-char-array-with-fun.html -kotlin -kotlin.annotation -kotlin.browser -kotlin.collections -kotlin.comparisons -kotlin.concurrent -kotlin.contracts -kotlin.coroutines -kotlin.coroutines.cancellation -kotlin.coroutines.intrinsics -kotlin.dom -kotlin.experimental -kotlin.io -kotlin.js -kotlin.jvm -kotlin.math -kotlin.native -kotlin.native.concurrent -kotlin.native.ref -kotlin.properties -kotlin.random -kotlin.ranges -kotlin.reflect -kotlin.reflect.full -kotlin.reflect.jvm -kotlin.sequences -kotlin.streams -kotlin.system -kotlin.text -kotlin.time -kotlinx.browser -kotlinx.cinterop -kotlinx.cinterop.internal -kotlinx.dom -kotlinx.wasm.jsinterop -org.khronos.webgl -org.w3c.css.masking -org.w3c.dom -org.w3c.dom.clipboard -org.w3c.dom.css -org.w3c.dom.encryptedmedia -org.w3c.dom.events -org.w3c.dom.mediacapture -org.w3c.dom.mediasource -org.w3c.dom.parsing -org.w3c.dom.pointerevents -org.w3c.dom.svg -org.w3c.dom.url -org.w3c.fetch -org.w3c.files -org.w3c.notifications -org.w3c.performance -org.w3c.workers -org.w3c.xhr - diff --git a/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/commonMain/kotlin/Clock.kt b/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/commonMain/kotlin/Clock.kt deleted file mode 100644 index 5459b2d7..00000000 --- a/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/commonMain/kotlin/Clock.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 example - -/** - * Documentation for expected class Clock - * in common module - */ -expect open class Clock() { - fun getTime(): String - /** - * Time in minis - */ - fun getTimesInMillis(): String - fun getYear(): String -} - diff --git a/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/commonMain/kotlin/House.kt b/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/commonMain/kotlin/House.kt deleted file mode 100644 index e79e2904..00000000 --- a/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/commonMain/kotlin/House.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 example - -class House(val street: String, val number: Int) { - - /** - * The owner of the house - */ - var owner: String = "" - - /** - * The owner of the house - */ - val differentOwner: String = "" - - fun addFloor() {} - - class Basement { - val pickles : List<Any> = mutableListOf() - } - - companion object { - val DEFAULT = House("",0) - } -} diff --git a/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jsMain/kotlin/Clock.kt b/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jsMain/kotlin/Clock.kt deleted file mode 100644 index aad5787d..00000000 --- a/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jsMain/kotlin/Clock.kt +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package example - -import greeteer.Greeter -import kotlin.js.Date - -/** - * Documentation for actual class Clock in JS - */ -actual open class Clock { - actual fun getTime() = Date.now().toString() - fun onlyJsFunction(): Int = 42 - - /** - * JS implementation of getTimeInMillis - */ - actual fun getTimesInMillis(): String = Date.now().toString() - - /** - * JS custom kdoc - */ - actual fun getYear(): String { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. - } -} - -fun main() { - Greeter().greet().also { println(it) } -} diff --git a/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jvmAndJsSecondCommonMain/kotlin/Greeter.kt b/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jvmAndJsSecondCommonMain/kotlin/Greeter.kt deleted file mode 100644 index e9e15d0b..00000000 --- a/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jvmAndJsSecondCommonMain/kotlin/Greeter.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 greeteer - -import example.Clock - -class Greeter { - /** - * Some docs for the [greet] function - */ - fun greet() = Clock().let{ "Hello there! THe time is ${it.getTime()}" } -} diff --git a/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jvmMain/kotlin/example/Clock.kt b/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jvmMain/kotlin/example/Clock.kt deleted file mode 100644 index f38ff749..00000000 --- a/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jvmMain/kotlin/example/Clock.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 example - -import greeteer.Greeter - -/** - * Documentation for actual class Clock in JVM - */ -actual open class Clock { - actual fun getTime(): String = System.currentTimeMillis().toString() - - /** - * Time in minis - */ - actual fun getTimesInMillis(): String = System.currentTimeMillis().toString() - - /** - * Documentation for onlyJVMFunction on... - * wait for it... - * ...JVM! - */ - fun onlyJVMFunction(): Double = 2.5 - - open fun getDayOfTheWeek(): String { - TODO("not implemented") - } - - /** - * JVM custom kdoc - */ - actual fun getYear(): String { - TODO("not implemented") - } -} - -fun clockList() = listOf(Clock()) - -fun main() { - Greeter().greet().also { println(it) } -} diff --git a/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jvmMain/kotlin/example/ClockDays.kt b/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jvmMain/kotlin/example/ClockDays.kt deleted file mode 100644 index e96acf1c..00000000 --- a/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jvmMain/kotlin/example/ClockDays.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 example - -/** - * frgergergrthe - * */ -enum class ClockDays { - /** - * dfsdfsdfds - * */ - FIRST, - SECOND, // test2 - THIRD, // test3 - FOURTH, // test4 - FIFTH // test5 -} diff --git a/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jvmMain/kotlin/example/HtmlTest.kt b/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jvmMain/kotlin/example/HtmlTest.kt deleted file mode 100644 index 2fa3622b..00000000 --- a/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jvmMain/kotlin/example/HtmlTest.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 example - -/** - * <!-- this shouldn't be visible --> - */ -class HtmlTest { - /** - * This is an example <!-- not visible --> of html - */ - fun test(){ - - } - - /** - * This is an <b> documentation </b> - */ - fun testP(){ - - } -} diff --git a/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jvmMain/kotlin/example/ParticularClock.kt b/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jvmMain/kotlin/example/ParticularClock.kt deleted file mode 100644 index 3b7a403d..00000000 --- a/plugins/base/src/test/resources/multiplatform/basicMultiplatformTest/jvmMain/kotlin/example/ParticularClock.kt +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. - */ - -package example - -import greeteer.Greeter - -class ParticularClock(private val clockDay: ClockDays) : Clock() { - - /** - * Rings bell [times] - */ - fun ringBell(times: Int) {} - - /** - * Uses provider [greeter] - */ - fun useGreeter(greeter: Greeter) { - - } - - /** - * Day of the week - */ - override fun getDayOfTheWeek() = clockDay.name -} - -/** - * A sample extension function - * When $a \ne 0$, there are two solutions to \(ax^2 + bx + c = 0\) and they are $$x = {-b \pm \sqrt{b^2-4ac} \over 2a}.$$ - * @usesMathJax - */ -fun Clock.extensionFun() { - -} |