Feature request for IDE: CurrentLineNumber

There’s the constant “CurrentMethodName” that one can use inside a method, usually for debugging, like this:

if someValue = nil then System.DebugLog "someValue is nil in "+CurrentMethodName return end

Now, wouldn’t it be great if we could also do this:

if someValue = nil then System.DebugLog "someValue is nil in "+CurrentMethodName+", line "+Str(CurrentLineNumber) return end

or

if someValue = nil then System.DebugLog "someValue is nil in "+CurrentMethodNameAndLine return end

Has someone made such a proposal, yet? I can’t currently login to Feedback - it keeps telling me that my password is wrong, even though I never changed it and the same pw works on the website.

when you write System.debuglog, you know the line number you’re on.
so you can write System.DebugLog "someValue is nil in "+CurrentMethodName+", line XXX"

plus I don’t think the line numbers are coded into introspection, whereas the methodname is.

There’s a feature request ticket from 2008 that mentions this <https://xojo.com/issue/279> but it seems to have been closed during the move to a new bug tracking system.

I’m not sure how much speed overhead this would introduce.

I had made a Feedback request only for exceptions: <https://xojo.com/issue/15331>

[quote=428952:@Jean-Yves Pochez]so you can write System.DebugLog “someValue is nil in “+CurrentMethodName+”, line XXX”

[/quote]

You could, but if an exception block could reference the line number, that would be pretty cool. I would want to see either a compiler switch or one in the IDE to turn it on with “off” being default (for performance reasons like @JulianS said). Then you could do a build and send it to a user who is having an odd crash that can’t be pinned down.

[code]
#TrackLineNumbers On

…tons of code

Exception
#If TrackingLineNumbers
MsgBox "Something really bad happened, on line "+str(CurrentLineNumber)
#Else
MsgBox “Something really bad happened, but I don’t know what.”
#EndIf[/code]

Line numbers could also be appended to the method names in the stack property of exceptions if they are turned on. (That would be really cool too)

Of course you could also write a little 6-line app that adds linenumber code to copy and paste back into the troubled method for a 1-off build if that’s the goal…
Just a textarea and a button with:

dim lines() as String=TextArea1.Text.Split(EndOfLine.OSX)
for i as integer=lines.Ubound DownTo 0
  lines.Insert(i,"LineNumber="+str(i+1))
next
lines.Insert(0,"dim LineNumber as Integer")
TextArea1.Text=join(lines,EndOfLine.OSX)

Although that would break any multiline code using the _

[quote=428951:@Thomas Tempelmann]
Has someone made such a proposal, yet? [/quote]
Yes
<https://xojo.com/issue/3447>
<https://xojo.com/issue/15223>
This would likely have to be done by the compiler as injecting it from the IDE side has the issues noted by Jim

Jean-Yves, you got that wrong: CurrentMethodName is not looked up at Runtime by Introspection but is simply a constant that’s inserted into every method at the top before the code is passed to the compiler, or the compiler has even hard-coded this identifier. Either way, it’s defined at compile time - no (slow) introspection necessary.

To make CurrentLineNumber work, it would require adding either something to the compiler (it can count the lines, after all), or by the IDE, before it sends the code to the compiler, by replacing any occurance of CurrentLineNumber with the actual line number.

To keep this well-performed, the IDE could simply first check whether the source code for the method contains CurrentLineNumber at all, and only if so, it would then analyse the code to make sure it’s really an identifier and not part of a string (where we would not want such a replacement). This way, it would not slow down compilation noticably.

Even better: It would be nice if we have a hook for this - like the editor hook for code reformatting, but this hook would be called before the source is passed to the compiler. Then we could inject our own modifications there, giving us effectively a customizable preprocessor. That way, Xojo would only have to add such a hook, while we could then make scripts doing things like this line number insertion if we feel the need for it, and much more.

Well, I once suggested that the code generator would pass the line number values and add them to the calls to Raise methods for exceptions.
This way you can have no overhead and pass line numbers for all those exceptions created in Xojo code.

[quote=428985:@Thomas Tempelmann]Jean-Yves, you got that wrong: CurrentMethodName is not looked up at Runtime by Introspection but is simply a constant that’s inserted into every method at the top before the code is passed to the compiler, or the compiler has even hard-coded this identifier. Either way, it’s defined at compile time - no (slow) introspection necessary.
[/quote]
correct

