Skip to content

Commit f2f190d

Browse files
Merge pull request #4714 from dotty-staging/tasty-reflect-add-members
Add tasty reflect members for definitions
2 parents 2acdd1f + b7c6f76 commit f2f190d

File tree

5 files changed

+219
-83
lines changed

5 files changed

+219
-83
lines changed

compiler/src/dotty/tools/dotc/tastyreflect/TastyImpl.scala

Lines changed: 110 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,9 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s
4949

5050
type Id = untpd.Ident
5151

52-
def IdDeco(x: Id): IdAPI = new IdAPI {
53-
def pos(implicit ctx: Context): Position = x.pos
52+
def IdDeco(id: Id): IdAPI = new IdAPI {
53+
def pos(implicit ctx: Context): Position = id.pos
54+
def name(implicit ctx: Context): String = id.name.toString
5455
}
5556

5657
def idClassTag: ClassTag[Id] = implicitly[ClassTag[Id]]
@@ -82,8 +83,8 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s
8283
}
8384
}
8485

85-
def PackageClauseDeco(x: PackageClause): PackageClauseAPI = new PackageClauseAPI {
86-
def definition(implicit ctx: Context): Definition = FromSymbol.packageDef(x.symbol)
86+
def PackageClauseDeco(pack: PackageClause): PackageClauseAPI = new PackageClauseAPI {
87+
def definition(implicit ctx: Context): Definition = FromSymbol.packageDef(pack.symbol)
8788
}
8889

8990
// ----- Statements -----------------------------------------------
@@ -101,6 +102,11 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s
101102
}
102103
}
103104

105+
def ImportDeco(imp: Import): ImportAPI = new ImportAPI {
106+
def expr(implicit ctx: Context): Tree = imp.expr
107+
def selector(implicit ctx: Context): List[ImportSelector] = imp.selectors
108+
}
109+
104110
type ImportSelector = untpd.Tree
105111

106112
def importSelectorClassTag: ClassTag[ImportSelector] = implicitly[ClassTag[ImportSelector]]
@@ -135,34 +141,36 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s
135141
x.isInstanceOf[Trees.MemberDef[_]]
136142
}
137143

