Skip to content

Commit 32d7099

Browse files
committed
Method Types + small API cleanup
1 parent 59cbbe1 commit 32d7099

File tree

2 files changed

+140
-126
lines changed

2 files changed

+140
-126
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package test.syntaxes
2+
3+
class DoingStuffOps[A](a: A):
4+
def doStuff: Unit = ()
5+
6+
trait DoingStuffSyntax:
7+
implicit def toDoingStuffOps[A](a: A): DoingStuffOps[A] = DoingStuffOps(a)
8+
9+
object doingstuff extends DoingStuffSyntax

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

Lines changed: 131 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -22,132 +22,118 @@ trait InkuireSupport:
2222
def doInkuireStuff(classDef: ClassDef): Unit = {
2323
val classType: Inkuire.Type = classDef.asInkuire(Set.empty).asInstanceOf[Inkuire.Type]
2424

25-
def varName(t: Inkuire.TypeLike): Option[String] = t match {
26-
case tpe: Inkuire.Type => Some(tpe.name.name)
27-
case tl: Inkuire.TypeLambda => varName(tl.result)
28-
case _ => None
29-
}
30-
31-
val variableNames: Set[String] = classType.params.map(_.typ)
32-
.flatMap(varName(_).toList).toSet
25+
val variableNames: Set[String] = classType.params.map(_.typ)
26+
.flatMap(varName(_).toList).toSet
3327

34-
val parents: Seq[Inkuire.Type] = classDef.parents.map(_.asInkuire(variableNames).asInstanceOf[Inkuire.Type])
28+
val parents: Seq[Inkuire.Type] = classDef.parents.map(_.asInkuire(variableNames).asInstanceOf[Inkuire.Type])
3529

36-
val isModule = classDef.symbol.flags.is(Flags.Module)
30+
val isModule = classDef.symbol.flags.is(Flags.Module)
3731

38-
if !isModule then Inkuire.db = Inkuire.db.copy(types = Inkuire.db.types.updated(classType.itid.get, (classType, parents)))
39-
40-
classDef.symbol.declaredTypes
41-
.filter(viableSymbol)
42-
.foreach {
43-
case typeSymbol: Symbol if typeSymbol.flags.is(Flags.Opaque) =>
44-
val typ = typeSymbol.tree.asInkuire(variableNames)
45-
if typ.isInstanceOf[Inkuire.Type] then {
46-
val t = typ.asInstanceOf[Inkuire.Type]
47-
Inkuire.db = Inkuire.db.copy(types = Inkuire.db.types.updated(t.itid.get, (t, Seq.empty)))
48-
}
49-
case typeSymbol: Symbol if !typeSymbol.isClassDef =>
50-
val typeDef = typeSymbol.tree.asInstanceOf[TypeDef]
51-
val typ = typeSymbol.tree.asInkuire(variableNames)
52-
if typ.isInstanceOf[Inkuire.Type] then {
53-
val t = typ.asInstanceOf[Inkuire.Type]
54-
val rhsTypeLike = typeDef.rhs.asInkuire(variableNames)
55-
Inkuire.db = Inkuire.db.copy(
56-
typeAliases = Inkuire.db.typeAliases.updated(t.itid.get, rhsTypeLike),
57-
types = Inkuire.db.types.updated(t.itid.get, (t, Seq.empty))
58-
)
59-
}
60-
if typeDef.rhs.symbol.flags.is(Flags.JavaDefined) then
61-
val typJava = typeDef.rhs.asInkuire(variableNames)
62-
if typJava.isInstanceOf[Inkuire.Type] then {
63-
val tJava = typJava.asInstanceOf[Inkuire.Type]
64-
Inkuire.db = Inkuire.db.copy(types = Inkuire.db.types.updated(tJava.itid.get, (tJava, Seq.empty)))
65-
}
66-
case _ =>
67-
}
32+
if !isModule then Inkuire.db = Inkuire.db.copy(types = Inkuire.db.types.updated(classType.itid.get, (classType, parents)))
6833

69-
def viableSymbol(s: Symbol): Boolean =
70-
!s.flags.is(Flags.Private) &&
71-
!s.flags.is(Flags.Protected) &&
72-
!s.flags.is(Flags.Override) &&
73-
!s.flags.is(Flags.Synthetic)
74-
75-
if classDef.symbol.isImplicitClass then // Implicit classes
76-
classDef.symbol.maybeOwner.declarations
77-
.filter { methodSymbol =>
78-
methodSymbol.name == classDef.symbol.name && methodSymbol.flags.is(Flags.Implicit) && methodSymbol.flags.is(Flags.Method)
34+
classDef.symbol.declaredTypes
35+
.filter(viableSymbol)
36+
.foreach {
37+
case typeSymbol: Symbol if typeSymbol.flags.is(Flags.Opaque) =>
38+
val typ = typeSymbol.tree.asInkuire(variableNames)
39+
if typ.isInstanceOf[Inkuire.Type] then {
40+
val t = typ.asInstanceOf[Inkuire.Type]
41+
Inkuire.db = Inkuire.db.copy(types = Inkuire.db.types.updated(t.itid.get, (t, Seq.empty)))
7942
}
80-
.foreach(handleImplicitConversion(_, variableNames))
81-
82-
classDef.symbol.declaredMethods
83-
.filter(viableSymbol)
84-
.tap { _.foreach { // Loop for implicit conversions
85-
case implicitConversion: Symbol if implicitConversion.flags.is(Flags.Implicit)
86-
&& classDef.symbol.flags.is(Flags.Module)
87-
&& implicitConversion.owner.fullName == ("scala.Predef$") =>
88-
handleImplicitConversion(implicitConversion, variableNames)
89-
case _ =>
90-
}}
91-
.tap { _.foreach { // Loop for functions and vals
92-
case methodSymbol: Symbol =>
93-
val defdef = methodSymbol.tree.asInstanceOf[DefDef]
94-
val methodVars = defdef.paramss.flatMap(_.params).collect {
95-
case TypeDef(name, _) => name
96-
}
97-
val vars = variableNames ++ methodVars
98-
val receiver: Option[Inkuire.TypeLike] =
99-
Some(classType)
100-
.filter(_ => !isModule)
101-
.orElse(methodSymbol.extendedSymbol.flatMap(s => partialAsInkuire(vars).lift(s.tpt)))
102-
val (name, ownerName) = nameAndOwnerName(classDef, methodSymbol)
103-
val sgn = Inkuire.ExternalSignature(
104-
signature = Inkuire.Signature(
105-
receiver = receiver,
106-
arguments = methodSymbol.nonExtensionTermParamLists.collect {
107-
case tpc@TermParamClause(params) if !tpc.isImplicit && !tpc.isGiven => params //TODO [Inkuire] Implicit parameters
108-
}.flatten.map(_.tpt.asInkuire(vars)),
109-
result = defdef.returnTpt.asInkuire(vars),
110-
context = Inkuire.SignatureContext(
111-
vars = vars.toSet,
112-
constraints = Map.empty //TODO [Inkuire] Type bounds
113-
)
114-
),
115-
name = name,
116-
packageName = ownerName,
117-
uri = methodSymbol.dri.externalLink.getOrElse(""),
118-
entryType = "def"
43+
case typeSymbol: Symbol if !typeSymbol.isClassDef =>
44+
val typeDef = typeSymbol.tree.asInstanceOf[TypeDef]
45+
val typ = typeSymbol.tree.asInkuire(variableNames)
46+
if typ.isInstanceOf[Inkuire.Type] then {
47+
val t = typ.asInstanceOf[Inkuire.Type]
48+
val rhsTypeLike = typeDef.rhs.asInkuire(variableNames)
49+
Inkuire.db = Inkuire.db.copy(
50+
typeAliases = Inkuire.db.typeAliases.updated(t.itid.get, rhsTypeLike),
51+
types = Inkuire.db.types.updated(t.itid.get, (t, Seq.empty))
11952
)
120-
val curriedSgn = sgn.copy(signature = Inkuire.curry(sgn.signature))
121-
Inkuire.db = Inkuire.db.copy(functions = Inkuire.db.functions :+ curriedSgn)
122-
}}
53+
}
54+
if typeDef.rhs.symbol.flags.is(Flags.JavaDefined) then
55+
val typJava = typeDef.rhs.asInkuire(variableNames)
56+
if typJava.isInstanceOf[Inkuire.Type] then {
57+
val tJava = typJava.asInstanceOf[Inkuire.Type]
58+
Inkuire.db = Inkuire.db.copy(types = Inkuire.db.types.updated(tJava.itid.get, (tJava, Seq.empty)))
59+
}
60+
case _ =>
61+
}
12362

124-
classDef.symbol.declaredFields
125-
.filter(viableSymbol)
126-
.foreach {
127-
case valSymbol: Symbol =>
128-
val valdef = valSymbol.tree.asInstanceOf[ValDef]
129-
val receiver: Option[Inkuire.TypeLike] =
130-
Some(classType)
131-
.filter(_ => !isModule)
132-
val (name, ownerName) = nameAndOwnerName(classDef, valSymbol)
133-
val sgn = Inkuire.ExternalSignature(
134-
signature = Inkuire.Signature(
135-
receiver = receiver,
136-
arguments = Seq.empty,
137-
result = valdef.tpt.asInkuire(variableNames),
138-
context = Inkuire.SignatureContext(
139-
vars = variableNames.toSet,
140-
constraints = Map.empty //TODO [Inkuire] Type bounds
141-
)
142-
),
143-
name = name,
144-
packageName = ownerName,
145-
uri = valSymbol.dri.externalLink.getOrElse(""),
146-
entryType = "val"
147-
)
148-
val curriedSgn = sgn.copy(signature = Inkuire.curry(sgn.signature))
149-
Inkuire.db = Inkuire.db.copy(functions = Inkuire.db.functions :+ curriedSgn)
63+
if classDef.symbol.isImplicitClass then // Implicit classes <- synthetic method with the same name
64+
classDef.symbol.maybeOwner.declarations
65+
.filter { methodSymbol =>
66+
methodSymbol.name == classDef.symbol.name && methodSymbol.flags.is(Flags.Implicit) && methodSymbol.flags.is(Flags.Method)
15067
}
68+
.foreach(handleImplicitConversion(_, variableNames))
69+
70+
classDef.symbol.declaredMethods
71+
.filter(viableSymbol)
72+
.tap { _.foreach { // Loop for implicit conversions
73+
case implicitConversion: Symbol if implicitConversion.flags.is(Flags.Implicit) =>
74+
handleImplicitConversion(implicitConversion, variableNames)
75+
case _ =>
76+
}}
77+
.tap { _.foreach { // Loop for functions and vals
78+
case methodSymbol: Symbol =>
79+
val defdef = methodSymbol.tree.asInstanceOf[DefDef]
80+
val methodVars = defdef.paramss.flatMap(_.params).collect {
81+
case TypeDef(name, _) => name
82+
}
83+
val vars = variableNames ++ methodVars
84+
val receiver: Option[Inkuire.TypeLike] =
85+
Some(classType)
86+
.filter(_ => !isModule)
87+
.orElse(methodSymbol.extendedSymbol.flatMap(s => partialAsInkuire(vars).lift(s.tpt)))
88+
val (name, ownerName) = nameAndOwnerName(classDef, methodSymbol)
89+
val sgn = Inkuire.ExternalSignature(
90+
signature = Inkuire.Signature(
91+
receiver = receiver,
92+
arguments = methodSymbol.nonExtensionTermParamLists.collect {
93+
case tpc@TermParamClause(params) if !tpc.isImplicit && !tpc.isGiven => params //TODO [Inkuire] Implicit parameters
94+
}.flatten.map(_.tpt.asInkuire(vars)),
95+
result = defdef.returnTpt.asInkuire(vars),
96+
context = Inkuire.SignatureContext(
97+
vars = vars.toSet,
98+
constraints = Map.empty //TODO [Inkuire] Type bounds
99+
)
100+
),
101+
name = name,
102+
packageName = ownerName,
103+
uri = methodSymbol.dri.externalLink.getOrElse(""),
104+
entryType = "def"
105+
)
106+
val curriedSgn = sgn.copy(signature = Inkuire.curry(sgn.signature))
107+
Inkuire.db = Inkuire.db.copy(functions = Inkuire.db.functions :+ curriedSgn)
108+
}}
109+
110+
classDef.symbol.declaredFields
111+
.filter(viableSymbol)
112+
.foreach {
113+
case valSymbol: Symbol =>
114+
val valdef = valSymbol.tree.asInstanceOf[ValDef]
115+
val receiver: Option[Inkuire.TypeLike] =
116+
Some(classType)
117+
.filter(_ => !isModule)
118+
val (name, ownerName) = nameAndOwnerName(classDef, valSymbol)
119+
val sgn = Inkuire.ExternalSignature(
120+
signature = Inkuire.Signature(
121+
receiver = receiver,
122+
arguments = Seq.empty,
123+
result = valdef.tpt.asInkuire(variableNames),
124+
context = Inkuire.SignatureContext(
125+
vars = variableNames.toSet,
126+
constraints = Map.empty //TODO [Inkuire] Type bounds
127+
)
128+
),
129+
name = name,
130+
packageName = ownerName,
131+
uri = valSymbol.dri.externalLink.getOrElse(""),
132+
entryType = "val"
133+
)
134+
val curriedSgn = sgn.copy(signature = Inkuire.curry(sgn.signature))
135+
Inkuire.db = Inkuire.db.copy(functions = Inkuire.db.functions :+ curriedSgn)
136+
}
151137
}
152138

153139
private def handleImplicitConversion(implicitConversion: Symbol, variableNames: Set[String]) = {
@@ -161,6 +147,8 @@ trait InkuireSupport:
161147
case _ =>
162148
}
163149

150+
private def hasStaticChild(classDef: ClassDef): Boolean = ???
151+
164152
private def nameAndOwnerName(classDef: ClassDef, symbol: Symbol): (String, String) =
165153
if classDef.symbol.flags.is(Flags.Module)
166154
&& (classDef.symbol.companionClass != Symbol.noSymbol || (Seq("apply", "unapply").contains(symbol.name))) then
@@ -174,14 +162,26 @@ trait InkuireSupport:
174162
ownerNameChain(classDef.symbol).mkString(".")
175163
)
176164

177-
def ownerNameChain(sym: Symbol): List[String] =
165+
private def ownerNameChain(sym: Symbol): List[String] =
178166
if sym.isNoSymbol then List.empty
179167
else if sym == defn.EmptyPackageClass then List.empty
180168
else if sym == defn.RootPackage then List.empty
181169
else if sym == defn.RootClass then List.empty
182170
else if sym.normalizedName.contains("$package") then ownerNameChain(sym.owner)
183171
else ownerNameChain(sym.owner) :+ sym.normalizedName
184172

173+
private def viableSymbol(s: Symbol): Boolean =
174+
!s.flags.is(Flags.Private) &&
175+
!s.flags.is(Flags.Protected) &&
176+
!s.flags.is(Flags.Override) &&
177+
!s.flags.is(Flags.Synthetic)
178+
179+
private def varName(t: Inkuire.TypeLike): Option[String] = t match {
180+
case tpe: Inkuire.Type => Some(tpe.name.name)
181+
case tl: Inkuire.TypeLambda => varName(tl.result)
182+
case _ => None
183+
}
184+
185185
private def paramsForClass(classDef: ClassDef, vars: Set[String]): Seq[Inkuire.Variance] =
186186
classDef.getTypeParams.map(mkTypeArgumentInkuire)
187187

@@ -190,7 +190,7 @@ trait InkuireSupport:
190190
def asInkuire(vars: Set[String]): Inkuire.TypeLike =
191191
partialAsInkuire(vars)(tpeTree)
192192

193-
def partialAsInkuire(vars: Set[String]): PartialFunction[Tree, Inkuire.TypeLike] = {
193+
private def partialAsInkuire(vars: Set[String]): PartialFunction[Tree, Inkuire.TypeLike] = {
194194
case TypeBoundsTree(low, high) => inner(low.tpe, vars) //TODO [Inkuire] Type bounds
195195
case tpeTree: Applied =>
196196
inner(tpeTree.tpe, vars)
@@ -201,7 +201,7 @@ trait InkuireSupport:
201201
case typeDef: TypeDef => mkTypeDef(typeDef)
202202
}
203203

204-
def mkTypeDef(typeDef: TypeDef): Inkuire.Type = typeDef.rhs match {
204+
private def mkTypeDef(typeDef: TypeDef): Inkuire.Type = typeDef.rhs match {
205205
case LambdaTypeTree(paramsDefs, _) =>
206206
val name = typeDef.symbol.normalizedName
207207
val normalizedName = if name.matches("_\\$\\d*") then "_" else name
@@ -218,7 +218,7 @@ trait InkuireSupport:
218218
)
219219
}
220220

221-
def mkTypeFromClassDef(classDef: ClassDef, vars: Set[String]): Inkuire.Type = {
221+
private def mkTypeFromClassDef(classDef: ClassDef, vars: Set[String]): Inkuire.Type = {
222222
Inkuire.Type(
223223
name = Inkuire.TypeName(classDef.name),
224224
itid = classDef.symbol.itid,
@@ -245,7 +245,7 @@ trait InkuireSupport:
245245
)
246246
}
247247

248-
def mkTypeArgumentInkuire(argument: TypeDef): Inkuire.Variance =
248+
private def mkTypeArgumentInkuire(argument: TypeDef): Inkuire.Variance =
249249
//TODO [Inkuire] Type bounds (other than just HKTs)
250250
val name = argument.symbol.normalizedName
251251
val normalizedName = if name.matches("_\\$\\d*") then "_" else name
@@ -263,7 +263,7 @@ trait InkuireSupport:
263263
else if argument.symbol.flags.is(Flags.Contravariant) then Inkuire.Contravariance(t)
264264
else Inkuire.Invariance(t)
265265

266-
def typeVariableDeclarationParamsNo(argument: TypeDef): Int =
266+
private def typeVariableDeclarationParamsNo(argument: TypeDef): Int =
267267
argument.rhs match
268268
case t: TypeTree => t.tpe match
269269
case TypeBounds(_, TypeLambda(names, _, _)) => names.size
@@ -346,5 +346,10 @@ trait InkuireSupport:
346346
inner(m.paramTypes(i), vars)
347347
case RecursiveType(tp) =>
348348
inner(tp, vars)
349-
case MethodType(_, params, resType) =>
350-
inner(resType, vars) //TODO [Inkuire] Method type
349+
case m@MethodType(_, typeList, resType) =>
350+
val name = s"Function${typeList.size-1}"
351+
Inkuire.Type(
352+
name = Inkuire.TypeName(name),
353+
params = typeList.map(p => Inkuire.Contravariance(inner(p, vars))) :+ Inkuire.Covariance(inner(resType, vars)),
354+
itid = Some(Inkuire.ITID(s"${name}scala.${name}//[]", isParsed = false))
355+
)

0 commit comments

Comments
 (0)