Skip to content

Commit 678f76d

Browse files
committed
Fix function-arrowing rendering
1 parent edd968c commit 678f76d

File tree

1 file changed

+50
-32
lines changed

1 file changed

+50
-32
lines changed

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

Lines changed: 50 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,13 @@ trait TypesSupport:
3535

3636
private def keyword(str: String): SignaturePart = Keyword(str)
3737

38-
private def tpe(str: String, dri: DRI)(using inCC: Option[Unit]): SignaturePart =
38+
private def tpe(str: String, dri: DRI)(using inCC: Option[Any]): SignaturePart =
3939
if inCC.isDefined then
4040
dotty.tools.scaladoc.Plain(str)
4141
else
4242
dotty.tools.scaladoc.Type(str, Some(dri))
4343

44-
private def tpe(str: String)(using inCC: Option[Unit]): SignaturePart =
44+
private def tpe(str: String)(using inCC: Option[Any]): SignaturePart =
4545
if inCC.isDefined then
4646
dotty.tools.scaladoc.Plain(str)
4747
else
@@ -52,7 +52,7 @@ trait TypesSupport:
5252

5353
extension (on: SignaturePart) def l: List[SignaturePart] = List(on)
5454

55-
private def tpe(using Quotes)(symbol: reflect.Symbol)(using inCC: Option[Unit]): SSignature =
55+
private def tpe(using Quotes)(symbol: reflect.Symbol)(using inCC: Option[Any]): SSignature =
5656
import SymOps._
5757
val dri: Option[DRI] = Option(symbol).filterNot(_.isHiddenByVisibility).map(_.dri)
5858
if inCC.isDefined then
@@ -98,9 +98,8 @@ trait TypesSupport:
9898
elideThis: reflect.ClassDef,
9999
indent: Int = 0,
100100
skipTypeSuffix: Boolean = false,
101-
// inCC means in capture-checking context.
102-
// Somewhat hacky, because it should be a Boolean, but then it'd clash with skipTypeSuffix
103-
inCC: Option[Unit] = None,
101+
// inCC means in capture-checking context. If defined, it carries the current capture-set contents.
102+
inCC: Option[List[reflect.TypeRepr]] = None,
104103
): SSignature =
105104
import reflect._
106105
def noSupported(name: String): SSignature =
@@ -115,15 +114,8 @@ trait TypesSupport:
115114
inParens(inner(left), shouldWrapInParens(left, tp, true))
116115
++ keyword(" & ").l
117116
++ inParens(inner(right), shouldWrapInParens(right, tp, false))
118-
case CapturingType(base, refs) =>
119-
inner(base) ++ renderCapturing(refs)
120117
case ByNameType(CapturingType(tpe, refs)) =>
121-
refs match
122-
case Nil => keyword("-> ") :: inner(tpe)
123-
case List(ref) if ref.isCaptureRoot =>
124-
keyword("=> ") :: inner(tpe)
125-
case refs =>
126-
keyword("->") :: (renderCaptureSet(refs) ++ (plain(" ") :: inner(tpe)))
118+
renderCaptureArrow(refs) ++ (plain(" ") :: inner(tpe))
127119
case ByNameType(tpe) => keyword("=>!! ") :: inner(tpe) // FIXME: does it need change for CC?
128120
case ConstantType(constant) =>
129121
plain(constant.show).l
@@ -137,6 +129,10 @@ trait TypesSupport:
137129
inner(tpe) :+ plain("*")
138130
case AppliedType(repeatedClass, Seq(tpe)) if isRepeated(repeatedClass) =>
139131
inner(tpe) :+ plain("*")
132+
case CapturingType(base, refs) => base match
133+
case t @ AppliedType(base, args) if t.isFunctionType =>
134+
functionType(t, base, args)(using inCC = Some(refs))
135+
case _ => inner(base) ++ renderCapturing(refs)
140136
case AnnotatedType(tpe, _) =>
141137
inner(tpe)
142138
case tl @ TypeLambda(params, paramBounds, AppliedType(tpe, args))
@@ -250,19 +246,7 @@ trait TypesSupport:
250246
++ plain(" ").l
251247
++ inParens(inner(rhs), shouldWrapInParens(rhs, t, false))
252248

253-
case t @ AppliedType(tpe, args) if t.isFunctionType =>
254-
val arrow = if t.isContextFunctionType then " ?=> " else " => "
255-
args match
256-
case Nil => Nil
257-
case List(rtpe) => plain("()").l ++ keyword(arrow).l ++ inner(rtpe)
258-
case List(arg, rtpe) =>
259-
val wrapInParens = stripAnnotated(arg) match
260-
case _: TermRef | _: TypeRef | _: ConstantType | _: ParamRef => false
261-
case at: AppliedType if !isInfix(at) && !at.isFunctionType && !at.isTupleN => false
262-
case _ => true
263-
inParens(inner(arg), wrapInParens) ++ keyword(arrow).l ++ inner(rtpe)
264-
case _ =>
265-
plain("(").l ++ commas(args.init.map(inner(_))) ++ plain(")").l ++ keyword(arrow).l ++ inner(args.last)
249+
case t @ AppliedType(tpe, args) if t.isFunctionType => functionType(t, tpe, args)
266250

