わかりました、以下のファイルを想定しますTwoStatements.scala
:
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
everyには body が 6 番目の要素として含まれていることに注意してください。それはBlock
、List
複数のステートメントの場合もあれば、メソッド呼び出し ( Apply
)、ゲッター ( Select
)、代入 ( Assign
)、if ステートメント ( If
) などの場合もあります。などの他の種類の宣言にValDef
も、コードが関連付けられています。
のようなものを探していた場合tree @ Statement(...)
、存在しません。TermTree
コードを表すものを識別するために (または、さらに良い方法として) を使用することもできisTerm
ますが、式の一部または完全なブロックからステートメントを区別することはできません。
実際のコードの AST を見て、それがどのように機能するかを学びます。
編集
プレゼンテーションを見ていて、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, name, impl) => (eliminated by refcheck)
// mods object name impl where impl = extends parents { defs }
case ValDef(mods, name, tpt, rhs) =>
// mods val name: tpt = rhs
// note missing type information is expressed by tpt = TypeTree()
case DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
// mods def name[tparams](vparams_1)...(vparams_n): tpt = rhs
// note missing type information is expressed by tpt = TypeTree()
case TypeDef(mods, name, tparams, 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, List(), 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 }