Skip to content

Commit

Permalink
debug: add location to evaluate expression hovers (#216551)
Browse files Browse the repository at this point in the history
Adopts microsoft/debug-adapter-protocol#481

fyi @roblourens, I think hover is the only place where this is relevant and this adds it there
  • Loading branch information
connor4312 committed Jun 18, 2024
1 parent f36a1ed commit 0dfcf2c
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 21 deletions.
31 changes: 19 additions & 12 deletions src/vs/workbench/contrib/debug/browser/debugHover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -451,8 +451,10 @@ interface IDebugHoverComputeResult {
}

class DebugHoverComputer {
private _currentRange: Range | undefined;
private _currentExpression: string | undefined;
private _current?: {
range: Range;
expression: string;
};

constructor(
private editor: ICodeEditor,
Expand All @@ -474,30 +476,35 @@ class DebugHoverComputer {
}

const { range, matchingExpression } = result;
const rangeChanged = this._currentRange ?
!this._currentRange.equalsRange(range) :
true;
this._currentExpression = matchingExpression;
this._currentRange = Range.lift(range);
return { rangeChanged, range: this._currentRange };
const rangeChanged = !this._current?.range.equalsRange(range);
this._current = { expression: matchingExpression, range: Range.lift(range) };
return { rangeChanged, range: this._current.range };
}

async evaluate(session: IDebugSession): Promise<IExpression | undefined> {
if (!this._currentExpression) {
if (!this._current) {
this.logService.error('No expression to evaluate');
return;
}

const textModel = this.editor.getModel();
const debugSource = textModel && session.getSourceForUri(textModel?.uri);

if (session.capabilities.supportsEvaluateForHovers) {
const expression = new Expression(this._currentExpression);
await expression.evaluate(session, this.debugService.getViewModel().focusedStackFrame, 'hover');
const expression = new Expression(this._current.expression);
await expression.evaluate(session, this.debugService.getViewModel().focusedStackFrame, 'hover', undefined, debugSource ? {
line: this._current.range.startLineNumber,
column: this._current.range.startColumn,
source: debugSource.raw,
} : undefined);
return expression;
} else {
const focusedStackFrame = this.debugService.getViewModel().focusedStackFrame;
if (focusedStackFrame) {
return await findExpressionInStackFrame(
focusedStackFrame,
coalesce(this._currentExpression.split('.').map(word => word.trim())));
coalesce(this._current.expression.split('.').map(word => word.trim()))
);
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/vs/workbench/contrib/debug/browser/debugSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -685,12 +685,12 @@ export class DebugSession implements IDebugSession, IDisposable {
return this.raw.variables({ variablesReference, filter, start, count }, token);
}

evaluate(expression: string, frameId: number, context?: string): Promise<DebugProtocol.EvaluateResponse | undefined> {
evaluate(expression: string, frameId: number, context?: string, location?: { line: number; column: number; source: DebugProtocol.Source }): Promise<DebugProtocol.EvaluateResponse | undefined> {
if (!this.raw) {
throw new Error(localize('noDebugAdapter', "No debugger available, can not send '{0}'", 'evaluate'));
}

return this.raw.evaluate({ expression, frameId, context });
return this.raw.evaluate({ expression, frameId, context, line: location?.line, column: location?.column, source: location?.source });
}

async restartFrame(frameId: number, threadId: number): Promise<void> {
Expand Down
8 changes: 7 additions & 1 deletion src/vs/workbench/contrib/debug/common/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,12 @@ export interface INewReplElementData {
source?: IReplElementSource;
}

export interface IDebugEvaluatePosition {
line: number;
column: number;
source: DebugProtocol.Source;
}


export interface IDebugSession extends ITreeElement {

Expand Down Expand Up @@ -431,7 +437,7 @@ export interface IDebugSession extends ITreeElement {
exceptionInfo(threadId: number): Promise<IExceptionInfo | undefined>;
scopes(frameId: number, threadId: number): Promise<DebugProtocol.ScopesResponse | undefined>;
variables(variablesReference: number, threadId: number | undefined, filter: 'indexed' | 'named' | undefined, start: number | undefined, count: number | undefined): Promise<DebugProtocol.VariablesResponse | undefined>;
evaluate(expression: string, frameId?: number, context?: string): Promise<DebugProtocol.EvaluateResponse | undefined>;
evaluate(expression: string, frameId?: number, context?: string, location?: IDebugEvaluatePosition): Promise<DebugProtocol.EvaluateResponse | undefined>;
customRequest(request: string, args: any): Promise<DebugProtocol.Response | undefined>;
cancel(progressId: string): Promise<DebugProtocol.CancelResponse | undefined>;
disassemble(memoryReference: string, offset: number, instructionOffset: number, instructionCount: number): Promise<DebugProtocol.DisassembledInstruction[] | undefined>;
Expand Down
12 changes: 7 additions & 5 deletions src/vs/workbench/contrib/debug/common/debugModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import * as nls from 'vs/nls';
import { ILogService } from 'vs/platform/log/common/log';
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
import { IEditorPane } from 'vs/workbench/common/editor';
import { DEBUG_MEMORY_SCHEME, DataBreakpointSetType, DataBreakpointSource, DebugTreeItemCollapsibleState, IBaseBreakpoint, IBreakpoint, IBreakpointData, IBreakpointUpdateData, IBreakpointsChangeEvent, IDataBreakpoint, IDebugModel, IDebugSession, IDebugVisualizationTreeItem, IEnablement, IExceptionBreakpoint, IExceptionInfo, IExpression, IExpressionContainer, IFunctionBreakpoint, IInstructionBreakpoint, IMemoryInvalidationEvent, IMemoryRegion, IRawModelUpdate, IRawStoppedDetails, IScope, IStackFrame, IThread, ITreeElement, MemoryRange, MemoryRangeType, State, isFrameDeemphasized } from 'vs/workbench/contrib/debug/common/debug';
import { DEBUG_MEMORY_SCHEME, DataBreakpointSetType, DataBreakpointSource, DebugTreeItemCollapsibleState, IBaseBreakpoint, IBreakpoint, IBreakpointData, IBreakpointUpdateData, IBreakpointsChangeEvent, IDataBreakpoint, IDebugEvaluatePosition, IDebugModel, IDebugSession, IDebugVisualizationTreeItem, IEnablement, IExceptionBreakpoint, IExceptionInfo, IExpression, IExpressionContainer, IFunctionBreakpoint, IInstructionBreakpoint, IMemoryInvalidationEvent, IMemoryRegion, IRawModelUpdate, IRawStoppedDetails, IScope, IStackFrame, IThread, ITreeElement, MemoryRange, MemoryRangeType, State, isFrameDeemphasized } from 'vs/workbench/contrib/debug/common/debug';
import { Source, UNKNOWN_SOURCE_LABEL, getUriFromSource } from 'vs/workbench/contrib/debug/common/debugSource';
import { DebugStorage } from 'vs/workbench/contrib/debug/common/debugStorage';
import { IDebugVisualizerService } from 'vs/workbench/contrib/debug/common/debugVisualizers';
Expand Down Expand Up @@ -198,7 +198,9 @@ export class ExpressionContainer implements IExpressionContainer {
session: IDebugSession | undefined,
stackFrame: IStackFrame | undefined,
context: string,
keepLazyVars = false): Promise<boolean> {
keepLazyVars = false,
location?: IDebugEvaluatePosition,
): Promise<boolean> {

if (!session || (!stackFrame && context !== 'repl')) {
this.value = context === 'repl' ? nls.localize('startDebugFirst', "Please start a debug session to evaluate expressions") : Expression.DEFAULT_VALUE;
Expand All @@ -208,7 +210,7 @@ export class ExpressionContainer implements IExpressionContainer {

this.session = session;
try {
const response = await session.evaluate(expression, stackFrame ? stackFrame.frameId : undefined, context);
const response = await session.evaluate(expression, stackFrame ? stackFrame.frameId : undefined, context, location);

if (response && response.body) {
this.value = response.body.result || '';
Expand Down Expand Up @@ -306,8 +308,8 @@ export class Expression extends ExpressionContainer implements IExpression {
}
}

async evaluate(session: IDebugSession | undefined, stackFrame: IStackFrame | undefined, context: string, keepLazyVars?: boolean): Promise<void> {
this.available = await this.evaluateExpression(this.name, session, stackFrame, context, keepLazyVars);
async evaluate(session: IDebugSession | undefined, stackFrame: IStackFrame | undefined, context: string, keepLazyVars?: boolean, location?: IDebugEvaluatePosition): Promise<void> {
this.available = await this.evaluateExpression(this.name, session, stackFrame, context, keepLazyVars, location);
}

override toString(): string {
Expand Down
11 changes: 10 additions & 1 deletion src/vs/workbench/contrib/debug/common/debugProtocol.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1377,6 +1377,15 @@ declare module DebugProtocol {
expression: string;
/** Evaluate the expression in the scope of this stack frame. If not specified, the expression is evaluated in the global scope. */
frameId?: number;
/** The contextual line where the expression should be evaluated. In the 'hover' context, this should be set to the start of the expression being hovered. */
line?: number;
/** The contextual column where the expression should be evaluated. This may be provided if `line` is also provided.
It is measured in UTF-16 code units and the client capability `columnsStartAt1` determines whether it is 0- or 1-based.
*/
column?: number;
/** The contextual source in which the `line` is found. This must be provided if `line` is provided. */
source?: Source;
/** The context in which the evaluate request is used.
Values:
'watch': evaluate is called from a watch view context.
Expand Down Expand Up @@ -2401,7 +2410,7 @@ declare module DebugProtocol {
Values:
'source': In `SourceBreakpoint`s
'exception': In exception breakpoints applied in the `ExceptionFilterOptions`
'data': In data breakpoints requested in the the `DataBreakpointInfo` request
'data': In data breakpoints requested in the `DataBreakpointInfo` request
'instruction': In `InstructionBreakpoint`s
etc.
*/
Expand Down

0 comments on commit 0dfcf2c

Please sign in to comment.