Uploaded image for project: 'Groovy'
  1. Groovy
  2. GROOVY-8742

Line number information for method is confusing debugger




      I have been investigating a case where the IDE will not break on a line breakpoint in a test method. This method has no parameters or local variables (this affects its line number table in the bytecode) and the code is all on one line, with a chain of three method calls. When line-breaking the code or assigning to temporary, the line numbers table changes and the line breakpoints work as expected.

      package a
      import org.junit.*
      final class Tests {
        void testSomething() { // line 29
          Assert.assertFalse(this.method(one(), "two", Three.class)) // line 30
        boolean method(... args) { true }
        def one() {}

      When compiled with Groovy 2.4 and normal/dynamic groovy, the method has line information:

            Line numbers:
              [pc: 4, line: 29]
              [pc: 19, line: 30]
              [pc: 68, line: 30]
            Local variable table:
              [pc: 0, pc: 109] local: this index: 0 type: a.Tests

      I have not tried with the "fast path" optimization disabled. I think its prelude is what bumps the PC from 0 to 4 and results in the two PC entries for line 30 (pc 19 and pc 68).

      If I assign the result of method to a new local variable, the line numbers are altered:

            Line numbers:
              [pc: 6, line: 30]
              [pc: 63, line: 30]
              [pc: 100, line: 31]
            Local variable table:
              [pc: 0, pc: 113] local: this index: 0 type: a.Tests
              [pc: 6, pc: 113] local: variable index: 2 type: java.lang.Object

      If I compile with invoke dynamic on, I get this for the original code:

            Line numbers:
              [pc: 0, line: 30]
            Local variable table:
              [pc: 0, pc: 30] local: this index: 0 type: a.Tests

      I'm not sure the exact outcome expected here in terms of the bytecode, but I looked at similar methods from Java sources. For a Java test method, the line number table began with [pc: 0, line: whatever].

      I looked at GROOVY-4505, which mentions that AsmClassGenerator.visitBlockStatement should not be writing line number information for the block statement (the source of line 29). StatementWriter.writeBlockStatement indeed retains a note about this. However, the overload in OptimizingStatementWriter still triggers `onLineNumber` from its `writeBlockStatement` -> writeGuards. Should onLineNumber check for BlockStatement and exit early? I tried this quickly and it did alter the line numbers table, but it did not help my debugger find the breakpoint on line 30.


        Issue Links



              paulk Paul King
              emilles Eric Milles
              1 Vote for this issue
              3 Start watching this issue