Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support letting a language server provide additional metadata on values #284

Open
orta opened this issue Jan 30, 2020 · 3 comments
Open
Labels
feature-request Request for new features or functionality upstream
Milestone

Comments

@orta
Copy link

orta commented Jan 30, 2020

👋 been enjoying this extension, great work.

It's a bit of a blue-sky idea, but an interesting case would be enum values.

For example selecting kind in the editor below could request some kind extended metadata about the raw value. So it would have the chance go from this:

Screen Shot 2020-01-30 at 12 44 24 PM

To this:

Frame 2

And maybe type information could then be available if you keep the mouse hovering?

@connor4312
Copy link
Member

connor4312 commented Jan 30, 2020

Thanks for the kind words!

Indeed, something we're talking about that would provide several things is the ability for language implementations in the editor to provide 'helper' APIs that debug adapters can use. This has many use cases--being able to figure out how to handle hovers correctly, better intellisense and autocompletion in the debug console/repl, figuring out renamed/mapped variables (like TS imports).

In your example, maybe there would be a way for the debug extension to ask the language server the metadata for a symbol in the current scope--the debug server knows the runtime position and the value of child.kind, and tssserver will know that that's a SyntaxKind enum, so it can pass that back. Then we could figure out how to show represent that nicely DAP variables response, the easy way we could do it without changes is to show SyntaxKind.VariableDeclarationList by default and let the user expand it to see the underlying value, like how we handle getters.

cc @weinand

@connor4312 connor4312 added feature-request Request for new features or functionality upstream labels Jan 30, 2020
@weinand
Copy link

weinand commented Jan 31, 2020

There are at least two obstacles that make collaboration between language servers and debuggers more difficult than expected:

  • VS Code knows nothing about language servers since they are an implementation detail of an extension. So VS Code debugging (or debug adapters) do not have generic access to language servers. That's the reason why we are starting to introduce new APIs (e.g. #89084) that the VS Code debugger or debug adapters can use to get access to specific language features (but not the full language server API).
  • There are basically no common types and abstractions shared between language API and debugger APIs. So it is not trivial to map some entity from the debugger world (e.g. a variable accessible in the current stack frame) to something in the language world (the correct variable with its type). Just using the name is not sufficient. The only shared information that can be used to map between the two worlds is the symbol's location in the source (if that information is actually available on the debugger side). And if the source language (e.g. TS) and the runtime language (e.g. JS) are different and require another mapping, things become even more difficult...

@connor4312 connor4312 added this to the Backlog milestone Feb 4, 2020
@hediet
Copy link
Member

hediet commented Jun 29, 2023

I'd love to revive this discussion! I think this is not that far out of reach.

JS Debug could provide a typescript language server plugin that exposes a command getNumberDisplay:

function getNumberDisplay(value: number, expression: string, scope: Range, uri: Uri): Promise<Display | undefined> {}

type Display = { value: string } | { functionExpression: string };

Const Enum Example

const enum Foo {
    A = 1,
    B = 2,
}

const x = Foo.A;
console.log(x);

const y = { kind: Foo.B };

getNumberDisplay(1, "x", ..., ...) would return { value: "Foo.A" }
getNumberDisplay(2, "y.kind", ..., ...) would return { value: "Foo.B" }

User Defined Example

/**
* @display {x => x.toString(2)}
*/
type Binary = number;

const binX: Binary = 0b11011;

getNumberDisplay(27, "binX", ..., ...) would return { functionExpression: "(x => x.toString(2))" }


Evaluate requests that resolve an expression to a number could then use this command to improve the representation.
For functionExpressions, it would eval ${functionExpression}(${value}).


I don't think getNumberDisplay is very hard to implement. We could start with just supporting variables that are in the given scope and then extend it to chained properties/array access etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature-request Request for new features or functionality upstream
Projects
None yet
Development

No branches or pull requests

4 participants