2011-03-10 14 views
13

Groovyでクロージャのソースをどのように印刷するのか知っている人は誰ですか?例えばGroovyでクローズ定義/ソースを印刷

、Iは(aにバインドさ)は、この閉鎖

def a = { it.twice() } 

を有するIはStringしたいと思う "it.twice()" または "{it.twice()}"

単純なtoString ofcourseのは動作しません:グルーヴィーでは不可能である

a.toString(); //results in: [email protected] 
+0

が、これはおそらく、あなたの状況と一致しないであろうことshuldが、あなたは他の道を行くことができるかもしれません。 GroovyShell以降。evaluate()は適切なvarバインディングを使用してStringを実行します。クロージャが単なる文字列だった場合はどうなりますか? –

答えて

24

短い回答はできません。長い答えは:
あなたがのためのコードを必要とするものに応じて、あなたはおそらく

で説明したように、実行時にクラスパスで利用可能なスクリプトのソースコードが必要になります

// file: example1.groovy 
def a = { it.twice() } 
println a.metaClass.classNode.getDeclaredMethods("doCall")[0].code.text 
// prints: { return it.twice() } 

しかし
で逃げることができそれはランタイム
で利用可能 ある場合

groovy.lang.MetaClass#getClassNode()
「はメタクラスの元 ASTへの参照を取得し 元ASTまたはNULLにすることができますよう、それは は「


を返すことができない場合テキストトリックは本当に、同じコード、ASTの表現のようなコードだけを返しません@returnあなただけならば、簡単に見

を取るとしたい場合はそのまままだ、それが役に立つかもしれません。このスクリプトで

// file: example2.groovy 
def b = {p-> p.twice() * "p"} 
println b.metaClass.classNode.getDeclaredMethods("doCall")[0].code.text 
// prints: { return (p.twice() * p) } 

を見てあなたの手にあまりにも多くの時間を持っていて、かなりそれが

OR、ちょうど今groovy.inspect.swingui.AstNodeToScriptVisitor

// file: example3.groovy 
def c = {w-> 
    [1,2,3].each { 
    println "$it" 
    (1..it).each {x-> 
     println 'this seems' << ' somewhat closer' << ''' to the 
     original''' << " $x" 
    } 
    } 
} 
def node = c.metaClass.classNode.getDeclaredMethods("doCall")[0].code 
def writer = new StringWriter() 
node.visit new groovy.inspect.swingui.AstNodeToScriptVisitor(writer) 
println writer 
// prints: return [1, 2, 3].each({ 
//  this.println("$it") 
//  return (1.. it).each({ java.lang.Object x -> 
//   return this.println('this seems' << ' somewhat closer' << ' to the \n  original' << " $x") 
//  }) 
// }) 

のような既存のものを盗む印刷するorg.codehaus.groovy.ast.GroovyCodeVisitorあなた自身を書くことができ何をするか分かりません。
あなたが元は、正確な、実行可能なコード...あなたは運
外である私が意味する場合は、あなたがソース行情報を使用することができますが、私がチェックした最後の時間は、それは本当に彼らに右

を取得していませんでした
// file: example1.groovy 
.... 
def code = a.metaClass.classNode.getDeclaredMethods("doCall")[0].code 
println "$code.lineNumber $code.columnNumber $code.lastLineNumber $code.lastColumnNumber" 
new File('example1.groovy').readLines() 
... etc etc you get the idea. 

行番号が、少なくとも元のコードの近くに

+0

クラスパスで利用可能なスクリプト「ランタイム」は正確に何を意味するのですか?それはまだ動作しません(ClassNodeは 'null'ですが)、私はすべてのソースを利用できます。 Groovyプロジェクトのクラスパスにスクリプトの場所を追加する必要がありますか? – Julian

+1

@Julianは、.groovyファイルがクラスパス内にあることを意味します。 getClassNode()は基本的にファイルをロードし、関連するastノードを保存する特別なフックを使ってファイルを再度コンパイルして返します。 – jpertino

+2

@jpertino Grails環境でどのように行うのか考えていますか?私は、統合テスト中にクラスパス上にあるConfig.groovyファイルを持っていますが、それはrun-app中ではありません。 – asinesio

5

を。 Groovyスクリプトを直接コンパイルせずに直接実行しても、スクリプトはJVMバイトコードに変換されます。クロージャは、まったく違った扱いを受けず、通常の方法のようにコンパイルされます。コードが実行されるまでに、ソースコードはもう利用できません。