@@ -7,10 +7,67 @@ import scala.util.matching.Regex
7
7
8
8
object Scaladoc2AnchorCreator :
9
9
10
- def getScaladoc2Type (using Quotes )(t : reflect.Tree ) =
11
- import reflect .*
12
- val regex = t match
13
- case d : DefDef => " def"
14
- case t : TypeDef => " type"
15
- case v : ValDef => " val|var"
16
- t.show(using Printer .TreeShortCode ).split(regex, 2 )(1 ).replace(" " ," " )
10
+ def getScaladoc2Type (using Quotes )(sym : quotes.reflect.Symbol ) = signatureAnchor(sym)
11
+
12
+ /** Creates the signature anchor
13
+ *
14
+ * - `X` for a `type X ...`
15
+ * - `x:X` for a `val x: X`
16
+ * - `f[U1,...](x1:T1,...)...:R` for a `def f[U1, ...](x1: T1, ...)...: R`
17
+ *
18
+ * Types are printed without their paths. No spaces are printed in the output
19
+ * except for the one after `(implicit`.
20
+ */
21
+ private def signatureAnchor (using Quotes )(sym : quotes.reflect.Symbol ): String =
22
+ import quotes .reflect .*
23
+ def signatureType (tp : quotes.reflect.TypeRepr ): String =
24
+ tp match
25
+ case mt @ MethodType (paramNames, paramTypes, res) =>
26
+ val openClause = if mt.isImplicit then " (implicit " else " ("
27
+ val closeClause = res match
28
+ case _ : MethodOrPoly => " )"
29
+ case _ => " ):"
30
+ paramNames.zip(paramTypes.map(signatureType))
31
+ .map((name, tpe) => s " $name: $tpe" )
32
+ .mkString(openClause, " ," , closeClause) + signatureType(res)
33
+ case PolyType (paramNames, paramBounds, res) =>
34
+ val closeClause = res match
35
+ case _ : MethodOrPoly => " ]"
36
+ case _ => " ]:"
37
+ paramNames.zip(paramBounds.map(signatureType))
38
+ .map((name, tpe) => s " $name$tpe" )
39
+ .mkString(" [" , " ," , closeClause) + signatureType(res)
40
+ case TypeLambda (paramNames, paramBounds, res) =>
41
+ paramNames.zip(paramBounds.map(signatureType))
42
+ .map((name, tpe) => s " $name$tpe" )
43
+ .mkString(" [" , " ," , " ]" ) + " =>" + signatureType(res)
44
+ case ByNameType (tp) =>
45
+ " :" + signatureType(tp)
46
+ case TypeBounds (low, hi) =>
47
+ val lowBound = if low =:= defn.NothingClass .typeRef then " " else " >:" + signatureType(low)
48
+ val hiBound = if low =:= defn.AnyClass .typeRef then " " else " <:" + signatureType(hi)
49
+ lowBound + hiBound
50
+ case tp : ParamRef =>
51
+ tp.binder match
52
+ case binder : MethodType => binder.paramNames(tp.paramNum) + " .type"
53
+ case binder : PolyType => binder.paramNames(tp.paramNum)
54
+ case binder : LambdaType => binder.paramNames(tp.paramNum)
55
+ case AppliedType (tycon, args) =>
56
+ args.map {
57
+ case tp : TypeBounds => " _" + signatureType(tp)
58
+ case tp => signatureType(tp)
59
+ }.mkString(signatureType(tycon) + " [" , " ," , " ]" )
60
+ case tp : AnnotatedType =>
61
+ signatureType(tp.underlying) + " @" + tp.annotation.symbol.owner.name
62
+ case tp : ThisType =>
63
+ signatureType(tp.tref) + " .this"
64
+ case tp : TypeRef =>
65
+ tp.name
66
+ case tp =>
67
+ // TODO handle other cases without using show (show does not have a stable representation)
68
+ tp.show(using Printer .TypeReprShortCode ).replace(" " ," " )
69
+
70
+ sym match
71
+ case sym if sym.isType => sym.name
72
+ case sym if sym.flags.is(Flags .Method ) => sym.name + signatureType(sym.info)
73
+ case sym => sym.name + " :" + signatureType(sym.info)
0 commit comments