2011-03-10 35 views
13

Bất kỳ ai biết cách in nguồn đóng của Groovy?in định nghĩa/nguồn đóng trong Groovy

Ví dụ, tôi có việc đóng cửa này (binded đến a)

def a = { it.twice() } 

Tôi muốn có String "it.twice()" hoặc "{it.twice()}"

Chỉ cần một toString ofcourse đơn giản sẽ không làm việc:

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

này có thể sẽ không phù hợp với hoàn cảnh của bạn, nhưng bạn có thể có thể đi theo con đường khác. Kể từ GroovyShell.assessment() thực hiện một String (với các ràng buộc var thích hợp), nếu việc đóng cửa chỉ đơn giản là một chuỗi? –

Trả lời

24

câu trả lời ngắn gọn là bạn không thể. câu trả lời dài là:
tùy thuộc vào những gì bạn cần mã kiếm, bạn có lẽ có thể nhận được ngay với

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

NHƯNG
bạn sẽ cần mã nguồn của kịch bản có sẵn trong classpath AT RUNTIME như được giải thích trong

groovy.lang.MetaClass # getClassNode()
"có được một tham chiếu đến AST ban đầu cho metaclass nếu nó là sẵn tại thời gian chạy
@return Các AST gốc hoặc null nếu nó không thể là trả lại"


các văn bản lừa không thực sự quay trở lại cùng mã, chỉ cần một mã như đại diện của AST, như có thể thấy trong kịch bản này

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

vẫn còn, nó có thể là hữu ích vì nó là nếu bạn chỉ muốn có một cái nhìn nhanh chóng

AND, nếu bạn có quá nhiều thời gian trên tay của bạn và không biết phải làm gì bạn có thể viết riêng bạn org.codehaus.groovy.ast.GroovyCodeVisitor đến khá in nó

OR, chỉ ăn cắp là một hiện như 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") 
//  }) 
// }) 

bây giờ.
nếu bạn muốn gốc, chính xác, mã Runnable ... bạn đang trên may mắn
tôi có nghĩa là, bạn có thể sử dụng thông tin dòng nguồn, nhưng thời gian qua tôi đã kiểm tra, nó đã không thực sự nhận được chúng ngay

// 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. 

số dòng shuld có ít nhất gần mã gốc mặc dù

+0

Tôi không hiểu 'script có sẵn trong classpath AT RUNTIME' có nghĩa là gì? Nó chưa hoạt động (ClassNode là 'null'), nhưng tôi có tất cả các nguồn có sẵn. Tôi có phải thêm vị trí của tập lệnh trong đường dẫn lớp của dự án Groovy không? – Julian

+1

@Julian có nghĩa là tệp .groovy phải ở trong classpath. getClassNode() về cơ bản sẽ tải tệp và biên dịch lại bằng một móc đặc biệt để lưu nút ast có liên quan và trả lại – jpertino

+2

@jpertino Bất kỳ suy nghĩ nào về cách bạn làm điều đó trong môi trường Grails? Tôi có một tập tin Config.groovy đó là trên đường dẫn lớp trong các bài kiểm tra tích hợp nhưng nó không phải là trong chạy ứng dụng. – asinesio

5

Đó không phải là có thể trong groovy. Ngay cả khi một tập lệnh groovy được chạy trực tiếp, mà không biên dịch nó trước, tập lệnh được chuyển đổi thành mã bytecode JVM. Đóng cửa không được xử lý khác nhau, chúng được biên dịch như các phương pháp thông thường. Khi mã được chạy, mã nguồn không còn nữa.

Các vấn đề liên quan