138-
def DefinitionDeco(x: Definition): DefinitionAPI = new DefinitionAPI {
144+
def DefinitionDeco(definition: Definition): DefinitionAPI = new DefinitionAPI {
139145

140-
def owner(implicit ctx: Context): Definition = FromSymbol.definition(x.symbol.owner)
146+
def name(implicit ctx: Context): String = definition.symbol.name.toString
147+
148+
def owner(implicit ctx: Context): Definition = FromSymbol.definition(definition.symbol.owner)
141149

142150
def flags(implicit ctx: Context): FlagSet =
143-
new FlagSet(x.symbol.flags)
151+
new FlagSet(definition.symbol.flags)
144152

145153
def privateWithin(implicit ctx: Context): Option[Type] = {
146-
val within = x.symbol.privateWithin
147-
if (within.exists && !x.symbol.is(core.Flags.Protected)) Some(within.typeRef)
154+
val within = definition.symbol.privateWithin
155+
if (within.exists && !definition.symbol.is(core.Flags.Protected)) Some(within.typeRef)
148156
else None
149157
}
150158

151159
def protectedWithin(implicit ctx: Context): Option[Type] = {
152-
val within = x.symbol.privateWithin
153-
if (within.exists && x.symbol.is(core.Flags.Protected)) Some(within.typeRef)
160+
val within = definition.symbol.privateWithin
161+
if (within.exists && definition.symbol.is(core.Flags.Protected)) Some(within.typeRef)
154162
else None
155163
}
156164

157165
def annots(implicit ctx: Context): List[Term] = {
158-
x.symbol.annotations.flatMap {
166+
definition.symbol.annotations.flatMap {
159167
case _: core.Annotations.LazyBodyAnnotation => Nil
160168
case annot => annot.tree :: Nil
161169
}
162170
}
163171

164172
def localContext(implicit ctx: Context): Context =
165-
if (x.hasType && x.symbol.exists) ctx.withOwner(x.symbol)
173+
if (definition.hasType && definition.symbol.exists) ctx.withOwner(definition.symbol)
166174
else ctx
167175
}
168176

@@ -177,13 +185,20 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s
177185
object ClassDef extends ClassDefExtractor {
178186
def unapply(x: ClassDef)(implicit ctx: Context): Option[(String, DefDef, List[Parent], Option[ValDef], List[Statement])] = x match {
179187
case x: tpd.TypeDef @unchecked if x.isClassDef =>
180-
val temp @ Trees.Template(constr, parents, self, _) = x.rhs
181-
val selfVal = if (self.isEmpty) None else Some(self)
182-
Some((x.name.toString, constr, parents, selfVal, temp.body))
188+
val deco = ClassDefDeco(x)
189+
Some((x.name.toString, deco.constructor, deco.parents, deco.self, deco.body))
183190
case _ => None
184191
}
185192
}
186193

194+
def ClassDefDeco(cdef: ClassDef): ClassDefAPI = new ClassDefAPI {
195+
private[this] val rhs = cdef.rhs.asInstanceOf[tpd.Template]
196+
def constructor(implicit ctx: Context): DefDef = rhs.constr
197+
def parents(implicit ctx: Context): List[tpd.Tree] = rhs.parents
198+
def self(implicit ctx: Context): Option[tpd.ValDef] = optional(rhs.self)
199+
def body(implicit ctx: Context): List[tpd.Tree] = rhs.body
200+
}
201+
187202
// DefDef
188203

189204
type DefDef = tpd.DefDef
@@ -193,11 +208,18 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s
193208
object DefDef extends DefDefExtractor {
194209
def unapply(x: DefDef)(implicit ctx: Context): Option[(String, List[TypeDef], List[List[ValDef]], TypeTree, Option[Term])] = x match {
195210
case x: tpd.DefDef @unchecked =>
196-
Some((x.name.toString, x.tparams, x.vparamss, x.tpt, if (x.rhs.isEmpty) None else Some(x.rhs)))
211+
Some((x.name.toString, x.tparams, x.vparamss, x.tpt, optional(x.rhs)))
197212
case _ => None
198213
}
199214
}
200215

216+
def DefDefDeco(ddef: DefDef): DefDefAPI = new DefDefAPI {
217+
def typeParams(implicit ctx: Context): List[TypeDef] = ddef.tparams
218+
def paramss(implicit ctx: Context): List[List[ValDef]] = ddef.vparamss
219+
def returnTpt(implicit ctx: Context): TypeTree = ddef.tpt
220+
def rhs(implicit ctx: Context): Option[Tree] = optional(ddef.rhs)
221+
}
222+
201223
// ValDef
202224

203225
type ValDef = tpd.ValDef
@@ -207,11 +229,16 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s
207229
object ValDef extends ValDefExtractor {
208230
def unapply(x: ValDef)(implicit ctx: Context): Option[(String, TypeTree, Option[Term])] = x match {
209231
case x: tpd.ValDef @unchecked =>
210-
Some((x.name.toString, x.tpt, if (x.rhs.isEmpty) None else Some(x.rhs)))
232+
Some((x.name.toString, x.tpt, optional(x.rhs)))
211233
case _ => None
212234
}
213235
}
214236

237+
def ValDefDeco(vdef: ValDef): ValDefAPI = new ValDefAPI {
238+
def tpt(implicit ctx: Context): TypeTree = vdef.tpt
239+
def rhs(implicit ctx: Context): Option[Tree] = optional(vdef.rhs)
240+
}
241+
215242
// TypeDef
216243

217244
type TypeDef = tpd.TypeDef
@@ -225,12 +252,21 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s
225252
}
226253
}
227254

