Skip to content

Commit 2533881

Browse files
committed
Fix function-arrowing rendering
1 parent 5e6b805 commit 2533881

File tree

1 file changed

+63
-35
lines changed

1 file changed

+63
-35
lines changed

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

Lines changed: 63 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,13 @@ trait TypesSupport:
4040

4141
private def keyword(str: String): SignaturePart = Keyword(str)
4242

43-
private def tpe(str: String, dri: DRI)(using inCC: Option[Unit]): SignaturePart =
43+
private def tpe(str: String, dri: DRI)(using inCC: Option[Any]): SignaturePart =
4444
if inCC.isDefined then
4545
dotty.tools.scaladoc.Plain(str)
4646
else
4747
dotty.tools.scaladoc.Type(str, Some(dri))
4848

49-
private def tpe(str: String)(using inCC: Option[Unit]): SignaturePart =
49+
private def tpe(str: String)(using inCC: Option[Any]): SignaturePart =
5050
if inCC.isDefined then
5151
dotty.tools.scaladoc.Plain(str)
5252
else
@@ -57,7 +57,7 @@ trait TypesSupport:
5757

5858
extension (on: SignaturePart) def l: List[SignaturePart] = List(on)
5959

60-
private def tpe(using Quotes)(symbol: reflect.Symbol)(using inCC: Option[Unit]): SSignature =
60+
private def tpe(using Quotes)(symbol: reflect.Symbol)(using inCC: Option[Any]): SSignature =
6161
import SymOps._
6262
val dri: Option[DRI] = Option(symbol).filterNot(_.isHiddenByVisibility).map(_.dri)
6363
if inCC.isDefined then
@@ -105,9 +105,8 @@ trait TypesSupport:
105105
originalOwner: reflect.Symbol,
106106
indent: Int = 0,
107107
skipTypeSuffix: Boolean = false,
108-
// inCC means in capture-checking context.
109-
// Somewhat hacky, because it should be a Boolean, but then it'd clash with skipTypeSuffix
110-
inCC: Option[Unit] = None,
108+
// inCC means in capture-checking context. If defined, it carries the current capture-set contents.
109+
inCC: Option[List[reflect.TypeRepr]] = None,
111110
): SSignature =
112111
import reflect._
113112
def noSupported(name: String): SSignature =
@@ -122,15 +121,8 @@ trait TypesSupport:
122121
inParens(inner(left, skipThisTypePrefix), shouldWrapInParens(left, tp, true))
123122
++ keyword(" & ").l
124123
++ inParens(inner(right, skipThisTypePrefix), shouldWrapInParens(right, tp, false))
125-
case CapturingType(base, refs) =>
126-
inner(base, skipThisTypePrefix) ++ renderCapturing(refs)
127124
case ByNameType(CapturingType(tpe, refs)) =>
128-
refs match
129-
case Nil => keyword("-> ") :: inner(tpe, skipThisTypePrefix)
130-
case List(ref) if ref.isCaptureRoot =>
131-
keyword("=> ") :: inner(tpe, skipThisTypePrefix)
132-
case refs =>
133-
keyword("->") :: (renderCaptureSet(refs) ++ (plain(" ") :: inner(tpe, skipThisTypePrefix)))
125+
renderCaptureArrow(refs, skipThisTypePrefix) ++ (plain(" ") :: inner(tpe, skipThisTypePrefix))
134126
case ByNameType(tpe) => keyword("=>!! ") :: inner(tpe, skipThisTypePrefix) // FIXME: does it need change for CC?
135127
case ConstantType(constant) =>
136128
plain(constant.show).l
@@ -142,6 +134,10 @@ trait TypesSupport:
142134
inner(tpe, skipThisTypePrefix) :+ plain("*")
143135
case AppliedType(repeatedClass, Seq(tpe)) if isRepeated(repeatedClass) =>
144136
inner(tpe, skipThisTypePrefix) :+ plain("*")
137+
case CapturingType(base, refs) => base match
138+
case t @ AppliedType(base, args) if t.isFunctionType =>
139+
functionType(t, base, args, skipThisTypePrefix)(using inCC = Some(refs))
140+
case _ => inner(base, skipThisTypePrefix) ++ renderCapturing(refs, skipThisTypePrefix)
145141
case AnnotatedType(tpe, _) =>
146142
inner(tpe, skipThisTypePrefix)
147143
case tl @ TypeLambda(params, paramBounds, AppliedType(tpe, args))
@@ -258,19 +254,7 @@ trait TypesSupport:
258254
++ plain(" ").l
259255
++ inParens(inner(rhs, skipThisTypePrefix), shouldWrapInParens(rhs, t, false))
260256

