From b7c6f76dfca1a30916f16f1e87a742c965a35113 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Fri, 22 Jun 2018 17:13:55 +0200 Subject: [PATCH] Add tasty reflect members for definitions --- .../tools/dotc/tastyreflect/TastyImpl.scala | 149 +++++++++++++----- .../tools/dotc/tastyreflect/package.scala | 4 +- library/src/scala/tasty/Tasty.scala | 92 +++++++++-- .../src/scala/tasty/util/ShowSourceCode.scala | 56 +++---- tests/pos/tasty/definitions.scala | 1 + 5 files changed, 219 insertions(+), 83 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/TastyImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/TastyImpl.scala index e41eeedf81a4..fdd78ccc4ed7 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/TastyImpl.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/TastyImpl.scala @@ -49,8 +49,9 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s type Id = untpd.Ident - def IdDeco(x: Id): IdAPI = new IdAPI { - def pos(implicit ctx: Context): Position = x.pos + def IdDeco(id: Id): IdAPI = new IdAPI { + def pos(implicit ctx: Context): Position = id.pos + def name(implicit ctx: Context): String = id.name.toString } def idClassTag: ClassTag[Id] = implicitly[ClassTag[Id]] @@ -82,8 +83,8 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s } } - def PackageClauseDeco(x: PackageClause): PackageClauseAPI = new PackageClauseAPI { - def definition(implicit ctx: Context): Definition = FromSymbol.packageDef(x.symbol) + def PackageClauseDeco(pack: PackageClause): PackageClauseAPI = new PackageClauseAPI { + def definition(implicit ctx: Context): Definition = FromSymbol.packageDef(pack.symbol) } // ----- Statements ----------------------------------------------- @@ -101,6 +102,11 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s } } + def ImportDeco(imp: Import): ImportAPI = new ImportAPI { + def expr(implicit ctx: Context): Tree = imp.expr + def selector(implicit ctx: Context): List[ImportSelector] = imp.selectors + } + type ImportSelector = untpd.Tree def importSelectorClassTag: ClassTag[ImportSelector] = implicitly[ClassTag[ImportSelector]] @@ -135,34 +141,36 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s x.isInstanceOf[Trees.MemberDef[_]] } - def DefinitionDeco(x: Definition): DefinitionAPI = new DefinitionAPI { + def DefinitionDeco(definition: Definition): DefinitionAPI = new DefinitionAPI { - def owner(implicit ctx: Context): Definition = FromSymbol.definition(x.symbol.owner) + def name(implicit ctx: Context): String = definition.symbol.name.toString + + def owner(implicit ctx: Context): Definition = FromSymbol.definition(definition.symbol.owner) def flags(implicit ctx: Context): FlagSet = - new FlagSet(x.symbol.flags) + new FlagSet(definition.symbol.flags) def privateWithin(implicit ctx: Context): Option[Type] = { - val within = x.symbol.privateWithin - if (within.exists && !x.symbol.is(core.Flags.Protected)) Some(within.typeRef) + val within = definition.symbol.privateWithin + if (within.exists && !definition.symbol.is(core.Flags.Protected)) Some(within.typeRef) else None } def protectedWithin(implicit ctx: Context): Option[Type] = { - val within = x.symbol.privateWithin - if (within.exists && x.symbol.is(core.Flags.Protected)) Some(within.typeRef) + val within = definition.symbol.privateWithin + if (within.exists && definition.symbol.is(core.Flags.Protected)) Some(within.typeRef) else None } def annots(implicit ctx: Context): List[Term] = { - x.symbol.annotations.flatMap { + definition.symbol.annotations.flatMap { case _: core.Annotations.LazyBodyAnnotation => Nil case annot => annot.tree :: Nil } } def localContext(implicit ctx: Context): Context = - if (x.hasType && x.symbol.exists) ctx.withOwner(x.symbol) + if (definition.hasType && definition.symbol.exists) ctx.withOwner(definition.symbol) else ctx } @@ -177,13 +185,20 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s object ClassDef extends ClassDefExtractor { def unapply(x: ClassDef)(implicit ctx: Context): Option[(String, DefDef, List[Parent], Option[ValDef], List[Statement])] = x match { case x: tpd.TypeDef @unchecked if x.isClassDef => - val temp @ Trees.Template(constr, parents, self, _) = x.rhs - val selfVal = if (self.isEmpty) None else Some(self) - Some((x.name.toString, constr, parents, selfVal, temp.body)) + val deco = ClassDefDeco(x) + Some((x.name.toString, deco.constructor, deco.parents, deco.self, deco.body)) case _ => None } } + def ClassDefDeco(cdef: ClassDef): ClassDefAPI = new ClassDefAPI { + private[this] val rhs = cdef.rhs.asInstanceOf[tpd.Template] + def constructor(implicit ctx: Context): DefDef = rhs.constr + def parents(implicit ctx: Context): List[tpd.Tree] = rhs.parents + def self(implicit ctx: Context): Option[tpd.ValDef] = optional(rhs.self) + def body(implicit ctx: Context): List[tpd.Tree] = rhs.body + } + // DefDef type DefDef = tpd.DefDef @@ -193,11 +208,18 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s object DefDef extends DefDefExtractor { def unapply(x: DefDef)(implicit ctx: Context): Option[(String, List[TypeDef], List[List[ValDef]], TypeTree, Option[Term])] = x match { case x: tpd.DefDef @unchecked => - Some((x.name.toString, x.tparams, x.vparamss, x.tpt, if (x.rhs.isEmpty) None else Some(x.rhs))) + Some((x.name.toString, x.tparams, x.vparamss, x.tpt, optional(x.rhs))) case _ => None } } + def DefDefDeco(ddef: DefDef): DefDefAPI = new DefDefAPI { + def typeParams(implicit ctx: Context): List[TypeDef] = ddef.tparams + def paramss(implicit ctx: Context): List[List[ValDef]] = ddef.vparamss + def returnTpt(implicit ctx: Context): TypeTree = ddef.tpt + def rhs(implicit ctx: Context): Option[Tree] = optional(ddef.rhs) + } + // ValDef type ValDef = tpd.ValDef @@ -207,11 +229,16 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s object ValDef extends ValDefExtractor { def unapply(x: ValDef)(implicit ctx: Context): Option[(String, TypeTree, Option[Term])] = x match { case x: tpd.ValDef @unchecked => - Some((x.name.toString, x.tpt, if (x.rhs.isEmpty) None else Some(x.rhs))) + Some((x.name.toString, x.tpt, optional(x.rhs))) case _ => None } } + def ValDefDeco(vdef: ValDef): ValDefAPI = new ValDefAPI { + def tpt(implicit ctx: Context): TypeTree = vdef.tpt + def rhs(implicit ctx: Context): Option[Tree] = optional(vdef.rhs) + } + // TypeDef type TypeDef = tpd.TypeDef @@ -225,12 +252,21 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s } } + def TypeDefDeco(tdef: TypeDef): TypeDefAPI = new TypeDefAPI { + def rhs(implicit ctx: Context): TypeOrBoundsTree = tdef.rhs + } + + // PackageDef + type PackageDef = PackageDefinition - def PackageDefDeco(t: PackageDef): PackageDefAPI = new PackageDefAPI { + def PackageDefDeco(pdef: PackageDef): PackageDefAPI = new PackageDefAPI { + + def owner(implicit ctx: Context): PackageDefinition = FromSymbol.packageDef(pdef.symbol.owner) + def members(implicit ctx: Context): List[Statement] = { - if (t.symbol.is(core.Flags.JavaDefined)) Nil // FIXME should also support java packages - else t.symbol.info.decls.iterator.map(FromSymbol.definition).toList + if (pdef.symbol.is(core.Flags.JavaDefined)) Nil // FIXME should also support java packages + else pdef.symbol.info.decls.iterator.map(FromSymbol.definition).toList } } @@ -252,15 +288,15 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s type Term = tpd.Tree - def TermDeco(tree: Term): TermAPI = new TermAPI { + def TermDeco(term: Term): TermAPI = new TermAPI { - def pos(implicit ctx: Context): Position = tree.pos + def pos(implicit ctx: Context): Position = term.pos - def tpe(implicit ctx: Context): Types.Type = tree.tpe + def tpe(implicit ctx: Context): Types.Type = term.tpe def toExpr[T: quoted.Type](implicit ctx: Context): quoted.Expr[T] = { typecheck(ctx) - new quoted.Exprs.TastyTreeExpr(tree).asInstanceOf[quoted.Expr[T]] + new quoted.Exprs.TastyTreeExpr(term).asInstanceOf[quoted.Expr[T]] } private def typecheck[T: quoted.Type](ctx: Contexts.Context): Unit = { @@ -270,7 +306,7 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s def doReport(m: MessageContainer)(implicit ctx: Contexts.Context): Unit = () }) val tp = QuotedTypeDeco(implicitly[quoted.Type[T]]).toTasty - ctx0.typer.typed(tree, tp.tpe) + ctx0.typer.typed(term, tp.tpe) if (ctx0.reporter.hasErrors) { val stack = new Exception().getStackTrace def filter(elem: StackTraceElement) = @@ -278,7 +314,7 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s !elem.getClassName.startsWith("dotty.tools.dotc") throw new scala.tasty.TastyTypecheckError( s"""Error during tasty reflection while typing term - |term: ${tree.show} + |term: ${term.show} |with expected type: ${tp.tpe.show} | | ${stack.takeWhile(filter).mkString("\n ")} @@ -321,7 +357,7 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s object This extends ThisExtractor { def unapply(x: Term)(implicit ctx: Context): Option[Option[Id]] = x match { - case Trees.This(qual) => Some(if (qual.isEmpty) None else Some(qual)) + case Trees.This(qual) => Some(optional(qual)) case _ => None } } @@ -414,7 +450,7 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s object Lambda extends LambdaExtractor { def unapply(x: Term)(implicit ctx: Context): Option[(Term, Option[TypeTree])] = x match { - case x: tpd.Closure @unchecked => Some((x.meth, if (x.tpt.isEmpty) None else Some(x.tpt))) + case x: tpd.Closure @unchecked => Some((x.meth, optional(x.tpt))) case _ => None } } @@ -435,7 +471,7 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s object Try extends TryExtractor { def unapply(x: Term)(implicit ctx: Context): Option[(Term, List[CaseDef], Option[Term])] = x match { - case x: tpd.Try @unchecked => Some((x.expr, x.cases, if (x.finalizer.isEmpty) None else Some(x.finalizer))) + case x: tpd.Try @unchecked => Some((x.expr, x.cases, optional(x.finalizer))) case _ => None } } @@ -497,12 +533,15 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s def CaseDefDeco(caseDef: CaseDef): CaseDefAPI = new CaseDefAPI { def show(implicit ctx: Context, s: Show[TastyImpl.this.type]): String = s.showCaseDef(caseDef) + def pattern(implicit ctx: Context): Pattern = caseDef.pat + def guard(implicit ctx: Context): Option[Term] = optional(caseDef.guard) + def rhs(implicit ctx: Context): Term = caseDef.body } object CaseDef extends CaseDefExtractor { def unapply(x: CaseDef): Option[(Pattern, Option[Term], Term)] = x match { case x: tpd.CaseDef @unchecked => - Some(x.pat, if (x.guard.isEmpty) None else Some(x.guard), x.body) + Some(x.pat, optional(x.guard), x.body) case _ => None } } @@ -575,9 +614,9 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s type TypeTree = tpd.Tree - def TypeTreeDeco(x: TypeTree): TypeTreeAPI = new TypeTreeAPI { - def pos(implicit ctx: Context): Position = x.pos - def tpe(implicit ctx: Context): Types.Type = x.tpe.stripTypeVar + def TypeTreeDeco(tpt: TypeTree): TypeTreeAPI = new TypeTreeAPI { + def pos(implicit ctx: Context): Position = tpt.pos + def tpe(implicit ctx: Context): Types.Type = tpt.tpe.stripTypeVar } def typeTreeClassTag: ClassTag[TypeTree] = implicitly[ClassTag[TypeTree]] @@ -682,8 +721,10 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s type TypeBoundsTree = tpd.Tree - def TypeBoundsTreeDeco(x: TypeBoundsTree): TypeBoundsTreeAPI = new TypeBoundsTreeAPI { - def tpe(implicit ctx: Context): TypeBounds = x.tpe.asInstanceOf[Types.TypeBounds] + def TypeBoundsTreeDeco(bounds: TypeBoundsTree): TypeBoundsTreeAPI = new TypeBoundsTreeAPI { + def tpe(implicit ctx: Context): TypeBounds = bounds.tpe.asInstanceOf[Types.TypeBounds] + def low(implicit ctx: Context): TypeTree = bounds.asInstanceOf[tpd.TypeBoundsTree].lo + def hi(implicit ctx: Context): TypeTree = bounds.asInstanceOf[tpd.TypeBoundsTree].hi } def typeBoundsTreeClassTag: ClassTag[TypeBoundsTree] = implicitly[ClassTag[TypeBoundsTree]] @@ -726,9 +767,24 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s def polyTypeClassTag: ClassTag[PolyType] = implicitly[ClassTag[PolyType]] def typeLambdaClassTag: ClassTag[TypeLambda] = implicitly[ClassTag[TypeLambda]] - def MethodTypeDeco(x: MethodType): MethodTypeAPI = new MethodTypeAPI { - def isErased: Boolean = x.isErasedMethod - def isImplicit: Boolean = x.isImplicitMethod + def MethodTypeDeco(tpe: MethodType): MethodTypeAPI = new MethodTypeAPI { + def isErased: Boolean = tpe.isErasedMethod + def isImplicit: Boolean = tpe.isImplicitMethod + def paramNames(implicit ctx: Context): List[String] = tpe.paramNames.map(_.toString) + def paramTypes(implicit ctx: Context): List[Type] = tpe.paramInfos + def resultTpe(implicit ctx: Context): Type = tpe.resType + } + + def PolyTypeDeco(tpe: Types.PolyType): PolyTypeAPI = new PolyTypeAPI { + def paramNames(implicit ctx: Context): List[String] = tpe.paramNames.map(_.toString) + def paramTypes(implicit ctx: Context): List[TypeBounds] = tpe.paramInfos + def resultTpe(implicit ctx: Context): Type = tpe.resType + } + + def TypeLambdaDeco(tpe: Types.TypeLambda): TypeLambdaAPI = new TypeLambdaAPI { + def paramNames(implicit ctx: Context): List[String] = tpe.paramNames.map(_.toString) + def paramTypes(implicit ctx: Context): List[TypeBounds] = tpe.paramInfos + def resultTpe(implicit ctx: Context): Type = tpe.resType } object Type extends TypeModule { @@ -894,6 +950,11 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s } } + def TypeBoundsDeco(tpe: TypeBounds): TypeBoundsAPI = new TypeBoundsAPI { + def low(implicit ctx: Context): Type = tpe.lo + def hi(implicit ctx: Context): Type = tpe.hi + } + // ----- NoPrefix -------------------------------------------------- type NoPrefix = Types.NoPrefix.type @@ -1015,6 +1076,11 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s } } + def SignatureDeco(sig: Signature): SignatureAPI = new SignatureAPI { + def paramSigs: List[String] = sig.paramsSig.map(_.toString) + def resultSig: String = sig.resSig.toString + } + // ===== Positions ================================================ type Position = SourcePosition @@ -1032,4 +1098,9 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s def endColumn = pos.endColumn } + // ===== Helpers ================================================== + + private def optional[T <: Trees.Tree[_]](tree: T): Option[tree.type] = + if (tree.isEmpty) None else Some(tree) + } diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/package.scala b/compiler/src/dotty/tools/dotc/tastyreflect/package.scala index 4a90eb60e9ab..187ffb8d176c 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/package.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/package.scala @@ -1,6 +1,7 @@ package dotty.tools.dotc import dotty.tools.dotc.ast.Trees.{Tree, Untyped} +import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.core.Symbols.Symbol import dotty.tools.dotc.core.Types.Type @@ -9,8 +10,9 @@ package object tastyreflect { type PackageDefinition = PackageDefinitionImpl[Type] /** Represents the symbol of a definition in tree form */ - case class PackageDefinitionImpl[-T >: Untyped] private[tastyreflect] (symbol: Symbol) extends Tree[T] { + case class PackageDefinitionImpl[-T >: Untyped] private[tastyreflect] (sym: Symbol) extends Tree[T] { type ThisTree[-T >: Untyped] = PackageDefinitionImpl[T] + override def denot(implicit ctx: Context) = sym.denot } } diff --git a/library/src/scala/tasty/Tasty.scala b/library/src/scala/tasty/Tasty.scala index f50681964fca..7b8d830f0d2c 100644 --- a/library/src/scala/tasty/Tasty.scala +++ b/library/src/scala/tasty/Tasty.scala @@ -43,8 +43,10 @@ abstract class Tasty { tasty => type Id - trait IdAPI extends Positioned - implicit def IdDeco(x: Id): IdAPI + trait IdAPI extends Positioned { + def name(implicit ctx: Context): String + } + implicit def IdDeco(id: Id): IdAPI implicit def idClassTag: ClassTag[Id] @@ -74,7 +76,7 @@ abstract class Tasty { tasty => trait PackageClauseAPI { def definition(implicit ctx: Context): Definition } - implicit def PackageClauseDeco(x: PackageClause): PackageClauseAPI + implicit def PackageClauseDeco(pack: PackageClause): PackageClauseAPI // ----- Statements ----------------------------------------------- @@ -89,6 +91,12 @@ abstract class Tasty { tasty => def unapply(x: Import)(implicit ctx: Context): Option[(Term, List[ImportSelector])] } + trait ImportAPI { + def expr(implicit ctx: Context): Term + def selector(implicit ctx: Context): List[ImportSelector] + } + implicit def ImportDeco(imp: Import): ImportAPI + type ImportSelector implicit def importSelectorClassTag: ClassTag[ImportSelector] @@ -120,6 +128,7 @@ abstract class Tasty { tasty => implicit def definitionClassTag: ClassTag[Definition] trait DefinitionAPI { + def name(implicit ctx: Context): String def flags(implicit ctx: Context): FlagSet def privateWithin(implicit ctx: Context): Option[Type] def protectedWithin(implicit ctx: Context): Option[Type] @@ -127,7 +136,7 @@ abstract class Tasty { tasty => def owner(implicit ctx: Context): Definition def localContext(implicit ctx: Context): Context } - implicit def DefinitionDeco(x: Definition): DefinitionAPI + implicit def DefinitionDeco(definition: Definition): DefinitionAPI // ClassDef @@ -140,6 +149,14 @@ abstract class Tasty { tasty => def unapply(x: ClassDef)(implicit ctx: Context): Option[(String, DefDef, List[Parent], Option[ValDef], List[Statement])] } + trait ClassDefAPI { + def constructor(implicit ctx: Context): DefDef + def parents(implicit ctx: Context): List[Parent] + def self(implicit ctx: Context): Option[ValDef] + def body(implicit ctx: Context): List[Statement] + } + implicit def ClassDefDeco(cdef: ClassDef): ClassDefAPI + // DefDef type DefDef <: Definition @@ -151,6 +168,14 @@ abstract class Tasty { tasty => def unapply(x: DefDef)(implicit ctx: Context): Option[(String, List[TypeDef], List[List[ValDef]], TypeTree, Option[Term])] } + trait DefDefAPI { + def typeParams(implicit ctx: Context): List[TypeDef] + def paramss(implicit ctx: Context): List[List[ValDef]] + def returnTpt(implicit ctx: Context): TypeTree + def rhs(implicit ctx: Context): Option[Term] + } + implicit def DefDefDeco(ddef: DefDef): DefDefAPI + // ValDef type ValDef <: Definition @@ -162,6 +187,12 @@ abstract class Tasty { tasty => def unapply(x: ValDef)(implicit ctx: Context): Option[(String, TypeTree, Option[Term])] } + trait ValDefAPI { + def tpt(implicit ctx: Context): TypeTree + def rhs(implicit ctx: Context): Option[Term] + } + implicit def ValDefDeco(vdef: ValDef): ValDefAPI + // TypeDef type TypeDef <: Definition @@ -173,14 +204,20 @@ abstract class Tasty { tasty => def unapply(x: TypeDef)(implicit ctx: Context): Option[(String, TypeOrBoundsTree /* TypeTree | TypeBoundsTree */)] } + trait TypeDefAPI { + def rhs(implicit ctx: Context): TypeOrBoundsTree + } + implicit def TypeDefDeco(tdef: TypeDef): TypeDefAPI + // PackageDef type PackageDef <: Definition trait PackageDefAPI { + def owner(implicit ctx: Context): PackageDef def members(implicit ctx: Context): List[Statement] } - implicit def PackageDefDeco(t: PackageDef): PackageDefAPI + implicit def PackageDefDeco(pdef: PackageDef): PackageDefAPI implicit def packageDefClassTag: ClassTag[PackageDef] @@ -200,7 +237,7 @@ abstract class Tasty { tasty => trait TermAPI extends Typed with Positioned { def toExpr[T: quoted.Type](implicit ctx: Context): quoted.Expr[T] } - implicit def TermDeco(t: Term): TermAPI + implicit def TermDeco(term: Term): TermAPI implicit def termClassTag: ClassTag[Term] @@ -363,6 +400,9 @@ abstract class Tasty { tasty => trait CaseDefAPI { def show(implicit ctx: Context, s: Show[tasty.type]): String + def pattern(implicit ctx: Context): Pattern + def guard(implicit ctx: Context): Option[Term] + def rhs(implicit ctx: Context): Term } implicit def CaseDefDeco(caseDef: CaseDef): CaseDefAPI @@ -377,8 +417,9 @@ abstract class Tasty { tasty => trait PatternAPI extends Typed with Positioned { def show(implicit ctx: Context, s: Show[tasty.type]): String + } - implicit def PatternDeco(x: Pattern): PatternAPI + implicit def PatternDeco(pattern: Pattern): PatternAPI implicit def patternClassTag: ClassTag[Pattern] @@ -428,7 +469,7 @@ abstract class Tasty { tasty => type TypeTree <: TypeOrBoundsTree with Parent trait TypeTreeAPI extends Typed with Positioned - implicit def TypeTreeDeco(x: TypeTree): TypeTreeAPI + implicit def TypeTreeDeco(tpt: TypeTree): TypeTreeAPI implicit def typeTreeClassTag: ClassTag[TypeTree] @@ -511,8 +552,10 @@ abstract class Tasty { tasty => trait TypeBoundsTreeAPI { def tpe(implicit ctx: Context): TypeBounds + def low(implicit ctx: Context): TypeTree + def hi(implicit ctx: Context): TypeTree } - implicit def TypeBoundsTreeDeco(x: TypeBoundsTree): TypeBoundsTreeAPI + implicit def TypeBoundsTreeDeco(tpt: TypeBoundsTree): TypeBoundsTreeAPI implicit def typeBoundsTreeClassTag: ClassTag[TypeBoundsTree] @@ -561,8 +604,25 @@ abstract class Tasty { tasty => trait MethodTypeAPI { def isImplicit: Boolean def isErased: Boolean + def paramNames(implicit ctx: Context): List[String] + def paramTypes(implicit ctx: Context): List[Type] + def resultTpe(implicit ctx: Context): Type + } + implicit def MethodTypeDeco(tpt: MethodType): MethodTypeAPI + + trait PolyTypeAPI { + def paramNames(implicit ctx: Context): List[String] + def paramTypes(implicit ctx: Context): List[TypeBounds] + def resultTpe(implicit ctx: Context): Type + } + implicit def PolyTypeDeco(tpt: PolyType): PolyTypeAPI + + trait TypeLambdaAPI { + def paramNames(implicit ctx: Context): List[String] + def paramTypes(implicit ctx: Context): List[TypeBounds] + def resultTpe(implicit ctx: Context): Type } - implicit def MethodTypeDeco(x: MethodType): MethodTypeAPI + implicit def TypeLambdaDeco(tpt: TypeLambda): TypeLambdaAPI val Type: TypeModule abstract class TypeModule { @@ -672,6 +732,12 @@ abstract class Tasty { tasty => def unapply(x: TypeBounds)(implicit ctx: Context): Option[(Type, Type)] } + trait TypeBoundsAPI { + def low(implicit ctx: Context): Type + def hi(implicit ctx: Context): Type + } + implicit def TypeBoundsDeco(bounds: TypeBounds): TypeBoundsAPI + // ----- NoPrefix ------------------------------------------------- type NoPrefix <: TypeOrBounds @@ -769,6 +835,12 @@ abstract class Tasty { tasty => def unapply(x: Signature)(implicit ctx: Context): Option[(List[String], String)] } + trait SignatureAPI { + def paramSigs: List[String] + def resultSig: String + } + implicit def SignatureDeco(sig: Signature): SignatureAPI + // ===== Positions ================================================ type Position diff --git a/library/src/scala/tasty/util/ShowSourceCode.scala b/library/src/scala/tasty/util/ShowSourceCode.scala index 06d0287a19bd..741a37910daf 100644 --- a/library/src/scala/tasty/util/ShowSourceCode.scala +++ b/library/src/scala/tasty/util/ShowSourceCode.scala @@ -100,8 +100,7 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty if (flags.isCase) this += "case " if (name == "package$") { - this += "package object " - printDefinitionName(cdef.owner) + this += "package object " += cdef.owner.name.stripSuffix("$") } else if (flags.isObject) this += "object " += name.stripSuffix("$") else if (flags.isTrait) this += "trait " += name @@ -285,8 +284,7 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty case Term.This(id) => id match { case Some(x) => - val Id(name) = x - this += name.stripSuffix("$") += "." + this += x.name.stripSuffix("$") += "." case None => } this += "this" @@ -331,10 +329,8 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty case Term.This(None) => } this += "super" - for (id <- idOpt) { - val Id(name) = id - inSquare(this += name) - } + for (id <- idOpt) + inSquare(this += id.name) this case Term.Typed(term, tpt) => @@ -558,9 +554,8 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty } def printTargDef(arg: TypeDef, isMember: Boolean = false): Buffer = { - val TypeDef(name, rhs) = arg - this += name - rhs match { + this += arg.name + arg.rhs match { case rhs @ TypeBoundsTree(lo, hi) => printBoundsTree(rhs) case rhs @ SyntheticBounds() => printTypeOrBound(rhs.tpe) @@ -572,13 +567,11 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty def printSeparated(list: List[TypeDef]): Unit = list match { case Nil => case x :: Nil => - val TypeDef(name, trhs) = x - this += name - printParam(trhs) + this += x.name + printParam(x.rhs) case x :: xs => - val TypeDef(name, trhs) = x - this += name - printParam(trhs) + this += x.name + printParam(x.rhs) this += ", " printSeparated(xs) } @@ -628,7 +621,7 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty } def printParamDef(arg: ValDef): Unit = { - val ValDef(name, tpt, rhs) = arg + val name = arg.name arg.owner match { case DefDef("", _, _, _, _) => val ClassDef(_, _, _, _, body) = arg.owner.owner @@ -650,14 +643,13 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty } this += name += ": " - printTypeTree(tpt) + printTypeTree(arg.tpt) } def printCaseDef(caseDef: CaseDef): Buffer = { - val CaseDef(pat, guard, body) = caseDef this += "case " - printPattern(pat) - guard match { + printPattern(caseDef.pattern) + caseDef.guard match { case Some(t) => this += " if " printTree(t) @@ -665,7 +657,7 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty } this += " =>" indented { - body match { + caseDef.rhs match { case Term.Block(stats, expr) => printStats(stats, expr) case body => @@ -845,7 +837,7 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty this += "." } } - printDefinitionName(sym) + this += sym.name.stripSuffix("$") case Type.TermRef(name, prefix) => prefix match { @@ -1021,27 +1013,25 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty } def printBoundsTree(bounds: TypeBoundsTree): Buffer = { - val TypeBoundsTree(lo, hi) = bounds - lo match { + bounds.low match { case TypeTree.Synthetic() => - case _ => + case low => this += " >: " - printTypeTree(lo) + printTypeTree(low) } - hi match { + bounds.hi match { case TypeTree.Synthetic() => this - case _ => + case hi => this += " <: " printTypeTree(hi) } } def printBounds(bounds: TypeBounds): Buffer = { - val TypeBounds(lo, hi) = bounds this += " >: " - printType(lo) + printType(bounds.low) this += " <: " - printType(hi) + printType(bounds.hi) } def printProtectedOrPrivate(definition: Definition): Boolean = { diff --git a/tests/pos/tasty/definitions.scala b/tests/pos/tasty/definitions.scala index c5bc08dbad86..d3d8a2c38e1e 100644 --- a/tests/pos/tasty/definitions.scala +++ b/tests/pos/tasty/definitions.scala @@ -25,6 +25,7 @@ object definitions { // ------ Definitions --------------------------------- trait Definition { + def name: String def owner: Definition = ??? }