-
Notifications
You must be signed in to change notification settings - Fork 29.5k
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
Extension API for Inline Values #105690
Comments
The current generic implementation works as follows:
This implementation is lightweight and scales well because:
Problems:
|
A first attempt for designing an extension API for inline values tried to use a similar approach as done for the debug hover with the EvaluatableExpressionProvider. In the debug hover case the provider returns an expression for a source location typically determined by the mouse, and then this expression is evaluated by the debug adapter and the result is presented in a hover window. For the "inline values" feature we tried to reuse the A prototype based on this approach showed two problem areas:
|
During debugging VS Code's "Inline Values" feature shows the value of variables "inline" in the editor: (see https://code.visualstudio.com/updates/v1_9#_inline-variable-values-in-source-code) Today the "Show Inline Values" feature of VS Code's debugger is based on a single, generic implementation in the VS Code core and provides neither customisability through settings, nor extensibility via extensions. The proposal is a first attempt to create an extension API for inline values. Proposal: The new API is basically a new provider that returns the "Inline values" information (a string) for specific lines of a document. But there is a twist: /**
* The inline values provider interface defines the contract between extensions and the VS Code inline values feature.
* In this contract the provider returns inline value information for a given document range
* and VS Code shows this information in the editor at the end of lines.
*/
export interface InlineValuesProvider {
/**
* Provide "inline value" information for a given document and range.
* VS Code calls this method whenever debugging stops in the given document.
* The returned inline values information is rendered in the editor at the end of lines.
*
* @param document The document for which the inline values information is needed.
* @param context A bag containing contextual information like the current location.
* @param token A cancellation token.
* @return An array of InlineValueDescriptors or a thenable that resolves to such. The lack of a result can be
* signaled by returning `undefined` or `null`.
*/
provideInlineValues(document: TextDocument, context: InlineValueContext, token: CancellationToken): ProviderResult<InlineValueDescriptor[]>;
}
/**
* An open ended information bag passed to the inline value provider.
* A minimal context containes just the document location where the debugger has stopped.
* Additional optional information might be scope information or variables and their values.
*/
export interface InlineValueContext {
/**
* The document location where execution has stopped.
* Typically this is used as the end position of the range where inline values are shown.
*/
position: Position;
// ... more to come, e.g. Scope information or variable/value candidate information
}
/**
* Inline value information can exist in multiple forms. The simplest is a direct string value (class InlineValue).
* A more complex one is an evaluatable expression.
* The InlineValueDescriptor is just an OR-type of all current and future inline value types.
*/
export type InlineValueDescriptor = InlineValue;
/**
* An InlineValue represents the value (string) that is shown in the editor at the end of a specific line.
*/
export class InlineValue {
/**
* The document's line where to show the inline value.
*/
readonly line: number;
/**
* The value to be shown for the line.
*/
readonly value: string;
/**
* Creates a new InlineValue object.
*
* @param line The document line where to show the inline value.
* @param value The value to be shown for the line.
*/
constructor(line: number, value: string);
}
export namespace languages {
/**
* Register a provider that returns inline values for text documents.
* In the active debug session VS Code shows this information in the editor at the end of lines.
*
* If multiple providers are registered for a language, inline values are concatenated.
*
* @param selector A selector that defines the documents this provider is applicable to.
* @param provider An inline values provider.
* @return A [disposable](#Disposable) that unregisters this provider when being disposed.
*/
export function registerInlineValuesProvider(selector: DocumentSelector, provider: InlineValuesProvider): Disposable;
} |
|
@gjsjohnmurray thanks for spotting this. |
Here is a new proposal that is better aligned with the "InlineHints" proposal and incorporates feedback from the API sync. Changes:
/**
* The inline values provider interface defines the contract between extensions and the VS Code debugger inline values feature.
* In this contract the provider returns inline value information for a given document range
* and VS Code shows this information in the editor at the end of lines.
*/
export interface InlineValuesProvider {
/**
* An optional event to signal that inline values have changed.
* @see [EventEmitter](#EventEmitter)
*/
onDidChangeInlineValues?: Event<void> | undefined;
/**
* Provide "inline value" information for a given document and range.
* VS Code calls this method whenever debugging stops in the given document.
* The returned inline values information is rendered in the editor at the end of lines.
*
* @param document The document for which the inline values information is needed.
* @param viewPort The visible document range for which inline values should be computed.
* @param context A bag containing contextual information like the current location.
* @param token A cancellation token.
* @return An array of InlineValueDescriptors or a thenable that resolves to such. The lack of a result can be
* signaled by returning `undefined` or `null`.
*/
provideInlineValues(document: TextDocument, viewPort: Range, context: InlineValueContext, token: CancellationToken): ProviderResult<InlineValue[]>;
}
/**
* An open ended information bag passed to the inline value provider.
* A minimal context containes just the document location where the debugger has stopped.
* Additional optional information might be scope information or variables and their values.
*/
export interface InlineValueContext {
/**
* The document range where execution has stopped.
* Typically the end position of the range denotes the line where the inline values are shown.
*/
stoppedLocation: Range;
// ... more to come, e.g. Scope information or variable/value candidate information
}
/**
* Inline value information can be provided by different means:
* - directly as a text value (class InlineValueText).
* - as a name to use for a variable lookup (class InlineValueVariableLookup)
* - as an evaluatable expression (class InlineValueEvaluatableExpression)
* The InlineValue types combines all inline value types into one type.
*/
export type InlineValue = InlineValueText | InlineValueVariableLookup | InlineValueEvaluatableExpression;
/**
* Provide inline value as text.
*/
export class InlineValueText {
/**
* The text of the inline value.
*/
readonly text: string;
/**
* The range of the inline value.
*/
readonly range: Range;
/**
* Creates a new InlineValueText object.
*
* @param text The value to be shown for the line.
* @param range The document line where to show the inline value.
*/
constructor(text: string, range: Range);
}
/**
* Provide inline value through a variable lookup.
*/
export class InlineValueVariableLookup {
/**
* The name of the variable to look up.
*/
readonly variableName: string;
/**
* How to perform the lookup.
*/
readonly caseSensitiveLookup: boolean;
/**
* The range of the inline value.
*/
readonly range: Range;
/**
* Creates a new InlineValueVariableLookup object.
*
* @param variableName The name of the variable to look up.
* @param range The document line where to show the inline value.
* @param caseSensitiveLookup How to perform the lookup. If missing lookup is case sensitive.
*/
constructor(variableName: string, range: Range, caseSensitiveLookup?: boolean);
}
/**
* Provide inline value through a expression evaluation.
*/
export class InlineValueEvaluatableExpression {
/**
* The expression to evaluate.
*/
readonly expression: string;
/**
* The range of the inline value.
*/
readonly range: Range;
/**
* Creates a new InlineValueEvaluatableExpression object.
*
* @param expression The expression to evaluate.
* @param range The document line where to show the inline value.
*/
constructor(expression: string, range: Range);
}
export namespace languages {
/**
* Register a provider that returns inline values for text documents.
* If debugging has stopped VS Code shows inline values in the editor at the end of lines.
*
* Multiple providers can be registered for a language. In that case providers are asked in
* parallel and the results are merged. A failing provider (rejected promise or exception) will
* not cause a failure of the whole operation.
*
* @param selector A selector that defines the documents this provider is applicable to.
* @param provider An inline values provider.
* @return A [disposable](#Disposable) that unregisters this provider when being disposed.
*/
export function registerInlineValuesProvider(selector: DocumentSelector, provider: InlineValuesProvider): Disposable;
} |
@testforstephen please take a look and provide feedback on behalf of the Java team. |
A first cut of the proposed API and its implementation has been released. The proposed API: vscode/src/vs/vscode.proposed.d.ts Lines 745 to 883 in d723065
Please note:
|
I've slightly changed the API to align it with the existing With this the Support for |
I like your proposal about I see @weinand did call out that since PowerShell's language and debugger are in the same extension, |
Reopened for further feedback and API finalization |
Issues for API meeting March 2:
Here is the full proposed API. |
Outcome of the API discussion:
/cc @jrieken |
From the perspective of Java debugger, we need leverage the debug runtime to resolve the duplicated variables from different scopes precisely. Current context just provides the stoppedLocation info, that seems not enough for us to resolve the current stack frame where the execution has stopped, since Java supports multi threads. I will suggest to add the Regarding scope, I haven't figured out how the client can make use of it. export interface InlineValueContext {
/**
* The document range where execution has stopped.
* Typically the end position of the range denotes the line where the inline values are shown.
*/
stoppedLocation: Range;
/**
* The stack frame where the execution has stopped.
*/
frameId: number;
// ... more to come, e.g. Scope information or variable/value candidate information
} |
@testforstephen thanks for the feedback. Please try the next Insiders. |
I would like to bring up a potential use case of the Currently, the Java debugger only reports one scope to vs code, that is the The UI state of the |
@akaroml is it really necessary to include the UI-state of the VARIABLE tree's scope-nodes in the The extension already has the static information via the |
Yes, we're currently using a setting to control the visibility of the static info. But meanwhile, we're evaluating whether to return a And below is another feedback about valueFormat. In the arguments of DAP requests |
@weinand please check @testforstephen's comment above. Our goal is to make it easier for users to inspect statics as well. The |
@testforstephen, @akaroml thanks for your input! here are my comments:
|
Proposed API for the Inline Values Provider. Since the last API discussion a /**
* A value-object that contains contextual information when requesting inline values from a InlineValuesProvider.
*/
export interface InlineValueContext {
/**
* The stack frame (as a DAP Id) where the execution has stopped.
*/
readonly frameId: number;
/**
* The document range where execution has stopped.
* Typically the end position of the range denotes the line where the inline values are shown.
*/
readonly stoppedLocation: Range;
} |
The InlineValuesProvider API has been finalized and will appear in the next Insiders. |
In this milestone we've finalised the API without changing it. So the test-plan item from the previous milestone still covers it. |
The API looks good. Here are some feedbacks about the implementation.
Screen.Recording.2021-03-23.at.15.34.55.mov
|
@testforstephen thanks for the feedback. |
Today the "Show Inline Values" feature of VS Code's debugger is based on a generic implementation in the VS Code core and provides neither customisability through settings, nor extensibility via extensions.
As a consequence, it is not a perfect fit for all languages (e.g. #101797) and sometimes even shows incorrect values because it doesn't understand the scope regions of the underlying language.
This features asks for an extension API that either replaces the built-in implementation completely or allows to replace parts of the implementation with custom code.
The text was updated successfully, but these errors were encountered: