Skip to content

Commit e464c18

Browse files
committed
Scaladoc: add support for named tuples
1 parent c61897d commit e464c18

File tree

3 files changed

+61
-29
lines changed

3 files changed

+61
-29
lines changed

Diff for: scaladoc-testcases/src/tests/namedTuples.scala

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package tests.namedTuples
2+
3+
import language.experimental.namedTuples
4+
import NamedTuple.*
5+
6+
type Person = (name: String, age: Int)
7+
8+
type Person2 = NamedTuple[("age2", "name2"), (Int, String)] //expected: type Person2 = (age2: Int, name2: String)
9+
10+
val x = (name = "Bob", age = 25) //expected: val x: (name: String, age: Int)
11+
12+
def foo(p1: (age: Int, name: String), p2: (name: String, age: Int)): Nothing
13+
= ???
14+
15+
def invalid1: NamedTuple[("age", String), (Int, Int)]
16+
= ???
17+
18+
def invalid2: NamedTuple[("age", "name"), (Int, Int, Int)]
19+
= ???
20+
21+
def invalid3: NamedTuple[("age", "name", "something"), (Int, Int)]
22+
= ???
23+

Diff for: scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala

+36-29
Original file line numberDiff line numberDiff line change
@@ -204,36 +204,43 @@ trait TypesSupport:
204204
prefix ++ plain("{ ").l ++ refinedElems.flatMap(e => parseRefinedElem(e.name, e.info)) ++ plain(" }").l
205205
}
206206
}
207+
208+
case AppliedType(tpe, args) if defn.isTupleClass(tpe.typeSymbol) && args.length > 1 =>
209+
inParens(commas(args.map(inner(_))))
210+
211+
case AppliedType(namedTuple, List(AppliedType(tuple1, names), AppliedType(tuple2, types)))
212+
if namedTuple.typeSymbol == Symbol.requiredModule("scala.NamedTuple").typeMember("NamedTuple")
213+
&& defn.isTupleClass(tuple1.typeSymbol) && defn.isTupleClass(tuple2.typeSymbol) && names.length == types.length
214+
&& names.forall { case ConstantType(StringConstant(_)) => true case _ => false } =>
215+
val elems = names
216+
.collect { case ConstantType(StringConstant(s)) => s }
217+
.zip(types)
218+
.map((name, tpe) => plain(name) +: plain(": ") +: inner(tpe))
219+
inParens(commas(elems))
220+
221+
case t @ AppliedType(tpe, List(lhs, rhs)) if isInfix(t) =>
222+
inParens(inner(lhs), shouldWrapInParens(lhs, t, true))
223+
++ plain(" ").l
224+
++ inner(tpe)
225+
++ plain(" ").l
226+
++ inParens(inner(rhs), shouldWrapInParens(rhs, t, false))
227+
228+
case t @ AppliedType(tpe, args) if t.isFunctionType =>
229+
val arrow = if t.isContextFunctionType then " ?=> " else " => "
230+
args match
231+
case Nil => Nil
232+
case List(rtpe) => plain("()").l ++ keyword(arrow).l ++ inner(rtpe)
233+
case List(arg, rtpe) =>
234+
val wrapInParens = stripAnnotated(arg) match
235+
case _: TermRef | _: TypeRef | _: ConstantType | _: ParamRef => false
236+
case at: AppliedType if !isInfix(at) && !at.isFunctionType && !at.isTupleN => false
237+
case _ => true
238+
inParens(inner(arg), wrapInParens) ++ keyword(arrow).l ++ inner(rtpe)
239+
case _ =>
240+
plain("(").l ++ commas(args.init.map(inner(_))) ++ plain(")").l ++ keyword(arrow).l ++ inner(args.last)
241+
207242
case t @ AppliedType(tpe, typeList) =>
208-
import dotty.tools.dotc.util.Chars._
209-
if defn.isTupleClass(tpe.typeSymbol) && typeList.length != 1 then
210-
typeList match
211-
case Nil => Nil
212-
case args => inParens(commas(args.map(inner(_))))
213-
else if isInfix(t) then
214-
val lhs = typeList.head
215-
val rhs = typeList.last
216-
inParens(inner(lhs), shouldWrapInParens(lhs, t, true))
217-
++ plain(" ").l
218-
++ inner(tpe)
219-
++ plain(" ").l
220-
++ inParens(inner(rhs), shouldWrapInParens(rhs, t, false))
221-
else if t.isFunctionType then
222-
val arrow = if t.isContextFunctionType then " ?=> " else " => "
223-
typeList match
224-
case Nil =>
225-
Nil
226-
case Seq(rtpe) =>
227-
plain("()").l ++ keyword(arrow).l ++ inner(rtpe)
228-
case Seq(arg, rtpe) =>
229-
val partOfSignature = stripAnnotated(arg) match
230-
case _: TermRef | _: TypeRef | _: ConstantType | _: ParamRef => inner(arg)
231-
case at: AppliedType if !isInfix(at) && !at.isFunctionType && !at.isTupleN => inner(arg)
232-
case _ => inParens(inner(arg))
233-
partOfSignature ++ keyword(arrow).l ++ inner(rtpe)
234-
case args =>
235-
plain("(").l ++ commas(args.init.map(inner(_))) ++ plain(")").l ++ keyword(arrow).l ++ inner(args.last)
236-
else inner(tpe) ++ plain("[").l ++ commas(typeList.map { t => t match
243+
inner(tpe) ++ plain("[").l ++ commas(typeList.map { t => t match
237244
case _: TypeBounds => keyword("_").l ++ inner(t)
238245
case _ => topLevelProcess(t)
239246
}) ++ plain("]").l

Diff for: scaladoc/test/dotty/tools/scaladoc/signatures/TranslatableSignaturesTestCases.scala

+2
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,5 @@ class ExtendsCall extends SignatureTest("extendsCall", SignatureTest.all)
124124
class RefinedFunctionTypes extends SignatureTest("refinedFunctionTypes", SignatureTest.all)
125125

126126
class RightAssocExtension extends SignatureTest("rightAssocExtension", SignatureTest.all)
127+
128+
class NamedTuples extends SignatureTest("namedTuples", SignatureTest.all)

0 commit comments

Comments
 (0)