[quote=428985:@Thomas Tempelmann]To make CurrentLineNumber work, it would require adding either something to the compiler (it can count the lines, after all), or by the IDE, before it sends the code to the compiler, by replacing any occurance of CurrentLineNumber with the actual line number.
[/quote]
The IDE cant insert this
Multi-line statements cant be handled properly
And there’s a dischord between the line numbers compilation errors would give and your code because its been modified
ie/ you write

     dim foo as integer // line 1
                        // line 2
     foo = "123"        // line 3

If the IDE inserted CurrentLineNumber the compiler would see

    currentlinenumber = 1
    dim foo as integer // line 1
    currentlinenumber = currentlineNumber + 1
                       // line 2
    currentlinenumber = currentlineNumber + 1
    foo = "123"        // line 3

and now foo = “123” is reported as line 6 by the compiler but it shows as line 3 in your code editor

Joe and I pondered this and came to the conclusion the only way to do it without these weird effects was to have the compiler do it. And it kind of already does it just isn’t exposed in any way that it can be used

currentlinenumber = 3

not use currentlinenumber + 1 as code is not linear from top to down, but may have loops.

Even better would be to detect currentlinenumber as keyword and just insert number there. That way you don’t get the variable and if the value not queried, there is no change.

[quote=428991:@Christian Schmitz]currentlinenumber = 3

not use currentlinenumber + 1 as code is not linear from top to down, but may have loops.

Even better would be to detect currentlinenumber as keyword and just insert number there. That way you don’t get the variable and if the value not queried, there is no change.[/quote]

The point is the compiler has to do this - the IDE cant do it correctly without side effects
The line numbers reported by compile errors would not match the code you have in the editor if the IDE injected something for line number

There had been a plan for this announced a few years ago where a compilation would also produce a file that could be used to in conjunction with the compiled version to match an Exception with a line number. (I’m sure I’m getting the details wrong here, but that was the general gist.) Nothing has come of that yet.

As proposed by @Thomas Tempelmann, none.

The compiler just need to treat the instruction CurrentLineNumber as any Constant, just replacing it with the correct value passed by the IDE. That should be easy to implement.

Famous last words…

If it truly was ‘easy’ it would have been done by now.

[quote=429014:@Ivan Tellez]As proposed by @Thomas Tempelmann, none.
The compiler just need to treat the instruction CurrentLineNumber as any Constant, just replacing it with the correct value passed by the IDE. That should be easy to implement.[/quote]
The IDE never passes any of this - nor should it
I compiler already does have a line count its just not accessible in any way

Could the IDE preprocess a method with code like this after stripping comments? Or does the compiler strip comments?

dim lines() as String=TextArea1.Text.Split(EndOfLine.OSX)

for i as integer=lines.Ubound DownTo 1
  if not (right(lines(i-1).trim,1)="_") then _
  lines.Insert(i,"LineNumber="+str(i+1))
next
lines.Insert(0,"dim LineNumber as Integer=1")
TextArea1.Text=join(lines,EndOfLine.OSX)

I updated it to handle multiline statements… handles loops fine. Feeding it to itself(?) gives this (notice there is no line 5):

dim LineNumber as Integer=1
dim lines() as String=TextArea1.Text.Split(EndOfLine.OSX)
LineNumber=2

LineNumber=3
for i as integer=lines.Ubound DownTo 1
LineNumber=4
  if not (right(lines(i-1).trim,1)="_") then _
  lines.Insert(i,"LineNumber="+str(i+1))
LineNumber=6
next
LineNumber=7
lines.Insert(0,"dim LineNumber as Integer=1")
LineNumber=8
TextArea1.Text=join(lines,EndOfLine.OSX)
LineNumber=9

LineNumber=10

Of course, now that I have this, it’s kind of a moot point… more of a matter of convenience as far as I’m concerned.

The IDE does no processing of the lines of text in a method / event and hands the text to the compiler
The compiler & its tokenizer / parser etc is what ignore comments

FWIW this code isn’t correct as you can have a comment after a _

If True _ // then
And True _ // another comment
Then
MsgBox"yay!"

End If

[quote=429045:@jim mckay]for i as integer=lines.Ubound DownTo 1
if not (right(lines(i-1).trim,1)="_") then _
lines.Insert(i,“LineNumber=”+str(i+1))
next
lines.Insert(0,“dim LineNumber as Integer=1”)
TextArea1.Text=join(lines,EndOfLine.OSX)[/quote]

[quote=429049:@Norman Palardy]FWIW this code isn’t correct as you can have a comment after a _
[/quote]

Yeah, that’s why I was hoping the IDE stripped comments…

nope …
the IDE tries to not have to interpret the entire grammar of the Xojo language as much as it can but there are places where features require it have some knowledge
and if the grammar changes then the code that has that knowledge embedded in it will also need to change