@@ -7,10 +7,66 @@ 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,...)(impliciti1:U1,impliciti2:U2,...)...:R` for a `def f[U1, ...](x1: T1, ...)(implicit i1: U1, i2: U2...)...: R`
17
+ *
18
+ * Types are printed without their paths. No spaces are printed in the output.
19
+ */
20
+ private def signatureAnchor (using Quotes )(sym : quotes.reflect.Symbol ): String =
21
+ import quotes .reflect .*
22
+ def signatureType (tp : quotes.reflect.TypeRepr ): String =
23
+ tp match
24
+ case mt @ MethodType (paramNames, paramTypes, res) =>
25
+ val implicitPrefix = if mt.isImplicit then " implicit " else " "
26
+ val closeClause = res match
27
+ case _ : MethodOrPoly => " )"
28
+ case _ => " ):"
29
+ paramNames.zip(paramTypes.map(signatureType))
30
+ .map((name, tpe) => s " $implicitPrefix$name: $tpe" )
31
+ .mkString(" (" , " ," , closeClause) + signatureType(res)
32
+ case PolyType (paramNames, paramBounds, res) =>
33
+ val closeClause = res match
34
+ case _ : MethodOrPoly => " ]"
35
+ case _ => " ]:"
36
+ paramNames.zip(paramBounds.map(signatureType))
37
+ .map((name, tpe) => s " $name$tpe" )
38
+ .mkString(" [" , " ," , closeClause) + signatureType(res)
39
+ case TypeLambda (paramNames, paramBounds, res) =>
40
+ paramNames.zip(paramBounds.map(signatureType))
41
+ .map((name, tpe) => s " $name$tpe" )
42
+ .mkString(" [" , " ," , " ]" ) + " =>" + signatureType(res)
43
+ case ByNameType (tp) =>
44
+ " :" + signatureType(tp)
45
+ case TypeBounds (low, hi) =>
46
+ val lowBound = if low =:= defn.NothingClass .typeRef then " " else " >:" + signatureType(low)
47
+ val hiBound = if low =:= defn.AnyClass .typeRef then " " else " <:" + signatureType(hi)
48
+ lowBound + hiBound
49
+ case tp : ParamRef =>
50
+ tp.binder match
51
+ case binder : MethodType => binder.paramNames(tp.paramNum) + " .type"
52
+ case binder : PolyType => binder.paramNames(tp.paramNum)
53
+ case binder : LambdaType => binder.paramNames(tp.paramNum)
54
+ case AppliedType (tycon, args) =>
55
+ args.map {
56
+ case tp : TypeBounds => " _" + signatureType(tp)
57
+ case tp => signatureType(tp)
58
+ }.mkString(signatureType(tycon) + " [" , " ," , " ]" )
59
+ case tp : AnnotatedType =>
60
+ signatureType(tp.underlying) + " @" + tp.annotation.symbol.owner.name
61
+ case tp : ThisType =>
62
+ signatureType(tp.tref) + " .this"
63
+ case tp : TypeRef =>
64
+ tp.name
65
+ case tp =>
66
+ // TODO handle other cases without using show (show does not have a stable representation)
67
+ tp.show(using Printer .TypeReprShortCode ).replace(" " ," " )
68
+
69
+ sym match
70
+ case sym if sym.isType => sym.name
71
+ case sym if sym.flags.is(Flags .Method ) => sym.name + signatureType(sym.info)
72
+ case sym => sym.name + " :" + signatureType(sym.info)
0 commit comments