Skip to content

Implement InlineValueProvider for TypeScript #119489

Closed

Description

I debug a test and get this:

image

Lots of inline debug values from a different unrelated test method.

Compared to devtools:

image

Activity

  1. isidorn commented on Mar 22, 2021

    @isidorn

    For this we would need the js-debug to use the inline value provider API created by Andre Weinand (@weinand)
    Thus forwarding to Andre Weinand (@weinand) and Connor Peet (@connor4312)

  2. connor4312 commented on Mar 22, 2021

    @connor4312
    Member

    Hm, we could parse the source and be smarter about only showing values in current and ancestor scopes.

    However this requires parsing TypeScript. Several months ago I actually moved away from using typescript to parse ASTs in favor of Acorn since it's much smaller and faster, and we did not actually need to parse TypeScript in the debugger. Maybe this is something that could live in the TypeScript language features since it already has the typescript package available. I would still be happy to help author it, thoughts Matt Bierner (@mjbvz)?

  3. weinand commented on Mar 22, 2021

    @weinand
    Contributor

    Yes, that's a good example where VS Code's built-in "inline values" support breaks down.
    Especially showing the function's source as its inline value is not really that smart ;-) (see #113987)

    Isidor Nikolic (@isidorn) yes, the now finalised "inline values provider" could help here but that would not provided by "js-debug" but by the TypeScript extension because "inline values provider" are registered for a language not a debugger (as Connor Peet (@connor4312) already alluded to).

    Connor Peet (@connor4312) it would be excellent if you could help author it.

  4. mjbvz commented on Mar 22, 2021

    @mjbvz
    Contributor

    Connor Peet (@connor4312) Should this come from the TS server? The typescript extension does not do any ast processing (and may not easily be able to since we try to strip out most all of the TypeScript files not related to tsserver)

  5. weinand commented on Mar 22, 2021

    @weinand
    Contributor

    Yes, if a language extension has no direct access to an AST, then it should delegate this functionality to a language server (e.g. by introducing a LSP extension).

  6. mjbvz commented on Mar 22, 2021

    @mjbvz
    Contributor

    We have this larger issue tracking debug asks from the TS team: #88857

    Connor Peet (@connor4312) If you can put together a short proposal on what you'd need specifically to implement this—basically here's the information we'll send over, what we need back, and a few illustrative examples of the expected behavior—I can try to get it scheduled for the next typescript version

  7. connor4312 commented on Mar 25, 2021

    @connor4312
    Member

    Sure:

    The InlineValuesProvider API allows languages to provide hints to the debugger what expressions or values to evaluate when debugging, showing them inline as Ben posted. VS Code has a built-in heuristic for these, but languages can provide them more intelligently.

    Specifically, for JavaScript, I think the following behaviors would be a good starting point, feel free to add/remove from these suggestions:

    • Inline values should only be provided in the current and parent scopes (solving the original issue)
    • Declarations and assignments assignments should evaluate the declared or assigned expression, bar in bar = foo() or foo in function foo() {}
    • Conditional expressions (ternary or if statements) should evaluate the conditional and none of its children, !foo && bar in if (!foo && bar)
    • Property assignments should be evaluated, foo() in { x: foo() }

    The debugger will not cause side-effects during evaluation, so you do not need to be concerned about that. Most of these would go through InlineValueEvaluatableExpression, but should use InlineValueVariableLookup when possible.

    I think I will later try to do some magic in js-debug so that evaluatable expressions are always invoked on the right call frame--since V8 optimizes away identifiers that are declared in parent scopes but unused in a child scope, calling everything on the top call frame may not always work.

  8. changed the title [-]Debug: inline values is overwhelming[/-] [+]Implement InlineValurProvider for TypeScript[/+] on Mar 25, 2021
  9. changed the title [-]Implement InlineValurProvider for TypeScript[/-] [+]Implement InlineValueProvider for TypeScript[/+] on Mar 25, 2021
  10. connor4312 commented on Mar 25, 2021

    @connor4312
    Member

    Giving this to you, Matt, since I don't think there's any work to be done on the debug front for now

  11. weinand commented on Mar 25, 2021

    @weinand
    Contributor

    Connor Peet (@connor4312) great proposal, thanks a lot!
    And if additional information is needed on the InlineValuesContext object or additional parameters on the InlineValueEvaluatableExpression object, just let me know. Those types can be extended easily.

  12. mjbvz commented on Mar 26, 2021

    @mjbvz
    Contributor

    Connor Peet (@connor4312) Thanks. Could you put together a few illustrative examples for the TS team. For a given code snippet for example, here's the complete list of inline values that should be returned.

    Also how will source mapping work with all this? Should TS be talking about ranges/vars in the original TS file? Or would this only be run on compiled JS?

  13. added
    upstreamIssue identified as 'upstream' component related (exists outside of VS Code)
    on Mar 26, 2021
  14. connor4312 commented on Mar 26, 2021

    @connor4312
    Member

    Could you put together a few illustrative examples for the TS team. For a given code snippet for example, here's the complete list of inline values that should be returned.

    function double(n: number) { // eval('double') -> double()
      return n * 2;
    }
    
    let x = 1; // InlineValueVariableLookup for x here
    
    if (x === 2) { // eval(x === 2) -> false
      x *= 2; // this line should NOT be evaluated since it's not the scope or its parents
    }
    
    if (x === 1) { // eval(x === 1) -> true
      x *= 2; // InlineValueVariableLookup for x here
      const y = {
        z: x ** 2, // eval(x ** 2) -> 16
      };
    
      console.log(x); // <-- paused here
    }

    Also how will source mapping work with all this? Should TS be talking about ranges/vars in the original TS file? Or would this only be run on compiled JS?

    They should report this information based on whatever file VS Code requests -- which will be the file the debugger is paused in. They don't have to do anything special to deal with sourcemaps/ranges. I don't think js-debug will either, but if it does then I'll take care of it as the TS language server is unaware of sourcemaps.

  15. mjbvz commented on Mar 30, 2021

    @mjbvz
    Contributor

    Opened microsoft/TypeScript#43449 to track this upstream

    Connor Peet (@connor4312) Can you please answer any of the TypeScript team's question about the expected behavior

  16. removed this from the April 2021 milestone on Mar 30, 2021
  17. locked and limited conversation to collaborators on May 14, 2021
  18. mjbvz commented on Mar 24, 2022

    @mjbvz
    Contributor

    Connor Peet (@connor4312) I'm assigning you since we decided this would need to come through a TypeScript plugin (which I think we'd have to develop)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

debugDebug viewlet, configurations, breakpoints, adapter issuestypescriptTypescript support issuesupstreamIssue identified as 'upstream' component related (exists outside of VS Code)

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions