Skip to content

Commit 73a7ac5

Browse files
katrinafyitgodzik
authored andcommitted
scaladoc: indicate optional parameters with = ... (scala#23676)
currently, there is no indication in the scaladoc when parameters may be optional. this leads to [long and overwhelming signatures][1] which is not at all user-friendly. users are forced to first intuit that this method *might* have some optional parameters, then manually find [the source code][2] to learn which parameters are optional. [1]: https://javadoc.io/static/com.lihaoyi/os-lib_3/0.11.5/os/proc.html#call-fffff910 [2]: https://github.com/com-lihaoyi/os-lib/blob/0.11.5/os/src/ProcessOps.scala#L192-L205 this PR suffixes `= ...` after the type signature of optional parameters. this makes it possible to tell that these parameters are optional and may be omitted. this applies to both method parameters and class parameters. the format is intentionally similar to the definition of such optional parameters in code: ```scala // new scaladoc display: def f(x: Int, s: String = ...): Nothing // code: def f(x: Int, s: String = "a"): Nothing ``` of course, the `...` term is different. i think this is a reasonable choice because (1) ellipsis commonly represents something present but omitted, and (2) it is not valid Scala, so there is no risk someone will think this is denoting a literal default value of `...`. a proper ellipsis character (rather than 3 periods) could also be considered, but i found that looked out of place amongst the monospace signature. about displaying the default value itself, this PR does not display the default value. this is because of anticipated difficulties around displaying an expression. this could be re-visited in future, but i think it should not hold up this PR. i believe that this PR alone is already a substantial improvement for the documentation of optional parameters. finally, here is a screenshot of the scaladoc from the new optionalParams.scala test case: <img width="663" height="646" alt="image" src="https://github.com/user-attachments/assets/870410ee-0535-484b-84c8-8b683464471e" /> this might be related to scala#13424
1 parent 282f393 commit 73a7ac5

File tree

5 files changed

+30
-4
lines changed

5 files changed

+30
-4
lines changed

scaladoc-testcases/src/tests/extendsCall.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ package extendsCall
33

44
class Impl() extends Base(Seq.empty, c = "-") //expected: class Impl() extends Base
55

6-
class Base(val a: Seq[String], val b: String = "", val c: String = "") //expected: class Base(val a: Seq[String], val b: String, val c: String)
6+
class Base(val a: Seq[String], val b: String = "", val c: String = "") //expected: class Base(val a: Seq[String], val b: String = ..., val c: String = ...)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package tests
2+
package optionalParams
3+
4+
class C(val a: Seq[String], val b: String = "", var c: String = "") //expected: class C(val a: Seq[String], val b: String = ..., var c: String = ...)
5+
{
6+
def m(x: Int, s: String = "a"): Nothing //expected: def m(x: Int, s: String = ...): Nothing
7+
= ???
8+
}
9+
10+
def f(x: Int, s: String = "a"): Nothing //expected: def f(x: Int, s: String = ...): Nothing
11+
= ???
12+
13+
extension (y: Int)
14+
def ext(x: Int = 0): Int //expected: def ext(x: Int = ...): Int
15+
= 0
16+
17+
def byname(s: => String = "a"): Int //expected: def byname(s: => String = ...): Int
18+
= 0
19+
20+
enum E(val x: Int = 0) //expected: enum E(val x: Int = ...)
21+
{
22+
case E1(y: Int = 10) extends E(y) //expected: final case class E1(y: Int = ...) extends E
23+
}

scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -443,12 +443,13 @@ trait ClassLikeSupport:
443443
val inlinePrefix = if argument.symbol.flags.is(Flags.Inline) then "inline " else ""
444444
val nameIfNotSynthetic = Option.when(!argument.symbol.flags.is(Flags.Synthetic))(argument.symbol.normalizedName)
445445
val name = argument.symbol.normalizedName
446+
val defaultValue = Option.when(argument.symbol.flags.is(Flags.HasDefault))(Plain(" = ..."))
446447
api.TermParameter(
447448
argument.symbol.getAnnotations(),
448449
inlinePrefix + prefix(argument.symbol),
449450
nameIfNotSynthetic,
450451
argument.symbol.dri,
451-
memberInfo.get(name).fold(argument.tpt.asSignature(classDef))(_.asSignature(classDef)),
452+
memberInfo.get(name).fold(argument.tpt.asSignature(classDef))(_.asSignature(classDef)) :++ defaultValue,
452453
isExtendedSymbol,
453454
isGrouped
454455
)

scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ trait TypesSupport:
233233
tpe(tp.typeSymbol)
234234
case _: TermRef | _: ParamRef =>
235235
val suffix = if tp.typeSymbol == Symbol.noSymbol then tpe(typeName).l else tpe(tp.typeSymbol)
236-
inner(qual)(using skipTypeSuffix = true) ++ plain(".").l ++ suffix
236+
inner(qual)(using indent = indent, skipTypeSuffix = true) ++ plain(".").l ++ suffix
237237
case ThisType(tr) =>
238238
findSupertype(elideThis, tr.typeSymbol) match
239239
case Some((sym, AppliedType(tr2, args))) =>
@@ -250,7 +250,7 @@ trait TypesSupport:
250250
val sig = inParens(inner(qual)(using indent = indent, skipTypeSuffix = true), wrapping)
251251
sig ++ plain(".").l ++ tpe(tp.typeSymbol)
252252
case _ =>
253-
val sig = inParens(inner(qual, skipThisTypePrefix), wrapping)
253+
val sig = inParens(inner(qual), wrapping)
254254
sig ++ keyword("#").l ++ tpe(tp.typeSymbol)
255255
}
256256

scaladoc/test/dotty/tools/scaladoc/signatures/TranslatableSignaturesTestCases.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,5 @@ class InfixTypes extends SignatureTest("infixTypes", SignatureTest.all)
124124
class ExtendsCall extends SignatureTest("extendsCall", SignatureTest.all)
125125

126126
class RightAssocExtension extends SignatureTest("rightAssocExtension", SignatureTest.all)
127+
128+
class OptionalParams extends SignatureTest("optionalParams", SignatureTest.all)

0 commit comments

Comments
 (0)