255+
def TypeDefDeco(tdef: TypeDef): TypeDefAPI = new TypeDefAPI {
256+
def rhs(implicit ctx: Context): TypeOrBoundsTree = tdef.rhs
257+
}
258+
259+
// PackageDef
260+
228261
type PackageDef = PackageDefinition
229262

230-
def PackageDefDeco(t: PackageDef): PackageDefAPI = new PackageDefAPI {
263+
def PackageDefDeco(pdef: PackageDef): PackageDefAPI = new PackageDefAPI {
264+
265+
def owner(implicit ctx: Context): PackageDefinition = FromSymbol.packageDef(pdef.symbol.owner)
266+
231267
def members(implicit ctx: Context): List[Statement] = {
232-
if (t.symbol.is(core.Flags.JavaDefined)) Nil // FIXME should also support java packages
233-
else t.symbol.info.decls.iterator.map(FromSymbol.definition).toList
268+
if (pdef.symbol.is(core.Flags.JavaDefined)) Nil // FIXME should also support java packages
269+
else pdef.symbol.info.decls.iterator.map(FromSymbol.definition).toList
234270
}
235271
}
236272

@@ -252,15 +288,15 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s
252288

253289
type Term = tpd.Tree
254290

255-
def TermDeco(tree: Term): TermAPI = new TermAPI {
291+
def TermDeco(term: Term): TermAPI = new TermAPI {
256292

257-
def pos(implicit ctx: Context): Position = tree.pos
293+
def pos(implicit ctx: Context): Position = term.pos
258294

259-
def tpe(implicit ctx: Context): Types.Type = tree.tpe
295+
def tpe(implicit ctx: Context): Types.Type = term.tpe
260296

261297
def toExpr[T: quoted.Type](implicit ctx: Context): quoted.Expr[T] = {
262298
typecheck(ctx)
263-
new quoted.Exprs.TastyTreeExpr(tree).asInstanceOf[quoted.Expr[T]]
299+
new quoted.Exprs.TastyTreeExpr(term).asInstanceOf[quoted.Expr[T]]
264300
}
265301

266302
private def typecheck[T: quoted.Type](ctx: Contexts.Context): Unit = {
@@ -270,15 +306,15 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s
270306
def doReport(m: MessageContainer)(implicit ctx: Contexts.Context): Unit = ()
271307
})
272308
val tp = QuotedTypeDeco(implicitly[quoted.Type[T]]).toTasty
273-
ctx0.typer.typed(tree, tp.tpe)
309+
ctx0.typer.typed(term, tp.tpe)
274310
if (ctx0.reporter.hasErrors) {
275311
val stack = new Exception().getStackTrace
276312
def filter(elem: StackTraceElement) =
277313
elem.getClassName.startsWith("dotty.tools.dotc.tasty.TastyImpl") ||
278314
!elem.getClassName.startsWith("dotty.tools.dotc")
279315
throw new scala.tasty.TastyTypecheckError(
280316
s"""Error during tasty reflection while typing term
281-
|term: ${tree.show}
317+
|term: ${term.show}
282318
|with expected type: ${tp.tpe.show}
283319
|
284320
| ${stack.takeWhile(filter).mkString("\n ")}
@@ -321,7 +357,7 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s
321357

322358
object This extends ThisExtractor {
323359
def unapply(x: Term)(implicit ctx: Context): Option[Option[Id]] = x match {
324-
case Trees.This(qual) => Some(if (qual.isEmpty) None else Some(qual))
360+
case Trees.This(qual) => Some(optional(qual))
325361
case _ => None
326362
}
327363
}
@@ -414,7 +450,7 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s
414450

415451
object Lambda extends LambdaExtractor {
416452
def unapply(x: Term)(implicit ctx: Context): Option[(Term, Option[TypeTree])] = x match {
417-
case x: tpd.Closure @unchecked => Some((x.meth, if (x.tpt.isEmpty) None else Some(x.tpt)))
453+
case x: tpd.Closure @unchecked => Some((x.meth, optional(x.tpt)))
418454
case _ => None
419455
}
420456
}
@@ -435,7 +471,7 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s
435471

436472
object Try extends TryExtractor {
437473
def unapply(x: Term)(implicit ctx: Context): Option[(Term, List[CaseDef], Option[Term])] = x match {
438-
case x: tpd.Try @unchecked => Some((x.expr, x.cases, if (x.finalizer.isEmpty) None else Some(x.finalizer)))
474+
case x: tpd.Try @unchecked => Some((x.expr, x.cases, optional(x.finalizer)))
439475
case _ => None
440476
}
441477
}
@@ -497,12 +533,15 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s
497533

498534
def CaseDefDeco(caseDef: CaseDef): CaseDefAPI = new CaseDefAPI {
499535
def show(implicit ctx: Context, s: Show[TastyImpl.this.type]): String = s.showCaseDef(caseDef)
536+
def pattern(implicit ctx: Context): Pattern = caseDef.pat
537+
def guard(implicit ctx: Context): Option[Term] = optional(caseDef.guard)
538+
def rhs(implicit ctx: Context): Term = caseDef.body
500539
}
501540

502541
object CaseDef extends CaseDefExtractor {
503542
def unapply(x: CaseDef): Option[(Pattern, Option[Term], Term)] = x match {
504543
case x: tpd.CaseDef @unchecked =>
505-
Some(x.pat, if (x.guard.isEmpty) None else Some(x.guard), x.body)
544+
Some(x.pat, optional(x.guard), x.body)
506545
case _ => None
507546
}
508547
}
@@ -575,9 +614,9 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s
575614

576615
type TypeTree = tpd.Tree
577616

578-
def TypeTreeDeco(x: TypeTree): TypeTreeAPI = new TypeTreeAPI {
579-
def pos(implicit ctx: Context): Position = x.pos
580-
def tpe(implicit ctx: Context): Types.Type = x.tpe.stripTypeVar
617+
def TypeTreeDeco(tpt: TypeTree): TypeTreeAPI = new TypeTreeAPI {
618+
def pos(implicit ctx: Context): Position = tpt.pos
619+
def tpe(implicit ctx: Context): Types.Type = tpt.tpe.stripTypeVar
581620
}
582621

583622
def typeTreeClassTag: ClassTag[TypeTree] = implicitly[ClassTag[TypeTree]]
@@ -682,8 +721,10 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s
682721

683722
type TypeBoundsTree = tpd.Tree
684723

685-
def TypeBoundsTreeDeco(x: TypeBoundsTree): TypeBoundsTreeAPI = new TypeBoundsTreeAPI {
686-
def tpe(implicit ctx: Context): TypeBounds = x.tpe.asInstanceOf[Types.TypeBounds]
724+
def TypeBoundsTreeDeco(bounds: TypeBoundsTree): TypeBoundsTreeAPI = new TypeBoundsTreeAPI {
725+
def tpe(implicit ctx: Context): TypeBounds = bounds.tpe.asInstanceOf[Types.TypeBounds]
726+
def low(implicit ctx: Context): TypeTree = bounds.asInstanceOf[tpd.TypeBoundsTree].lo
727+
def hi(implicit ctx: Context): TypeTree = bounds.asInstanceOf[tpd.TypeBoundsTree].hi
687728
}
688729

689730
def typeBoundsTreeClassTag: ClassTag[TypeBoundsTree] = implicitly[ClassTag[TypeBoundsTree]]
@@ -726,9 +767,24 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s
726767
def polyTypeClassTag: ClassTag[PolyType] = implicitly[ClassTag[PolyType]]
727768
def typeLambdaClassTag: ClassTag[TypeLambda] = implicitly[ClassTag[TypeLambda]]
728769

729-
def MethodTypeDeco(x: MethodType): MethodTypeAPI = new MethodTypeAPI {
730-
def isErased: Boolean = x.isErasedMethod
731-
def isImplicit: Boolean = x.isImplicitMethod
770+
def MethodTypeDeco(tpe: MethodType): MethodTypeAPI = new MethodTypeAPI {
771+
def isErased: Boolean = tpe.isErasedMethod
772+
def isImplicit: Boolean = tpe.isImplicitMethod
773+
def paramNames(implicit ctx: Context): List[String] = tpe.paramNames.map(_.toString)
774+
def paramTypes(implicit ctx: Context): List[Type] = tpe.paramInfos
775+
def resultTpe(implicit ctx: Context): Type = tpe.resType
776+
}
777+
778+
def PolyTypeDeco(tpe: Types.PolyType): PolyTypeAPI = new PolyTypeAPI {
779+
def paramNames(implicit ctx: Context): List[String] = tpe.paramNames.map(_.toString)
780+
def paramTypes(implicit ctx: Context): List[TypeBounds] = tpe.paramInfos
781+
def resultTpe(implicit ctx: Context): Type = tpe.resType
782+
}
783+
784+
def TypeLambdaDeco(tpe: Types.TypeLambda): TypeLambdaAPI = new TypeLambdaAPI {
785+
def paramNames(implicit ctx: Context): List[String] = tpe.paramNames.map(_.toString)
786+
def paramTypes(implicit ctx: Context): List[TypeBounds] = tpe.paramInfos
787+
def resultTpe(implicit ctx: Context): Type = tpe.resType
732788
}
733789

734790
object Type extends TypeModule {
@@ -894,6 +950,11 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s
894950
}
895951
}
896952

953+
def TypeBoundsDeco(tpe: TypeBounds): TypeBoundsAPI = new TypeBoundsAPI {
954+
def low(implicit ctx: Context): Type = tpe.lo
955+
def hi(implicit ctx: Context): Type = tpe.hi
956+
}
957+
897958
// ----- NoPrefix --------------------------------------------------
898959

899960
type NoPrefix = Types.NoPrefix.type
@@ -1015,6 +1076,11 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s
10151076
}
10161077
}
10171078

1079+
def SignatureDeco(sig: Signature): SignatureAPI = new SignatureAPI {
1080+
def paramSigs: List[String] = sig.paramsSig.map(_.toString)
1081+
def resultSig: String = sig.resSig.toString
1082+
}
1083+
10181084
// ===== Positions ================================================
10191085

10201086
type Position = SourcePosition
@@ -1032,4 +1098,9 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s
10321098
def endColumn = pos.endColumn
10331099
}
10341100

1101+
// ===== Helpers ==================================================
1102+
1103+
private def optional[T <: Trees.Tree[_]](tree: T): Option[tree.type] =
1104+
if (tree.isEmpty) None else Some(tree)
1105+
10351106
}
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package dotty.tools.dotc
22

33
import dotty.tools.dotc.ast.Trees.{Tree, Untyped}
4+
import dotty.tools.dotc.core.Contexts.Context
45
import dotty.tools.dotc.core.Symbols.Symbol
56
import dotty.tools.dotc.core.Types.Type
67

@@ -9,8 +10,9 @@ package object tastyreflect {
910
type PackageDefinition = PackageDefinitionImpl[Type]
1011

1112
/** Represents the symbol of a definition in tree form */
12-
case class PackageDefinitionImpl[-T >: Untyped] private[tastyreflect] (symbol: Symbol) extends Tree[T] {
13+
case class PackageDefinitionImpl[-T >: Untyped] private[tastyreflect] (sym: Symbol) extends Tree[T] {
1314
type ThisTree[-T >: Untyped] = PackageDefinitionImpl[T]
15+
override def denot(implicit ctx: Context) = sym.denot
1416
}
1517

1618
}

0 commit comments

Comments
 (0)