Skip to content

Commit ef97436

Browse files
committed
scaladoc: render parens in more places for disambiguation
1 parent fe0f685 commit ef97436

File tree

3 files changed

+27
-62
lines changed

3 files changed

+27
-62
lines changed

scaladoc-testcases/src/tests/functionTypeSignatures.scala

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ package tests.functionTypeSignatures
22

33
type A = ((Int, Int)) => Int
44

5-
type B = (Int | String) => Int //expected: type B = Int | String => Int
5+
type B = (Int | String) => Int
66

7-
type B1 = Int | String => Int
7+
type B1 = Int | String => Int //expected: type B1 = (Int | String) => Int
88

9-
type C = (Int & String) => Int //expected: type C = Int & String => Int
9+
type C = (Int & String) => Int
1010

11-
type C1 = Int & String => Int
11+
type C1 = Int & String => Int //expected: type C1 = (Int & String) => Int
1212

1313
type D = Int | (String => Int)
1414

scaladoc-testcases/src/tests/infixTypes.scala

+17-17
Original file line numberDiff line numberDiff line change
@@ -30,24 +30,24 @@ def foo[A, B, C, D]: (A SomeTrait B) +++ (C SomeTrait2 D) //expected: def foo[A,
3030

3131
// left-associative, same precedence
3232

33-
def a0[X, Y, Z]: X +++ Y +++ Z
33+
def a0[X, Y, Z]: X +++ Y +++ Z //expected: def a0[X, Y, Z]: (X +++ Y) +++ Z
3434
= a1
3535

36-
def a1[X, Y, Z]: (X +++ Y) +++ Z //expected: def a1[X, Y, Z]: X +++ Y +++ Z
36+
def a1[X, Y, Z]: (X +++ Y) +++ Z
3737
= a0
3838

3939
def a2[X, Y, Z]: X +++ (Y +++ Z)
4040
= ???
4141

4242
// right-associative, same precedence
4343

44-
def a3[X, Y, Z]: X ++: Y ++: Z
44+
def a3[X, Y, Z]: X ++: Y ++: Z //expected: def a3[X, Y, Z]: X ++: (Y ++: Z)
4545
= ???
4646

4747
def a4[X, Y, Z]: (X ++: Y) ++: Z
4848
= ???
4949

50-
def a5[X, Y, Z]: X ++: (Y ++: Z) //expected: def a3[X, Y, Z]: X ++: Y ++: Z
50+
def a5[X, Y, Z]: X ++: (Y ++: Z)
5151
= ???
5252

5353
// left and right associative, same precedence
@@ -60,60 +60,60 @@ def a7[X, Y, Z]: X +++ (Y ++: Z)
6060

6161
// left-associative, mixed precedence
6262

63-
def b0[X, Y, Z]: X +++ Y *** Z
63+
def b0[X, Y, Z]: X +++ Y *** Z //expected: def b0[X, Y, Z]: X +++ (Y *** Z)
6464
= ???
6565

6666
def b1[X, Y, Z]: (X +++ Y) *** Z
6767
= ???
6868

69-
def b2[X, Y, Z]: X +++ (Y *** Z) //expected: def b2[X, Y, Z]: X +++ Y *** Z
69+
def b2[X, Y, Z]: X +++ (Y *** Z)
7070
= ???
7171

72-
def b3[X, Y, Z]: X *** Y +++ Z
72+
def b3[X, Y, Z]: X *** Y +++ Z //expected: def b3[X, Y, Z]: (X *** Y) +++ Z
7373
= ???
7474

75-
def b4[X, Y, Z]: (X *** Y) +++ Z //expected: def b4[X, Y, Z]: X *** Y +++ Z
75+
def b4[X, Y, Z]: (X *** Y) +++ Z
7676
= ???
7777

7878
def b5[X, Y, Z]: X *** (Y +++ Z)
7979
= ???
8080

8181
// right-associative, mixed precedence
8282

83-
def c0[X, Y, Z]: X ++: Y **: Z
83+
def c0[X, Y, Z]: X ++: Y **: Z //expected: def c0[X, Y, Z]: X ++: (Y **: Z)
8484
= ???
8585

8686
def c1[X, Y, Z]: (X ++: Y) **: Z
8787
= ???
8888

89-
def c2[X, Y, Z]: X ++: (Y **: Z) //expected: def c2[X, Y, Z]: X ++: Y **: Z
89+
def c2[X, Y, Z]: X ++: (Y **: Z)
9090
= ???
9191

92-
def c3[X, Y, Z]: X **: Y ++: Z
92+
def c3[X, Y, Z]: X **: Y ++: Z //expected: def c3[X, Y, Z]: (X **: Y) ++: Z
9393
= ???
9494

95-
def c4[X, Y, Z]: (X **: Y) ++: Z //expected: def c4[X, Y, Z]: X **: Y ++: Z
95+
def c4[X, Y, Z]: (X **: Y) ++: Z
9696
= ???
9797

9898
def c5[X, Y, Z]: X **: (Y ++: Z)
9999
= ???
100100

101101
// left and right associative, mixed precedence
102102

103-
def d0[X, Y, Z]: X +++ Y **: Z
103+
def d0[X, Y, Z]: X +++ Y **: Z //expected: def d0[X, Y, Z]: X +++ (Y **: Z)
104104
= ???
105105

