diff --git a/core/api/core.api b/core/api/core.api index d3b4817b9f..063f56c5fe 100644 --- a/core/api/core.api +++ b/core/api/core.api @@ -3440,15 +3440,20 @@ public abstract interface class org/jetbrains/dokka/model/properties/WithExtraPr public abstract fun withNewExtras (Lorg/jetbrains/dokka/model/properties/PropertyContainer;)Ljava/lang/Object; } -public abstract interface class org/jetbrains/dokka/pages/ClasslikePage : org/jetbrains/dokka/pages/ContentPage { +public abstract interface class org/jetbrains/dokka/pages/ClasslikePage : org/jetbrains/dokka/pages/ContentPage, org/jetbrains/dokka/pages/WithDocumentables { +} + +public final class org/jetbrains/dokka/pages/ClasslikePage$DefaultImpls { + public static fun getDocumentable (Lorg/jetbrains/dokka/pages/ClasslikePage;)Lorg/jetbrains/dokka/model/Documentable; } public final class org/jetbrains/dokka/pages/ClasslikePageNode : org/jetbrains/dokka/pages/ClasslikePage { - public fun (Ljava/lang/String;Lorg/jetbrains/dokka/pages/ContentNode;Ljava/util/Set;Lorg/jetbrains/dokka/model/Documentable;Ljava/util/List;Ljava/util/List;)V - public synthetic fun (Ljava/lang/String;Lorg/jetbrains/dokka/pages/ContentNode;Ljava/util/Set;Lorg/jetbrains/dokka/model/Documentable;Ljava/util/List;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Ljava/lang/String;Lorg/jetbrains/dokka/pages/ContentNode;Ljava/util/Set;Ljava/util/List;Ljava/util/List;Ljava/util/List;)V + public synthetic fun (Ljava/lang/String;Lorg/jetbrains/dokka/pages/ContentNode;Ljava/util/Set;Ljava/util/List;Ljava/util/List;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public fun getChildren ()Ljava/util/List; public fun getContent ()Lorg/jetbrains/dokka/pages/ContentNode; public fun getDocumentable ()Lorg/jetbrains/dokka/model/Documentable; + public fun getDocumentables ()Ljava/util/List; public fun getDri ()Ljava/util/Set; public fun getEmbeddedResources ()Ljava/util/List; public fun getName ()Ljava/lang/String; @@ -3846,6 +3851,7 @@ public abstract interface class org/jetbrains/dokka/pages/ContentPage : org/jetb } public final class org/jetbrains/dokka/pages/ContentPage$DefaultImpls { + public static fun getDocumentable (Lorg/jetbrains/dokka/pages/ContentPage;)Lorg/jetbrains/dokka/model/Documentable; public static synthetic fun modified$default (Lorg/jetbrains/dokka/pages/ContentPage;Ljava/lang/String;Lorg/jetbrains/dokka/pages/ContentNode;Ljava/util/Set;Ljava/util/List;Ljava/util/List;ILjava/lang/Object;)Lorg/jetbrains/dokka/pages/ContentPage; } @@ -3982,15 +3988,20 @@ public final class org/jetbrains/dokka/pages/ListStyle : java/lang/Enum, org/jet public static fun values ()[Lorg/jetbrains/dokka/pages/ListStyle; } -public abstract interface class org/jetbrains/dokka/pages/MemberPage : org/jetbrains/dokka/pages/ContentPage { +public abstract interface class org/jetbrains/dokka/pages/MemberPage : org/jetbrains/dokka/pages/ContentPage, org/jetbrains/dokka/pages/WithDocumentables { +} + +public final class org/jetbrains/dokka/pages/MemberPage$DefaultImpls { + public static fun getDocumentable (Lorg/jetbrains/dokka/pages/MemberPage;)Lorg/jetbrains/dokka/model/Documentable; } public final class org/jetbrains/dokka/pages/MemberPageNode : org/jetbrains/dokka/pages/MemberPage { - public fun (Ljava/lang/String;Lorg/jetbrains/dokka/pages/ContentNode;Ljava/util/Set;Lorg/jetbrains/dokka/model/Documentable;Ljava/util/List;Ljava/util/List;)V - public synthetic fun (Ljava/lang/String;Lorg/jetbrains/dokka/pages/ContentNode;Ljava/util/Set;Lorg/jetbrains/dokka/model/Documentable;Ljava/util/List;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Ljava/lang/String;Lorg/jetbrains/dokka/pages/ContentNode;Ljava/util/Set;Ljava/util/List;Ljava/util/List;Ljava/util/List;)V + public synthetic fun (Ljava/lang/String;Lorg/jetbrains/dokka/pages/ContentNode;Ljava/util/Set;Ljava/util/List;Ljava/util/List;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public fun getChildren ()Ljava/util/List; public fun getContent ()Lorg/jetbrains/dokka/pages/ContentNode; public fun getDocumentable ()Lorg/jetbrains/dokka/model/Documentable; + public fun getDocumentables ()Ljava/util/List; public fun getDri ()Ljava/util/Set; public fun getEmbeddedResources ()Ljava/util/List; public fun getName ()Ljava/lang/String; @@ -4000,15 +4011,20 @@ public final class org/jetbrains/dokka/pages/MemberPageNode : org/jetbrains/dokk public fun modified (Ljava/lang/String;Lorg/jetbrains/dokka/pages/ContentNode;Ljava/util/Set;Ljava/util/List;Ljava/util/List;)Lorg/jetbrains/dokka/pages/MemberPageNode; } -public abstract interface class org/jetbrains/dokka/pages/ModulePage : org/jetbrains/dokka/pages/ContentPage { +public abstract interface class org/jetbrains/dokka/pages/ModulePage : org/jetbrains/dokka/pages/ContentPage, org/jetbrains/dokka/pages/WithDocumentables { +} + +public final class org/jetbrains/dokka/pages/ModulePage$DefaultImpls { + public static fun getDocumentable (Lorg/jetbrains/dokka/pages/ModulePage;)Lorg/jetbrains/dokka/model/Documentable; } public final class org/jetbrains/dokka/pages/ModulePageNode : org/jetbrains/dokka/pages/RootPageNode, org/jetbrains/dokka/pages/ModulePage { - public fun (Ljava/lang/String;Lorg/jetbrains/dokka/pages/ContentNode;Lorg/jetbrains/dokka/model/Documentable;Ljava/util/List;Ljava/util/List;)V - public synthetic fun (Ljava/lang/String;Lorg/jetbrains/dokka/pages/ContentNode;Lorg/jetbrains/dokka/model/Documentable;Ljava/util/List;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Ljava/lang/String;Lorg/jetbrains/dokka/pages/ContentNode;Ljava/util/List;Ljava/util/List;Ljava/util/List;)V + public synthetic fun (Ljava/lang/String;Lorg/jetbrains/dokka/pages/ContentNode;Ljava/util/List;Ljava/util/List;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public fun getChildren ()Ljava/util/List; public fun getContent ()Lorg/jetbrains/dokka/pages/ContentNode; public fun getDocumentable ()Lorg/jetbrains/dokka/model/Documentable; + public fun getDocumentables ()Ljava/util/List; public fun getDri ()Ljava/util/Set; public fun getEmbeddedResources ()Ljava/util/List; public fun getName ()Ljava/lang/String; @@ -4022,6 +4038,10 @@ public final class org/jetbrains/dokka/pages/ModulePageNode : org/jetbrains/dokk public abstract interface class org/jetbrains/dokka/pages/MultimoduleRootPage : org/jetbrains/dokka/pages/ContentPage { } +public final class org/jetbrains/dokka/pages/MultimoduleRootPage$DefaultImpls { + public static fun getDocumentable (Lorg/jetbrains/dokka/pages/MultimoduleRootPage;)Lorg/jetbrains/dokka/model/Documentable; +} + public final class org/jetbrains/dokka/pages/MultimoduleRootPageNode : org/jetbrains/dokka/pages/RootPageNode, org/jetbrains/dokka/pages/MultimoduleRootPage { public fun (Ljava/util/Set;Lorg/jetbrains/dokka/pages/ContentNode;Ljava/util/List;)V public synthetic fun (Ljava/util/Set;Lorg/jetbrains/dokka/pages/ContentNode;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V @@ -4041,15 +4061,20 @@ public final class org/jetbrains/dokka/pages/MultimoduleTable : org/jetbrains/do public static final field INSTANCE Lorg/jetbrains/dokka/pages/MultimoduleTable; } -public abstract interface class org/jetbrains/dokka/pages/PackagePage : org/jetbrains/dokka/pages/ContentPage { +public abstract interface class org/jetbrains/dokka/pages/PackagePage : org/jetbrains/dokka/pages/ContentPage, org/jetbrains/dokka/pages/WithDocumentables { +} + +public final class org/jetbrains/dokka/pages/PackagePage$DefaultImpls { + public static fun getDocumentable (Lorg/jetbrains/dokka/pages/PackagePage;)Lorg/jetbrains/dokka/model/Documentable; } public final class org/jetbrains/dokka/pages/PackagePageNode : org/jetbrains/dokka/pages/PackagePage { - public fun (Ljava/lang/String;Lorg/jetbrains/dokka/pages/ContentNode;Ljava/util/Set;Lorg/jetbrains/dokka/model/Documentable;Ljava/util/List;Ljava/util/List;)V - public synthetic fun (Ljava/lang/String;Lorg/jetbrains/dokka/pages/ContentNode;Ljava/util/Set;Lorg/jetbrains/dokka/model/Documentable;Ljava/util/List;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Ljava/lang/String;Lorg/jetbrains/dokka/pages/ContentNode;Ljava/util/Set;Ljava/util/List;Ljava/util/List;Ljava/util/List;)V + public synthetic fun (Ljava/lang/String;Lorg/jetbrains/dokka/pages/ContentNode;Ljava/util/Set;Ljava/util/List;Ljava/util/List;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public fun getChildren ()Ljava/util/List; public fun getContent ()Lorg/jetbrains/dokka/pages/ContentNode; public fun getDocumentable ()Lorg/jetbrains/dokka/model/Documentable; + public fun getDocumentables ()Ljava/util/List; public fun getDri ()Ljava/util/Set; public fun getEmbeddedResources ()Ljava/util/List; public fun getName ()Ljava/lang/String; @@ -4264,6 +4289,10 @@ public final class org/jetbrains/dokka/pages/UtilsKt { public static final fun recursiveMapTransform (Lorg/jetbrains/dokka/pages/ContentNode;Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)Lorg/jetbrains/dokka/pages/ContentNode; } +public abstract interface class org/jetbrains/dokka/pages/WithDocumentables { + public abstract fun getDocumentables ()Ljava/util/List; +} + public final class org/jetbrains/dokka/pages/WrongRendererTypeException : java/lang/Exception { public fun (Lkotlin/reflect/KClass;)V public final fun component1 ()Lkotlin/reflect/KClass; diff --git a/core/src/main/kotlin/pages/PageNodes.kt b/core/src/main/kotlin/pages/PageNodes.kt index 9fc4d6e884..75e27dccab 100644 --- a/core/src/main/kotlin/pages/PageNodes.kt +++ b/core/src/main/kotlin/pages/PageNodes.kt @@ -18,9 +18,14 @@ interface PageNode : WithChildren { interface ContentPage : PageNode { val content: ContentNode val dri: Set - val documentable: Documentable? val embeddedResources: List + @Deprecated("Deprecated. Remove its usages from your code.", + ReplaceWith("documentables.firstOrNull()") + ) + val documentable: Documentable? + get() = if (this is WithDocumentables) this.documentables.firstOrNull() else null + fun modified( name: String = this.name, content: ContentNode = this.content, @@ -30,6 +35,10 @@ interface ContentPage : PageNode { ): ContentPage } +interface WithDocumentables { + val documentables: List +} + abstract class RootPageNode(val forceTopLevelName: Boolean = false) : PageNode { val parentMap: Map by lazy { IdentityHashMap().apply { @@ -64,7 +73,7 @@ abstract class RootPageNode(val forceTopLevelName: Boolean = false) : PageNode { class ModulePageNode( override val name: String, override val content: ContentNode, - override val documentable: Documentable?, + override val documentables: List = listOf(), override val children: List, override val embeddedResources: List = listOf() ) : RootPageNode(), ModulePage { @@ -81,14 +90,14 @@ class ModulePageNode( children: List ): ModulePageNode = if (name == this.name && content === this.content && embeddedResources === this.embeddedResources && children shallowEq this.children) this - else ModulePageNode(name, content, documentable, children, embeddedResources) + else ModulePageNode(name, content, documentables, children, embeddedResources) } class PackagePageNode( override val name: String, override val content: ContentNode, override val dri: Set, - override val documentable: Documentable?, + override val documentables: List = listOf(), override val children: List, override val embeddedResources: List = listOf() ) : PackagePage { @@ -108,14 +117,14 @@ class PackagePageNode( children: List ): PackagePageNode = if (name == this.name && content === this.content && embeddedResources === this.embeddedResources && children shallowEq this.children) this - else PackagePageNode(name, content, dri, documentable, children, embeddedResources) + else PackagePageNode(name, content, dri, documentables, children, embeddedResources) } class ClasslikePageNode( override val name: String, override val content: ContentNode, override val dri: Set, - override val documentable: Documentable?, + override val documentables: List = listOf(), override val children: List, override val embeddedResources: List = listOf() ) : ClasslikePage { @@ -130,14 +139,14 @@ class ClasslikePageNode( children: List ): ClasslikePageNode = if (name == this.name && content === this.content && embeddedResources === this.embeddedResources && children shallowEq this.children) this - else ClasslikePageNode(name, content, dri, documentable, children, embeddedResources) + else ClasslikePageNode(name, content, dri, documentables, children, embeddedResources) } class MemberPageNode( override val name: String, override val content: ContentNode, override val dri: Set, - override val documentable: Documentable?, + override val documentables: List = listOf(), override val children: List = emptyList(), override val embeddedResources: List = listOf() ) : MemberPage { @@ -152,7 +161,7 @@ class MemberPageNode( children: List ): MemberPageNode = if (name == this.name && content === this.content && embeddedResources === this.embeddedResources && children shallowEq this.children) this - else MemberPageNode(name, content, dri, documentable, children, embeddedResources) + else MemberPageNode(name, content, dri, documentables, children, embeddedResources) } @@ -165,8 +174,6 @@ class MultimoduleRootPageNode( override val children: List = emptyList() - override val documentable: Documentable? = null - override fun modified(name: String, children: List): RootPageNode = MultimoduleRootPageNode(dri, content, embeddedResources) diff --git a/core/src/main/kotlin/pages/Pages.kt b/core/src/main/kotlin/pages/Pages.kt index b65e72d611..90ae09e8ce 100644 --- a/core/src/main/kotlin/pages/Pages.kt +++ b/core/src/main/kotlin/pages/Pages.kt @@ -2,10 +2,10 @@ package org.jetbrains.dokka.pages interface MultimoduleRootPage : ContentPage -interface ModulePage : ContentPage +interface ModulePage : ContentPage, WithDocumentables -interface PackagePage : ContentPage +interface PackagePage : ContentPage, WithDocumentables -interface ClasslikePage : ContentPage +interface ClasslikePage : ContentPage, WithDocumentables -interface MemberPage : ContentPage \ No newline at end of file +interface MemberPage : ContentPage, WithDocumentables \ No newline at end of file diff --git a/docs/src/doc/docs/user_guide/base-specific/frontend.md b/docs/src/doc/docs/user_guide/base-specific/frontend.md index 851e16a025..e6802639dd 100644 --- a/docs/src/doc/docs/user_guide/base-specific/frontend.md +++ b/docs/src/doc/docs/user_guide/base-specific/frontend.md @@ -39,6 +39,12 @@ Keep in mind that this value will be passed exactly to the output html, so it ha By setting a boolean property `separateInheritedMembers` dokka will split inherited members (like functions, properties etc.) from ones declared in viewed class. Separated members will have it's own tabs on the page. +## Merging declarations with name clashing + +By setting a boolean property `mergeImplicitExpectActualDeclarations` dokka will merge declarations that do not have `expect`/`actual` keywords but have the same fully qualified name. +The declarations will be displayed on one page. +By default, it is disabled. The page names of such declaration have a prefix that is the name of source set. + ### Examples In order to override a logo and style it accordingly a css file named `logo-styles.css` is needed: ```css diff --git a/integration-tests/gradle/projects/stdlib/stdlib.diff b/integration-tests/gradle/projects/stdlib/stdlib.diff index 71d27c9925..20404297ef 100644 --- a/integration-tests/gradle/projects/stdlib/stdlib.diff +++ b/integration-tests/gradle/projects/stdlib/stdlib.diff @@ -37,7 +37,7 @@ diff --git a/build.gradle b/build.gradle index aa8f21b..dd6a2ae 100644 --- a/build.gradle +++ b/build.gradle -@@ -1,80 +1,428 @@ +@@ -1,80 +1,444 @@ +import org.jetbrains.dokka.Platform + plugins { @@ -163,6 +163,7 @@ index aa8f21b..dd6a2ae 100644 + task dokkaStdlib(type: org.jetbrains.dokka.gradle.DokkaTask) { + outputDirectory.set(new File(outputDir, "/kotlin-stdlib")) + moduleName.set("kotlin-stdlib") ++ pluginsMapConfiguration.set(["org.jetbrains.dokka.base.DokkaBase": """{ "mergeImplicitExpectActualDeclarations": "true" }"""]) + dokkaSourceSets { + register("kotlin-stdlib-common") { + skipDeprecated.set(false) @@ -179,6 +180,16 @@ index aa8f21b..dd6a2ae 100644 + sourceRoots.from("$kotlin_root/core/builtins/native") + sourceRoots.from("$kotlin_root/core/builtins/src") + sourceRoots.from("$kotlin_sources/kotlin-stdlib-common") ++ sourceLink { ++ localDirectory.set(file("$kotlin_sources/kotlin-stdlib-common")) ++ remoteUrl.set(new URL("https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib/common/src")) ++ remoteLineSuffix.set("#L") ++ } ++ sourceLink { ++ localDirectory.set(file("$kotlin_root/core/builtins/src")) ++ remoteUrl.set(new URL("https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib/src")) ++ remoteLineSuffix.set("#L") ++ } + } + + register("kotlin-stdlib-java-common") { @@ -220,6 +231,11 @@ index aa8f21b..dd6a2ae 100644 + matchingRegex.set("kotlin.coroutines.experimental.migration(\$|\\.).*") + suppress.set(true) + } ++ sourceLink { ++ localDirectory.set(file("$kotlin_sources/kotlin-stdlib")) ++ remoteUrl.set(new URL("https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib/jvm/src")) ++ remoteLineSuffix.set("#L") ++ } + } + + diff --git a/integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/kotlin/StdlibGradleIntegrationTest.kt b/integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/kotlin/StdlibGradleIntegrationTest.kt index a5b61b1d4c..ba51a1ceb8 100644 --- a/integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/kotlin/StdlibGradleIntegrationTest.kt +++ b/integration-tests/gradle/src/integrationTest/kotlin/org/jetbrains/dokka/it/gradle/kotlin/StdlibGradleIntegrationTest.kt @@ -52,8 +52,8 @@ class StdlibGradleIntegrationTest(override val versions: BuildVersions) : Abstra projectOutputLocation.allHtmlFiles().forEach { file -> assertContainsNoErrorClass(file) -// assertNoUnresolvedLinks(file) -// assertNoHrefToMissingLocalFileOrDirectory(file) + assertNoUnresolvedLinks(file) + assertNoHrefToMissingLocalFileOrDirectory(file) assertNoEmptyLinks(file) assertNoEmptySpans(file) assertNoUnsubstitutedTemplatesInHtml(file) diff --git a/integration-tests/src/main/kotlin/org/jetbrains/dokka/it/AbstractIntegrationTest.kt b/integration-tests/src/main/kotlin/org/jetbrains/dokka/it/AbstractIntegrationTest.kt index fcf6b9ddb5..c5ea0093c1 100644 --- a/integration-tests/src/main/kotlin/org/jetbrains/dokka/it/AbstractIntegrationTest.kt +++ b/integration-tests/src/main/kotlin/org/jetbrains/dokka/it/AbstractIntegrationTest.kt @@ -71,7 +71,7 @@ abstract class AbstractIntegrationTest { hrefSplits.first() } else href - val targetFile = if (href.startsWith("file")) { + val targetFile = if (href.startsWith("file:/")) { File(URL(hrefWithoutAnchors).path) } else { File(file.parent, hrefWithoutAnchors) diff --git a/plugins/base/api/base.api b/plugins/base/api/base.api index b17b405294..40ee6813a2 100644 --- a/plugins/base/api/base.api +++ b/plugins/base/api/base.api @@ -68,25 +68,29 @@ public final class org/jetbrains/dokka/base/DokkaBase : org/jetbrains/dokka/plug public final class org/jetbrains/dokka/base/DokkaBaseConfiguration : org/jetbrains/dokka/plugability/ConfigurableBlock { public static final field Companion Lorg/jetbrains/dokka/base/DokkaBaseConfiguration$Companion; + public static final field mergeImplicitExpectActualDeclarationsDefault Z public static final field separateInheritedMembersDefault Z public fun ()V - public fun (Ljava/util/List;Ljava/util/List;ZLjava/lang/String;)V - public synthetic fun (Ljava/util/List;Ljava/util/List;ZLjava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Ljava/util/List;Ljava/util/List;ZLjava/lang/String;Z)V + public synthetic fun (Ljava/util/List;Ljava/util/List;ZLjava/lang/String;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun component1 ()Ljava/util/List; public final fun component2 ()Ljava/util/List; public final fun component3 ()Z public final fun component4 ()Ljava/lang/String; - public final fun copy (Ljava/util/List;Ljava/util/List;ZLjava/lang/String;)Lorg/jetbrains/dokka/base/DokkaBaseConfiguration; - public static synthetic fun copy$default (Lorg/jetbrains/dokka/base/DokkaBaseConfiguration;Ljava/util/List;Ljava/util/List;ZLjava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/dokka/base/DokkaBaseConfiguration; + public final fun component5 ()Z + public final fun copy (Ljava/util/List;Ljava/util/List;ZLjava/lang/String;Z)Lorg/jetbrains/dokka/base/DokkaBaseConfiguration; + public static synthetic fun copy$default (Lorg/jetbrains/dokka/base/DokkaBaseConfiguration;Ljava/util/List;Ljava/util/List;ZLjava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/dokka/base/DokkaBaseConfiguration; public fun equals (Ljava/lang/Object;)Z public final fun getCustomAssets ()Ljava/util/List; public final fun getCustomStyleSheets ()Ljava/util/List; public final fun getFooterMessage ()Ljava/lang/String; + public final fun getMergeImplicitExpectActualDeclarations ()Z public final fun getSeparateInheritedMembers ()Z public fun hashCode ()I public final fun setCustomAssets (Ljava/util/List;)V public final fun setCustomStyleSheets (Ljava/util/List;)V public final fun setFooterMessage (Ljava/lang/String;)V + public final fun setMergeImplicitExpectActualDeclarations (Z)V public final fun setSeparateInheritedMembers (Z)V public fun toString ()Ljava/lang/String; } @@ -1342,28 +1346,39 @@ public class org/jetbrains/dokka/base/translators/documentables/DefaultPageCreat public fun (Lorg/jetbrains/dokka/base/DokkaBaseConfiguration;Lorg/jetbrains/dokka/base/transformers/pages/comments/CommentsToContentConverter;Lorg/jetbrains/dokka/base/signatures/SignatureProvider;Lorg/jetbrains/dokka/utilities/DokkaLogger;Ljava/util/List;)V public synthetic fun (Lorg/jetbrains/dokka/base/DokkaBaseConfiguration;Lorg/jetbrains/dokka/base/transformers/pages/comments/CommentsToContentConverter;Lorg/jetbrains/dokka/base/signatures/SignatureProvider;Lorg/jetbrains/dokka/utilities/DokkaLogger;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V protected fun contentForBrief (Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Lorg/jetbrains/dokka/model/Documentable;)V - protected fun contentForClasslike (Lorg/jetbrains/dokka/model/DClasslike;)Lorg/jetbrains/dokka/pages/ContentGroup; + protected fun contentForClasslikesAndEntries (Ljava/util/List;)Lorg/jetbrains/dokka/pages/ContentGroup; + protected fun contentForComments (Ljava/util/List;Z)Ljava/util/List; + protected fun contentForComments (Lorg/jetbrains/dokka/links/DRI;Ljava/util/Set;Ljava/util/Map;Z)Ljava/util/List; protected fun contentForComments (Lorg/jetbrains/dokka/model/Documentable;Z)Ljava/util/List; + public static synthetic fun contentForComments$default (Lorg/jetbrains/dokka/base/translators/documentables/DefaultPageCreator;Ljava/util/List;ZILjava/lang/Object;)Ljava/util/List; + public static synthetic fun contentForComments$default (Lorg/jetbrains/dokka/base/translators/documentables/DefaultPageCreator;Lorg/jetbrains/dokka/links/DRI;Ljava/util/Set;Ljava/util/Map;ZILjava/lang/Object;)Ljava/util/List; public static synthetic fun contentForComments$default (Lorg/jetbrains/dokka/base/translators/documentables/DefaultPageCreator;Lorg/jetbrains/dokka/model/Documentable;ZILjava/lang/Object;)Ljava/util/List; protected fun contentForDescription (Lorg/jetbrains/dokka/model/Documentable;)Ljava/util/List; - protected fun contentForEnumEntry (Lorg/jetbrains/dokka/model/DEnumEntry;)Lorg/jetbrains/dokka/pages/ContentGroup; protected fun contentForFunction (Lorg/jetbrains/dokka/model/DFunction;)Lorg/jetbrains/dokka/pages/ContentGroup; protected fun contentForMember (Lorg/jetbrains/dokka/model/Documentable;)Lorg/jetbrains/dokka/pages/ContentGroup; + protected fun contentForMembers (Ljava/util/List;)Lorg/jetbrains/dokka/pages/ContentGroup; protected fun contentForModule (Lorg/jetbrains/dokka/model/DModule;)Lorg/jetbrains/dokka/pages/ContentGroup; protected fun contentForPackage (Lorg/jetbrains/dokka/model/DPackage;)Lorg/jetbrains/dokka/pages/ContentGroup; protected fun contentForProperty (Lorg/jetbrains/dokka/model/DProperty;)Lorg/jetbrains/dokka/pages/ContentGroup; + protected fun contentForScope (Ljava/util/Set;Ljava/util/Set;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/Map;)Lorg/jetbrains/dokka/pages/ContentGroup; protected fun contentForScope (Lorg/jetbrains/dokka/model/WithScope;Lorg/jetbrains/dokka/links/DRI;Ljava/util/Set;)Lorg/jetbrains/dokka/pages/ContentGroup; + protected fun contentForScopes (Ljava/util/List;Ljava/util/Set;)Lorg/jetbrains/dokka/pages/ContentGroup; protected fun divergentBlock (Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Ljava/lang/String;Ljava/util/Collection;Lorg/jetbrains/dokka/pages/ContentKind;Lorg/jetbrains/dokka/model/properties/PropertyContainer;)V public static synthetic fun divergentBlock$default (Lorg/jetbrains/dokka/base/translators/documentables/DefaultPageCreator;Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Ljava/lang/String;Ljava/util/Collection;Lorg/jetbrains/dokka/pages/ContentKind;Lorg/jetbrains/dokka/model/properties/PropertyContainer;ILjava/lang/Object;)V protected fun getContentBuilder ()Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder; public final fun getCustomTagContentProviders ()Ljava/util/List; public final fun getLogger ()Lorg/jetbrains/dokka/utilities/DokkaLogger; + protected final fun getMergeImplicitExpectActualDeclarations ()Z protected final fun getSeparateInheritedMembers ()Z public fun pageForClasslike (Lorg/jetbrains/dokka/model/DClasslike;)Lorg/jetbrains/dokka/pages/ClasslikePageNode; + public fun pageForClasslikes (Ljava/util/List;)Lorg/jetbrains/dokka/pages/ClasslikePageNode; + public fun pageForEnumEntries (Ljava/util/List;)Lorg/jetbrains/dokka/pages/ClasslikePageNode; public fun pageForEnumEntry (Lorg/jetbrains/dokka/model/DEnumEntry;)Lorg/jetbrains/dokka/pages/ClasslikePageNode; public fun pageForFunction (Lorg/jetbrains/dokka/model/DFunction;)Lorg/jetbrains/dokka/pages/MemberPageNode; + public fun pageForFunctions (Ljava/util/List;)Lorg/jetbrains/dokka/pages/MemberPageNode; public fun pageForModule (Lorg/jetbrains/dokka/model/DModule;)Lorg/jetbrains/dokka/pages/ModulePageNode; public fun pageForPackage (Lorg/jetbrains/dokka/model/DPackage;)Lorg/jetbrains/dokka/pages/PackagePageNode; + public fun pageForProperties (Ljava/util/List;)Lorg/jetbrains/dokka/pages/MemberPageNode; public fun pageForProperty (Lorg/jetbrains/dokka/model/DProperty;)Lorg/jetbrains/dokka/pages/MemberPageNode; protected fun toHeaderString (Lorg/jetbrains/dokka/model/doc/TagWrapper;)Ljava/lang/String; } @@ -1462,6 +1477,8 @@ public class org/jetbrains/dokka/base/translators/documentables/PageContentBuild public static synthetic fun linkNode$default (Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Ljava/lang/String;Lorg/jetbrains/dokka/links/DRI;Lorg/jetbrains/dokka/pages/DCI;Ljava/util/Set;Ljava/util/Set;Lorg/jetbrains/dokka/model/properties/PropertyContainer;ILjava/lang/Object;)Lorg/jetbrains/dokka/pages/ContentDRILink; public final fun list (Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;Ljava/util/Set;Lkotlin/jvm/functions/Function2;)V public static synthetic fun list$default (Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Ljava/util/List;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;Ljava/util/Set;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V + public final fun multiBlock (Ljava/lang/String;ILorg/jetbrains/dokka/pages/Kind;Ljava/lang/Iterable;Ljava/util/Set;Ljava/util/Set;Lorg/jetbrains/dokka/model/properties/PropertyContainer;ZZLjava/util/List;ZLkotlin/jvm/functions/Function3;)V + public static synthetic fun multiBlock$default (Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Ljava/lang/String;ILorg/jetbrains/dokka/pages/Kind;Ljava/lang/Iterable;Ljava/util/Set;Ljava/util/Set;Lorg/jetbrains/dokka/model/properties/PropertyContainer;ZZLjava/util/List;ZLkotlin/jvm/functions/Function3;ILjava/lang/Object;)V public final fun operator (Ljava/lang/String;)V public final fun orderedList (Lorg/jetbrains/dokka/pages/Kind;Ljava/util/Set;Ljava/util/Set;Lorg/jetbrains/dokka/model/properties/PropertyContainer;Lkotlin/jvm/functions/Function1;)V public static synthetic fun orderedList$default (Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Lorg/jetbrains/dokka/pages/Kind;Ljava/util/Set;Ljava/util/Set;Lorg/jetbrains/dokka/model/properties/PropertyContainer;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V diff --git a/plugins/base/base-test-utils/api/base-test-utils.api b/plugins/base/base-test-utils/api/base-test-utils.api index b6ec84a15c..a0b535f2f7 100644 --- a/plugins/base/base-test-utils/api/base-test-utils.api +++ b/plugins/base/base-test-utils/api/base-test-utils.api @@ -62,8 +62,8 @@ public final class org/jetbrains/dokka/base/testApi/testRunner/BaseTestMethods : } public final class renderers/RawTestPage : org/jetbrains/dokka/pages/RootPageNode, org/jetbrains/dokka/pages/ContentPage { - public fun (Lorg/jetbrains/dokka/pages/ContentNode;Ljava/lang/String;Ljava/util/Set;Lorg/jetbrains/dokka/model/Documentable;Ljava/util/List;Ljava/util/List;)V - public synthetic fun (Lorg/jetbrains/dokka/pages/ContentNode;Ljava/lang/String;Ljava/util/Set;Lorg/jetbrains/dokka/model/Documentable;Ljava/util/List;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Lorg/jetbrains/dokka/pages/ContentNode;Ljava/lang/String;Ljava/util/Set;Ljava/util/List;Ljava/util/List;)V + public synthetic fun (Lorg/jetbrains/dokka/pages/ContentNode;Ljava/lang/String;Ljava/util/Set;Ljava/util/List;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public fun getChildren ()Ljava/util/List; public fun getContent ()Lorg/jetbrains/dokka/pages/ContentNode; public fun getDocumentable ()Lorg/jetbrains/dokka/model/Documentable; diff --git a/plugins/base/base-test-utils/src/main/kotlin/renderers/TestPage.kt b/plugins/base/base-test-utils/src/main/kotlin/renderers/TestPage.kt index 67ba2dd3d2..4066c7c662 100644 --- a/plugins/base/base-test-utils/src/main/kotlin/renderers/TestPage.kt +++ b/plugins/base/base-test-utils/src/main/kotlin/renderers/TestPage.kt @@ -1,15 +1,14 @@ package renderers import org.jetbrains.dokka.DokkaConfiguration +import org.jetbrains.dokka.base.signatures.KotlinSignatureProvider +import org.jetbrains.dokka.base.transformers.pages.comments.CommentsToContentConverter +import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.model.Documentable import org.jetbrains.dokka.model.doc.DocTag import org.jetbrains.dokka.model.properties.PropertyContainer import org.jetbrains.dokka.pages.* import org.jetbrains.dokka.utilities.DokkaConsoleLogger -import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder -import org.jetbrains.dokka.base.signatures.KotlinSignatureProvider -import org.jetbrains.dokka.base.transformers.pages.comments.CommentsToContentConverter fun testPage(callback: PageContentBuilder.DocumentableContentBuilder.() -> Unit): RawTestPage { val content = PageContentBuilder( @@ -29,7 +28,6 @@ class RawTestPage( override val content: ContentNode, override val name: String = "testPage", override val dri: Set = setOf(DRI.topLevel), - override val documentable: Documentable? = null, override val embeddedResources: List = emptyList(), override val children: List = emptyList(), ): RootPageNode(), ContentPage { diff --git a/plugins/base/src/main/kotlin/DokkaBaseConfiguration.kt b/plugins/base/src/main/kotlin/DokkaBaseConfiguration.kt index 21757d702f..8ea8818ded 100644 --- a/plugins/base/src/main/kotlin/DokkaBaseConfiguration.kt +++ b/plugins/base/src/main/kotlin/DokkaBaseConfiguration.kt @@ -8,12 +8,14 @@ data class DokkaBaseConfiguration( var customStyleSheets: List = defaultCustomStyleSheets, var customAssets: List = defaultCustomAssets, var separateInheritedMembers: Boolean = separateInheritedMembersDefault, - var footerMessage: String = defaultFooterMessage + var footerMessage: String = defaultFooterMessage, + var mergeImplicitExpectActualDeclarations: Boolean = mergeImplicitExpectActualDeclarationsDefault ) : ConfigurableBlock { companion object { val defaultFooterMessage = "© ${Year.now().value} Copyright" val defaultCustomStyleSheets: List = emptyList() val defaultCustomAssets: List = emptyList() const val separateInheritedMembersDefault: Boolean = false + const val mergeImplicitExpectActualDeclarationsDefault: Boolean = false } } \ No newline at end of file diff --git a/plugins/base/src/main/kotlin/renderers/html/htmlPreprocessors.kt b/plugins/base/src/main/kotlin/renderers/html/htmlPreprocessors.kt index 43526dc352..3297d09f12 100644 --- a/plugins/base/src/main/kotlin/renderers/html/htmlPreprocessors.kt +++ b/plugins/base/src/main/kotlin/renderers/html/htmlPreprocessors.kt @@ -1,14 +1,14 @@ package org.jetbrains.dokka.base.renderers.html -import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import org.jetbrains.dokka.base.DokkaBase import org.jetbrains.dokka.base.DokkaBaseConfiguration import org.jetbrains.dokka.base.renderers.sourceSets -import org.jetbrains.dokka.base.templating.AddToSearch import org.jetbrains.dokka.base.templating.AddToSourcesetDependencies import org.jetbrains.dokka.base.templating.toJsonString -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.model.* +import org.jetbrains.dokka.model.DEnum +import org.jetbrains.dokka.model.DEnumEntry +import org.jetbrains.dokka.model.DFunction +import org.jetbrains.dokka.model.withDescendants import org.jetbrains.dokka.pages.* import org.jetbrains.dokka.plugability.DokkaContext import org.jetbrains.dokka.plugability.configuration @@ -30,19 +30,18 @@ abstract class NavigationDataProvider { when { this !is ClasslikePageNode -> children.filterIsInstance().map { visit(it) } - documentable is DEnum -> - children.filter { it is ContentPage && it.documentable is DEnumEntry }.map { visit(it as ContentPage) } + documentables.any { it is DEnum } -> + children.filter { it is WithDocumentables && it.documentables.any { it is DEnumEntry } } + .map { visit(it as ContentPage) } else -> emptyList() }.sortedBy { it.name.toLowerCase() } /** - * Parenthesis is applied in 2 cases: + * Parenthesis is applied in 1 case: * - page only contains functions (therefore documentable from this page is [DFunction]) - * - page merges only functions (documentable is null because [SameMethodNamePageMergerStrategy][org.jetbrains.dokka.base.transformers.pages.merger.SameMethodNamePageMergerStrategy] - * removes it from page) */ private val ContentPage.displayableName: String - get() = if (documentable is DFunction || (documentable == null && dri.all { it.callable != null })) { + get() = if (this is WithDocumentables && documentables.all { it is DFunction }) { "$name()" } else { name diff --git a/plugins/base/src/main/kotlin/transformers/pages/merger/SameMethodNamePageMergerStrategy.kt b/plugins/base/src/main/kotlin/transformers/pages/merger/SameMethodNamePageMergerStrategy.kt index 2fb70fc841..6c12c71954 100644 --- a/plugins/base/src/main/kotlin/transformers/pages/merger/SameMethodNamePageMergerStrategy.kt +++ b/plugins/base/src/main/kotlin/transformers/pages/merger/SameMethodNamePageMergerStrategy.kt @@ -23,7 +23,7 @@ class SameMethodNamePageMergerStrategy(val logger: DokkaLogger) : PageMergerStra children = members.flatMap { it.children }.distinct(), content = squashDivergentInstances(members).withSourceSets(members.allSourceSets()), embeddedResources = members.flatMap { it.embeddedResources }.distinct(), - documentable = null + documentables = members.flatMap { it.documentables } ) return (pages - members) + listOf(merged) @@ -37,9 +37,9 @@ class SameMethodNamePageMergerStrategy(val logger: DokkaLogger) : PageMergerStra .reduce { acc, node -> acc.mapTransform { g -> g.copy(children = (g.children + - (node.dfs { it is ContentDivergentGroup && it.groupID == g.groupID } as? ContentDivergentGroup) - ?.children?.single() - ).filterNotNull() + ((node.dfs { it is ContentDivergentGroup && it.groupID == g.groupID } as? ContentDivergentGroup) + ?.children ?: emptyList()) + ) ) } } diff --git a/plugins/base/src/main/kotlin/transformers/pages/samples/SamplesTransformer.kt b/plugins/base/src/main/kotlin/transformers/pages/samples/SamplesTransformer.kt index 3ff7a77d26..db133bb823 100644 --- a/plugins/base/src/main/kotlin/transformers/pages/samples/SamplesTransformer.kt +++ b/plugins/base/src/main/kotlin/transformers/pages/samples/SamplesTransformer.kt @@ -35,14 +35,18 @@ abstract class SamplesTransformer(val context: DokkaContext) : PageTransformer { "" return input.transformContentPagesTree { page -> - page.documentable?.documentation?.entries?.fold(page) { acc, entry -> - entry.value.children.filterIsInstance().fold(acc) { acc, sample -> + val samples = (page as? WithDocumentables)?.documentables?.flatMap { + it.documentation.entries.flatMap { entry -> + entry.value.children.filterIsInstance().map { entry.key to it } + } + } + + samples?.fold(page as ContentPage) { acc, (sampleSourceSet, sample) -> acc.modified( - content = acc.content.addSample(page, entry.key, sample.name, analysis), + content = acc.content.addSample(page, sampleSourceSet, sample.name, analysis), embeddedResources = acc.embeddedResources + kotlinPlaygroundScript ) - } - } ?: page + } ?: page } } diff --git a/plugins/base/src/main/kotlin/transformers/pages/sourcelinks/SourceLinksTransformer.kt b/plugins/base/src/main/kotlin/transformers/pages/sourcelinks/SourceLinksTransformer.kt index f66ff2229c..933050552a 100644 --- a/plugins/base/src/main/kotlin/transformers/pages/sourcelinks/SourceLinksTransformer.kt +++ b/plugins/base/src/main/kotlin/transformers/pages/sourcelinks/SourceLinksTransformer.kt @@ -1,15 +1,15 @@ package org.jetbrains.dokka.base.transformers.pages.sourcelinks -import com.intellij.psi.PsiElement import com.intellij.psi.PsiDocumentManager +import com.intellij.psi.PsiElement import org.jetbrains.dokka.DokkaConfiguration -import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder -import org.jetbrains.dokka.model.DocumentableSource import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet import org.jetbrains.dokka.analysis.DescriptorDocumentableSource import org.jetbrains.dokka.analysis.PsiDocumentableSource import org.jetbrains.dokka.base.DokkaBase import org.jetbrains.dokka.base.resolvers.anchors.SymbolAnchorHint +import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder +import org.jetbrains.dokka.model.DocumentableSource import org.jetbrains.dokka.model.WithSources import org.jetbrains.dokka.model.toDisplaySourceSets import org.jetbrains.dokka.pages.* @@ -32,8 +32,9 @@ class SourceLinksTransformer(val context: DokkaContext) : PageTransformer { override fun invoke(input: RootPageNode) = input.transformContentPagesTree { node -> - when (val documentable = node.documentable) { - is WithSources -> resolveSources(documentable) + when (node) { + is WithDocumentables -> + node.documentables.filterIsInstance().flatMap { resolveSources(it) } .takeIf { it.isNotEmpty() } ?.let { node.addSourcesContent(it) } ?: node @@ -65,23 +66,26 @@ class SourceLinksTransformer(val context: DokkaContext) : PageTransformer { private fun PageContentBuilder.buildSourcesContent( node: ContentPage, sources: List> - ) = contentFor( - node.dri.first(), - node.documentable!!.sourceSets.toSet() - ) { - header(2, "Sources", kind = ContentKind.Source) - +ContentTable( - header = emptyList(), - children = sources.map { - buildGroup(node.dri, setOf(it.first), kind = ContentKind.Source, extra = mainExtra + SymbolAnchorHint(it.second, ContentKind.Source)) { - link("${it.first.displayName} source", it.second) - } - }, - dci = DCI(node.dri, ContentKind.Source), - sourceSets = node.documentable!!.sourceSets.toDisplaySourceSets(), - style = emptySet(), - extra = mainExtra + SimpleAttr.header("Sources") - ) + ): ContentGroup { + val documentables = (node as? WithDocumentables)?.documentables.orEmpty() + return contentFor( + node.dri, + documentables.flatMap { it.sourceSets }.toSet() + ) { + header(2, "Sources", kind = ContentKind.Source) + +ContentTable( + header = emptyList(), + children = sources.map { + buildGroup(node.dri, setOf(it.first), kind = ContentKind.Source, extra = mainExtra + SymbolAnchorHint(it.second, ContentKind.Source)) { + link("${it.first.displayName} source", it.second) + } + }, + dci = DCI(node.dri, ContentKind.Source), + sourceSets = documentables.flatMap { it.sourceSets }.toDisplaySourceSets(), + style = emptySet(), + extra = mainExtra + SimpleAttr.header("Sources") + ) + } } private fun DocumentableSource.toLink(sourceLink: SourceLink): String { diff --git a/plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt b/plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt index e2aca6f9f7..c5136c27ca 100644 --- a/plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt +++ b/plugins/base/src/main/kotlin/translators/documentables/DefaultPageCreator.kt @@ -1,9 +1,14 @@ 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.base.transformers.documentables.ClashingDriIdentifier import org.jetbrains.dokka.base.transformers.documentables.InheritorsInfo 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.links.DRI import org.jetbrains.dokka.model.* @@ -15,11 +20,6 @@ import org.jetbrains.dokka.utilities.DokkaLogger import org.jetbrains.kotlin.utils.addToStdlib.safeAs import kotlin.reflect.KClass import kotlin.reflect.full.isSubclassOf -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.transformers.documentables.ClashingDriIdentifier -import org.jetbrains.dokka.base.transformers.pages.tags.CustomTagContentProvider private typealias GroupedTags = Map, List>> @@ -35,66 +35,139 @@ open class DefaultPageCreator( ) { protected open val contentBuilder = PageContentBuilder(commentsToContentConverter, signatureProvider, logger) + protected val mergeImplicitExpectActualDeclarations = + configuration?.mergeImplicitExpectActualDeclarations + ?: DokkaBaseConfiguration.mergeImplicitExpectActualDeclarationsDefault + protected val separateInheritedMembers = configuration?.separateInheritedMembers ?: DokkaBaseConfiguration.separateInheritedMembersDefault - open fun pageForModule(m: DModule) = - ModulePageNode(m.name.ifEmpty { "" }, contentForModule(m), m, m.packages.map(::pageForPackage)) + open fun pageForModule(m: DModule): ModulePageNode = + ModulePageNode(m.name.ifEmpty { "" }, contentForModule(m), listOf(m), m.packages.map(::pageForPackage)) open fun pageForPackage(p: DPackage): PackagePageNode = PackagePageNode( - p.name, contentForPackage(p), setOf(p.dri), p, - p.classlikes.renameClashingDocumentable().map(::pageForClasslike) + - p.functions.renameClashingDocumentable() - .map(::pageForFunction) + p.properties.mapNotNull(::pageForProperty) + p.name, contentForPackage(p), setOf(p.dri), listOf(p), + if (mergeImplicitExpectActualDeclarations) + p.classlikes.mergeClashingDocumentable().map(::pageForClasslikes) + + p.functions.mergeClashingDocumentable().map(::pageForFunctions) + + p.properties.mergeClashingDocumentable().map(::pageForProperties) + else + p.classlikes.renameClashingDocumentable().map(::pageForClasslike) + + p.functions.renameClashingDocumentable().map(::pageForFunction) + + p.properties.mapNotNull(::pageForProperty) ) - open fun pageForEnumEntry(e: DEnumEntry): ClasslikePageNode = - ClasslikePageNode( - e.nameAfterClash(), contentForEnumEntry(e), setOf(e.dri), e, - e.classlikes.renameClashingDocumentable().map(::pageForClasslike) + - e.filteredFunctions.renameClashingDocumentable().map(::pageForFunction) + - e.filteredProperties.renameClashingDocumentable().mapNotNull(::pageForProperty) - ) + open fun pageForEnumEntry(e: DEnumEntry): ClasslikePageNode = pageForEnumEntries(listOf(e)) - open fun pageForClasslike(c: DClasslike): ClasslikePageNode { - val constructors = if (c is WithConstructors) c.constructors else emptyList() + open fun pageForClasslike(c: DClasslike): ClasslikePageNode = pageForClasslikes(listOf(c)) + + open fun pageForEnumEntries(documentables: List): 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( - c.nameAfterClash(), contentForClasslike(c), setOf(c.dri), c, - constructors.map(::pageForFunction) + - c.classlikes.renameClashingDocumentable().map(::pageForClasslike) + - c.filteredFunctions.renameClashingDocumentable().map(::pageForFunction) + - c.filteredProperties.renameClashingDocumentable().mapNotNull(::pageForProperty) + - if (c is DEnum) c.entries.map(::pageForEnumEntry) else emptyList() + documentables.first().nameAfterClash(), contentForClasslikesAndEntries(documentables), dri, documentables, + childrenPages + ) + } + + open fun pageForClasslikes(documentables: List): 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 constructors = documentables.flatMap { if (it is WithConstructors) it.constructors else emptyList() } + + val classlikes = documentables.flatMap { it.classlikes } + val functions = documentables.flatMap { it.filteredFunctions } + val props = documentables.flatMap { it.filteredProperties } + val entries = documentables.flatMap { if (it is DEnum) it.entries else emptyList() } + + val childrenPages = constructors.map(::pageForFunction) + + if (mergeImplicitExpectActualDeclarations) + classlikes.mergeClashingDocumentable().map(::pageForClasslikes) + + functions.mergeClashingDocumentable().map(::pageForFunctions) + + props.mergeClashingDocumentable().map(::pageForProperties) + + entries.mergeClashingDocumentable().map(::pageForEnumEntries) + else + classlikes.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.toClashedName() where T : Documentable, T : WithExtraProperties = (extra[ClashingDriIdentifier]?.value?.joinToString(", ", "[", "]") { it.displayName } ?: "") + name.orEmpty() - @Suppress("UNCHECKED_CAST") private fun List.renameClashingDocumentable(): List = groupBy { it.dri }.values.flatMap { elements -> if (elements.size == 1) elements else elements.mapNotNull { element -> - when (element) { - is DClass -> element.copy(extra = element.extra + DriClashAwareName(element.toClashedName())) - is DObject -> element.copy(extra = element.extra + DriClashAwareName(element.toClashedName())) - is DAnnotation -> element.copy(extra = element.extra + DriClashAwareName(element.toClashedName())) - is DInterface -> element.copy(extra = element.extra + DriClashAwareName(element.toClashedName())) - is DEnum -> element.copy(extra = element.extra + DriClashAwareName(element.toClashedName())) - is DFunction -> element.copy(extra = element.extra + DriClashAwareName(element.toClashedName())) - is DProperty -> element.copy(extra = element.extra + DriClashAwareName(element.toClashedName())) - is DTypeAlias -> element.copy(extra = element.extra + DriClashAwareName(element.toClashedName())) - else -> null - } as? T? + element.renameClashingDocumentable() } } - open fun pageForFunction(f: DFunction) = MemberPageNode(f.nameAfterClash(), contentForFunction(f), setOf(f.dri), f) + @Suppress("UNCHECKED_CAST") + private fun 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 List.mergeClashingDocumentable(): List> = + groupBy { it.dri }.values.toList() + + open fun pageForFunction(f: DFunction) = + MemberPageNode(f.nameAfterClash(), contentForFunction(f), setOf(f.dri), listOf(f)) + + open fun pageForFunctions(fs: List): 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) + } open fun pageForProperty(p: DProperty): MemberPageNode? = - MemberPageNode(p.nameAfterClash(), contentForProperty(p), setOf(p.dri), p) + MemberPageNode(p.nameAfterClash(), contentForProperty(p), setOf(p.dri), listOf(p)) + + open fun pageForProperties(ps: List): 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.isInherited(): Boolean where T : Documentable, T : WithExtraProperties = sourceSets.all { sourceSet -> extra[InheritedMember]?.isInherited(sourceSet) == true } @@ -168,148 +241,193 @@ open class DefaultPageCreator( } } + protected open fun contentForScopes( + scopes: List, + sourceSets: Set + ): ContentGroup { + val types = scopes.flatMap { it.classlikes } + scopes.filterIsInstance().flatMap { it.typealiases } + val inheritors = scopes.fold(mutableMapOf>()) { acc, scope -> + val inheritorsForScope = + scope.safeAs>()?.let { it.extra[InheritorsInfo] }?.let { inheritors -> + inheritors.value.filter { it.value.isNotEmpty() } + }.orEmpty() + inheritorsForScope.forEach { (k, v) -> + acc.compute(k) { _, value -> value?.plus(v) ?: v } + } + acc + } + + return contentForScope( + @Suppress("UNCHECKED_CAST") + (scopes as List).dri, + sourceSets, + types, + scopes.flatMap { it.functions }, + scopes.flatMap { it.properties }, + inheritors + ) + } + protected open fun contentForScope( s: WithScope, dri: DRI, sourceSets: Set - ) = contentBuilder.contentFor(s as Documentable) { + ): ContentGroup { val types = listOf( s.classlikes, (s as? DPackage)?.typealiases ?: emptyList() ).flatten() + val inheritors = + s.safeAs>()?.let { it.extra[InheritorsInfo] }?.let { inheritors -> + inheritors.value.filter { it.value.isNotEmpty() } + }.orEmpty() + + return contentForScope(setOf(dri), sourceSets, types, s.functions, s.properties, inheritors) + } + + protected open fun contentForScope( + dri: Set, + sourceSets: Set, + types: List, + functions: List, + properties: List, + inheritors: SourceSetDependent> + ) = contentBuilder.contentFor(dri, sourceSets) { divergentBlock("Types", types, ContentKind.Classlikes, extra = mainExtra + SimpleAttr.header("Types")) if (separateInheritedMembers) { - val (inheritedFunctions, memberFunctions) = s.functions.splitInherited() - val (inheritedProperties, memberProperties) = s.properties.splitInherited() + val (inheritedFunctions, memberFunctions) = functions.splitInherited() + val (inheritedProperties, memberProperties) = properties.splitInherited() propertiesBlock("Properties", memberProperties, sourceSets) propertiesBlock("Inherited properties", inheritedProperties, sourceSets) functionsBlock("Functions", memberFunctions) functionsBlock("Inherited functions", inheritedFunctions) } else { - functionsBlock("Functions", s.functions) - propertiesBlock("Properties", s.properties, sourceSets) + functionsBlock("Functions", functions) + propertiesBlock("Properties", properties, sourceSets) } - s.safeAs>()?.let { it.extra[InheritorsInfo] }?.let { inheritors -> - val map = inheritors.value.filter { it.value.isNotEmpty() } - if (map.values.any()) { - header(2, "Inheritors") { } - +ContentTable( - header = listOf(contentBuilder.contentFor(mainDRI, mainSourcesetData) { - text("Name") - }), - children = map.entries.flatMap { entry -> entry.value.map { Pair(entry.key, it) } } - .groupBy({ it.second }, { it.first }).map { (classlike, platforms) -> - val label = classlike.classNames?.substringAfterLast(".") ?: classlike.toString() - .also { logger.warn("No class name found for DRI $classlike") } - buildGroup( - setOf(classlike), - platforms.toSet(), - ContentKind.Inheritors, - extra = mainExtra + SymbolAnchorHint(label, ContentKind.Inheritors) - ) { - link(label, classlike) - } - }, - dci = DCI(setOf(dri), ContentKind.Inheritors), - sourceSets = sourceSets.toDisplaySourceSets(), - style = emptySet(), - extra = mainExtra + SimpleAttr.header("Inheritors") - ) - } + if (inheritors.values.any()) { + header(2, "Inheritors") { } + +ContentTable( + header = listOf(contentBuilder.contentFor(mainDRI, mainSourcesetData) { + text("Name") + }), + children = inheritors.entries.flatMap { entry -> entry.value.map { Pair(entry.key, it) } } + .groupBy({ it.second }, { it.first }).map { (classlike, platforms) -> + val label = classlike.classNames?.substringAfterLast(".") ?: classlike.toString() + .also { logger.warn("No class name found for DRI $classlike") } + buildGroup( + setOf(classlike), + platforms.toSet(), + ContentKind.Inheritors, + extra = mainExtra + SymbolAnchorHint(label, ContentKind.Inheritors) + ) { + link(label, classlike) + } + }, + dci = DCI(dri, ContentKind.Inheritors), + sourceSets = sourceSets.toDisplaySourceSets(), + style = emptySet(), + extra = mainExtra + SimpleAttr.header("Inheritors") + ) } } private fun Iterable.sorted() = sortedWith(compareBy({ it.name }, { it.parameters.size }, { it.dri.toString() })) - protected open fun contentForEnumEntry(e: DEnumEntry) = contentBuilder.contentFor(e) { - group(kind = ContentKind.Cover) { - cover(e.name) - sourceSetDependentHint(e.dri, e.sourceSets.toSet()) { - +buildSignature(e) - +contentForDescription(e) - } - } - group(styles = setOf(ContentStyle.TabbedContent)) { - +contentForComments(e) - +contentForScope(e, e.dri, e.sourceSets) - } - } - - protected open fun contentForClasslike(c: DClasslike) = contentBuilder.contentFor(c) { - @Suppress("UNCHECKED_CAST") - val extensions = (c as WithExtraProperties) - .extra[CallableExtensions]?.extensions - ?.filterIsInstance().orEmpty() - // 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(c.name.orEmpty()) - sourceSetDependentHint(c.dri, c.sourceSets) { - +buildSignature(c) - +contentForDescription(c) + /** + * @param documentables a list of [DClasslike] and [DEnumEntry] with the same dri in different sourceSets + */ + protected open fun contentForClasslikesAndEntries(documentables: List): ContentGroup = + contentBuilder.contentFor(documentables.dri, documentables.sourceSets) { + val classlikes = documentables.filterIsInstance() + + @Suppress("UNCHECKED_CAST") + val extensions = (classlikes as List>).flatMap { + it.extra[CallableExtensions]?.extensions + ?.filterIsInstance().orEmpty() } - } - group(styles = setOf(ContentStyle.TabbedContent), sourceSets = mainSourcesetData + extensions.sourceSets) { - +contentForComments(c) - if (c is WithConstructors) { - block( - "Constructors", - 2, - ContentKind.Constructors, - c.constructors, - c.sourceSets, - needsAnchors = true, - extra = PropertyContainer.empty() + SimpleAttr.header("Constructors") - ) { - link(it.name, it.dri, kind = ContentKind.Main, styles = setOf(ContentStyle.RowTitle)) - sourceSetDependentHint( - it.dri, - it.sourceSets.toSet(), - kind = ContentKind.SourceSetDependentHint, - styles = emptySet(), - extra = PropertyContainer.empty() - ) { + // 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) - contentForBrief(it) + +contentForDescription(it) } } } - if (c is DEnum) { - block( - "Entries", - 2, - ContentKind.Classlikes, - c.entries, - c.sourceSets.toSet(), - needsSorting = false, - needsAnchors = true, - extra = mainExtra + SimpleAttr.header("Entries"), - styles = emptySet() - ) { - link(it.name, it.dri) - sourceSetDependentHint( - it.dri, - it.sourceSets.toSet(), - kind = ContentKind.SourceSetDependentHint, - extra = PropertyContainer.empty() - ) { - +buildSignature(it) - contentForBrief(it) + + group(styles = setOf(ContentStyle.TabbedContent), sourceSets = mainSourcesetData + extensions.sourceSets) { + +contentForComments(documentables) + val csWithConstructor = classlikes.filterIsInstance() + if (csWithConstructor.isNotEmpty()) { + val constructorsToDocumented = csWithConstructor.flatMap { it.constructors } + multiBlock( + "Constructors", + 2, + ContentKind.Constructors, + constructorsToDocumented.groupBy { it.parameters.map { it.dri } } + .map { (_, v) -> v.first().name to v }, + @Suppress("UNCHECKED_CAST") + (csWithConstructor as List).sourceSets, + needsAnchors = true, + extra = PropertyContainer.empty() + SimpleAttr.header("Constructors") + ) { key, ds -> + link(key, ds.first().dri, kind = ContentKind.Main, styles = setOf(ContentStyle.RowTitle)) + sourceSetDependentHint( + ds.dri, + ds.sourceSets, + kind = ContentKind.SourceSetDependentHint, + styles = emptySet(), + extra = PropertyContainer.empty() + ) { + ds.forEach { + +buildSignature(it) + contentForBrief(it) + } + } } } - } - +contentForScope(c, c.dri, c.sourceSets) + val csEnum = classlikes.filterIsInstance() + if (csEnum.isNotEmpty()) { + multiBlock( + "Entries", + 2, + ContentKind.Classlikes, + csEnum.flatMap { it.entries }.groupBy { it.name }.toList(), + csEnum.sourceSets, + needsSorting = false, + needsAnchors = true, + extra = mainExtra + SimpleAttr.header("Entries"), + styles = emptySet() + ) { key, ds -> + link(key, ds.first().dri) + sourceSetDependentHint( + ds.dri, + ds.sourceSets, + kind = ContentKind.SourceSetDependentHint, + extra = PropertyContainer.empty() + ) { + ds.forEach { + +buildSignature(it) + contentForBrief(it) + } + } + } + } + +contentForScopes(documentables.filterIsInstance(), documentables.sourceSets) - divergentBlock( - "Extensions", - extensions, - ContentKind.Extensions, - extra = mainExtra + SimpleAttr.header("Extensions") - ) + divergentBlock( + "Extensions", + extensions, + ContentKind.Extensions, + extra = mainExtra + SimpleAttr.header("Extensions") + ) + } } - } @Suppress("UNCHECKED_CAST") private inline fun GroupedTags.withTypeUnnamed(): SourceSetDependent = @@ -347,7 +465,7 @@ open class DefaultPageCreator( if (customTags.isNotEmpty()) { group(styles = setOf(TextStyle.Block)) { platforms.forEach { platform -> - customTags.forEach { (tagName, sourceSetTag) -> + customTags.forEach { (_, sourceSetTag) -> sourceSetTag[platform]?.let { tag -> customTagContentProviders.filter { it.isApplicable(tag) }.forEach { provider -> with(provider) { @@ -379,8 +497,8 @@ open class DefaultPageCreator( }.children } - private fun Documentable.getPossibleFallbackSourcesets(sourceSet: DokkaSourceSet) = - this.sourceSets.filter { it.sourceSetID in sourceSet.dependentSourceSets } + private fun Set.getPossibleFallbackSourcesets(sourceSet: DokkaSourceSet) = + this.filter { it.sourceSetID in sourceSet.dependentSourceSets } private fun Map.fallback(sourceSets: List): V? = sourceSets.firstOrNull { it in this.keys }.let { this[it] } @@ -388,8 +506,19 @@ open class DefaultPageCreator( protected open fun contentForComments( d: Documentable, isPlatformHintedContent: Boolean = true + ) = contentForComments(d.dri, d.sourceSets, d.groupedTags, isPlatformHintedContent) + + protected open fun contentForComments( + d: List, + isPlatformHintedContent: Boolean = true + ) = contentForComments(d.first().dri, d.sourceSets, d.groupedTags, isPlatformHintedContent) + + protected open fun contentForComments( + dri: DRI, + sourceSets: Set, + tags: GroupedTags, + isPlatformHintedContent: Boolean = true ): List { - val tags = d.groupedTags fun DocumentableContentBuilder.buildContent( platforms: Set, @@ -417,7 +546,7 @@ open class DefaultPageCreator( buildContent(availablePlatforms) { table(kind = ContentKind.Parameters, sourceSets = availablePlatforms) { availablePlatforms.forEach { platform -> - val possibleFallbacks = d.getPossibleFallbackSourcesets(platform) + val possibleFallbacks = sourceSets.getPossibleFallbackSourcesets(platform) params.mapNotNull { (_, param) -> (param[platform] ?: param.fallback(possibleFallbacks))?.let { row(sourceSets = setOf(platform), kind = ContentKind.Parameters) { @@ -451,7 +580,7 @@ open class DefaultPageCreator( buildContent(availablePlatforms) { table(kind = ContentKind.Sample) { availablePlatforms.forEach { platform -> - val possibleFallbacks = d.getPossibleFallbackSourcesets(platform) + val possibleFallbacks = sourceSets.getPossibleFallbackSourcesets(platform) seeAlsoTags.forEach { (_, see) -> (see[platform] ?: see.fallback(possibleFallbacks))?.let { row( @@ -537,12 +666,11 @@ open class DefaultPageCreator( } } - return contentBuilder.contentFor(d) { + return contentBuilder.contentFor(dri, sourceSets) { if (tags.isNotEmpty()) { contentForSamples() contentForSeeAlso() - if (d !is DProperty) - contentForParams() + contentForParams() contentForThrows() } }.children @@ -558,7 +686,8 @@ open class DefaultPageCreator( We purposefully ignore all other tags as they should not be visible in brief */ - it.firstMemberOfTypeOrNull() ?: it.firstMemberOfTypeOrNull().takeIf { documentable is DProperty } + it.firstMemberOfTypeOrNull() ?: it.firstMemberOfTypeOrNull() + .takeIf { documentable is DProperty } }?.let { group(sourceSets = setOf(sourceSet), kind = ContentKind.BriefComment) { if (documentable.hasSeparatePage) createBriefComment(documentable, sourceSet, it) @@ -568,9 +697,13 @@ open class DefaultPageCreator( } } - private fun DocumentableContentBuilder.createBriefComment(documentable: Documentable, sourceSet: DokkaSourceSet, tag: TagWrapper){ + private fun DocumentableContentBuilder.createBriefComment( + documentable: Documentable, + sourceSet: DokkaSourceSet, + tag: TagWrapper + ) { (documentable as? WithSources)?.documentableLanguage(sourceSet)?.let { - when(it){ + when (it) { DocumentableLanguage.KOTLIN -> firstParagraphComment(tag.root) DocumentableLanguage.JAVA -> firstSentenceComment(tag.root) } @@ -581,22 +714,27 @@ open class DefaultPageCreator( protected open fun contentForProperty(p: DProperty) = contentForMember(p) - protected open fun contentForMember(d: Documentable) = contentBuilder.contentFor(d) { - group(kind = ContentKind.Cover) { - cover(d.name.orEmpty()) - } - divergentGroup(ContentDivergentGroup.GroupID("member")) { - instance(setOf(d.dri), d.sourceSets.toSet()) { - divergent { - +buildSignature(d) - } - after { - +contentForDescription(d) - +contentForComments(d, isPlatformHintedContent = false) + protected open fun contentForMember(d: Documentable) = contentForMembers(listOf(d)) + + protected open fun contentForMembers(doumentables: List) = + 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) + +contentForComments(d, isPlatformHintedContent = false) + } + } } } } - } private fun DocumentableContentBuilder.functionsBlock(name: String, list: Collection) = divergentBlock( name, @@ -610,22 +748,24 @@ open class DefaultPageCreator( list: Collection, sourceSets: Set ) { - block( + multiBlock( name, 2, ContentKind.Properties, - list, + list.groupBy { it.name }.toList(), sourceSets, needsAnchors = true, extra = mainExtra + SimpleAttr.header(name), headers = listOf( headers("Name", "Summary") ) - ) { - link(it.name, it.dri, kind = ContentKind.Main) - sourceSetDependentHint(it.dri, it.sourceSets.toSet(), kind = ContentKind.SourceSetDependentHint) { - +buildSignature(it) - contentForBrief(it) + ) { key, props -> + link(key, props.first().dri, kind = ContentKind.Main) + sourceSetDependentHint(props.dri, props.sourceSets, kind = ContentKind.SourceSetDependentHint) { + props.forEach { + +buildSignature(it) + contentForBrief(it) + } } } } @@ -699,7 +839,7 @@ open class DefaultPageCreator( if (customTags.isEmpty()) return documentable.sourceSets.forEach { sourceSet -> - customTags.forEach { (tagName, sourceSetTag) -> + customTags.forEach { (_, sourceSetTag) -> sourceSetTag[sourceSet]?.let { tag -> customTagContentProviders.filter { it.isApplicable(tag) }.forEach { provider -> with(provider) { @@ -716,9 +856,19 @@ open class DefaultPageCreator( private val List.sourceSets: Set get() = flatMap { it.sourceSets }.toSet() + private val List.dri: Set + get() = map { it.dri }.toSet() + private val Documentable.groupedTags: GroupedTags get() = documentation.flatMap { (pd, doc) -> - doc.children.asSequence().map { pd to it }.toList() + doc.children.map { pd to it }.toList() + }.groupBy { it.second::class } + + private val List.groupedTags: GroupedTags + get() = this.flatMap { + it.documentation.flatMap { (pd, doc) -> + doc.children.map { pd to it }.toList() + } }.groupBy { it.second::class } private val Documentable.descriptions: SourceSetDependent @@ -730,6 +880,7 @@ open class DefaultPageCreator( private val Documentable.hasSeparatePage: Boolean get() = this !is DTypeAlias + @Suppress("UNCHECKED_CAST") private fun T.nameAfterClash(): String = ((this as? WithExtraProperties)?.extra?.get(DriClashAwareName)?.value ?: name).orEmpty() } diff --git a/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt b/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt index 8c3fcd84c5..7b6fbc7a39 100644 --- a/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt +++ b/plugins/base/src/main/kotlin/translators/documentables/PageContentBuilder.kt @@ -227,6 +227,45 @@ open class PageContentBuilder( } } + fun >> multiBlock( + name: String, + level: Int, + kind: Kind = ContentKind.Main, + groupedElements: Iterable, + sourceSets: Set = mainSourcesetData, + styles: Set