261-
case t @ AppliedType(tpe, args) if t.isFunctionType =>
262-
val arrow = if t.isContextFunctionType then " ?=> " else " => "
263-
args match
264-
case Nil => Nil
265-
case List(rtpe) => plain("()").l ++ keyword(arrow).l ++ inner(rtpe, skipThisTypePrefix)
266-
case List(arg, rtpe) =>
267-
val wrapInParens = stripAnnotated(arg) match
268-
case _: TermRef | _: TypeRef | _: ConstantType | _: ParamRef => false
269-
case at: AppliedType if !isInfix(at) && !at.isFunctionType && !at.isTupleN => false
270-
case _ => true
271-
inParens(inner(arg, skipThisTypePrefix), wrapInParens) ++ keyword(arrow).l ++ inner(rtpe, skipThisTypePrefix)
272-
case _ =>
273-
plain("(").l ++ commas(args.init.map(inner(_, skipThisTypePrefix))) ++ plain(")").l ++ keyword(arrow).l ++ inner(args.last, skipThisTypePrefix)
257+
case t @ AppliedType(tpe, args) if t.isFunctionType => functionType(t, tpe, args, skipThisTypePrefix)
274258

275259
case t @ AppliedType(tpe, typeList) =>
276260
inner(tpe, skipThisTypePrefix) ++ plain("[").l ++ commas(typeList.map { t => t match
@@ -358,6 +342,27 @@ trait TypesSupport:
358342
s"${tpe.show(using Printer.TypeReprStructure)}"
359343
throw MatchError(msg)
360344

345+
private def functionType(using Quotes)(t: reflect.TypeRepr, tpe: reflect.TypeRepr, args: List[reflect.TypeRepr], skipThisTypePrefix: Boolean)(using
346+
elideThis: reflect.ClassDef,
347+
indent: Int,
348+
originalOwner: reflect.Symbol,
349+
inCC: Option[List[reflect.TypeRepr]],
350+
): SSignature =
351+
import reflect._
352+
val arrow = if t.isContextFunctionType then keyword(" ?=> ").l // FIXME: can we have contextual functions with capture sets?
353+
else plain(" ") :: (renderCaptureArrow(inCC, skipThisTypePrefix) ++ plain(" ").l)
354+
args match
355+
case Nil => Nil
356+
case List(rtpe) => plain("()").l ++ arrow ++ inner(rtpe, skipThisTypePrefix)
357+
case List(arg, rtpe) =>
358+
val wrapInParens = stripAnnotated(arg) match
359+
case _: TermRef | _: TypeRef | _: ConstantType | _: ParamRef => false
360+
case at: AppliedType if !isInfix(at) && !at.isFunctionType && !at.isTupleN => false
361+
case _ => true
362+
inParens(inner(arg, skipThisTypePrefix), wrapInParens) ++ arrow ++ inner(rtpe, skipThisTypePrefix)
363+
case _ =>
364+
plain("(").l ++ commas(args.init.map(inner(_, skipThisTypePrefix))) ++ plain(")").l ++ arrow ++ inner(args.last, skipThisTypePrefix)
365+
361366
private def typeBound(using Quotes)(t: reflect.TypeRepr, low: Boolean, skipThisTypePrefix: Boolean)(using elideThis: reflect.ClassDef, originalOwner: reflect.Symbol) =
362367
import reflect._
363368
val ignore = if (low) t.typeSymbol == defn.NothingClass else t.typeSymbol == defn.AnyClass
@@ -370,7 +375,7 @@ trait TypesSupport:
370375
}
371376

372377
private def typeBoundsTreeOfHigherKindedType(using Quotes)(low: reflect.TypeRepr, high: reflect.TypeRepr, skipThisTypePrefix: Boolean)(
373-
using elideThis: reflect.ClassDef, originalOwner: reflect.Symbol, inCC: Option[Unit]
378+
using elideThis: reflect.ClassDef, originalOwner: reflect.Symbol, inCC: Option[List[reflect.TypeRepr]]
374379
) =
375380
import reflect._
376381
def regularTypeBounds(low: TypeRepr, high: TypeRepr) =
@@ -464,25 +469,48 @@ trait TypesSupport:
464469
case AnnotatedType(tr, _) => stripAnnotated(tr)
465470
case other => other
466471

467-
private def renderCapability(using Quotes)(ref: reflect.TypeRepr)(using elideThis: reflect.ClassDef): List[SignaturePart] =
472+
private def renderCapability(using Quotes)(ref: reflect.TypeRepr, skipThisTypePrefix: Boolean)(
473+
using elideThis: reflect.ClassDef, originalOwner: reflect.Symbol
474+
): SSignature =
468475
import reflect._
469476
ref match
470-
case ReachCapability(c) => renderCapability(c) :+ Keyword("*")
477+
case ReachCapability(c) => renderCapability(c, skipThisTypePrefix) :+ Keyword("*")
471478
case ThisType(_) => List(Keyword("this"))
472-
case t => inner(t)(using skipTypeSuffix = true, inCC = Some(()))
479+
case t => inner(t, skipThisTypePrefix)(using skipTypeSuffix = true, inCC = Some(Nil))
473480

474-
private def renderCaptureSet(using Quotes)(refs: List[reflect.TypeRepr])(using elideThis: reflect.ClassDef): List[SignaturePart] =
481+
private def renderCaptureSet(using Quotes)(refs: List[reflect.TypeRepr], skipThisTypePrefix: Boolean)(
482+
using elideThis: reflect.ClassDef, originalOwner: reflect.Symbol
483+
): SSignature =
475484
import dotty.tools.scaladoc.tasty.NameNormalizer._
476485
import reflect._
477486
refs match
478487
case List(ref) if ref.isCaptureRoot => Nil
479488
case refs =>
480-
val res0 = refs.map(renderCapability)
489+
val res0 = refs.map(renderCapability(_, skipThisTypePrefix))
481490
val res1 = res0 match
482491
case Nil => Nil
483492
case other => other.reduce((r, e) => r ++ (List(Plain(", ")) ++ e))
484493
Plain("{") :: (res1 ++ List(Plain("}")))
485494

486-
private def renderCapturing(using Quotes)(refs: List[reflect.TypeRepr])(using elideThis: reflect.ClassDef): List[SignaturePart] =
495+
private def renderCapturing(using Quotes)(refs: List[reflect.TypeRepr], skipThisTypePrefix: Boolean)(
496+
using elideThis: reflect.ClassDef, originalOwner: reflect.Symbol
497+
): SSignature =
487498
import reflect._
488-
Keyword("^") :: renderCaptureSet(refs)
499+
Keyword("^") :: renderCaptureSet(refs, skipThisTypePrefix)
500+
501+
private def renderCaptureArrow(using Quotes)(refs: List[reflect.TypeRepr], skipThisTypePrefix: Boolean)(
502+
using elideThis: reflect.ClassDef, originalOwner: reflect.Symbol
503+
): SSignature =
504+
import reflect._
505+
refs match
506+
case Nil => List(Keyword("->"))
507+
case List(ref) if ref.isCaptureRoot => List(Keyword("=>"))
508+
case refs => Keyword("->") :: renderCaptureSet(refs, skipThisTypePrefix)
509+
510+
private def renderCaptureArrow(using Quotes)(refs: Option[List[reflect.TypeRepr]], skipThisTypePrefix: Boolean)(
511+
using elideThis: reflect.ClassDef, originalOwner: reflect.Symbol
512+
): SSignature =
513+
import reflect._
514+
refs match
515+
case None => List(Keyword("=>")) // FIXME: is this correct? or should it be `->` by default?
516+
case Some(refs) => renderCaptureArrow(refs, skipThisTypePrefix)

0 commit comments

Comments
 (0)