for ( tree @ Apply(Select(rcvr,nme.DIV),List(Literal(Constant(0)))) <- unit.body; if rcvr.tpe <:< deFinitions.IntClass.tpe) { unit.error(tree.pos,"definitely division by zero") }
该表达式将所有除以零.我无法弄清楚如何做类似的事情来找到所有可执行语句(TermTrees ??).
解决方法
class TwoStatements { def f { println("first statement") println("second statement") } }
试试这些命令:
scalac -Yshow-trees -Xprint:typer TwoStatements.scala scalac -Yshow-trees-compact -Xprint:typer TwoStatements.scala scalac -Yshow-trees-stringified -Xprint:typer TwoStatements.scala scalac -Ybrowse:typer TwoStatements.scala
请注意,typer是产生输出的阶段.因此,请选择适合您自己的插件运行阶段的阶段.
-Yshow-trees-compact是一个产生与你自己的代码中使用的输出完全(或非常接近)的输出,但它很难阅读.
其他的更容易阅读,但可能会混淆翻译成您自己的代码. -Yshow-trees-stringified可能比-Yshow-trees更有用,因为它显示的信息最多.另一方面,-Ybrowse:typer是交互式的,并显示所选树节点的代码,这可能会有所帮助,特别是如果你查看较大的程序.
如果您尝试使用链接博客中的示例-Yshow-trees-compact,您将看到以下代码段:
Apply( Select( Select(This(newTypeName("Test")),newTermName("five")),// assigned to rcvr newTermName("$div") // compared to nme.DIV ),List(Literal(Constant(0)))) // as is )
所以我建议你看看你想要处理的代码是如何在你的插件工作的阶段被翻译成的,然后只需抓住代码片段,并用变量替换任何不感兴趣的部分.
您会注意到每个DefDef都将body作为其第六个元素.它可能是一个带有多个语句列表的块,它可能是方法调用(Apply),getter(Select),assigment(Assign),if语句(If)等等.其他类型的声明,例如ValDef,也有与之关联的代码.
如果您正在寻找像tree @ Statement(…)这样的东西,它就不存在了.您可以使用TermTree
(或者,更好的方法是isTerm)来识别代表代码的内容,但这不会让您将表达式或完整块的部分语句分开.
查看实际代码的AST,并了解它是如何工作的.
编辑
观看a presentation只是在scala / reflecti / api / Trees.scala文件的末尾引用了我的评论:
// A standard pattern match case EmptyTree => case PackageDef(pid,stats) => // package pid { stats } case ClassDef(mods,name,tparams,impl) => // mods class name [tparams] impl where impl = extends parents { defs } case ModuleDef(mods,impl) => (eliminated by refcheck) // mods object name impl where impl = extends parents { defs } case ValDef(mods,tpt,rhs) => // mods val name: tpt = rhs // note missing type information is expressed by tpt = TypeTree() case DefDef(mods,vparamss,rhs) => // mods def name[tparams](vparams_1)...(vparams_n): tpt = rhs // note missing type information is expressed by tpt = TypeTree() case TypeDef(mods,rhs) => (eliminated by erasure) // mods type name[tparams] = rhs // mods type name[tparams] >: lo <: hi,where lo,hi are in a TypeBoundsTree,and DEFERRED is set in mods case LabelDef(name,params,rhs) => // used for tailcalls and like // while/do are desugared to label defs as follows: // while (cond) body ==> LabelDef($L,List(),if (cond) { body; L$() } else ()) // do body while (cond) ==> LabelDef($L,body; if (cond) L$() else ()) case Import(expr,selectors) => (eliminated by typecheck) // import expr.{selectors} // Selectors are a list of pairs of names (from,to). // The last (and maybe only name) may be a nme.WILDCARD // for instance // import qual.{x,y => z,_} would be represented as // Import(qual,List(("x","x"),("y","z"),(WILDCARD,null))) case Template(parents,self,body) => // extends parents { self => body } // if self is missing it is represented as emptyValDef case Block(stats,expr) => // { stats; expr } case CaseDef(pat,guard,body) => (eliminated by transmatch/explicitouter) // case pat if guard => body case Alternative(trees) => (eliminated by transmatch/explicitouter) // pat1 | ... | patn case Star(elem) => (eliminated by transmatch/explicitouter) // pat* case Bind(name,body) => (eliminated by transmatch/explicitouter) // name @ pat case UnApply(fun: Tree,args) (introduced by typer,eliminated by transmatch/explicitouter) // used for unapply's case ArrayValue(elemtpt,trees) => (introduced by uncurry) // used to pass arguments to vararg arguments // for instance,printf("%s%d",foo,42) is translated to after uncurry to: // Apply( // Ident("printf"),// Literal("%s%d"),// ArrayValue(<Any>,List(Ident("foo"),Literal(42)))) case Function(vparams,body) => (eliminated by lambdalift) // vparams => body where vparams:List[ValDef] case Assign(lhs,rhs) => // lhs = rhs case AssignorNamedArg(lhs,rhs) => (eliminated by typer,resurrected by reifier) // @annotation(lhs = rhs) case If(cond,thenp,elsep) => // if (cond) thenp else elsep case Match(selector,cases) => // selector match { cases } case Return(expr) => // return expr case Try(block,catches,finalizer) => // try block catch { catches } finally finalizer where catches: List[CaseDef] case Throw(expr) => // throw expr case New(tpt) => // new tpt always in the context: (new tpt).<init>[targs](args) case Typed(expr,tpt) => (eliminated by erasure) // expr: tpt case TypeApply(fun,args) => // fun[args] case Apply(fun,args) => // fun(args) // for instance fun[targs](args) is expressed as Apply(TypeApply(fun,targs),args) case ApplyDynamic(qual,args) (introduced by erasure,eliminated by cleanup) // fun(args) case Super(qual,mix) => // qual.super[mix] qual is always This(something),if mix is empty,it is tpnme.EMPTY case This(qual) => // qual.this case Select(qualifier,selector) => // qualifier.selector case Ident(name) => // name // note: type checker converts idents that refer to enclosing fields or methods // to selects; name ==> this.name case ReferencetoBoxed(ident) => (created by typer,eliminated by lambdalift) // synthetic node emitted by macros to reference capture vars directly without going through ``elem'' // var x = ...; fun { x } will emit Ident(x),which gets transformed to Select(Ident(x),"elem") // if ReferencetoBoxed were used instead of Ident,no transformation would be performed case Literal(value) => // value case TypeTree() => (introduced by refcheck) // a type that's not written out,but given in the tpe attribute case Annotated(annot,arg) => (eliminated by typer) // arg @annot for types,arg: @annot for exprs case SingletonTypeTree(ref) => (eliminated by uncurry) // ref.type case SelectFromTypeTree(qualifier,selector) => (eliminated by uncurry) // qualifier # selector,a path-dependent type p.T is expressed as p.type # T case CompoundTypeTree(templ: Template) => (eliminated by uncurry) // parent1 with ... with parentN { refinement } case AppliedTypeTree(tpt,args) => (eliminated by uncurry) // tpt[args] case TypeBoundsTree(lo,hi) => (eliminated by uncurry) // >: lo <: hi case ExistentialTypeTree(tpt,whereClauses) => (eliminated by uncurry) // tpt forSome { whereClauses }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。