Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/programflow-visualization/frontend/frontend.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ExtensionContext } from 'vscode';
import * as vscode from 'vscode';
import { VisualizationPanel } from './visualization_panel';
import { MessagePort } from 'worker_threads';
import * as TraceCache from '../trace_cache';
Expand All @@ -7,6 +8,7 @@ let panel: VisualizationPanel | undefined = undefined;

export async function startFrontend(
context: ExtensionContext,
outChannel: vscode.OutputChannel,
filePath: string,
fileHash: string,
tracePort: MessagePort | null): Promise<Failure | undefined> {
Expand All @@ -16,7 +18,7 @@ export async function startFrontend(
}

panel?.dispose();
panel = await VisualizationPanel.getVisualizationPanel(context, filePath, fileHash, trace, tracePort);
panel = await VisualizationPanel.getVisualizationPanel(context, outChannel, filePath, fileHash, trace, tracePort);
if (!panel) {
return failure("Frontend couldn't be initialized!");
}
Expand Down
59 changes: 40 additions & 19 deletions src/programflow-visualization/frontend/visualization_panel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,17 @@ export class VisualizationPanel {
private _trace: FrontendTrace;
private _traceIndex: number;
private _tracePortSelfClose: boolean;
private _outChannel: vscode.OutputChannel;

private constructor(context: vscode.ExtensionContext, filePath: string, fileHash: string, trace: BackendTrace, tracePort: MessagePort | null) {
private constructor(
context: vscode.ExtensionContext,
outChannel: vscode.OutputChannel,
filePath: string,
fileHash: string,
trace: BackendTrace,
tracePort: MessagePort | null
) {
this._outChannel = outChannel;
this._fileHash = fileHash;
this._tracePort = tracePort;
this._backendTrace = { trace: trace, complete: trace.length > 0 };
Expand Down Expand Up @@ -74,8 +83,8 @@ export class VisualizationPanel {
if (this._panel?.active) {
this.updateLineHighlight();
}
}, undefined, context.subscriptions);
}, undefined, context.subscriptions);


// Message Receivers
this._panel.webview.onDidReceiveMessage(
Expand Down Expand Up @@ -118,12 +127,13 @@ export class VisualizationPanel {

public static async getVisualizationPanel(
context: vscode.ExtensionContext,
outChannel: vscode.OutputChannel,
filePath: string,
fileHash: string,
trace: BackendTrace,
tracePort: MessagePort | null
): Promise<VisualizationPanel | undefined> {
return new VisualizationPanel(context, filePath, fileHash, trace, tracePort);
return new VisualizationPanel(context, outChannel, filePath, fileHash, trace, tracePort);
}

// TODO: Look if Typescript is possible OR do better documentation in all files
Expand Down Expand Up @@ -186,34 +196,45 @@ export class VisualizationPanel {

private async updateLineHighlight(remove: boolean = false) {
if (this._trace.length === 0) {
this._outChannel.appendLine("updateLineHighlight: no trace available, aborting");
return;
}
const traceFile = this._trace[this._traceIndex][3]!;
let editor: vscode.TextEditor | undefined = vscode.window.visibleTextEditors.filter(
editor => path.basename(editor.document.uri.path) === path.basename(this._trace[this._traceIndex][3]!)
editor => path.basename(editor.document.uri.path) === path.basename(traceFile)
)[0];

const openPath = vscode.Uri.parse(this._trace[this._traceIndex][3]!);
const openPath = vscode.Uri.parse(traceFile);
if (!editor || editor.document.uri.path !== openPath.path) {
// How can it be that editor is not null/undefined, but the path does not match?
await vscode.commands.executeCommand('workbench.action.focusFirstEditorGroup');
const document = await vscode.workspace.openTextDocument(openPath);
editor = await vscode.window.showTextDocument(document);
}

if (remove || editor.document.lineCount < this._trace[this._traceIndex][0]) {
const traceLine = this._trace[this._traceIndex][0];
if (remove) {
this._outChannel.appendLine(
"updateLineHighlight: removing highlighting in " + editor.document.fileName);
editor.setDecorations(nextLineExecuteHighlightType, []);
} else if (editor.document.lineCount < traceLine) {
// How can it be that traceLine is out of range?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The document/source file might have changed since the visualization was computed. If we start the visualization and remove all content from the source file, we need to remove the line highlighting.

this._outChannel.appendLine(
"updateLineHighlight: removing highlighting in " + editor.document.fileName +
"(out of range)");
editor.setDecorations(nextLineExecuteHighlightType, []);
} else {
this.setNextLineHighlighting(editor);
}
}

private setNextLineHighlighting(editor: vscode.TextEditor) {
if (this._trace.length === 0) {
return;
}
const nextLine = this._trace[this._traceIndex][0] - 1;

if (nextLine > -1) {
this.setEditorDecorations(editor, nextLineExecuteHighlightType, nextLine);
const hlLine = traceLine - 1; // why - 1
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

traceLine is one-based, VSCode works with zero-based line indices though.

if (hlLine > -1) {
this._outChannel.appendLine(
"updateLineHighlight: highlighting line " + hlLine + " in " + editor.document.fileName);
this.setEditorDecorations(editor, nextLineExecuteHighlightType, hlLine);
} else {
// how can this happen?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure. Maybe there was a way that this could happen back when the trace was generated though the Debug Adapter Protocol. I don't know why this should happen with the current trace generator. I probably left it there, just in case...

this._outChannel.appendLine(
"updateLineHighlight: cannot highlight line " + hlLine + " in " +
editor.document.fileName + "(out of range)");
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/programflow-visualization/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export function getProgFlowVizCallback(context: vscode.ExtensionContext, outChan
tracePort = startBackend(context, file, outChannel);
}

const result = await startFrontend(context, file.fsPath, fileHash, tracePort);
const result = await startFrontend(context, outChannel, file.fsPath, fileHash, tracePort);
if (result) {
await vscode.window.showErrorMessage("Error ProgramFlow-Visualization: " + result.errorMessage);
return;
Expand Down
3 changes: 2 additions & 1 deletion src/programflow-visualization/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/**
/**
* For better readable code
*/
type Try = Success | Failure;
Expand All @@ -7,6 +7,7 @@ type Failure = { errorMessage: string };

// State Types for the Frontend
type FrontendTrace = Array<FrontendTraceElem>;
// FIXME: what are this array elements? Why isn't there a type with named fields?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See generateHTML in HTMLGenerator.ts: it corresponds to a single rendered visualization step. It has the following elements:

  • Line number
  • the stack rendered as an HTML fragment
  • the heap rendered as an HTML fragment
  • current filename
  • the current state of the output

I don't know why there isn't a type with named fields. It was already solved this way before I integrated the visualization into the WYPP plugin and to be honest, I just did not fix it because it already worked and my main main focus was to get everything working.

type FrontendTraceElem = [number, string, string, string, string];
// ############################################################################################
// State Types for the Backend
Expand Down