Added image and YouTube link
Use gj :: locate to get to the source of your errors.
Using VS Code, with either the Serenji extension or the basic InterSystems ObjectScript extension, click on the gj :: locate caption in the status bar. Enter an ObjectScript error message or a line reference from a class or .mac routine. Then gj :: locate will take you directly to the corresponding line in your source code.
The first step in debugging any error is to make sure you are looking at the correct line of code. Error messages give the error location in terms of the compiled .int code, not your source code. There are many special rules about how lines of source code map to corresponding lines in the compiled .int routines and most people don’t know them all. Locating the correct source line for an error is an essential first step in debugging any problem. gj :: locate solves this problem by converting the location of an error in compiled .int code to the corresponding location in your source, and then taking you there.
Simply copy and paste any InterSystems IRIS error message into gj :: locate and it will take you directly to the corresponding source line.
It doesn’t just work with error messages. You can use gj :: locate to open any class or routine and go straight to the line you want. For example, you can enter alpha^Greek.Alphabet
to go to the alpha method in Greek.Alphabet.cls.
You can specify a location using any of these formats to get quickly and directly to where you want to be:
If you install the gj :: locate userscript in your browser, you can navigate seamlessly from an error message in the Management Portal Application Error Log to the source code in just two clicks.
Like this:
This extension requires either the Serenji extension or the basic InterSystems ObjectScript extension to be installed.
To install the gj :: locate VS Code extension, go to the Extensions view (⌘/Ctrl+Shift+X), search for “gjlocate” and click the install button.
Once installed a gj :: locate panel will appear on the status bar. Click it to invoke gj :: locate.
If you are using multi-root workspaces please read the note in Known Limitations and Issues.
Finally, we find it useful to associate a keyboard shortcut with the gj :: locate command, which is named gjLocate
. Our preference is Alt+Z Alt+P since, to some extent, gj :: locate mimics the ObjectScript zprint
command.
If you install the gj :: locate userscript in your browser, you will be able to copy error messages from any InterSystems Management Portal (all versions of IRIS, Ensemble and Caché going back to 2007) and paste them into VS Code with just two clicks
Install a userscript manager such as Tampermonkey. Follow the instructions here. This is a plugin for your browser that allows you to install and manage userscripts.
Install the gj :: locate userscript by clicking the Install This Script button on this page.
Navigate to the Application Error Log page in any InterSystems Management Portal. You’ll see an additional gj :: locate button against each error log entry. Click it.
Surely it can’t be that difficult to get from label+offset^routine
to the actual source line responsible for the error? For an expert it isn’t that hard … most of the time. But there are enough oddities and special rules that even an expert can get it badly wrong.
Take, for example, the following error message:
set characterCount = characterCount + 1
^
zeta+5^Greek.Alphabet.1 *characterCount
It’s 2:30am and you’ve just been woken up to fix a mission critical problem in your Greek Alphabet application. How do you find the corresponding source code line for this error?
First you have to know a few things. Like, you have to know that when a routine ends with a period followed by a number it means it’s a class, not a routine. So now you go open up Greek.Alphabet.cls.
Yes, the error message says the problem is in the Greek.Alphabet class, but as you can see, it’s empty.
Closer inspection reveals that the source code must have come from one of the superclasses. Greek.Zeta.cls would be a good guess. Let’s look in there.
Well, here we are. It’s obviously line 10 which is zeta+5
. But hang on, the error message was <UNDEFINED>
and the undefined variable is characterCount
. How can that possibly be? characterCount
is clearly being set on the previous line. This error is impossible!
It’s now 3am and you are feeling a bit challenged!
Then you remember! Methods are given a z
prefix when compiled into an .int routine. Aha! Zeta is the 6th letter of the Greek alphabet, but the 7th letter is Eta. We should be looking for a method called eta.
Let’s look at Greek.Eta.cls
Hmm. It’s nearly identical to Greek.Zeta.cls and characterCount
has clearly been initialised on the previous line. What’s going on? At this point you just want to go back to bed.
More head scratching. Perhaps the problem is something to do with that #include
line. Let’s look in there.
Line 5 looks promising. But… oh no, characterCount
can’t be undefined here. It’s impossible.
So, eventually, after scolling down 20 or so lines you find some more code:
Now we know why characterCount
is undefined, and fortunately it looks like an easy fix.
The real error is at line 25 of Greek.Utils.inc. This is a somewhat contrived example that spotlights some of the many gotchas you might encounter. Getting from an error message to the corresponding source line can be difficult, especially at 3am.
So finally, here’s how you’d do it with gj :: locate
The source location is determined using an empirical method. This approach has a number of limitations that are unlikely to be encountered in most normal cases. If however, you are doing something exotic, the results may be affected. Generally, using the Serenji extension instead of the basic InterSystems ObjectScript extension will give better results because it is able to access source code that has not been downloaded to the client.
#if
directives are ignored. Any code lines within and after a #if
block may be incorrect.$$$
macros that resolve to multiple lines are not accounted for. Most $$$
macros resolve to a line fragment which will be handled correctly. Multiline macros are not common.}
would be mis-identified as the end of a method block.>
of a &js<>
block and have code or comments following the >
are not handled correctly.&htmlABC<
… >CBA
) are not recognised as &html<>
blocks and not treated correctly.##sql(
… )
as an alternative to &sql(
… )
is not recognised.&sql( /* in-line comment */ )
is not handled correctly.See CHANGELOG.