267251
case t @ AppliedType(tpe, typeList) =>
268252
inner(tpe) ++ plain("[").l ++ commas(typeList.map { t => t match
@@ -348,6 +332,27 @@ trait TypesSupport:
348332
s"${tpe.show(using Printer.TypeReprStructure)}"
349333
throw MatchError(msg)
350334

335+
private def functionType(using Quotes)(t: reflect.TypeRepr, tpe: reflect.TypeRepr, args: List[reflect.TypeRepr])(using
336+
elideThis: reflect.ClassDef,
337+
indent: Int,
338+
skipTypeSuffix: Boolean,
339+
inCC: Option[List[reflect.TypeRepr]],
340+
): SSignature =
341+
import reflect._
342+
val arrow = if t.isContextFunctionType then keyword(" ?=> ").l // FIXME: can we have contextual functions with capture sets?
343+
else plain(" ") :: (renderCaptureArrow(inCC) ++ plain(" ").l)
344+
args match
345+
case Nil => Nil
346+
case List(rtpe) => plain("()").l ++ arrow ++ inner(rtpe)
347+
case List(arg, rtpe) =>
348+
val wrapInParens = stripAnnotated(arg) match
349+
case _: TermRef | _: TypeRef | _: ConstantType | _: ParamRef => false
350+
case at: AppliedType if !isInfix(at) && !at.isFunctionType && !at.isTupleN => false
351+
case _ => true
352+
inParens(inner(arg), wrapInParens) ++ arrow ++ inner(rtpe)
353+
case _ =>
354+
plain("(").l ++ commas(args.init.map(inner(_))) ++ plain(")").l ++ arrow ++ inner(args.last)
355+
351356
private def typeBound(using Quotes)(t: reflect.TypeRepr, low: Boolean)(using elideThis: reflect.ClassDef) =
352357
import reflect._
353358
val ignore = if (low) t.typeSymbol == defn.NothingClass else t.typeSymbol == defn.AnyClass
@@ -359,7 +364,7 @@ trait TypesSupport:
359364
case _ => Nil
360365
}
361366

362-
private def typeBoundsTreeOfHigherKindedType(using Quotes)(low: reflect.TypeRepr, high: reflect.TypeRepr)(using elideThis: reflect.ClassDef, inCC: Option[Unit]) =
367+
private def typeBoundsTreeOfHigherKindedType(using Quotes)(low: reflect.TypeRepr, high: reflect.TypeRepr)(using elideThis: reflect.ClassDef, inCC: Option[List[reflect.TypeRepr]]) =
363368
import reflect._
364369
def regularTypeBounds(low: TypeRepr, high: TypeRepr) =
365370
if low == high then keyword(" = ").l ++ inner(low)(using elideThis)
@@ -450,14 +455,14 @@ trait TypesSupport:
450455
case AnnotatedType(tr, _) => stripAnnotated(tr)
451456
case other => other
452457

453-
private def renderCapability(using Quotes)(ref: reflect.TypeRepr)(using elideThis: reflect.ClassDef): List[SignaturePart] =
458+
private def renderCapability(using Quotes)(ref: reflect.TypeRepr)(using elideThis: reflect.ClassDef): SSignature =
454459
import reflect._
455460
ref match
456461
case ReachCapability(c) => renderCapability(c) :+ Keyword("*")
457462
case ThisType(_) => List(Keyword("this"))
458-
case t => inner(t)(using skipTypeSuffix = true, inCC = Some(()))
463+
case t => inner(t)(using skipTypeSuffix = true, inCC = Some(Nil))
459464

460-
private def renderCaptureSet(using Quotes)(refs: List[reflect.TypeRepr])(using elideThis: reflect.ClassDef): List[SignaturePart] =
465+
private def renderCaptureSet(using Quotes)(refs: List[reflect.TypeRepr])(using elideThis: reflect.ClassDef): SSignature =
461466
import dotty.tools.scaladoc.tasty.NameNormalizer._
462467
import reflect._
463468
refs match
@@ -469,6 +474,19 @@ trait TypesSupport:
469474
case other => other.reduce((r, e) => r ++ (List(Plain(", ")) ++ e))
470475
Plain("{") :: (res1 ++ List(Plain("}")))
471476

472-
private def renderCapturing(using Quotes)(refs: List[reflect.TypeRepr])(using elideThis: reflect.ClassDef): List[SignaturePart] =
477+
private def renderCapturing(using Quotes)(refs: List[reflect.TypeRepr])(using elideThis: reflect.ClassDef): SSignature =
473478
import reflect._
474479
Keyword("^") :: renderCaptureSet(refs)
480+
481+
private def renderCaptureArrow(using Quotes)(refs: List[reflect.TypeRepr])(using elideThis: reflect.ClassDef): SSignature =
482+
import reflect._
483+
refs match
484+
case Nil => List(Keyword("->"))
485+
case List(ref) if ref.isCaptureRoot => List(Keyword("=>"))
486+
case refs => Keyword("->") :: renderCaptureSet(refs)
487+
488+
private def renderCaptureArrow(using Quotes)(refs: Option[List[reflect.TypeRepr]])(using elideThis: reflect.ClassDef): SSignature =
489+
import reflect._
490+
refs match
491+
case None => List(Keyword("=>")) // FIXME: is this correct? or should it be `->` by default?
492+
case Some(refs) => renderCaptureArrow(refs)

0 commit comments

Comments
 (0)