提交 e537fd9e 编写于 作者: A Andre Weinand

first cut of proposed "inline values provider" API

上级 c9607e61
......@@ -266,7 +266,7 @@ export interface HoverProvider {
}
/**
* An evaluatable expression represents additional information for an expression in a document. Evaluatable expression are
* An evaluatable expression represents additional information for an expression in a document. Evaluatable expressions are
* evaluated by a debugger or runtime and their result is rendered in a tooltip-like widget.
* @internal
*/
......@@ -275,15 +275,16 @@ export interface EvaluatableExpression {
* The range to which this expression applies.
*/
range: IRange;
/*
/**
* This expression overrides the expression extracted from the range.
*/
expression?: string;
}
/**
* The hover provider interface defines the contract between extensions and
* the [hover](https://code.visualstudio.com/docs/editor/intellisense)-feature.
* The evaluatable expression provider interface defines the contract between extensions and
* the debug hover.
* @internal
*/
export interface EvaluatableExpressionProvider {
......@@ -295,6 +296,73 @@ export interface EvaluatableExpressionProvider {
provideEvaluatableExpression(model: model.ITextModel, position: Position, token: CancellationToken): ProviderResult<EvaluatableExpression>;
}
/**
* An open ended information bag passed to the inline value provider.
* A minimal context containes just the document location where the debugger has stopped.
* @internal
*/
export interface InlineValueContext {
stoppedLocation: Range;
}
/**
* Provide inline value as text.
* @internal
*/
export interface InlineValueText {
type: 'text';
text: string;
range: IRange;
}
/**
* Provide inline value through a variable lookup.
* @internal
*/
export interface InlineValueVariableLookup {
type: 'variable';
variableName: string;
caseSensitiveLookup: boolean;
range: IRange;
}
/**
* Provide inline value through an expression evaluation.
* @internal
*/
export interface InlineValueExpression {
type: 'expression';
expression: string;
range: IRange;
}
/**
* 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.
* @internal
*/
export type InlineValue = InlineValueText | InlineValueVariableLookup | InlineValueExpression;
/**
* The inline values provider interface defines the contract between extensions and
* the debugger's inline values feature.
* @internal
*/
export interface InlineValuesProvider {
/**
*/
onDidChangeInlineValues?: Event<void> | undefined;
/**
* Provide the "inline values" for the given range and document. Multiple hovers at the same
* position will be merged by the editor. A hover can have a range which defaults
* to the word range at the position when omitted.
*/
provideInlineValues(model: model.ITextModel, viewPort: Range, context: InlineValueContext, token: CancellationToken): ProviderResult<InlineValue[]>;
}
export const enum CompletionItemKind {
Method,
Function,
......@@ -1745,6 +1813,11 @@ export const HoverProviderRegistry = new LanguageFeatureRegistry<HoverProvider>(
*/
export const EvaluatableExpressionProviderRegistry = new LanguageFeatureRegistry<EvaluatableExpressionProvider>();
/**
* @internal
*/
export const InlineValuesProviderRegistry = new LanguageFeatureRegistry<InlineValuesProvider>();
/**
* @internal
*/
......
......@@ -734,8 +734,149 @@ declare module 'vscode' {
//#endregion
//#region inline value provider: https://github.com/microsoft/vscode/issues/105690
/**
* 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 an 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;
}
//#endregion
// eslint-disable-next-line vscode-dts-region-comments
//#region debug
//#region @weinand: variables view action contributions
/**
* A DebugProtocolVariableContainer is an opaque stand-in type for the intersection of the Scope and Variable types defined in the Debug Adapter Protocol.
......
......@@ -250,6 +250,31 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
}));
}
// --- inline values
$registerInlineValuesProvider(handle: number, selector: IDocumentFilterDto[], eventHandle: number | undefined): void {
const provider = <modes.InlineValuesProvider>{
provideInlineValues: (model: ITextModel, viewPort: EditorRange, context: modes.InlineValueContext, token: CancellationToken): Promise<modes.InlineValue[] | undefined> => {
return this._proxy.$provideInlineValues(handle, model.uri, viewPort, context, token);
}
};
if (typeof eventHandle === 'number') {
const emitter = new Emitter<void>();
this._registrations.set(eventHandle, emitter);
provider.onDidChangeInlineValues = emitter.event;
}
this._registrations.set(handle, modes.InlineValuesProviderRegistry.register(selector, provider));
}
$emitInlineValuesEvent(eventHandle: number, event?: any): void {
const obj = this._registrations.get(eventHandle);
if (obj instanceof Emitter) {
obj.fire(event);
}
}
// --- occurrences
$registerDocumentHighlightProvider(handle: number, selector: IDocumentFilterDto[]): void {
......
......@@ -409,6 +409,10 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
registerEvaluatableExpressionProvider(selector: vscode.DocumentSelector, provider: vscode.EvaluatableExpressionProvider): vscode.Disposable {
return extHostLanguageFeatures.registerEvaluatableExpressionProvider(extension, checkSelector(selector), provider, extension.identifier);
},
registerInlineValuesProvider(selector: vscode.DocumentSelector, provider: vscode.InlineValuesProvider): vscode.Disposable {
checkProposedApiEnabled(extension);
return extHostLanguageFeatures.registerInlineValuesProvider(extension, checkSelector(selector), provider, extension.identifier);
},
registerDocumentHighlightProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentHighlightProvider): vscode.Disposable {
return extHostLanguageFeatures.registerDocumentHighlightProvider(extension, checkSelector(selector), provider);
},
......@@ -1165,6 +1169,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
EndOfLine: extHostTypes.EndOfLine,
EnvironmentVariableMutatorType: extHostTypes.EnvironmentVariableMutatorType,
EvaluatableExpression: extHostTypes.EvaluatableExpression,
InlineValueText: extHostTypes.InlineValueText,
InlineValueVariableLookup: extHostTypes.InlineValueVariableLookup,
InlineValueEvaluatableExpression: extHostTypes.InlineValueEvaluatableExpression,
EventEmitter: Emitter,
ExtensionKind: extHostTypes.ExtensionKind,
ExtensionMode: extHostTypes.ExtensionMode,
......
......@@ -378,6 +378,8 @@ export interface MainThreadLanguageFeaturesShape extends IDisposable {
$registerTypeDefinitionSupport(handle: number, selector: IDocumentFilterDto[]): void;
$registerHoverProvider(handle: number, selector: IDocumentFilterDto[]): void;
$registerEvaluatableExpressionProvider(handle: number, selector: IDocumentFilterDto[]): void;
$registerInlineValuesProvider(handle: number, selector: IDocumentFilterDto[], eventHandle: number | undefined): void;
$emitInlineValuesEvent(eventHandle: number, event?: any): void;
$registerDocumentHighlightProvider(handle: number, selector: IDocumentFilterDto[]): void;
$registerLinkedEditingRangeProvider(handle: number, selector: IDocumentFilterDto[]): void;
$registerReferenceSupport(handle: number, selector: IDocumentFilterDto[]): void;
......@@ -1466,6 +1468,10 @@ export interface ILinkedEditingRangesDto {
wordPattern?: IRegExpDto;
}
export interface IInlineValueContextDto {
stoppedLocation: IRange;
}
export interface ExtHostLanguageFeaturesShape {
$provideDocumentSymbols(handle: number, resource: UriComponents, token: CancellationToken): Promise<modes.DocumentSymbol[] | undefined>;
$provideCodeLenses(handle: number, resource: UriComponents, token: CancellationToken): Promise<ICodeLensListDto | undefined>;
......@@ -1477,6 +1483,7 @@ export interface ExtHostLanguageFeaturesShape {
$provideTypeDefinition(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<IDefinitionLinkDto[]>;
$provideHover(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<modes.Hover | undefined>;
$provideEvaluatableExpression(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<modes.EvaluatableExpression | undefined>;
$provideInlineValues(handle: number, resource: UriComponents, range: IRange, context: modes.InlineValueContext, token: CancellationToken): Promise<modes.InlineValue[] | undefined>;
$provideDocumentHighlights(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<modes.DocumentHighlight[] | undefined>;
$provideLinkedEditingRanges(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<ILinkedEditingRangesDto | undefined>;
$provideReferences(handle: number, resource: UriComponents, position: IPosition, context: modes.ReferenceContext, token: CancellationToken): Promise<ILocationDto[] | undefined>;
......
......@@ -359,6 +359,14 @@ const newCommands: ApiCommand[] = [
};
}))
),
// --- debug support
new ApiCommand(
'vscode.executeInlineValueProvider', '_executeInlineValueProvider', 'Execute inline value provider',
[ApiCommandArgument.Uri, ApiCommandArgument.Range],
new ApiCommandResult<modes.InlineValue[], vscode.InlineValue[]>('A promise that resolves to an array of InlineValue objects', result => {
return result.map(typeConverters.InlineValue.to);
})
),
// --- open'ish commands
new ApiCommand(
'vscode.open', '_workbench.open', 'Opens the provided resource in the editor. Can be a text or binary file, or a http(s) url. If you need more control over the options for opening a text file, use vscode.window.showTextDocument instead.',
......
......@@ -291,6 +291,24 @@ class EvaluatableExpressionAdapter {
}
}
class InlineValuesAdapter {
constructor(
private readonly _documents: ExtHostDocuments,
private readonly _provider: vscode.InlineValuesProvider,
) { }
public provideInlineValues(resource: URI, viewPort: IRange, context: extHostProtocol.IInlineValueContextDto, token: CancellationToken): Promise<modes.InlineValue[] | undefined> {
const doc = this._documents.getDocument(resource);
return asPromise(() => this._provider.provideInlineValues(doc, typeConvert.Range.to(viewPort), typeConvert.InlineValueContext.to(context), token)).then(value => {
if (Array.isArray(value)) {
return value.map(iv => typeConvert.InlineValue.from(iv));
}
return undefined;
});
}
}
class DocumentHighlightAdapter {
constructor(
......@@ -1334,7 +1352,8 @@ type Adapter = DocumentSymbolAdapter | CodeLensAdapter | DefinitionAdapter | Hov
| RangeFormattingAdapter | OnTypeFormattingAdapter | NavigateTypeAdapter | RenameAdapter
| SuggestAdapter | SignatureHelpAdapter | LinkProviderAdapter | ImplementationAdapter
| TypeDefinitionAdapter | ColorProviderAdapter | FoldingProviderAdapter | DeclarationAdapter
| SelectionRangeAdapter | CallHierarchyAdapter | DocumentSemanticTokensAdapter | DocumentRangeSemanticTokensAdapter | EvaluatableExpressionAdapter
| SelectionRangeAdapter | CallHierarchyAdapter | DocumentSemanticTokensAdapter | DocumentRangeSemanticTokensAdapter
| EvaluatableExpressionAdapter | InlineValuesAdapter
| LinkedEditingRangeAdapter | InlineHintsAdapter;
class AdapterData {
......@@ -1568,6 +1587,27 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF
return this._withAdapter(handle, EvaluatableExpressionAdapter, adapter => adapter.provideEvaluatableExpression(URI.revive(resource), position, token), undefined);
}
// --- debug inline values
registerInlineValuesProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.InlineValuesProvider, extensionId?: ExtensionIdentifier): vscode.Disposable {
const eventHandle = typeof provider.onDidChangeInlineValues === 'function' ? this._nextHandle() : undefined;
const handle = this._addNewAdapter(new InlineValuesAdapter(this._documents, provider), extension);
this._proxy.$registerInlineValuesProvider(handle, this._transformDocumentSelector(selector), eventHandle);
let result = this._createDisposable(handle);
if (eventHandle !== undefined) {
const subscription = provider.onDidChangeInlineValues!(_ => this._proxy.$emitInlineValuesEvent(eventHandle));
result = Disposable.from(result, subscription);
}
return result;
}
$provideInlineValues(handle: number, resource: UriComponents, range: IRange, context: extHostProtocol.IInlineValueContextDto, token: CancellationToken): Promise<modes.InlineValue[] | undefined> {
return this._withAdapter(handle, InlineValuesAdapter, adapter => adapter.provideInlineValues(URI.revive(resource), range, context, token), undefined);
}
// --- occurrences
registerDocumentHighlightProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentHighlightProvider): vscode.Disposable {
......
......@@ -850,6 +850,66 @@ export namespace EvaluatableExpression {
}
}
export namespace InlineValue {
export function from(inlineValue: vscode.InlineValue): modes.InlineValue {
if (inlineValue instanceof types.InlineValueText) {
return <modes.InlineValueText>{
type: 'text',
text: inlineValue.text,
range: Range.from(inlineValue.range)
};
} else if (inlineValue instanceof types.InlineValueVariableLookup) {
return <modes.InlineValueVariableLookup>{
type: 'variable',
variableName: inlineValue.variableName,
caseSensitiveLookup: inlineValue.caseSensitiveLookup,
range: Range.from(inlineValue.range)
};
} else if (inlineValue instanceof types.InlineValueEvaluatableExpression) {
return <modes.InlineValueExpression>{
type: 'expression',
expression: inlineValue.expression,
range: Range.from(inlineValue.range)
};
} else {
throw new Error(`Unknown 'InlineValue' type`);
}
}
export function to(inlineValue: modes.InlineValue): vscode.InlineValue {
switch (inlineValue.type) {
case 'text':
return <vscode.InlineValueText>{
text: inlineValue.text,
range: Range.to(inlineValue.range)
};
case 'variable':
return <vscode.InlineValueVariableLookup>{
variableName: inlineValue.variableName,
caseSensitiveLookup: inlineValue.caseSensitiveLookup,
range: Range.to(inlineValue.range)
};
case 'expression':
return <vscode.InlineValueEvaluatableExpression>{
expression: inlineValue.expression,
range: Range.to(inlineValue.range)
};
}
}
}
export namespace InlineValueContext {
export function from(inlineValueContext: vscode.InlineValueContext): extHostProtocol.IInlineValueContextDto {
return <extHostProtocol.IInlineValueContextDto>{
stoppedLocation: Range.from(inlineValueContext.stoppedLocation)
};
}
export function to(inlineValueContext: extHostProtocol.IInlineValueContextDto): types.InlineValueContext {
return new types.InlineValueContext(Range.to(inlineValueContext.stoppedLocation));
}
}
export namespace DocumentHighlight {
export function from(documentHighlight: vscode.DocumentHighlight): modes.DocumentHighlight {
return {
......
......@@ -2439,6 +2439,51 @@ export class EvaluatableExpression implements vscode.EvaluatableExpression {
}
}
@es5ClassCompat
export class InlineValueText implements vscode.InlineValueText {
readonly range: Range;
readonly text: string;
constructor(text: string, range: Range) {
this.text = text;
this.range = range;
}
}
@es5ClassCompat
export class InlineValueVariableLookup implements vscode.InlineValueVariableLookup {
readonly variableName: string;
readonly caseSensitiveLookup: boolean;
readonly range: Range;
constructor(variableName: string, range: Range, caseSensitiveLookup: boolean) {
this.variableName = variableName;
this.caseSensitiveLookup = caseSensitiveLookup;
this.range = range;
}
}
@es5ClassCompat
export class InlineValueEvaluatableExpression implements vscode.InlineValueEvaluatableExpression {
readonly expression: string;
readonly range: Range;
constructor(expression: string, range: Range) {
this.expression = expression;
this.range = range;
}
}
@es5ClassCompat
export class InlineValueContext implements vscode.InlineValueContext {
readonly stoppedLocation: vscode.Range;
constructor(range: vscode.Range) {
this.stoppedLocation = range;
}
}
//#region file api
export enum FileChangeType {
......
......@@ -11,7 +11,10 @@ import { setProperty } from 'vs/base/common/jsonEdit';
import { Constants } from 'vs/base/common/uint';
import { KeyCode } from 'vs/base/common/keyCodes';
import { IKeyboardEvent, StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { StandardTokenType } from 'vs/editor/common/modes';
import { InlineValuesProviderRegistry, StandardTokenType } from 'vs/editor/common/modes';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { flatten } from 'vs/base/common/arrays';
import { onUnexpectedExternalError } from 'vs/base/common/errors';
import { DEFAULT_WORD_REGEXP } from 'vs/editor/common/model/wordHelper';
import { ICodeEditor, IEditorMouseEvent, MouseTargetType, IPartialEditorMouseEvent } from 'vs/editor/browser/editorBrowser';
import { IDecorationOptions } from 'vs/editor/common/editorCommon';
......@@ -47,7 +50,7 @@ const MAX_NUM_INLINE_VALUES = 100; // JS Global scope can have 700+ entries. We
const MAX_INLINE_DECORATOR_LENGTH = 150; // Max string length of each inline decorator when debugging. If exceeded ... is added
const MAX_TOKENIZATION_LINE_LEN = 500; // If line is too long, then inline values for the line are skipped
function createInlineValueDecoration(lineNumber: number, contentText: string): IDecorationOptions {
function createInlineValueDecoration(lineNumber: number, contentText: string, column = Constants.MAX_SAFE_SMALL_INTEGER): IDecorationOptions {
// If decoratorText is too long, trim and add ellipses. This could happen for minified files with everything on a single line
if (contentText.length > MAX_INLINE_DECORATOR_LENGTH) {
contentText = contentText.substr(0, MAX_INLINE_DECORATOR_LENGTH) + '...';
......@@ -57,8 +60,8 @@ function createInlineValueDecoration(lineNumber: number, contentText: string): I
range: {
startLineNumber: lineNumber,
endLineNumber: lineNumber,
startColumn: Constants.MAX_SAFE_SMALL_INTEGER,
endColumn: Constants.MAX_SAFE_SMALL_INTEGER
startColumn: column,
endColumn: column
},
renderOptions: {
after: {
......@@ -572,20 +575,77 @@ export class DebugEditorContribution implements IDebugEditorContribution {
this.removeInlineValuesScheduler.cancel();
const scopes = await stackFrame.getMostSpecificScopes(stackFrame.range);
// Get all top level children in the scope chain
const decorationsPerScope = await Promise.all(scopes.map(async scope => {
const children = await scope.getChildren();
let range = new Range(0, 0, stackFrame.range.startLineNumber, stackFrame.range.startColumn);
if (scope.range) {
range = range.setStartPosition(scope.range.startLineNumber, scope.range.startColumn);
}
let allDecorations: IDecorationOptions[];
return createInlineValueDecorationsInsideRange(children, range, model, this.wordToLineNumbersMap);
}));
if (InlineValuesProviderRegistry.has(model)) {
const findVariable = async (key: string): Promise<string | undefined> => {
const scopes = await stackFrame.getMostSpecificScopes(stackFrame.range);
for (let scope of scopes) {
const variables = await scope.getChildren();
for (let v of variables) {
if (v.name === key) {
return v.value;
}
}
}
return undefined;
};
const ranges = this.editor.getVisibleRangesPlusViewportAboveBelow();
const ctx = { stoppedLocation: new Range(1, 1, stackFrame.range.startLineNumber, stackFrame.range.startColumn) };
const token = new CancellationTokenSource().token;
const providers = InlineValuesProviderRegistry.ordered(model).reverse();
allDecorations = [];
const promises = flatten(providers.map(provider => ranges.map(range => Promise.resolve(provider.provideInlineValues(model, range, ctx, token)).then(async (result) => {
if (result) {
for (let iv of result) {
let text: string;
switch (iv.type) {
case 'text':
text = iv.text;
break;
case 'variable':
const value = await findVariable(iv.variableName);
text = `${iv.variableName} = ${value}`;
break;
case 'expression':
text = `eval(${iv.expression})`;
break;
}
if (text) {
allDecorations.push(createInlineValueDecoration(iv.range.startLineNumber, text, iv.range.startColumn));
}
}
}
}, err => {
onUnexpectedExternalError(err);
}))));
await Promise.all(promises);
} else { // one-size-fits-all strategy
const scopes = await stackFrame.getMostSpecificScopes(stackFrame.range);
// Get all top level variables in the scope chain
const decorationsPerScope = await Promise.all(scopes.map(async scope => {
const variables = await scope.getChildren();
let range = new Range(0, 0, stackFrame.range.startLineNumber, stackFrame.range.startColumn);
if (scope.range) {
range = range.setStartPosition(scope.range.startLineNumber, scope.range.startColumn);
}
return createInlineValueDecorationsInsideRange(variables, range, model, this.wordToLineNumbersMap);
}));
allDecorations = decorationsPerScope.reduce((previous, current) => previous.concat(current), []);
}
const allDecorations = decorationsPerScope.reduce((previous, current) => previous.concat(current), []);
this.editor.setDecorations(INLINE_VALUE_DECORATION_KEY, allDecorations);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册