This commit is contained in:
Henning Dieterichs
2023-09-07 15:00:50 +02:00
parent d45dfdaa71
commit a9656e1e12
37 changed files with 5502 additions and 3664 deletions

View File

@@ -4,23 +4,24 @@ import {
GraphNode,
GraphVisualizationData,
} from "@hediet/debug-visualizer-data-extraction";
import { hotClass, registerUpdateReconciler } from "@hediet/node-reload";
import { DebugSessionProxy } from "../proxies/DebugSessionProxy";
import { DebuggerViewProxy } from "../proxies/DebuggerViewProxy";
import { FormattedMessage } from "../webviewContract";
import {
DebugSessionVisualizationSupport,
VisualizationBackend,
GetVisualizationDataArgs,
VisualizationBackend,
VisualizationBackendBase,
} from "./VisualizationBackend";
import { parseEvaluationResultFromGenericDebugAdapter } from "./parseEvaluationResultFromGenericDebugAdapter";
import { FormattedMessage } from "../webviewContract";
import { hotClass, registerUpdateReconciler } from "@hediet/node-reload";
import { DebuggerViewProxy } from "../proxies/DebuggerViewProxy";
registerUpdateReconciler(module);
@hotClass(module)
export class GenericVisualizationSupport
implements DebugSessionVisualizationSupport {
implements DebugSessionVisualizationSupport
{
constructor(private readonly debuggerView: DebuggerViewProxy) {}
createBackend(
@@ -87,12 +88,12 @@ export class GenericVisualizationBackend extends VisualizationBackendBase {
return parseEvaluationResultFromGenericDebugAdapter(
reply.result,
{
debugAdapterType: this.debugSession.session
.configuration.type,
debugAdapterType:
this.debugSession.session.configuration.type,
}
);
}
} catch (error) {
} catch (error: any) {
return {
kind: "error",
message: {

View File

@@ -1,17 +1,20 @@
import {
ApiHasNotBeenInitializedCode,
CallFrameRequest,
CallFramesRequest,
DataExtractionResult,
DataExtractorId,
DataResult,
getExpressionForDataExtractorApi,
getExpressionToInitializeDataExtractorApi,
ApiHasNotBeenInitializedCode,
} from "@hediet/debug-visualizer-data-extraction";
import { hotClass, registerUpdateReconciler } from "@hediet/node-reload";
import { existsSync, readFileSync, watch } from "fs";
import { observable, reaction } from "mobx";
import { window, workspace } from "vscode";
import { Disposable } from "@hediet/std/disposable";
import { window } from "vscode";
import { Config } from "../Config";
import { DebugSessionProxy, StackFrame, StackTraceInfo } from "../proxies/DebugSessionProxy";
import { DebuggerViewProxy } from "../proxies/DebuggerViewProxy";
import { DebugSessionProxy } from "../proxies/DebugSessionProxy";
import { FileWatcher } from "../webview/WebviewConnection";
import { FormattedMessage } from "../webviewContract";
import {
DebugSessionVisualizationSupport,
@@ -19,22 +22,14 @@ import {
VisualizationBackend,
VisualizationBackendBase,
} from "./VisualizationBackend";
import { Disposable } from "@hediet/std/disposable";
import { DebouncedRunner } from "../utils/DebouncedRunner";
import { FileWatcher } from "../webview/WebviewConnection";
registerUpdateReconciler(module);
@hotClass(module)
export class JsEvaluationEngine implements DebugSessionVisualizationSupport {
constructor(
private readonly debuggerView: DebuggerViewProxy,
private readonly config: Config
) {}
constructor(private readonly debuggerView: DebuggerViewProxy, private readonly config: Config) {}
createBackend(
session: DebugSessionProxy
): VisualizationBackend | undefined {
createBackend(session: DebugSessionProxy): VisualizationBackend | undefined {
const supportedDebugAdapters = [
"node",
"node2",
@@ -48,25 +43,21 @@ export class JsEvaluationEngine implements DebugSessionVisualizationSupport {
];
if (supportedDebugAdapters.indexOf(session.session.type) !== -1) {
return new JsVisualizationBackend(
session,
this.debuggerView,
this.config
);
return new JsVisualizationBackend(session, this.debuggerView, this.config);
}
return undefined;
}
}
class CallFrameState {
public request: CallFramesRequest | undefined = undefined;
}
class JsVisualizationBackend extends VisualizationBackendBase {
public readonly expressionLanguageId = "javascript";
private initializePromise: Promise<void> | undefined = undefined;
constructor(
debugSession: DebugSessionProxy,
debuggerView: DebuggerViewProxy,
private readonly config: Config
) {
constructor(debugSession: DebugSessionProxy, debuggerView: DebuggerViewProxy, private readonly config: Config) {
super(debugSession, debuggerView);
}
@@ -79,20 +70,13 @@ class JsVisualizationBackend extends VisualizationBackendBase {
public async getVisualizationData(
args: GetVisualizationDataArgs
): Promise<
| { kind: "data"; result: DataExtractionResult }
| { kind: "error"; message: FormattedMessage }
> {
const result = await this._getVisualizationData(args);
): Promise<{ kind: "data"; result: DataExtractionResult } | { kind: "error"; message: FormattedMessage }> {
let result = await this.getVisualizationDataIfInitialized(args);
if (result.kind === "not-initialized") {
await this.initializeApiSafe();
const result2 = await this._getVisualizationData(args);
if (result2.kind !== "not-initialized") {
return result2;
} else {
await this.initializeApiOrWait();
result = await this.getVisualizationDataIfInitialized(args);
if (result.kind === "not-initialized") {
return {
kind: "error",
message: "Could not initialize API",
@@ -103,103 +87,74 @@ class JsVisualizationBackend extends VisualizationBackendBase {
return result;
}
private async _getVisualizationData({
expression,
preferredExtractorId,
}: GetVisualizationDataArgs): Promise<
private async getVisualizationDataIfInitialized(
args: GetVisualizationDataArgs
): Promise<
| { kind: "data"; result: DataExtractionResult }
| { kind: "error"; message: FormattedMessage }
| { kind: "not-initialized" }
> {
try {
const frameId = this.debuggerView.getActiveStackFrameId(
this.debugSession
);
const { expression, preferredExtractorId } = args;
let callFrameState: CallFrameState;
if (args.sessionStore.data instanceof CallFrameState) {
callFrameState = args.sessionStore.data;
} else {
callFrameState = new CallFrameState();
args.sessionStore.data = callFrameState;
}
const variableNames = new Array<string>();
if (frameId) {
const scopes = await this.debugSession.getScopes({ frameId });
const scopeVariables = await Promise.all(
scopes
.filter((s) => !s.expensive && s.name !== "Global")
.map((s) =>
this.debugSession.getVariables({
variablesReference: s.variablesReference,
})
)
);
for (const variables of scopeVariables) {
variableNames.push(
...variables
.filter((v) => v.value !== "undefined")
.map((v) => v.name)
try {
const frameId = this.debuggerView.getActiveStackFrameId(this.debugSession);
const stackTrace = await this.debuggerView.activeDebugSession!.getStackTrace({
threadId: 0,
levels: 20,
});
const variableNames = await getVariableNames(this.debugSession, frameId);
let tryCount = 0;
while (true) {
tryCount++;
let callFrameDataValue = "null";
if (callFrameState.request) {
callFrameDataValue = await getCallFramesSnapshotValue(
this.debugSession,
stackTrace,
callFrameState.request
);
}
const result = await this.evaluateVisualizationDataRequest(
expression,
preferredExtractorId,
variableNames,
callFrameDataValue,
frameId
);
if (variableNames.length > 50) {
variableNames.length = 50;
if (result.kind === "NoExtractors") {
throw new Error("No extractors");
} else if (result.kind === "Error") {
throw new Error(result.message + "\n" + (result as any).stack);
} else if (result.kind === "Data") {
return {
kind: "data",
result: result.extractionResult,
};
} else if (result.kind === "OutdatedCallFrameSnapshot") {
if (tryCount >= 2) {
throw new Error("OutdatedCallFrameSnapshot");
}
callFrameState.request = result.callFramesRequest;
} else {
throw new Error("Invalid Data");
}
}
const preferredExtractorExpr = preferredExtractorId
? `"${preferredExtractorId}"`
: "undefined";
const body = `${getExpressionForDataExtractorApi()}.getData(
() => (${expression}),
expr => eval(expr),
${preferredExtractorExpr},
{${variableNames.map((n) => `${n}: () => ${n}`).join(",")}},
)`;
const wrappedExpr = `
(() => {
try {
return ${body};
} catch (e) {
return JSON.stringify({
kind: "Error",
message: e.message,
stack: e.stack
});
}
})()
`;
const reply = await this.debugSession.evaluate({
expression: wrappedExpr,
frameId,
context: this.getContext(),
});
const resultStr = reply.result;
const jsonData =
this.getContext() === "copy"
? resultStr
: resultStr.substr(1, resultStr.length - 2);
const result = JSON.parse(jsonData) as DataResult;
if (result.kind === "NoExtractors") {
throw new Error("No extractors");
} else if (result.kind === "Error") {
throw new Error(result.message + "\n" + (result as any).stack);
} else if (result.kind === "Data") {
return {
kind: "data",
result: result.extractionResult,
};
} else {
throw new Error("Invalid Data");
} catch (error: any) {
if (typeof error.message === "string" && error.message.indexOf(ApiHasNotBeenInitializedCode) !== -1) {
return { kind: "not-initialized" };
}
} catch (error) {
if (
typeof error.message === "string" &&
error.message.indexOf(ApiHasNotBeenInitializedCode) !== -1
) {
return {
kind: "not-initialized",
};
}
return {
kind: "error",
message: error.message,
@@ -207,11 +162,42 @@ class JsVisualizationBackend extends VisualizationBackendBase {
}
}
private initializeApiSafe(): Promise<void> {
private async evaluateVisualizationDataRequest(
expression: string,
preferredExtractorId: DataExtractorId | undefined,
variableNames: string[],
callFrameDataValue: string,
frameId: number | undefined
): Promise<DataResult> {
const preferredExtractorExpr = preferredExtractorId ? `"${preferredExtractorId}"` : "undefined";
const body = `${getExpressionForDataExtractorApi()}.getData(
() => (${expression}),
expr => eval(expr),
${preferredExtractorExpr},
{${variableNames.map((n) => `${n}: () => ${n}`).join(",")}},
${callFrameDataValue}
)`;
const wrappedExpr = `(() => {
try { return ${body}; }
catch (e) { return JSON.stringify({ kind: "Error", message: e.message, stack: e.stack }); }
})()
`;
const reply = await this.debugSession.evaluate({
expression: wrappedExpr,
frameId,
context: this.getContext(),
});
const resultStr = reply.result;
const jsonData = this.getContext() === "copy" ? resultStr : resultStr.substr(1, resultStr.length - 2);
const result = JSON.parse(jsonData) as DataResult;
return result;
}
private initializeApiOrWait(): Promise<void> {
if (!this.initializePromise) {
this.initializePromise = this.initializeApi().finally(
() => (this.initializePromise = undefined)
);
this.initializePromise = this.initializeApi().finally(() => (this.initializePromise = undefined));
}
return this.initializePromise;
}
@@ -219,10 +205,10 @@ class JsVisualizationBackend extends VisualizationBackendBase {
private async initializeApi(): Promise<void> {
// prefer existing is true, so that manually registered (possibly newer) extractors are not overwritten.
const expression = `${getExpressionToInitializeDataExtractorApi()}.registerDefaultExtractors(true);`;
await this.debugSession.evaluate({
const frameId = this.debuggerView.getActiveStackFrameId(this.debugSession);
const result = await this.debugSession.evaluate({
expression,
frameId: undefined,
frameId,
context: this.getContext(),
});
@@ -235,18 +221,140 @@ class JsVisualizationBackend extends VisualizationBackendBase {
this.dispose.untrack(this.customScripts);
this.customScripts?.dispose();
this.customScripts = this.dispose.track(
new CustomScripts(this.debugSession, this.config, () =>
this.onChangeEmitter.emit()
)
new CustomScripts(this.debugSession, this.debuggerView, this.config, () => this.onChangeEmitter.emit())
);
}
}
let globalCallFrameId = 0;
async function getCallFramesSnapshotValue(
debugSession: DebugSessionProxy,
stackTrace: StackTraceInfo,
callFramesRequest: CallFramesRequest
): Promise<string> {
const globalFnDef = `
function getGlobal() {
if (typeof globalThis === "object") {
return globalThis;
} else if (typeof global === "object") {
return global;
} else if (typeof window === "object") {
return window;
}
throw new Error("No global available");
}`;
const callFrameId = globalCallFrameId++;
let idx = 0;
let skippedCount = 0;
const skippedCounts: Record<number, number> = {};
let frames = stackTrace.stackFrames;
const firstAsyncFrameIdx = frames.findIndex((f) => f.id === 0);
if (firstAsyncFrameIdx !== -1) {
frames = frames.slice(0, firstAsyncFrameIdx);
}
const result = await Promise.all(
frames.map(async (frame) => {
function matches(frame: StackFrame, callFrameRequest: CallFrameRequest): boolean {
if (frame.name !== callFrameRequest.methodName) {
return false;
}
return true;
}
if (!callFramesRequest.requestedCallFrames.some((r) => matches(frame, r))) {
if (skippedCount === 0) {
idx++;
}
skippedCount++;
skippedCounts[idx - 1] = skippedCount;
return undefined;
}
skippedCount = 0;
const curFrameIdx = idx;
idx++;
const scopes = await debugSession.getScopes({ frameId: frame.id });
const scopeVariables = await Promise.all(
scopes
.filter((s) => !s.expensive && s.name.indexOf(":") !== -1)
.map((s) => debugSession.getVariables({ variablesReference: s.variablesReference }))
);
const variables = new Set(scopeVariables.flatMap((v) => v.map((v) => v.name)));
await debugSession.evaluate({
expression: `
(() => {
${globalFnDef}
const g = getGlobal();
(g.$$hedietDbgVslzr${callFrameId} = g.$$hedietDbgVslzr${callFrameId} || [])[${curFrameIdx}] = {
vars: { ${[...variables].map((v) => `${v}: ${v}`).join(", ")} },
...${JSON.stringify({
methodName: frame.name,
source: { path: frame.source.path, name: frame.source.name },
})}
};
})();
`,
frameId: frame.id,
context: "repl",
});
return true;
})
);
if (!result.some((r) => r)) {
return `{ requestId: ${JSON.stringify(callFramesRequest.requestId)}, frames: [] }`;
}
return `
(() => {
${globalFnDef}
const g = getGlobal();
const r = g.$$hedietDbgVslzr${callFrameId};
delete g.$$hedietDbgVslzr${callFrameId};
${Object.entries(skippedCounts)
.map(([idx, val]) => `r[${idx}] = { skippedFrames: ${val} };\n`)
.join("")}
return { requestId: ${JSON.stringify(callFramesRequest.requestId)}, frames: r };
})()
`;
}
async function getVariableNames(debugSession: DebugSessionProxy, frameId: number | undefined) {
const variableNames = new Array<string>();
if (frameId) {
const scopes = await debugSession.getScopes({ frameId });
const scopeVariables = await Promise.all(
scopes
.filter((s) => !s.expensive && s.name !== "Global")
.map((s) =>
debugSession.getVariables({
variablesReference: s.variablesReference,
})
)
);
for (const variables of scopeVariables) {
variableNames.push(...variables.filter((v) => v.value !== "undefined").map((v) => v.name));
}
if (variableNames.length > 50) {
variableNames.length = 50;
}
}
return variableNames;
}
class CustomScripts {
public readonly dispose = Disposable.fn();
constructor(
debugSession: DebugSessionProxy,
debuggerView: DebuggerViewProxy,
config: Config,
changeHandler: () => void
) {
@@ -256,9 +364,7 @@ class CustomScripts {
async (files) => {
for (const file of files) {
if (!file.fileExists) {
window.showErrorMessage(
`The file ${file.path} does not exist.`
);
window.showErrorMessage(`The file ${file.path} does not exist.`);
continue;
}
@@ -278,20 +384,16 @@ class CustomScripts {
}
)
(
${
file.content === undefined
? "undefined"
: `function (module) { ${file.content} }`
}
${file.content === undefined ? "undefined" : `function (module) { ${file.content} }`}
)`;
try {
await debugSession.evaluate({
expression,
frameId: undefined,
frameId: debuggerView.getActiveStackFrameId(debugSession),
context: "repl",
});
} catch (e) {
} catch (e: any) {
window.showErrorMessage(
'Error while running custom visualization extractor script "' +
file.path +

View File

@@ -1,39 +1,33 @@
import {
DataExtractionResult,
DataExtractorId,
GraphNode,
GraphVisualizationData,
} from "@hediet/debug-visualizer-data-extraction";
import { hotClass, registerUpdateReconciler } from "@hediet/node-reload";
import { Config } from "../Config";
import { DebugSessionProxy } from "../proxies/DebugSessionProxy";
import { DebuggerViewProxy } from "../proxies/DebuggerViewProxy";
import { FormattedMessage } from "../webviewContract";
import {
DebugSessionVisualizationSupport,
VisualizationBackend,
GetVisualizationDataArgs,
VisualizationBackend,
VisualizationBackendBase,
} from "./VisualizationBackend";
import { Config } from "../Config";
import { parseEvaluationResultFromGenericDebugAdapter } from "./parseEvaluationResultFromGenericDebugAdapter";
import { FormattedMessage } from "../webviewContract";
import { hotClass, registerUpdateReconciler } from "@hediet/node-reload";
import { DebuggerViewProxy } from "../proxies/DebuggerViewProxy";
registerUpdateReconciler(module);
@hotClass(module)
export class PyEvaluationEngine
implements DebugSessionVisualizationSupport {
export class PyEvaluationEngine implements DebugSessionVisualizationSupport {
constructor(
private readonly debuggerView: DebuggerViewProxy,
private readonly config: Config
) { }
) {}
createBackend(
session: DebugSessionProxy
): VisualizationBackend | undefined {
const supportedDebugAdapters = [
"python",
];
const supportedDebugAdapters = ["python"];
if (supportedDebugAdapters.indexOf(session.session.type) !== -1) {
return new PyVisualizationBackend(
@@ -81,7 +75,8 @@ export class PyVisualizationBackend extends VisualizationBackendBase {
try {
// inject vscodedebugvisualizer for python
await this.debugSession.evaluate({
expression: 'from vscodedebugvisualizer import visualize\ntry:\n import debugvisualizer\nexcept ImportError:\n pass',
expression:
"from vscodedebugvisualizer import visualize\ntry:\n import debugvisualizer\nexcept ImportError:\n pass",
frameId,
context: this.getContext(),
});
@@ -97,21 +92,23 @@ export class PyVisualizationBackend extends VisualizationBackendBase {
result = result.replace(/\\'/g, "'");
result = result.replace(/\\\\/g, "\\");
return parseEvaluationResultFromGenericDebugAdapter(
result,
{
debugAdapterType: this.debugSession.session
.configuration.type,
}
);
return parseEvaluationResultFromGenericDebugAdapter(result, {
debugAdapterType: this.debugSession.session.configuration.type,
});
} catch (error) {
let errorTyped = error as Error;
if (errorTyped.message.includes("ModuleNotFoundError: No module named 'vscodedebugvisualizer'")) {
if (
errorTyped.message.includes(
"ModuleNotFoundError: No module named 'vscodedebugvisualizer'"
)
) {
return {
kind: "error",
message: {
kind: "list",
items: ["Please make sure vscodedebugvisualizer is installed: `pip install vscodedebugvisualizer`"],
items: [
"Please make sure vscodedebugvisualizer is installed: `pip install vscodedebugvisualizer`",
],
},
};
}
@@ -145,5 +142,4 @@ export class PyVisualizationBackend extends VisualizationBackendBase {
pythonInject += "visualize(" + args.expression + ")";
return pythonInject;
}
}

View File

@@ -1,10 +1,18 @@
import { DataExtractionResult, DataResult } from "@hediet/debug-visualizer-data-extraction";
import {
DataExtractionResult,
DataResult,
} from "@hediet/debug-visualizer-data-extraction";
import { hotClass, registerUpdateReconciler } from "@hediet/node-reload";
import { Config } from "../Config";
import { DebuggerViewProxy } from "../proxies/DebuggerViewProxy";
import { DebugSessionProxy } from "../proxies/DebugSessionProxy";
import { DebuggerViewProxy } from "../proxies/DebuggerViewProxy";
import { FormattedMessage } from "../webviewContract";
import { DebugSessionVisualizationSupport, GetVisualizationDataArgs, VisualizationBackend, VisualizationBackendBase } from "./VisualizationBackend";
import {
DebugSessionVisualizationSupport,
GetVisualizationDataArgs,
VisualizationBackend,
VisualizationBackendBase,
} from "./VisualizationBackend";
registerUpdateReconciler(module);
@@ -13,12 +21,12 @@ export class RbEvaluationEngine implements DebugSessionVisualizationSupport {
constructor(
private readonly debuggerView: DebuggerViewProxy,
private readonly config: Config
) { }
) {}
createBackend(
session: DebugSessionProxy
): VisualizationBackend | undefined {
const supportedDebugAdapters = ['rdbg'];
const supportedDebugAdapters = ["rdbg"];
if (supportedDebugAdapters.indexOf(session.session.type) !== -1) {
return new RbVisualizationBackend(
@@ -32,13 +40,13 @@ export class RbEvaluationEngine implements DebugSessionVisualizationSupport {
}
class RbVisualizationBackend extends VisualizationBackendBase {
public readonly expressionLanguageId = 'ruby';
public readonly expressionLanguageId = "ruby";
constructor(
debugSession: DebugSessionProxy,
debuggerView: DebuggerViewProxy,
private readonly config: Config
) {
super(debugSession, debuggerView)
super(debugSession, debuggerView);
}
private readonly defaultContext = "repl";
@@ -46,8 +54,8 @@ class RbVisualizationBackend extends VisualizationBackendBase {
public async getVisualizationData(
args: GetVisualizationDataArgs
): Promise<
| { kind: "data"; result: DataExtractionResult; }
| { kind: "error"; message: FormattedMessage; }
| { kind: "data"; result: DataExtractionResult }
| { kind: "error"; message: FormattedMessage }
> {
const result = await this._getVisualizationData(args);
return result;
@@ -55,7 +63,7 @@ class RbVisualizationBackend extends VisualizationBackendBase {
private async _getVisualizationData({
expression,
preferredExtractorId
preferredExtractorId,
}: GetVisualizationDataArgs): Promise<
| { kind: "data"; result: DataExtractionResult }
| { kind: "error"; message: FormattedMessage }
@@ -69,9 +77,9 @@ class RbVisualizationBackend extends VisualizationBackendBase {
const initialReply = await this.debugSession.evaluate({
expression: "require 'debugvisualizer'",
frameId,
context: this.defaultContext
context: this.defaultContext,
});
if (initialReply.result.includes('LoadError')) {
if (initialReply.result.includes("LoadError")) {
return {
kind: "error",
message: {
@@ -82,49 +90,56 @@ class RbVisualizationBackend extends VisualizationBackendBase {
kind: "inlineList",
items: [
"Install the gem by executing:",
{ kind: "code", content: "$ bundle add debugvisualizer" },
{
kind: "code",
content: "$ bundle add debugvisualizer",
},
],
},
{
kind: "inlineList",
items: [
"If bundler is not being used, install the gem by executing:",
{ kind: "code", content: "$ gem install debugvisualizer" },
{
kind: "code",
content:
"$ gem install debugvisualizer",
},
],
}
},
],
}
},
};
}
const preferredId = preferredExtractorId || '';
const preferredId = preferredExtractorId || "";
const wrappedExpr = `
DebugVisualizer.to_debug_visualizer_protocol_json("${preferredId}", ${expression})
`;
const reply = await this.debugSession.evaluate({
expression: wrappedExpr,
frameId,
context: this.defaultContext
})
context: this.defaultContext,
});
let dataResult: DataResult;
try {
// Debuggee converts result to a JSON string twice.
dataResult = JSON.parse(JSON.parse(reply.result)) as DataResult;
} catch (error) {
let message = error.message
} catch (error: any) {
let message = error.message;
// The `reply.result` is as follows when error occurs in the evaluation of an expression and parsing will fail.
// e.g. "#<ZeroDivisionError: divided by 0>"
// In this case, it is more beneficial to display this error message.
if (reply.result.includes('Error')) message = reply.result;
throw new Error(message)
if (reply.result.includes("Error")) message = reply.result;
throw new Error(message);
}
switch (dataResult.kind) {
case 'NoExtractors':
case "NoExtractors":
throw new Error("No extractors");
case 'Error':
case "Error":
throw new Error(dataResult.message);
case 'Data':
case "Data":
return {
kind: "data",
result: dataResult.extractionResult,
@@ -132,10 +147,10 @@ class RbVisualizationBackend extends VisualizationBackendBase {
default:
throw new Error("Invalid Data");
}
} catch (error) {
} catch (error: any) {
return {
kind: "error",
message: error.message
message: error.message,
};
}
}

View File

@@ -3,11 +3,11 @@ import {
DataExtractorId,
} from "@hediet/debug-visualizer-data-extraction";
import { Disposable } from "@hediet/std/disposable";
import { DebugSessionProxy } from "../proxies/DebugSessionProxy";
import { CompletionItem, FormattedMessage } from "../webviewContract";
import { reaction } from "mobx";
import { DebuggerViewProxy } from "../proxies/DebuggerViewProxy";
import { EventEmitter, EventSource } from "@hediet/std/events";
import { reaction } from "mobx";
import { DebugSessionProxy } from "../proxies/DebugSessionProxy";
import { DebuggerViewProxy } from "../proxies/DebuggerViewProxy";
import { CompletionItem, FormattedMessage } from "../webviewContract";
export interface DebugSessionVisualizationSupport {
createBackend(session: DebugSessionProxy): VisualizationBackend | undefined;
@@ -32,8 +32,11 @@ export interface VisualizationBackend extends Disposable {
}
export interface GetVisualizationDataArgs {
expression: string;
preferredExtractorId: DataExtractorId | undefined;
readonly expression: string;
readonly preferredExtractorId: DataExtractorId | undefined;
// Can be used to attach data to the session.
readonly sessionStore: { data: unknown };
}
export abstract class VisualizationBackendBase implements VisualizationBackend {
@@ -49,7 +52,7 @@ export abstract class VisualizationBackendBase implements VisualizationBackend {
this.dispose.track({
dispose: reaction(
() => debuggerView.getActiveStackFrameId(debugSession),
activeStackFrameId => {
(activeStackFrameId) => {
if (activeStackFrameId !== undefined) {
this.onChangeEmitter.emit();
}

View File

@@ -65,7 +65,7 @@ export function parseEvaluationResultFromGenericDebugAdapter(
},
};
}
} catch (e) {
} catch (e: any) {
return {
kind: "error",
message: e.message,
@@ -93,7 +93,7 @@ function isEnclosedWith(str: string, char: string): boolean {
function parseJson(str: string, context: ParseEvaluationResultContext) {
try {
return JSON.parse(str);
} catch (error) {
} catch (error: any) {
throw new FormattedError({
kind: "list",
items: [