2011-03-10 3 views
13

Groovy에서 클로저 소스를 인쇄하는 방법을 아는 사람은 누구입니까?Groovy에서 클로저 정의/소스 인쇄

예를 들어, 나는 (a에 바인더 제본)이 폐쇄

def a = { it.twice() } 

내가 String "it.twice()"또는 "{it.twice()}"

을하고 싶은이

그냥 간단한 toString 당연히 작동하지 않습니다 : 그루비에 수 없습니다

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의 표현처럼 단지 코드를 반환하지 않습니다 "


텍스트 트릭을 반환

// 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 파일을 가지고 있지만 실행 응용 프로그램에서는 그렇지 않습니다. – asinesio

5

합니다. Groovy 스크립트를 직접 컴파일하지 않고 직접 실행하는 경우에도 스크립트는 JVM 바이트 코드로 변환됩니다. 클로저는 다르게 처리되지 않으며 정기적 인 방법으로 컴파일됩니다. 코드가 실행될 때까지는 소스 코드를 더 이상 사용할 수 없습니다.