Return to Blog Home

VSCode Inline Watch Expressions

Source 

VSCode Inline Watch Expressions

Seeing your expressions within the actual code!

The VSCode debugger is an amazing tool, and by default it even inlines some values, but what if you wanted to inline any value? Well with this extension you can!

Inline Watchs

Thankfully it wasn't the first time I had worked with the VSCode Extension API - and spefically the debugger API - so I knew what I needed to do:

Intrestingly enough, the VSCode Deugger API doesn't provide a way to get all the current watch expressions, which while fine for additions - I manually captured each value - when a user deleted an expression, there was no indication of this event - the solution I went with was clearing out all the values after each debug step, and then re-adding them.

How did I get the values? Well the Debugger API receives a evaluate request command every time the evaluation is done, which is shortly followed by a evaluate response command - containing both the evaluated value and a seq id - which I used to match the request to the response.


After this had been added, I quickly realized it was too greedy - imagine you want to watch an i variable, well now every instance of i in your code is suffixed with this value.

Custom Ranges

The solution was custom ranges - select an expression, run the Add command, and it will both add this as a watch expression, and limit the watch expression to the added ranges.

Of course this needed to come with the ability to remove a range, and additionally reset all added ranges, so I added those as well.

One Issue

There does exist one issue with this extension, and that's the fact that if two expressions end on the same line, there is no stable guarnteed way to enforce the order of the suffix rendering

To demonstrate, consider this expression:

[1, 3, 6].reduce((sum, number) => sum + number, 0)

with the expressions:

as such:

[1, 3, 6].reduce((sum, number) => sum + number, 0)
                                  ^^^
[1, 3, 6].reduce((sum, number) => sum + number, 0)
                                        ^^^^^^
[1, 3, 6].reduce((sum, number) => sum + number, 0)
                                  ^^^^^^^^^^^^

Initally the output will be correct:

[1, 3, 6].reduce((sum, number) => ((sum = 0) + (number = 1) = 1), 0)
[1, 3, 6].reduce((sum, number) => ((sum = 1) + (number = 3) = 4), 0)

but then when the lengths of the suffix change the output will be incorrect:

[1, 3, 6].reduce((sum, number) => ((sum = 4) + (number = 10) = 6), 0)

when it should be:

[1, 3, 6].reduce((sum, number) => ((sum = 4) + (number = 6) = 10), 0)

Try as I might - padding the strings, adding margin, etc - nothing works stably, and while I did track down the code that is reordering the decorators, I see no way to customize or override this behaviour.

Future

While I actually had a more visually impressive vision in my mind, try as I might with the Comments API, CodeLens API, and others, the Decorator API was the closest one - my vision was and still is to have the values appear on the next/previous line, not inlined:

[1, 3, 6].reduce((sum, number) => sum + number, 0)
//                                |     |    |
//                                1     3    4

similar to power-assert, but the only way I could new blank lines was with the Editor API - which literally edits the code file, which while it would work would make it a lot more difficult to use.

Or alternativly:

[1, 3, 6].reduce((sum, number) => sum + number, 0)
                               /* sum = 1 */
                                                                   /* number = 3 */
                                                             /* sum + number = 4 */

As you can see I have yet to find the perfect solution, but until then it's still a pretty useful extension for me at least!