diff options
Diffstat (limited to 'plugins')
15 files changed, 387 insertions, 114 deletions
diff --git a/plugins/base/api/base.api b/plugins/base/api/base.api index 48a7a14a..e2f61c69 100644 --- a/plugins/base/api/base.api +++ b/plugins/base/api/base.api @@ -824,6 +824,7 @@ public abstract interface class org/jetbrains/dokka/base/signatures/JvmSignature public abstract fun annotationsInline (Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Lorg/jetbrains/dokka/model/AnnotationTarget;)V public abstract fun annotationsInlineWithIgnored (Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Lorg/jetbrains/dokka/model/AnnotationTarget;Ljava/util/Set;Lorg/jetbrains/dokka/base/signatures/AtStrategy;Lkotlin/Pair;Ljava/lang/String;)V public abstract fun modifiers (Lorg/jetbrains/dokka/model/properties/WithExtraProperties;)Ljava/util/Map; + public abstract fun parametersBlock (Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Lorg/jetbrains/dokka/model/DFunction;Lkotlin/jvm/functions/Function2;)V public abstract fun plus (Ljava/util/Map;Ljava/util/Map;)Ljava/util/Map; public abstract fun stylesIfDeprecated (Lorg/jetbrains/dokka/model/properties/WithExtraProperties;Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;)Ljava/util/Set; public abstract fun toSignatureString (Ljava/util/Collection;)Ljava/lang/String; @@ -836,6 +837,7 @@ public final class org/jetbrains/dokka/base/signatures/JvmSignatureUtils$Default public static fun annotations (Lorg/jetbrains/dokka/base/signatures/JvmSignatureUtils;Lorg/jetbrains/dokka/model/properties/WithExtraProperties;)Ljava/util/Map; public static fun annotationsBlockWithIgnored (Lorg/jetbrains/dokka/base/signatures/JvmSignatureUtils;Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Lorg/jetbrains/dokka/model/AnnotationTarget;Ljava/util/Set;Lorg/jetbrains/dokka/base/signatures/AtStrategy;Lkotlin/Pair;Ljava/lang/String;)V public static fun annotationsInlineWithIgnored (Lorg/jetbrains/dokka/base/signatures/JvmSignatureUtils;Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Lorg/jetbrains/dokka/model/AnnotationTarget;Ljava/util/Set;Lorg/jetbrains/dokka/base/signatures/AtStrategy;Lkotlin/Pair;Ljava/lang/String;)V + public static fun parametersBlock (Lorg/jetbrains/dokka/base/signatures/JvmSignatureUtils;Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Lorg/jetbrains/dokka/model/DFunction;Lkotlin/jvm/functions/Function2;)V public static fun plus (Lorg/jetbrains/dokka/base/signatures/JvmSignatureUtils;Ljava/util/Map;Ljava/util/Map;)Ljava/util/Map; public static fun stylesIfDeprecated (Lorg/jetbrains/dokka/base/signatures/JvmSignatureUtils;Lorg/jetbrains/dokka/model/properties/WithExtraProperties;Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;)Ljava/util/Set; public static fun toSignatureString (Lorg/jetbrains/dokka/base/signatures/JvmSignatureUtils;Ljava/util/Collection;)Ljava/lang/String; @@ -853,6 +855,7 @@ public final class org/jetbrains/dokka/base/signatures/KotlinSignatureProvider : public fun annotationsInline (Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Lorg/jetbrains/dokka/model/AnnotationTarget;)V public fun annotationsInlineWithIgnored (Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Lorg/jetbrains/dokka/model/AnnotationTarget;Ljava/util/Set;Lorg/jetbrains/dokka/base/signatures/AtStrategy;Lkotlin/Pair;Ljava/lang/String;)V public fun modifiers (Lorg/jetbrains/dokka/model/properties/WithExtraProperties;)Ljava/util/Map; + public fun parametersBlock (Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Lorg/jetbrains/dokka/model/DFunction;Lkotlin/jvm/functions/Function2;)V public fun plus (Ljava/util/Map;Ljava/util/Map;)Ljava/util/Map; public fun signature (Lorg/jetbrains/dokka/model/Documentable;)Ljava/util/List; public fun stylesIfDeprecated (Lorg/jetbrains/dokka/model/properties/WithExtraProperties;Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;)Ljava/util/Set; @@ -873,6 +876,7 @@ public final class org/jetbrains/dokka/base/signatures/KotlinSignatureUtils : or public final fun getDriOrNull (Lorg/jetbrains/dokka/model/Bound;)Lorg/jetbrains/dokka/links/DRI; public final fun getDrisOfAllNestedBounds (Lorg/jetbrains/dokka/model/Projection;)Ljava/util/List; public fun modifiers (Lorg/jetbrains/dokka/model/properties/WithExtraProperties;)Ljava/util/Map; + public fun parametersBlock (Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Lorg/jetbrains/dokka/model/DFunction;Lkotlin/jvm/functions/Function2;)V public fun plus (Ljava/util/Map;Ljava/util/Map;)Ljava/util/Map; public fun stylesIfDeprecated (Lorg/jetbrains/dokka/model/properties/WithExtraProperties;Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;)Ljava/util/Set; public fun toSignatureString (Ljava/util/Collection;)Ljava/lang/String; 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 d3db4866..b6ec84a1 100644 --- a/plugins/base/base-test-utils/api/base-test-utils.api +++ b/plugins/base/base-test-utils/api/base-test-utils.api @@ -85,6 +85,14 @@ public final class renderers/TestPageKt { public static final fun testPage (Lkotlin/jvm/functions/Function1;)Lrenderers/RawTestPage; } +public final class signatures/Parameter : utils/Tag { + public fun <init> ([Ljava/lang/Object;)V +} + +public final class signatures/Parameters : utils/Tag { + public fun <init> ([Ljava/lang/Object;)V +} + public final class signatures/SignatureUtilsKt { public static final fun firstSignature (Lorg/jsoup/nodes/Element;)Lorg/jsoup/nodes/Element; public static final fun renderedContent (Lutils/TestOutputWriter;Ljava/lang/String;)Lorg/jsoup/nodes/Element; @@ -131,6 +139,7 @@ public final class utils/I : utils/Tag { public final class utils/JsoupUtilsKt { public static final fun match (Lorg/jsoup/nodes/Element;[Ljava/lang/Object;Z)V public static synthetic fun match$default (Lorg/jsoup/nodes/Element;[Ljava/lang/Object;ZILjava/lang/Object;)V + public static final fun withClasses (Lutils/Tag;[Ljava/lang/String;)Lutils/Tag; } public final class utils/P : utils/Tag { @@ -146,7 +155,9 @@ public final class utils/Span : utils/Tag { } public class utils/Tag { - public fun <init> (Ljava/lang/String;[Ljava/lang/Object;)V + public fun <init> (Ljava/lang/String;[Ljava/lang/Object;Ljava/util/List;)V + public synthetic fun <init> (Ljava/lang/String;[Ljava/lang/Object;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun getExpectedClasses ()Ljava/util/List; public final fun getMatchers ()[Ljava/lang/Object; public final fun getName ()Ljava/lang/String; } diff --git a/plugins/base/base-test-utils/src/main/kotlin/renderers/JsoupUtils.kt b/plugins/base/base-test-utils/src/main/kotlin/renderers/JsoupUtils.kt index a4dadca4..22581d3a 100644 --- a/plugins/base/base-test-utils/src/main/kotlin/renderers/JsoupUtils.kt +++ b/plugins/base/base-test-utils/src/main/kotlin/renderers/JsoupUtils.kt @@ -21,7 +21,7 @@ fun Element.match(vararg matchers: Any, ignoreSpanWithTokenStyle:Boolean = false .zip(matchers) .forEach { (n, m) -> m.accepts(n, ignoreSpan = ignoreSpanWithTokenStyle) } -open class Tag(val name: String, vararg val matchers: Any) +open class Tag(val name: String, vararg val matchers: Any, val expectedClasses: List<String> = emptyList()) class Div(vararg matchers: Any) : Tag("div", *matchers) class P(vararg matchers: Any) : Tag("p", *matchers) class Span(vararg matchers: Any) : Tag("span", *matchers) @@ -34,16 +34,24 @@ class Dt(vararg matchers: Any) : Tag("dt", *matchers) class Dd(vararg matchers: Any) : Tag("dd", *matchers) object Wbr : Tag("wbr") object Br : Tag("br") + +fun Tag.withClasses(vararg classes: String) = Tag(name, *matchers, expectedClasses = classes.toList()) + private fun Any.accepts(n: Node, ignoreSpan:Boolean = true) { when (this) { is String -> assert(n is TextNode && n.text().trim() == this.trim()) { "\"$this\" expected but found: $n" } is Tag -> { - assert(n is Element && n.tagName() == name) { "Tag $name expected but found: $n" } - if (n is Element && matchers.isNotEmpty()) n.match(*matchers, ignoreSpanWithTokenStyle = ignoreSpan) + check(n is Element) { "Expected node to be Element: $n" } + assert(n.tagName() == name) { "Tag \"$name\" expected but found: \"$n\"" } + expectedClasses.forEach { + assert(n.hasClass(it)) { "Expected to find class \"$it\" for tag \"$name\", found: ${n.classNames()}" } + } + if (matchers.isNotEmpty()) n.match(*matchers, ignoreSpanWithTokenStyle = ignoreSpan) } else -> throw IllegalArgumentException("$this is not proper matcher") } } + private fun List<Node>.uniteConsecutiveTextNodes(): MutableList<Node> { val resList = mutableListOf<Node>() var acc = StringBuilder() diff --git a/plugins/base/base-test-utils/src/main/kotlin/renderers/SignatureUtils.kt b/plugins/base/base-test-utils/src/main/kotlin/renderers/SignatureUtils.kt index e77b8757..ddaefd8c 100644 --- a/plugins/base/base-test-utils/src/main/kotlin/renderers/SignatureUtils.kt +++ b/plugins/base/base-test-utils/src/main/kotlin/renderers/SignatureUtils.kt @@ -2,6 +2,7 @@ package signatures import org.jsoup.Jsoup import org.jsoup.nodes.Element +import utils.Tag import utils.TestOutputWriter fun TestOutputWriter.renderedContent(path: String = "root/example.html") = @@ -9,4 +10,7 @@ fun TestOutputWriter.renderedContent(path: String = "root/example.html") = .single() fun Element.signature() = select("div.symbol.monospace") -fun Element.firstSignature() = signature().first()
\ No newline at end of file +fun Element.firstSignature() = signature().first() + +class Parameters(vararg matchers: Any) : Tag("span", *matchers, expectedClasses = listOf("parameters")) +class Parameter(vararg matchers: Any) : Tag("span", *matchers, expectedClasses = listOf("parameter"))
\ No newline at end of file diff --git a/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt b/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt index 8d258461..2906e8f2 100644 --- a/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt +++ b/plugins/base/src/main/kotlin/renderers/html/HtmlRenderer.kt @@ -98,6 +98,21 @@ open class HtmlRenderer( } 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") { + if (node.hasStyle(ContentStyle.Indented)) { + // could've been done with CSS (padding-left, ::before, etc), but the indent needs to + // consist of physical spaces, otherwise select and copy won't work properly + repeat(4) { consumer.onTagContentEntity(Entities.nbsp) } + } + childrenCallback() + } + } node.dci.kind == ContentKind.BriefComment -> div("brief $additionalClasses") { childrenCallback() } node.dci.kind == ContentKind.Cover -> div("cover $additionalClasses") { //TODO this can be removed childrenCallback() diff --git a/plugins/base/src/main/kotlin/signatures/JvmSignatureUtils.kt b/plugins/base/src/main/kotlin/signatures/JvmSignatureUtils.kt index 94af96e2..b6841323 100644 --- a/plugins/base/src/main/kotlin/signatures/JvmSignatureUtils.kt +++ b/plugins/base/src/main/kotlin/signatures/JvmSignatureUtils.kt @@ -174,6 +174,57 @@ interface JvmSignatureUtils { parameters.flatMap { listOf(it.dri) + it.type.drisOfAllNestedBounds }) return t.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] + */ + fun PageContentBuilder.DocumentableContentBuilder.parametersBlock( + function: DFunction, paramBuilder: PageContentBuilder.DocumentableContentBuilder.(DParameter) -> Unit + ) { + val shouldWrap = function.shouldWrapParams() + val parametersStyle = if (shouldWrap) setOf(ContentStyle.Wrapped) else emptySet() + val elementStyle = if (shouldWrap) setOf(ContentStyle.Indented) else emptySet() + group(kind = SymbolContentKind.Parameters, styles = parametersStyle) { + function.parameters.dropLast(1).forEach { + group(kind = SymbolContentKind.Parameter, styles = elementStyle) { + paramBuilder(it) + punctuation(", ") + } + } + group(kind = SymbolContentKind.Parameter, styles = elementStyle) { + paramBuilder(function.parameters.last()) + } + } + } + + /** + * Determines whether parameters in a function (including constructor) should be wrapped + * + * Without wrapping: + * ``` + * class SimpleClass(foo: String, bar: String) {} + * ``` + * With wrapping: + * ``` + * class SimpleClass( + * foo: String, + * bar: String, + * baz: String + * ) + * ``` + */ + private fun DFunction.shouldWrapParams() = this.parameters.size >= 3 } sealed class AtStrategy diff --git a/plugins/base/src/main/kotlin/signatures/KotlinSignatureProvider.kt b/plugins/base/src/main/kotlin/signatures/KotlinSignatureProvider.kt index 47e16e69..3f8c1703 100644 --- a/plugins/base/src/main/kotlin/signatures/KotlinSignatureProvider.kt +++ b/plugins/base/src/main/kotlin/signatures/KotlinSignatureProvider.kt @@ -7,15 +7,13 @@ 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.base.translators.documentables.PageContentBuilder.DocumentableContentBuilder 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.ContentKind -import org.jetbrains.dokka.pages.ContentNode -import org.jetbrains.dokka.pages.TextStyle -import org.jetbrains.dokka.pages.TokenStyle +import org.jetbrains.dokka.pages.* import org.jetbrains.dokka.plugability.DokkaContext import org.jetbrains.dokka.plugability.plugin import org.jetbrains.dokka.plugability.querySingle @@ -179,19 +177,19 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog annotationsInline(pConstructor) keyword("constructor") } - list( - elements = pConstructor.parameters, - prefix = "(", - suffix = ")", - separator = ", ", - separatorStyles = mainStyles + TokenStyle.Punctuation, - surroundingCharactersStyle = mainStyles + TokenStyle.Punctuation, - sourceSets = pConstructor.sourceSets.toSet() - ) { - annotationsInline(it) - text(it.name.orEmpty()) - operator(": ") - signatureForProjection(it.type) + + // 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()) { + punctuation("(") + parametersBlock(pConstructor) { param -> + annotationsInline(param) + text(param.name.orEmpty()) + operator(": ") + signatureForProjection(param.type) + } + punctuation(")") } } } @@ -283,17 +281,21 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog punctuation(".") } link(f.name, f.dri, styles = mainStyles + TokenStyle.Function) + + // for a function, opening and closing parentheses must be present + // anyway, even if it has no parameters, resulting in `fun test(): R` punctuation("(") - list(f.parameters, - separatorStyles = mainStyles + TokenStyle.Punctuation) { - annotationsInline(it) - processExtraModifiers(it) - text(it.name!!) - operator(": ") - signatureForProjection(it.type) - it.extra[DefaultValue]?.run { - operator(" = ") - highlightValue(value) + if (f.parameters.isNotEmpty()) { + parametersBlock(f) { param -> + annotationsInline(param) + processExtraModifiers(param) + text(param.name!!) + operator(": ") + signatureForProjection(param.type) + param.extra[DefaultValue]?.run { + operator(" = ") + highlightValue(value) + } } } punctuation(")") diff --git a/plugins/base/src/main/resources/dokka/styles/style.css b/plugins/base/src/main/resources/dokka/styles/style.css index ad28e895..cc8b6823 100644 --- a/plugins/base/src/main/resources/dokka/styles/style.css +++ b/plugins/base/src/main/resources/dokka/styles/style.css @@ -886,6 +886,10 @@ td.content { padding-bottom: 0; } +.parameters.wrapped > .parameter { + display: block; +} + .table-row .with-platform-tabs .sourceset-depenent-content .brief { padding: 8px; } diff --git a/plugins/base/src/test/kotlin/content/signatures/SkippingParenthesisForConstructorsTest.kt b/plugins/base/src/test/kotlin/content/signatures/SkippingParenthesisForConstructorsTest.kt index 12160db8..508a0a36 100644 --- a/plugins/base/src/test/kotlin/content/signatures/SkippingParenthesisForConstructorsTest.kt +++ b/plugins/base/src/test/kotlin/content/signatures/SkippingParenthesisForConstructorsTest.kt @@ -98,8 +98,13 @@ class ConstructorsSignaturesTest : BaseAbstractTest() { group { +"class " link { +"SomeClass" } - +"(a: " - group { link { +"String" } } + +"(" + group { + group { + +"a: " + group { link { +"String" } } + } + } +")" } } @@ -131,8 +136,13 @@ class ConstructorsSignaturesTest : BaseAbstractTest() { group { +"class " link { +"SomeClass" } - +"(a: " // TODO: Make sure if we still do not want to have "val" here - group { link { +"String" } } + +"(" + group { + group { + +"a: " // TODO: Make sure if we still do not want to have "val" here + group { link { +"String" } } + } + } +")" } } @@ -165,8 +175,13 @@ class ConstructorsSignaturesTest : BaseAbstractTest() { group { +"class " link { +"SomeClass" } - +"(a: " - group { link { +"String" } } + +"(" + group { + group { + +"a: " + group { link { +"String" } } + } + } +")" } } @@ -227,8 +242,13 @@ class ConstructorsSignaturesTest : BaseAbstractTest() { group { +"class " link { +"SomeClass" } - +"(a: " - group { link { +"String" } } + +"(" + group { + group { + +"a: " + group { link { +"String" } } + } + } +")" } skipAllNotMatching() @@ -243,9 +263,14 @@ class ConstructorsSignaturesTest : BaseAbstractTest() { group { +"fun " link { +"SomeClass" } - +"(a: " + +"(" group { - link { +"String" } + group { + +"a: " + group { + link { +"String" } + } + } } +")" } diff --git a/plugins/base/src/test/kotlin/signatures/SignatureTest.kt b/plugins/base/src/test/kotlin/signatures/SignatureTest.kt index 9ca6a5db..7ab0f663 100644 --- a/plugins/base/src/test/kotlin/signatures/SignatureTest.kt +++ b/plugins/base/src/test/kotlin/signatures/SignatureTest.kt @@ -4,6 +4,7 @@ import org.jetbrains.dokka.DokkaSourceSetID import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest import org.junit.jupiter.api.Test import utils.* +import kotlin.test.assertFalse class SignatureTest : BaseAbstractTest() { private val configuration = dokkaConfiguration { @@ -93,10 +94,12 @@ class SignatureTest : BaseAbstractTest() { ) { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/simple-fun.html").firstSignature().match( - "fun ", A("simpleFun"), "(a: ", A("Int"), - ", b: ", A("Boolean"), ", c: ", A("Any"), - "): ", A("String"), Span(), - ignoreSpanWithTokenStyle = true + "fun ", A("simpleFun"), "(", Parameters( + Parameter("a: ", A("Int"), ","), + Parameter("b: ", A("Boolean"), ","), + Parameter("c: ", A("Any")), + ), "): ", A("String"), Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -114,9 +117,10 @@ class SignatureTest : BaseAbstractTest() { ) { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/simple-fun.html").firstSignature().match( - "fun ", A("simpleFun"), "(a: (", A("Int"), - ") -> ", A("String"), "): ", A("String"), Span(), - ignoreSpanWithTokenStyle = true + "fun ", A("simpleFun"), "(", Parameters( + Parameter("a: (", A("Int"), ") -> ", A("String")), + ),"): ", A("String"), Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -174,9 +178,11 @@ class SignatureTest : BaseAbstractTest() { ) { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/simple-fun.html").firstSignature().match( - "inline suspend fun <", A("T"), " : ", A("String"), "> ", A("simpleFun"), - "(a: ", A("Int"), ", b: ", A("String"), "): ", A("T"), Span(), - ignoreSpanWithTokenStyle = true + "inline suspend fun <", A("T"), " : ", A("String"), "> ", A("simpleFun"), "(", Parameters( + Parameter("a: ", A("Int"), ","), + Parameter("b: ", A("String")), + ), "): ", A("T"), Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -194,8 +200,10 @@ class SignatureTest : BaseAbstractTest() { ) { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/simple-fun.html").firstSignature().match( - "fun ", A("simpleFun"), "(vararg params: ", A("Int"), ")", Span(), - ignoreSpanWithTokenStyle = true + "fun ", A("simpleFun"), "(", Parameters( + Parameter("vararg params: ", A("Int")), + ), ")", Span(), + ignoreSpanWithTokenStyle = true ) } } @@ -655,9 +663,11 @@ class SignatureTest : BaseAbstractTest() { pluginOverrides = listOf(writerPlugin) ) { renderingStage = { _, _ -> - writerPlugin.writer.renderedContent("root/kotlinAsJavaPlugin/-a-b-c/some-fun.html").signature().first().match( - "fun ", A("someFun"), "(xd: ", A("XD"), "<", A("Int"), - ", ", A("String"), ">):", A("Int"), Span(), + writerPlugin.writer.renderedContent("root/kotlinAsJavaPlugin/-a-b-c/some-fun.html").signature().first() + .match( + "fun ", A("someFun"), "(", Parameters( + Parameter("xd: ", A("XD"), "<", A("Int"), ", ", A("String"), ">"), + ), "):", A("Int"), Span(), ignoreSpanWithTokenStyle = true ) } @@ -666,8 +676,6 @@ class SignatureTest : BaseAbstractTest() { @Test fun `generic constructor params`() { - - val writerPlugin = TestOutputWriterPlugin() testInline( @@ -694,13 +702,40 @@ class SignatureTest : BaseAbstractTest() { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/-generic-class/-generic-class.html").signature().zip( listOf( - arrayOf("fun <", A("T"), "> ", A("GenericClass"), "(x: ", A("T"), ")", Span()), - arrayOf("fun ", A("GenericClass"), "(x: ", A("Int"), ", y: ", A("String"), ")", Span()), - arrayOf("fun <", A("T"), "> ", A("GenericClass"), "(x: ", A("Int"), ", y: ", A("List"), "<", A("T"), ">)", Span()), - arrayOf("fun ", A("GenericClass"), "(x: ", A("Boolean"), ", y: ", A("Int"), ", z:", A("String"), ")", Span()), - arrayOf("fun <", A("T"), "> ", A("GenericClass"), "(x: ", A("List"), "<", A("Comparable"), - "<", A("Lazy"), "<", A("T"), ">>>?)", Span()), - arrayOf("fun ", A("GenericClass"), "(x: ", A("Int"), ")", Span()), + arrayOf( + "fun <", A("T"), "> ", A("GenericClass"), "(", Parameters( + Parameter("x: ", A("T")) + ), ")", Span() + ), + arrayOf( + "fun ", A("GenericClass"), "(", Parameters( + Parameter("x: ", A("Int"), ", "), + Parameter("y: ", A("String")) + ), ")", Span() + ), + arrayOf( + "fun <", A("T"), "> ", A("GenericClass"), "(", Parameters( + Parameter("x: ", A("Int"), ", "), + Parameter("y: ", A("List"), "<", A("T"), ">") + ), ")", Span() + ), + arrayOf( + "fun ", A("GenericClass"), "(", Parameters( + Parameter("x: ", A("Boolean"), ", "), + Parameter("y: ", A("Int"), ", "), + Parameter("z:", A("String")) + ), ")", Span() + ), + arrayOf( + "fun <", A("T"), "> ", A("GenericClass"), "(", Parameters( + Parameter("x: ", A("List"), "<", A("Comparable"), "<", A("Lazy"), "<", A("T"), ">>>?") + ), ")", Span() + ), + arrayOf( + "fun ", A("GenericClass"), "(", Parameters( + Parameter("x: ", A("Int")) + ), ")", Span() + ), ) ).forEach { it.first.match(*it.second, ignoreSpanWithTokenStyle = true) @@ -721,8 +756,10 @@ class SignatureTest : BaseAbstractTest() { ) { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/example/simple-fun.html").firstSignature().match( - "fun", A("simpleFun"), "(int: ", A("Int"), " = 1, string: ", A("String"), - " = \"string\"): ", A("String"), Span(), + "fun", A("simpleFun"), "(", Parameters( + Parameter("int: ", A("Int"), " = 1,"), + Parameter("string: ", A("String"), " = \"string\"") + ), "): ", A("String"), Span(), ignoreSpanWithTokenStyle = true ) } @@ -730,6 +767,53 @@ class SignatureTest : BaseAbstractTest() { } @Test + fun `fun with single param should NOT have any wrapped or indented parameters`() { + val source = source("fun assertNoIndent(int: Int): String = \"\"") + val writerPlugin = TestOutputWriterPlugin() + + testInline( + source, + configuration, + pluginOverrides = listOf(writerPlugin) + ) { + renderingStage = { _, _ -> + val signature = writerPlugin.writer.renderedContent("root/example/assert-no-indent.html").firstSignature() + signature.match( + "fun", A("assertNoIndent"), "(", Parameters( + Parameter("int: ", A("Int")), + ), "): ", A("String"), Span(), + ignoreSpanWithTokenStyle = true + ) + assertFalse { signature.select("span.parameters").single().hasClass("wrapped") } + assertFalse { signature.select("span.parameters > span.parameter").single().hasClass("indented") } + } + } + } + + @Test + fun `fun with many params should have wrapped and indented parameters`() { + val source = source("fun assertParamsIndent(int: Int, string: String, long: Long): String = \"\"") + val writerPlugin = TestOutputWriterPlugin() + + testInline( + source, + configuration, + pluginOverrides = listOf(writerPlugin) + ) { + renderingStage = { _, _ -> + writerPlugin.writer.renderedContent("root/example/assert-params-indent.html").firstSignature().match( + "fun", A("assertParamsIndent"), "(", Parameters( + Parameter("int: ", A("Int"), ",").withClasses("indented"), + Parameter("string: ", A("String"), ",").withClasses("indented"), + Parameter("long: ", A("Long")).withClasses("indented") + ).withClasses("wrapped"), "): ", A("String"), Span(), + ignoreSpanWithTokenStyle = true + ) + } + } + } + + @Test fun `const val with default values`() { val source = source("const val simpleVal = 1") val writerPlugin = TestOutputWriterPlugin() diff --git a/plugins/base/src/test/kotlin/utils/contentUtils.kt b/plugins/base/src/test/kotlin/utils/contentUtils.kt index be796c89..66e5ef53 100644 --- a/plugins/base/src/test/kotlin/utils/contentUtils.kt +++ b/plugins/base/src/test/kotlin/utils/contentUtils.kt @@ -38,19 +38,24 @@ fun ContentMatcherBuilder<*>.bareSignature( +("${keywords.joinToString("") { "$it " }}fun ") link { +name } +"(" - params.forEachIndexed { id, (n, t) -> + if (params.isNotEmpty()) { + group { + params.forEachIndexed { id, (n, t) -> + group { + t.annotations.forEach { + unwrapAnnotation(it) + } + t.keywords.forEach { + +it + } - t.annotations.forEach { - unwrapAnnotation(it) - } - t.keywords.forEach { - +it + +"$n: " + group { link { +(t.type) } } + if (id != params.lastIndex) + +", " + } + } } - - +"$n: " - group { link { +(t.type) } } - if (id != params.lastIndex) - +", " } +")" if (returnType != null) { @@ -101,19 +106,24 @@ fun ContentMatcherBuilder<*>.bareSignatureWithReceiver( +"." link { +name } +"(" - params.forEachIndexed { id, (n, t) -> + if (params.isNotEmpty()) { + group { + params.forEachIndexed { id, (n, t) -> + group { + t.annotations.forEach { + unwrapAnnotation(it) + } + t.keywords.forEach { + +it + } - t.annotations.forEach { - unwrapAnnotation(it) - } - t.keywords.forEach { - +it + +"$n: " + group { link { +(t.type) } } + if (id != params.lastIndex) + +", " + } + } } - - +"$n: " - group { link { +(t.type) } } - if (id != params.lastIndex) - +", " } +")" if (returnType != null) { diff --git a/plugins/javadoc/api/javadoc.api b/plugins/javadoc/api/javadoc.api index e2f3750d..bfea687a 100644 --- a/plugins/javadoc/api/javadoc.api +++ b/plugins/javadoc/api/javadoc.api @@ -644,6 +644,7 @@ public final class org/jetbrains/dokka/javadoc/signatures/JavadocSignatureProvid public fun annotationsInline (Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Lorg/jetbrains/dokka/model/AnnotationTarget;)V public fun annotationsInlineWithIgnored (Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Lorg/jetbrains/dokka/model/AnnotationTarget;Ljava/util/Set;Lorg/jetbrains/dokka/base/signatures/AtStrategy;Lkotlin/Pair;Ljava/lang/String;)V public fun modifiers (Lorg/jetbrains/dokka/model/properties/WithExtraProperties;)Ljava/util/Map; + public fun parametersBlock (Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Lorg/jetbrains/dokka/model/DFunction;Lkotlin/jvm/functions/Function2;)V public fun plus (Ljava/util/Map;Ljava/util/Map;)Ljava/util/Map; public fun signature (Lorg/jetbrains/dokka/model/Documentable;)Ljava/util/List; public fun stylesIfDeprecated (Lorg/jetbrains/dokka/model/properties/WithExtraProperties;Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;)Ljava/util/Set; diff --git a/plugins/kotlin-as-java/api/kotlin-as-java.api b/plugins/kotlin-as-java/api/kotlin-as-java.api index 4dd8b33a..f941582e 100644 --- a/plugins/kotlin-as-java/api/kotlin-as-java.api +++ b/plugins/kotlin-as-java/api/kotlin-as-java.api @@ -19,6 +19,7 @@ public final class org/jetbrains/dokka/kotlinAsJava/signatures/JavaSignatureProv public fun annotationsInline (Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Lorg/jetbrains/dokka/model/AnnotationTarget;)V public fun annotationsInlineWithIgnored (Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Lorg/jetbrains/dokka/model/AnnotationTarget;Ljava/util/Set;Lorg/jetbrains/dokka/base/signatures/AtStrategy;Lkotlin/Pair;Ljava/lang/String;)V public fun modifiers (Lorg/jetbrains/dokka/model/properties/WithExtraProperties;)Ljava/util/Map; + public fun parametersBlock (Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Lorg/jetbrains/dokka/model/DFunction;Lkotlin/jvm/functions/Function2;)V public fun plus (Ljava/util/Map;Ljava/util/Map;)Ljava/util/Map; public fun signature (Lorg/jetbrains/dokka/model/Documentable;)Ljava/util/List; public fun stylesIfDeprecated (Lorg/jetbrains/dokka/model/properties/WithExtraProperties;Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;)Ljava/util/Set; @@ -36,6 +37,7 @@ public final class org/jetbrains/dokka/kotlinAsJava/signatures/JavaSignatureUtil public fun annotationsInline (Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Lorg/jetbrains/dokka/model/AnnotationTarget;)V public fun annotationsInlineWithIgnored (Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Lorg/jetbrains/dokka/model/AnnotationTarget;Ljava/util/Set;Lorg/jetbrains/dokka/base/signatures/AtStrategy;Lkotlin/Pair;Ljava/lang/String;)V public fun modifiers (Lorg/jetbrains/dokka/model/properties/WithExtraProperties;)Ljava/util/Map; + public fun parametersBlock (Lorg/jetbrains/dokka/base/translators/documentables/PageContentBuilder$DocumentableContentBuilder;Lorg/jetbrains/dokka/model/DFunction;Lkotlin/jvm/functions/Function2;)V public fun plus (Ljava/util/Map;Ljava/util/Map;)Ljava/util/Map; public fun stylesIfDeprecated (Lorg/jetbrains/dokka/model/properties/WithExtraProperties;Lorg/jetbrains/dokka/DokkaConfiguration$DokkaSourceSet;)Ljava/util/Set; public fun toSignatureString (Ljava/util/Collection;)Ljava/lang/String; diff --git a/plugins/kotlin-as-java/src/main/kotlin/signatures/JavaSignatureProvider.kt b/plugins/kotlin-as-java/src/main/kotlin/signatures/JavaSignatureProvider.kt index 65b34017..fa1f668f 100644 --- a/plugins/kotlin-as-java/src/main/kotlin/signatures/JavaSignatureProvider.kt +++ b/plugins/kotlin-as-java/src/main/kotlin/signatures/JavaSignatureProvider.kt @@ -8,10 +8,7 @@ import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder import org.jetbrains.dokka.links.DRI import org.jetbrains.dokka.model.* import org.jetbrains.dokka.model.properties.WithExtraProperties -import org.jetbrains.dokka.pages.ContentKind -import org.jetbrains.dokka.pages.ContentNode -import org.jetbrains.dokka.pages.TextStyle -import org.jetbrains.dokka.pages.TokenStyle +import org.jetbrains.dokka.pages.* import org.jetbrains.dokka.plugability.DokkaContext import org.jetbrains.dokka.plugability.plugin import org.jetbrains.dokka.plugability.querySingle @@ -143,12 +140,14 @@ class JavaSignatureProvider internal constructor(ctcc: CommentsToContentConverte +buildSignature(it) } punctuation("(") - list(f.parameters, separatorStyles = mainStyles + TokenStyle.Punctuation) { - annotationsInline(it) - text(it.modifiers()[sourceSet]?.toSignatureString() ?: "", styles = mainStyles + TokenStyle.Keyword) - signatureForProjection(it.type) - text(nbsp.toString()) - text(it.name!!) + if (f.parameters.isNotEmpty()) { + parametersBlock(f) { + annotationsInline(it) + text(it.modifiers()[sourceSet]?.toSignatureString() ?: "", styles = mainStyles + TokenStyle.Keyword) + signatureForProjection(it.type) + text(nbsp.toString()) + text(it.name!!) + } } punctuation(")") } diff --git a/plugins/kotlin-as-java/src/test/kotlin/KotlinAsJavaPluginTest.kt b/plugins/kotlin-as-java/src/test/kotlin/KotlinAsJavaPluginTest.kt index 5fcb22aa..b9627f9b 100644 --- a/plugins/kotlin-as-java/src/test/kotlin/KotlinAsJavaPluginTest.kt +++ b/plugins/kotlin-as-java/src/test/kotlin/KotlinAsJavaPluginTest.kt @@ -1,20 +1,19 @@ package kotlinAsJavaPlugin -import org.jetbrains.dokka.model.dfs -import org.jetbrains.dokka.pages.* -import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest -import org.jetbrains.kotlin.utils.addToStdlib.cast -import org.junit.jupiter.api.Test import matchers.content.* import org.jetbrains.dokka.DokkaConfiguration +import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest import org.jetbrains.dokka.jdk +import org.jetbrains.dokka.model.dfs +import org.jetbrains.dokka.pages.* +import org.jetbrains.kotlin.utils.addToStdlib.cast import org.junit.Assert +import org.junit.jupiter.api.Test +import signatures.Parameter +import signatures.Parameters import signatures.renderedContent import signatures.signature -import utils.A -import utils.Span -import utils.TestOutputWriterPlugin -import utils.match +import utils.* import kotlin.test.assertEquals class KotlinAsJavaPluginTest : BaseAbstractTest() { @@ -331,7 +330,9 @@ class KotlinAsJavaPluginTest : BaseAbstractTest() { ) { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/kotlinAsJavaPlugin/-a-b-c/some-fun.html").signature().first().match( - "final ", A("Integer"), A("someFun"), "(", A("Integer"), "xd)", Span(), ignoreSpanWithTokenStyle = true + "final ", A("Integer"), A("someFun"), "(", Parameters( + Parameter(A("Integer"), "xd") + ), ")", Span(), ignoreSpanWithTokenStyle = true ) } } @@ -368,8 +369,9 @@ class KotlinAsJavaPluginTest : BaseAbstractTest() { ) { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/kotlinAsJavaPlugin/-a-b-c/some-fun.html").signature().first().match( - "final ", A("Integer"), A("someFun"), "(", A("Map"), "<", A("String"), - ", ", A("Integer"), "> xd)", Span(), ignoreSpanWithTokenStyle = true + "final ", A("Integer"), A("someFun"), "(", Parameters( + Parameter(A("Map"), "<", A("String"), ", ", A("Integer"), "> xd"), + ), ")", Span(), ignoreSpanWithTokenStyle = true ) } } @@ -433,7 +435,9 @@ class KotlinAsJavaPluginTest : BaseAbstractTest() { ) { renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/kotlinAsJavaPlugin/-test-kt/sample.html").signature().first().match( - "final static ", A("String"), A("sample"), "(", A("Integer"), "a)", Span(), ignoreSpanWithTokenStyle = true + "final static ", A("String"), A("sample"), "(", Parameters( + Parameter(A("Integer"), "a"), + ), ")", Span(), ignoreSpanWithTokenStyle = true ) } } @@ -476,7 +480,56 @@ class KotlinAsJavaPluginTest : BaseAbstractTest() { } renderingStage = { _, _ -> writerPlugin.writer.renderedContent("root/kotlinAsJavaPlugin/-test/-test.html").signature().first().match( - A("Test"), A("Test"), "(", A("Integer"), "xd)", Span(), ignoreSpanWithTokenStyle = true + A("Test"), A("Test"), "(", Parameters( + Parameter(A("Integer"), "xd") + ), ")", Span(), ignoreSpanWithTokenStyle = true + ) + } + } + } + + @Test + fun `should add wrapping and indent to parameters if too many`() { + val writerPlugin = TestOutputWriterPlugin() + val configuration = dokkaConfiguration { + sourceSets { + sourceSet { + sourceRoots = listOf("src/") + externalDocumentationLinks = listOf( + DokkaConfiguration.ExternalDocumentationLink.jdk(8), + stdlibExternalDocumentationLink + ) + } + } + } + testInline( + """ + |/src/main/kotlin/kotlinAsJavaPlugin/Wrapped.kt + |package kotlinAsJavaPlugin + | + |class Wrapped(val xd: Int, val l: Long, val s: String) + """.trimMargin(), + configuration, + pluginOverrides = listOf(writerPlugin), + cleanupOutput = true + ) { + pagesGenerationStage = { root -> + val content = root.children + .flatMap { it.children<ContentPage>() } + .map { it.content }.single().mainContents + + val text = content.single { it is ContentHeader }.children + .single() as ContentText + + assertEquals("Constructors", text.text) + } + renderingStage = { _, _ -> + writerPlugin.writer.renderedContent("root/kotlinAsJavaPlugin/-wrapped/-wrapped.html").signature().first().match( + A("Wrapped"), A("Wrapped"), "(", Parameters( + Parameter(A("Integer"), "xd,").withClasses("indented"), + Parameter(A("Long"), "l,").withClasses("indented"), + Parameter(A("String"), "s").withClasses("indented"), + ).withClasses("wrapped"), ")", Span(), ignoreSpanWithTokenStyle = true ) } } |