Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

__LINE__ feature in Groovy

Tags:

groovy

It is possible to get current line number by __LINE__ in Ruby or Perl. For example:

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

Is there the same feature in Groovy?

like image 973
kwatch Avatar asked Feb 23 '12 04:02

kwatch


2 Answers

Not directly, but you can get it through an Exception (or Throwable) stack trace. For example:

 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)

A word of caution though: getting the line number, file name, or method like this is very slow.

like image 192
ataylor Avatar answered Sep 28 '22 04:09

ataylor


I'm not an expert in Groovy, but I don't think so. I know that Java and C# don't have it.

The __LINE__ feature really started to help with debugging in C. C doesn't have exceptions or many of the other features modern languages have, but it did have macros that the compiler could expand anywhere in the code, which is why we needed __FILE__, __LINE__, etc to let us know where we were when something bad happened. This is how assert works in C and C++. The JVM has very good debugging tools, and combined with assert and exceptions, you can very easily pinpoint where something went wrong (stack traces are way better than just a line number anyway).

I believe the reason Ruby and Perl have those macros is because they were created by C hackers. I've never used either of those languages enough to know the level of debugging support or how useful the macros really are.

like image 28
parkovski Avatar answered Sep 28 '22 02:09

parkovski