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:
- Grab all Watch expressions
- Add decorator to wherever the expression appears in the code, suffixing it with the value of the expression.
- Update these values and decorators as the expressions get evaluated.
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:
sum
number
sum + number
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!