106106
def d1[X, Y, Z]: (X +++ Y) **: Z
107107
= ???
108108

109-
def d2[X, Y, Z]: X +++ (Y **: Z) //expected: def d2[X, Y, Z]: X +++ Y **: Z
109+
def d2[X, Y, Z]: X +++ (Y **: Z)
110110
= ???
111111

112-
def d3[X, Y, Z]: X *** Y ++: Z
112+
def d3[X, Y, Z]: X *** Y ++: Z //expected: def d3[X, Y, Z]: (X *** Y) ++: Z
113113
= ???
114114

115-
def d4[X, Y, Z]: (X *** Y) ++: Z //expected: def d4[X, Y, Z]: X *** Y ++: Z
115+
def d4[X, Y, Z]: (X *** Y) ++: Z
116116
= ???
117117

118-
def d5[X, Y, Z]: X *** (Y ++: Z) //expected: def d5[X, Y, Z]: X *** (Y ++: Z)
118+
def d5[X, Y, Z]: X *** (Y ++: Z)
119119
= ???

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

+6-41
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,7 @@ trait TypesSupport:
209209
plain("()").l ++ keyword(arrow).l ++ inner(rtpe)
210210
case Seq(arg, rtpe) =>
211211
val partOfSignature = arg match
212-
case tpe @ (_: TermRef | _: TypeRef | _: ConstantType | _: ParamRef | _: AndType | _: OrType) => inner(arg)
213-
case tpe: AppliedType if !tpe.isFunctionType && !tpe.isTupleN => inner(arg)
212+
case _: TermRef | _: TypeRef | _: ConstantType | _: ParamRef => inner(arg)
214213
case _ => inParens(inner(arg))
215214
partOfSignature ++ keyword(arrow).l ++ inner(rtpe)
216215
case args =>
@@ -346,38 +345,6 @@ trait TypesSupport:
346345
private def shouldWrapInParens(using Quotes)(inner: reflect.TypeRepr, outer: reflect.TypeRepr, isLeft: Boolean) =
347346
import reflect._
348347

349-
// Duplication of dotty.tools.dotc.parsing.precedence because we cannot construct Name here
350-
def precedence(opName: String) =
351-
import dotty.tools.dotc.util.Chars.{isScalaLetter, isOperatorPart}
352-
val isOpAssignmentName = opName match
353-
case "!=" | "<=" | ">=" | "" => false
354-
case name =>
355-
name.length > 0 && name.last == '=' && name.head != '=' && isOperatorPart(name.head)
356-
opName.head match
357-
case _ if isOpAssignmentName => 0
358-
case c if isScalaLetter(c) => 1
359-
case '|' => 2
360-
case '^' => 3
361-
case '&' => 4
362-
case '=' | '!' => 5
363-
case '<' | '>' => 6
364-
case ':' => 7
365-
case '+' | '-' => 8
366-
case '*' | '/' | '%' => 9
367-
case _ => 10
368-
369-
def shouldWrap(innerOp: String, outerOp: String) =
370-
val innerPrec = precedence(innerOp)
371-
val outerPrec = precedence(outerOp)
372-
val innerLeftAssoc = !innerOp.endsWith(":")
373-
val outerLeftAssoc = !outerOp.endsWith(":")
374-
375-
if innerLeftAssoc == outerLeftAssoc && outerLeftAssoc == isLeft
376-
then innerPrec < outerPrec
377-
else innerPrec <= outerPrec
378-
379-
def opName(at: AppliedType) = at.tycon.typeSymbol.name
380-
381348
(inner, outer) match
382349
case (_: AndType, _: TypeRef) => true
383350
case (_: OrType, _: TypeRef) => true
@@ -388,13 +355,11 @@ trait TypesSupport:
388355
case (_: OrType, _: AndType) => true
389356
case (_: OrType, _: OrType) => false
390357

391-
case (at: AppliedType, _: AndType) => at.isFunctionType || isInfix(at) && shouldWrap(opName(at), "&")
392-
case (at: AppliedType, _: OrType) => at.isFunctionType || isInfix(at) && shouldWrap(opName(at), "|")
393-
case (_: AndType, at: AppliedType) => isInfix(at) && shouldWrap("&", opName(at))
394-
case (_: OrType, at: AppliedType) => isInfix(at) && shouldWrap("|", opName(at))
395-
case (at1: AppliedType, at2: AppliedType) => isInfix(at2) && (
396-
at1.isFunctionType || isInfix(at1) && shouldWrap(opName(at1), opName(at2))
397-
)
358+
case (at: AppliedType, _: AndType) => at.isFunctionType || isInfix(at)
359+
case (at: AppliedType, _: OrType) => at.isFunctionType || isInfix(at)
360+
case (_: AndType, at: AppliedType) => isInfix(at)
361+
case (_: OrType, at: AppliedType) => isInfix(at)
362+
case (at1: AppliedType, at2: AppliedType) => isInfix(at2) && (at1.isFunctionType || isInfix(at1))
398363
case _ => false
399364

400365
private def isInfix(using Quotes)(at: reflect.AppliedType) =

0 commit comments

Comments
 (0)