2012-02-23 6 views
6

RubyまたはPerlで現在の行番号を__LINE__で取得できます。 例:Groovyの__LINE__機能

print "filename: #{__FILE__}, line: #{__LINE__}" 

Groovyにも同じ機能はありますか?

答えて

2

直接ではありませんが、例外(またはThrowable)スタックトレースを介して取得できます。たとえば:

StackTraceElement getStackFrame(String debugMethodName) { 
    def ignorePackages = [ 
     'sun.', 
     'java.lang', 
     'org.codehaus', 
     'groovy.lang' 
    ] 
    StackTraceElement frame = null 
    Throwable t = new Throwable() 
    t.stackTrace.eachWithIndex { StackTraceElement stElement, int index -> 
     if (stElement.methodName.contains(debugMethodName)) { 
      int callerIndex = index + 1 
      while (t.stackTrace[callerIndex].isNativeMethod() || 
        ignorePackages.any { String packageName -> 
         t.stackTrace[callerIndex].className.startsWith(packageName) 
        }) { 
       callerIndex++ 
      } 
      frame = t.stackTrace[callerIndex] 
      return 
     } 
    } 
    frame 
} 

int getLineNumber() { 
    getStackFrame('getLineNumber')?.lineNumber ?: -1 
} 

String getFileName() { 
    getStackFrame('getFileName')?.fileName 
} 

String getMethodName() { 
    getStackFrame('getMethodName')?.methodName 
} 

def foo() { 
    println "looking at $fileName:$lineNumber ($methodName)" 
} 

foo() 

// ==> looking at test.groovy:39 (foo) 

注意の言葉は、しかし:、行番号を取得し、ファイル名、またはこのような方法は非常に遅いです。

+0

なぜそれは遅いですか? Perlで(つまり、 'caller'を介して)相当することは非常に速いです。 – tchrist

+0

Javaのスタックトレースはかなり深いことがあります。メソッド[Throwable.fillInStackTrace](http://docs.oracle.com/javase/6/docs/api/java/lang/Throwable.html#fillInStackTrace%28%29)は、スタックトレースデータを構築するのに少し時間がかかります構造。詳細はhttp://stackoverflow.com/a/3980148/190201をご覧ください。確かにデバッグにはあまりにも遅すぎることはありませんが、使用する前にそのコストを認識することは良いことです。 – ataylor

1

私はGroovyの専門家ではありませんが、私はそうは思わないです。私はJavaとC#がそれを持っていないことを知っています。

__LINE__は、Cでのデバッグに本当に役立ち始めました.Cには、現代の言語には例外やその他の多くの機能はありませんが、コンパイラがコード内のどこにでも展開できるマクロがありました。 __FILE____LINE__などが必要でした。何か不具合が起きたときに私たちがどこにいるかを教えてください。これは、assertがCおよびC++で動作する方法です。 JVMには非常に優れたデバッグツールがあり、assertと例外を組み合わせることで、何かが間違っている場所を簡単に特定できます(スタックトレースは単なる行番号よりも優れています)。

RubyとPerlがそれらのマクロを持っているのは、Cハッカーが作成したものだからです。私はデバッグサポートのレベルやマクロの有用性を知るのに十分なほどの言語を使用したことはありません。

+0

実際にあまり使われていないことを確認できます。デバッガの内部であろうと外部であろうと、Perlのフレームに関する情報を取得する通常の方法は、フレーム番号を引数として 'caller'関数を使うことです。 0は現在の場所、1は呼び出し元、2は*彼の*呼び出し元などです。これで、そのフレームのパッケージ、ファイル名、行、サブルーチン、および他のものが返されます。だから、普通の '__FILE__'と' __LINE__'疑似マクロではなく、その情報を得るために関数インタフェースを使うのが普通です。 – tchrist

関連する問題