@@ -7,10 +7,66 @@ import scala.util.matching.Regex
77
88object Scaladoc2AnchorCreator :
99
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