2012-02-23 16 views
6

È possibile ottenere il numero di linea corrente tramite __LINE__ in Ruby o Perl. Per esempio:__LINE__ funzionalità in Groovy

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

C'è la stessa caratteristica in Groovy?

risposta

2

Non direttamente, ma è possibile ottenerlo attraverso una traccia di stack Exception (o Throwable). Per esempio:

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) 

Una parola di cautela però: ricevendo il numero di riga, il nome del file, o un metodo come questo è molto lento.

+0

Perché è così lento? L'equivalente in Perl (che significa 'caller') è molto veloce. – tchrist

+0

Le tracce dello stack Java possono essere abbastanza profonde, ancora più groovy. Il metodo [Throwable.fillInStackTrace] (http://docs.oracle.com/javase/6/docs/api/java/lang/Throwable.html#fillInStackTrace%28%29) richiede solo un po 'di tempo per creare i dati di traccia dello stack struttura. Controlla http://stackoverflow.com/a/3980148/190201 per un look più approfondito. Non è certamente troppo lento da usare per il debug, ma è bene essere consapevoli dei suoi costi prima di usarlo. – ataylor

1

Non sono un esperto di Groovy, ma non penso. So che Java e C# non ce l'hanno.

La funzionalità __LINE__ ha veramente iniziato ad aiutare con il debug in C. C non ha eccezioni o molte altre caratteristiche dei linguaggi moderni, ma aveva macro che il compilatore poteva espandere ovunque nel codice, ecco perché avevamo bisogno di __FILE__, __LINE__, ecc. per farci sapere dove eravamo quando accadeva qualcosa di brutto. Questo è il modo in cui assert funziona in C e C++. La JVM ha strumenti di debug molto buoni, e combinata con assert ed eccezioni, puoi facilmente individuare dove qualcosa è andato storto (le tracce dello stack sono comunque migliori di un semplice numero di linea).

Credo che il motivo per cui Ruby e Perl hanno quei macro è perché sono stati creati dagli hacker C. Non ho mai usato nessuno di quei linguaggi per conoscere il livello di supporto per il debug o quanto sono davvero utili i macro.

+0

Posso confermare che non sono molto utilizzati. Il modo normale per ottenere informazioni su un frame in Perl, sia all'interno del debugger che al di fuori di esso, è usare la funzione 'caller' con un numero di frame come argomento. 0 è dove sei adesso, 1 è il tuo chiamante, 2 è * il suo * chiamante, ecc. Questo ora restituisce il pacchetto del frame, il nome del file, la riga, la subroutine e un mucchio di altre cose. Quindi normalmente utilizzerai l'interfaccia funzionale per ottenere quelle informazioni, non i vecchi pseudo-machi '__FILE__' e' __LINE__'. – tchrist