From 79df65e41848ea19736cadc75ce3d2a1e911b798 Mon Sep 17 00:00:00 2001 From: Cijie Xia Date: Wed, 18 Nov 2020 17:48:17 +0800 Subject: [PATCH 01/17] extract the API for creating graphs for CodeQL --- data-extraction/src/js/helpers/createGraph.ts | 1 + demos/python/graph.py | 2 +- .../EvaluationWatchService/CodeQLService.ts | 128 ++++++++++++++++++ extension/src/EvaluationWatchService/index.ts | 1 + extension/src/debugger/VsCodeDebuggerView.ts | 1 + extension/src/extension.ts | 64 +-------- .../src/webview/InternalWebviewManager.ts | 2 +- extension/src/webview/WebviewConnection.ts | 9 ++ webview/src/components/GUI.tsx | 4 +- 9 files changed, 148 insertions(+), 64 deletions(-) create mode 100644 extension/src/EvaluationWatchService/CodeQLService.ts diff --git a/data-extraction/src/js/helpers/createGraph.ts b/data-extraction/src/js/helpers/createGraph.ts index 77aa6d4..8d08dfb 100644 --- a/data-extraction/src/js/helpers/createGraph.ts +++ b/data-extraction/src/js/helpers/createGraph.ts @@ -27,6 +27,7 @@ export function createGraph( nodes: [], edges: [], }; + let idCounter = 1; const ids = new Map(); function getId(item: T): string { diff --git a/demos/python/graph.py b/demos/python/graph.py index 6a178df..0658663 100644 --- a/demos/python/graph.py +++ b/demos/python/graph.py @@ -21,7 +21,7 @@ id = str(i) graph["nodes"].append({"id": id, "label": id}) # connects the node to a random edge - targetId = str(randint(1, i - 1)) + targetId = str(randint(1, i - 1)) graph["edges"].append({"from": id, "to": targetId}) json_graph = dumps(graph) print("i is " + str(i)) diff --git a/extension/src/EvaluationWatchService/CodeQLService.ts b/extension/src/EvaluationWatchService/CodeQLService.ts new file mode 100644 index 0000000..e1adc65 --- /dev/null +++ b/extension/src/EvaluationWatchService/CodeQLService.ts @@ -0,0 +1,128 @@ +import { + EvaluationWatchService, + EvaluationWatcher, + EvaluationWatcherOptions, +} from "./EvaluationWatchService"; +import { observable, autorun, action } from "mobx"; +import { Disposable } from "@hediet/std/disposable"; +import { DataExtractorId, GraphNode, GraphVisualizationData } from "@hediet/debug-visualizer-data-extraction"; +import { DataExtractionState, CompletionItem } from "../webviewContract"; +import { hotClass } from "@hediet/node-reload"; +import { VsCodeDebuggerView } from "../debugger/VsCodeDebuggerView"; +import { EvaluationEngine } from "./EvaluationEngine/EvaluationEngine"; + +@hotClass(module) +export class CodeQLWatchService implements EvaluationWatchService { + public readonly dispose = Disposable.fn(); + private watcher : CodeQLWatcher; + + constructor() { + this.watcher = new CodeQLWatcher('', this, {preferredDataExtractor: undefined}); + this.dispose.track({ + dispose: autorun(() => { + this.watcher.refresh(); + }), + }); + } + + public createEvaluationWatcher( + expression: string, + options: EvaluationWatcherOptions + ): EvaluationWatcher { + this.refresh(this.watcher); + return this.watcher; + } + + public createCodeQLGraph() { + const graph : GraphVisualizationData = { + kind: { graph: true }, + nodes: [], + edges: [] + }; + + const result = { + kind: "data", + result: { + availableExtractors: [], + usedExtractor: { + id: "generic" as any, + name: "Generic", + priority: 1, + }, + data: graph, + }, + } as DataExtractionState; + + const node1: GraphNode = { + id: "1", + label: "foo1()", + color: "red", + shape: "box", + }; + + graph.nodes.push(node1); + + const node2: GraphNode = { + id: "2", + label: "foo2()", + color: "lightblue", + shape: "box", + }; + + graph.nodes.push(node2); + + graph.edges.push({ from: "1", to: "2", label: "taint" }); + + this.watcher._state = result; + } + + get languageId(): string | undefined { + return undefined; + } + + public async refresh(w: CodeQLWatcher): Promise { + } + + public async getCompletions( + text: string, + column: number + ): Promise { + return []; + } +} + +class CodeQLWatcher implements EvaluationWatcher { + constructor( + public readonly expression: string, + private readonly source: CodeQLWatchService, + options: EvaluationWatcherOptions + ) { + this._preferredDataExtractor = options.preferredDataExtractor; + } + + @observable + private _preferredDataExtractor: DataExtractorId | undefined = undefined; + + public get preferredDataExtractor(): DataExtractorId | undefined { + return this._preferredDataExtractor; + } + + @action + public setPreferredDataExtractor(id: DataExtractorId | undefined): void { + this._preferredDataExtractor = id; + this.refresh(); + } + + public refresh(): void { + this.source.refresh(this); + } + + @observable + public _state: DataExtractionState = { kind: "error", message:"Unexpected error" }; + public get state(): DataExtractionState { + return this._state; + } + + public dispose(): void { + } +} diff --git a/extension/src/EvaluationWatchService/index.ts b/extension/src/EvaluationWatchService/index.ts index 4062c46..8449299 100644 --- a/extension/src/EvaluationWatchService/index.ts +++ b/extension/src/EvaluationWatchService/index.ts @@ -1,2 +1,3 @@ export * from "./EvaluationWatchServiceImpl"; export * from "./EvaluationWatchService"; +export * from "./CodeQLService"; diff --git a/extension/src/debugger/VsCodeDebuggerView.ts b/extension/src/debugger/VsCodeDebuggerView.ts index bf864b0..a725dd7 100644 --- a/extension/src/debugger/VsCodeDebuggerView.ts +++ b/extension/src/debugger/VsCodeDebuggerView.ts @@ -18,6 +18,7 @@ export class VsCodeDebuggerView { } public get activeFrameId(): number | undefined { + console.log("move"); if (!this._activeDebugSession) { return undefined; } else { diff --git a/extension/src/extension.ts b/extension/src/extension.ts index 48375f4..80162d6 100644 --- a/extension/src/extension.ts +++ b/extension/src/extension.ts @@ -17,7 +17,7 @@ import { WebviewServer } from "./webview/WebviewServer"; import { Config } from "./Config"; import { VsCodeDebugger } from "./debugger/VsCodeDebugger"; import { VsCodeDebuggerView } from "./debugger/VsCodeDebuggerView"; -import { EvaluationWatchServiceImpl } from "./EvaluationWatchService"; +import { CodeQLWatchService } from "./EvaluationWatchService"; import { ComposedEvaluationEngine, JsEvaluationEngine, @@ -37,19 +37,8 @@ export class Extension { public readonly dispose = Disposable.fn(); private readonly config = new Config(); - private readonly debugger = this.dispose.track(new VsCodeDebugger()); - private readonly debuggerView = this.dispose.track( - new VsCodeDebuggerView(this.debugger) - ); - public readonly dataSource = new EvaluationWatchServiceImpl( - this.debuggerView, - new ComposedEvaluationEngine([ - new ConfiguredEvaluationEngine(this.config), - new JsEvaluationEngine(), - new GenericEvaluationEngine(), - ]) - ); + public readonly dataSource = new CodeQLWatchService(); private readonly server = new WebviewServer(this.dataSource, this.config); private readonly views = this.dispose.track( @@ -72,52 +61,7 @@ export class Extension { ) ); - this.dispose.track( - commands.registerCommand( - "vscode-debug-visualizer.visualizer-set-expression", - () => { - const editor = window.activeTextEditor; - if (!editor) { - return; - } - - const selection = editor.selection; - - let selectedText; - if (selection.isEmpty) { - const lineText = editor.document.lineAt(selection.start) - .text; - const regexp = /`(.*)`/g; - selectedText = ""; - let match; - while ((match = regexp.exec(lineText))) { - if ( - match.index <= selection.start.character && - selection.start.character <= - match.index + match[0].length - ) { - selectedText = match[1]; - } - } - } else { - selectedText = editor.document.getText(selection); - } - - if (!selectedText) { - return; - } - - const connections = [...this.server.connections.values()]; - const latestConnection = - connections[connections.length - 1]; - - if (latestConnection) { - latestConnection.setExpression(selectedText); - } else { - this.views.createNew(selectedText); - } - } - ) - ); + // The API for creating graph + this.dataSource.createCodeQLGraph(); } } diff --git a/extension/src/webview/InternalWebviewManager.ts b/extension/src/webview/InternalWebviewManager.ts index 312547c..64535aa 100644 --- a/extension/src/webview/InternalWebviewManager.ts +++ b/extension/src/webview/InternalWebviewManager.ts @@ -38,7 +38,7 @@ export class InternalWebviewManager { public createNew(expression: string | undefined = undefined) { const webviewPanel = window.createWebviewPanel( debugVisualizer, - "Debug Visualizer", + "CodeQL Visualizer", ViewColumn.Two, { enableScripts: true, diff --git a/extension/src/webview/WebviewConnection.ts b/extension/src/webview/WebviewConnection.ts index 094db82..79e2452 100644 --- a/extension/src/webview/WebviewConnection.ts +++ b/extension/src/webview/WebviewConnection.ts @@ -28,6 +28,15 @@ export class WebviewConnection { ) { let authenticated = false; + this.watcher = this.dispose.track( + evaluationWatchService.createEvaluationWatcher( + '', + { + preferredDataExtractor: undefined, + } + ) + ); + function throwIfNotAuthenticated() { if (!authenticated) { throw new RequestHandlingError("Not authenticated"); diff --git a/webview/src/components/GUI.tsx b/webview/src/components/GUI.tsx index 010799a..7b66c7c 100644 --- a/webview/src/components/GUI.tsx +++ b/webview/src/components/GUI.tsx @@ -22,9 +22,9 @@ export class GUI extends React.Component<{ model: Model }> { height: "100%", }} > -
+ {/*
-
+
*/}
Date: Fri, 20 Nov 2020 12:56:47 +0800 Subject: [PATCH 02/17] deelte used dependency include --- extension/src/EvaluationWatchService/CodeQLService.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/extension/src/EvaluationWatchService/CodeQLService.ts b/extension/src/EvaluationWatchService/CodeQLService.ts index e1adc65..9f6c4ee 100644 --- a/extension/src/EvaluationWatchService/CodeQLService.ts +++ b/extension/src/EvaluationWatchService/CodeQLService.ts @@ -8,8 +8,6 @@ import { Disposable } from "@hediet/std/disposable"; import { DataExtractorId, GraphNode, GraphVisualizationData } from "@hediet/debug-visualizer-data-extraction"; import { DataExtractionState, CompletionItem } from "../webviewContract"; import { hotClass } from "@hediet/node-reload"; -import { VsCodeDebuggerView } from "../debugger/VsCodeDebuggerView"; -import { EvaluationEngine } from "./EvaluationEngine/EvaluationEngine"; @hotClass(module) export class CodeQLWatchService implements EvaluationWatchService { From d69a8cb4717dff44b9d6b7a457aaaf35d5249bb8 Mon Sep 17 00:00:00 2001 From: Robert MacGillivray Date: Sat, 28 Nov 2020 03:20:01 -0700 Subject: [PATCH 03/17] Update CodeQLService.ts - iteratively unpacking my data structure (+ a test) --- .../EvaluationWatchService/CodeQLService.ts | 226 +++++++++++------- 1 file changed, 139 insertions(+), 87 deletions(-) diff --git a/extension/src/EvaluationWatchService/CodeQLService.ts b/extension/src/EvaluationWatchService/CodeQLService.ts index 9f6c4ee..aad839c 100644 --- a/extension/src/EvaluationWatchService/CodeQLService.ts +++ b/extension/src/EvaluationWatchService/CodeQLService.ts @@ -1,41 +1,49 @@ import { - EvaluationWatchService, - EvaluationWatcher, - EvaluationWatcherOptions, + EvaluationWatchService, + EvaluationWatcher, + EvaluationWatcherOptions, } from "./EvaluationWatchService"; import { observable, autorun, action } from "mobx"; import { Disposable } from "@hediet/std/disposable"; import { DataExtractorId, GraphNode, GraphVisualizationData } from "@hediet/debug-visualizer-data-extraction"; import { DataExtractionState, CompletionItem } from "../webviewContract"; import { hotClass } from "@hediet/node-reload"; +//import { TaintVisNode } from "../../../../visualization-helpers/vis-helpers"; + +type TaintVisNode = { + uniqueID: string; + label: string; + tainted: boolean; + children: TaintVisNode[]; +} @hotClass(module) export class CodeQLWatchService implements EvaluationWatchService { - public readonly dispose = Disposable.fn(); - private watcher : CodeQLWatcher; + public readonly dispose = Disposable.fn(); + private watcher : CodeQLWatcher; - constructor() { + constructor() { this.watcher = new CodeQLWatcher('', this, {preferredDataExtractor: undefined}); - this.dispose.track({ - dispose: autorun(() => { - this.watcher.refresh(); - }), - }); - } - - public createEvaluationWatcher( - expression: string, - options: EvaluationWatcherOptions - ): EvaluationWatcher { - this.refresh(this.watcher); - return this.watcher; + this.dispose.track({ + dispose: autorun(() => { + this.watcher.refresh(); + }), + }); + } + + public createEvaluationWatcher( + expression: string, + options: EvaluationWatcherOptions + ): EvaluationWatcher { + this.refresh(this.watcher); + return this.watcher; } public createCodeQLGraph() { const graph : GraphVisualizationData = { - kind: { graph: true }, - nodes: [], - edges: [] + kind: { graph: true }, + nodes: [], + edges: [] }; const result = { @@ -49,78 +57,122 @@ export class CodeQLWatchService implements EvaluationWatchService { }, data: graph, }, - } as DataExtractionState; - - const node1: GraphNode = { - id: "1", - label: "foo1()", - color: "red", - shape: "box", - }; - - graph.nodes.push(node1); - - const node2: GraphNode = { - id: "2", - label: "foo2()", - color: "lightblue", - shape: "box", - }; - - graph.nodes.push(node2); - - graph.edges.push({ from: "1", to: "2", label: "taint" }); + } as DataExtractionState; + + const root:TaintVisNode = { + uniqueID: "1", + label: "foo()", + tainted: true, + children: [] + } + + root.children.push({ + uniqueID: "2", + label: "bar()", + tainted: false, + children: [] + }) + + root.children.push({ + uniqueID: "3", + label: "bar2()", + tainted: false, + children: [] + }) + + const foo2: TaintVisNode = { + uniqueID: "4", + label: "foo2()", + tainted: true, + children: [] + } + + root.children[0].children.push(foo2); + root.children[1].children.push(foo2); + + let open: TaintVisNode[] = [root]; + let gnRoot: GraphNode = { + id:root.uniqueID, + label:root.label, + color:(root.tainted ? "red" : "lightblue"), + shape:"box" + } + graph.nodes.push(gnRoot); + while (open.length > 0) { + let current = open.pop(); + if (current?.children != null && current.children.length > 0) { + for (let i = 0; i < current?.children.length; i++) { + open.push(current.children[i]); + let newNode: GraphNode = { + id:current.children[i].uniqueID, + label:current.children[i].label, + color:(current.children[i].tainted ? "red" : "lightblue"), + shape:"box" + } + graph.nodes.push(newNode); + let newLabel = ""; + if (current.tainted && current.children[i].tainted) { + newLabel = "taint"; + } else if (current.tainted && !current.children[i].tainted) { + newLabel = "sanitized"; + } else if (!current.tainted && current.children[i].tainted) { + newLabel = "spontaneous taint"; + } + graph.edges.push({ from: current.uniqueID, to: current.children[i].uniqueID, label:newLabel}); + } + } + } - this.watcher._state = result; + this.watcher._state = result; } - get languageId(): string | undefined { - return undefined; - } + get languageId(): string | undefined { + return undefined; + } - public async refresh(w: CodeQLWatcher): Promise { - } + public async refresh(w: CodeQLWatcher): Promise { + } - public async getCompletions( - text: string, - column: number - ): Promise { + public async getCompletions( + text: string, + column: number + ): Promise { return []; - } + } } class CodeQLWatcher implements EvaluationWatcher { - constructor( - public readonly expression: string, - private readonly source: CodeQLWatchService, - options: EvaluationWatcherOptions - ) { - this._preferredDataExtractor = options.preferredDataExtractor; - } - - @observable - private _preferredDataExtractor: DataExtractorId | undefined = undefined; - - public get preferredDataExtractor(): DataExtractorId | undefined { - return this._preferredDataExtractor; - } - - @action - public setPreferredDataExtractor(id: DataExtractorId | undefined): void { - this._preferredDataExtractor = id; - this.refresh(); - } - - public refresh(): void { - this.source.refresh(this); - } - - @observable - public _state: DataExtractionState = { kind: "error", message:"Unexpected error" }; - public get state(): DataExtractionState { - return this._state; - } - - public dispose(): void { - } + constructor( + public readonly expression: string, + private readonly source: CodeQLWatchService, + options: EvaluationWatcherOptions + ) { + this._preferredDataExtractor = options.preferredDataExtractor; + } + + @observable + private _preferredDataExtractor: DataExtractorId | undefined = undefined; + + public get preferredDataExtractor(): DataExtractorId | undefined { + return this._preferredDataExtractor; + } + + @action + public setPreferredDataExtractor(id: DataExtractorId | undefined): void { + this._preferredDataExtractor = id; + this.refresh(); + } + + public refresh(): void { + this.source.refresh(this); + } + + @observable + public _state: DataExtractionState = { kind: "error", message:"Unexpected error" }; + public get state(): DataExtractionState { + return this._state; + } + + public dispose(): void { + } } From 146132df610c9fa3cb871cca2be83c8624a9b49d Mon Sep 17 00:00:00 2001 From: Robert MacGillivray Date: Sat, 28 Nov 2020 13:28:13 -0700 Subject: [PATCH 04/17] Pass root Node to createCodeQLGraph Function --- .../EvaluationWatchService/CodeQLService.ts | 42 +------------------ extension/src/extension.ts | 34 ++++++++++++++- extension/src/vis-helpers.ts | 6 +++ 3 files changed, 41 insertions(+), 41 deletions(-) create mode 100644 extension/src/vis-helpers.ts diff --git a/extension/src/EvaluationWatchService/CodeQLService.ts b/extension/src/EvaluationWatchService/CodeQLService.ts index aad839c..299e1ca 100644 --- a/extension/src/EvaluationWatchService/CodeQLService.ts +++ b/extension/src/EvaluationWatchService/CodeQLService.ts @@ -8,14 +8,7 @@ import { Disposable } from "@hediet/std/disposable"; import { DataExtractorId, GraphNode, GraphVisualizationData } from "@hediet/debug-visualizer-data-extraction"; import { DataExtractionState, CompletionItem } from "../webviewContract"; import { hotClass } from "@hediet/node-reload"; -//import { TaintVisNode } from "../../../../visualization-helpers/vis-helpers"; - -type TaintVisNode = { - uniqueID: string; - label: string; - tainted: boolean; - children: TaintVisNode[]; -} +import { TaintVisNode } from "../vis-helpers"; @hotClass(module) export class CodeQLWatchService implements EvaluationWatchService { @@ -39,7 +32,7 @@ export class CodeQLWatchService implements EvaluationWatchService { return this.watcher; } - public createCodeQLGraph() { + public createCodeQLGraph(root:TaintVisNode) { const graph : GraphVisualizationData = { kind: { graph: true }, nodes: [], @@ -58,37 +51,6 @@ export class CodeQLWatchService implements EvaluationWatchService { data: graph, }, } as DataExtractionState; - - const root:TaintVisNode = { - uniqueID: "1", - label: "foo()", - tainted: true, - children: [] - } - - root.children.push({ - uniqueID: "2", - label: "bar()", - tainted: false, - children: [] - }) - - root.children.push({ - uniqueID: "3", - label: "bar2()", - tainted: false, - children: [] - }) - - const foo2: TaintVisNode = { - uniqueID: "4", - label: "foo2()", - tainted: true, - children: [] - } - - root.children[0].children.push(foo2); - root.children[1].children.push(foo2); let open: TaintVisNode[] = [root]; let gnRoot: GraphNode = { diff --git a/extension/src/extension.ts b/extension/src/extension.ts index 80162d6..49eed3e 100644 --- a/extension/src/extension.ts +++ b/extension/src/extension.ts @@ -18,6 +18,7 @@ import { Config } from "./Config"; import { VsCodeDebugger } from "./debugger/VsCodeDebugger"; import { VsCodeDebuggerView } from "./debugger/VsCodeDebuggerView"; import { CodeQLWatchService } from "./EvaluationWatchService"; +import { TaintVisNode } from "./vis-helpers"; import { ComposedEvaluationEngine, JsEvaluationEngine, @@ -61,7 +62,38 @@ export class Extension { ) ); + const root:TaintVisNode = { + uniqueID: "1", + label: "foo()", + tainted: true, + children: [] + } + + root.children.push({ + uniqueID: "2", + label: "bar()", + tainted: false, + children: [] + }) + + root.children.push({ + uniqueID: "3", + label: "bar2()", + tainted: false, + children: [] + }) + + const foo2: TaintVisNode = { + uniqueID: "4", + label: "foo2()", + tainted: true, + children: [] + } + + root.children[0].children.push(foo2); + root.children[1].children.push(foo2); + // The API for creating graph - this.dataSource.createCodeQLGraph(); + this.dataSource.createCodeQLGraph(root); } } diff --git a/extension/src/vis-helpers.ts b/extension/src/vis-helpers.ts new file mode 100644 index 0000000..5e396c6 --- /dev/null +++ b/extension/src/vis-helpers.ts @@ -0,0 +1,6 @@ +export type TaintVisNode = { + uniqueID: string; + label: string; + tainted: boolean; + children: TaintVisNode[]; +} \ No newline at end of file From b048f3327197f573f213a1ca047b251a06e2d357 Mon Sep 17 00:00:00 2001 From: Robert MacGillivray Date: Sun, 29 Nov 2020 03:20:37 -0700 Subject: [PATCH 05/17] tsconfig changes to be referenced externally --- data-extraction/tsconfig.json | 3 ++- extension/tsconfig.json | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/data-extraction/tsconfig.json b/data-extraction/tsconfig.json index 3bcd10e..72f9f36 100644 --- a/data-extraction/tsconfig.json +++ b/data-extraction/tsconfig.json @@ -10,7 +10,8 @@ "declaration": true, "declarationMap": true, "newLine": "LF", - "sourceMap": true + "sourceMap": true, + "composite": true }, "include": ["./src/**/*"] } diff --git a/extension/tsconfig.json b/extension/tsconfig.json index c13016f..cdbd6d7 100644 --- a/extension/tsconfig.json +++ b/extension/tsconfig.json @@ -8,7 +8,8 @@ "rootDir": "src", "strict": true, "skipLibCheck": true, - "experimentalDecorators": true + "experimentalDecorators": true, + "composite": true }, "include": [ "src/**/*", From b631a69ef73ee452e529aea33eae470a84fec1e8 Mon Sep 17 00:00:00 2001 From: Cijie Xia Date: Mon, 30 Nov 2020 00:28:34 +0800 Subject: [PATCH 06/17] Change the visualizer activation event to upon start-up --- extension/package.json | 5 +---- extension/src/extension.ts | 10 +--------- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/extension/package.json b/extension/package.json index d39de5b..5ef1077 100644 --- a/extension/package.json +++ b/extension/package.json @@ -36,10 +36,7 @@ "Other" ], "activationEvents": [ - "onCommand:vscode-debug-visualizer.new-visualizer", - "onCommand:vscode-debug-visualizer.visualizer-set-expression", - "onDebug", - "onWebviewPanel:debugVisualizer" + "*" ], "main": "./dist/extension.js", "contributes": { diff --git a/extension/src/extension.ts b/extension/src/extension.ts index 49eed3e..f6722a8 100644 --- a/extension/src/extension.ts +++ b/extension/src/extension.ts @@ -53,15 +53,6 @@ export class Extension { i.show(); } - this.dispose.track( - commands.registerCommand( - "vscode-debug-visualizer.new-visualizer", - () => { - this.views.createNew(); - } - ) - ); - const root:TaintVisNode = { uniqueID: "1", label: "foo()", @@ -94,6 +85,7 @@ export class Extension { root.children[1].children.push(foo2); // The API for creating graph + this.views.createNew(); this.dataSource.createCodeQLGraph(root); } } From 8ef1bf6a706e47434ac39287e31dc5e9a0ff1b01 Mon Sep 17 00:00:00 2001 From: Cijie Xia Date: Mon, 30 Nov 2020 02:09:07 +0800 Subject: [PATCH 07/17] read JSON data and render the graph --- .../EvaluationWatchService/CodeQLService.ts | 38 ++---------- extension/src/extension.ts | 61 +++++++++---------- 2 files changed, 33 insertions(+), 66 deletions(-) diff --git a/extension/src/EvaluationWatchService/CodeQLService.ts b/extension/src/EvaluationWatchService/CodeQLService.ts index 299e1ca..61f749e 100644 --- a/extension/src/EvaluationWatchService/CodeQLService.ts +++ b/extension/src/EvaluationWatchService/CodeQLService.ts @@ -32,7 +32,7 @@ export class CodeQLWatchService implements EvaluationWatchService { return this.watcher; } - public createCodeQLGraph(root:TaintVisNode) { + public createCodeQLGraph(graphData: any) { const graph : GraphVisualizationData = { kind: { graph: true }, nodes: [], @@ -52,39 +52,9 @@ export class CodeQLWatchService implements EvaluationWatchService { }, } as DataExtractionState; - let open: TaintVisNode[] = [root]; - let gnRoot: GraphNode = { - id:root.uniqueID, - label:root.label, - color:(root.tainted ? "red" : "lightblue"), - shape:"box" - } - graph.nodes.push(gnRoot); - while (open.length > 0) { - let current = open.pop(); - if (current?.children != null && current.children.length > 0) { - for (let i = 0; i < current?.children.length; i++) { - open.push(current.children[i]); - let newNode: GraphNode = { - id:current.children[i].uniqueID, - label:current.children[i].label, - color:(current.children[i].tainted ? "red" : "lightblue"), - shape:"box" - } - graph.nodes.push(newNode); - let newLabel = ""; - if (current.tainted && current.children[i].tainted) { - newLabel = "taint"; - } else if (current.tainted && !current.children[i].tainted) { - newLabel = "sanitized"; - } else if (!current.tainted && current.children[i].tainted) { - newLabel = "spontaneous taint"; - } - graph.edges.push({ from: current.uniqueID, to: current.children[i].uniqueID, label:newLabel}); - } - } - } - + graph.nodes = graphData.nodes; + graph.edges = graphData.edges; + this.watcher._state = result; } diff --git a/extension/src/extension.ts b/extension/src/extension.ts index f6722a8..c2595d5 100644 --- a/extension/src/extension.ts +++ b/extension/src/extension.ts @@ -25,6 +25,8 @@ import { GenericEvaluationEngine, ConfiguredEvaluationEngine, } from "./EvaluationWatchService/EvaluationEngine"; +let fs = require('fs'); +let codeQLVisViewOpened: boolean = false; export function activate(context: ExtensionContext) { context.subscriptions.push( @@ -53,39 +55,34 @@ export class Extension { i.show(); } - const root:TaintVisNode = { - uniqueID: "1", - label: "foo()", - tainted: true, - children: [] - } - - root.children.push({ - uniqueID: "2", - label: "bar()", - tainted: false, - children: [] - }) - - root.children.push({ - uniqueID: "3", - label: "bar2()", - tainted: false, - children: [] - }) - - const foo2: TaintVisNode = { - uniqueID: "4", - label: "foo2()", - tainted: true, - children: [] - } - - root.children[0].children.push(foo2); - root.children[1].children.push(foo2); // The API for creating graph - this.views.createNew(); - this.dataSource.createCodeQLGraph(root); + + + + fs.readFile('/Users/cijiexia/Project/vscode-codeql/codeqlVisData.json', 'utf8', (err: any, data: any) =>{ + if (err){ + console.log(err); + } else { + + let obj = JSON.parse(data); //now it an object + console.log(obj); + + if (!codeQLVisViewOpened) { + this.views.createNew(); + codeQLVisViewOpened = true; + } + + this.dataSource.createCodeQLGraph(obj); + + }}); + + + + + + + + } } From 4d8879bde8b6b1ef80dc4c21ea22bf2d2de3d0f3 Mon Sep 17 00:00:00 2001 From: Robert MacGillivray Date: Sun, 29 Nov 2020 12:34:54 -0700 Subject: [PATCH 08/17] Test Relative Pathing --- extension/src/extension.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extension/src/extension.ts b/extension/src/extension.ts index c2595d5..c539003 100644 --- a/extension/src/extension.ts +++ b/extension/src/extension.ts @@ -60,7 +60,7 @@ export class Extension { - fs.readFile('/Users/cijiexia/Project/vscode-codeql/codeqlVisData.json', 'utf8', (err: any, data: any) =>{ + fs.readFile('../../../codeqlVisData.json', 'utf8', (err: any, data: any) =>{ if (err){ console.log(err); } else { From 90aabcdecd836087072ed472ce51f306929470ca Mon Sep 17 00:00:00 2001 From: jskitsko Date: Sun, 29 Nov 2020 21:48:19 -0700 Subject: [PATCH 09/17] Slight path fix --- extension/src/extension.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extension/src/extension.ts b/extension/src/extension.ts index c539003..5d51db9 100644 --- a/extension/src/extension.ts +++ b/extension/src/extension.ts @@ -60,7 +60,7 @@ export class Extension { - fs.readFile('../../../codeqlVisData.json', 'utf8', (err: any, data: any) =>{ + fs.readFile(__dirname+'/../../../codeqlVisData.json', 'utf8', (err: any, data: any) =>{ if (err){ console.log(err); } else { From ae0e29a4356e204e26bb9877be4a842da2cf44b5 Mon Sep 17 00:00:00 2001 From: Robert MacGillivray Date: Thu, 3 Dec 2020 00:48:31 -0700 Subject: [PATCH 10/17] Register New Command w/ Argument --- extension/package.json | 7 ++++- extension/src/extension.ts | 52 +++++++++++++++----------------------- 2 files changed, 27 insertions(+), 32 deletions(-) diff --git a/extension/package.json b/extension/package.json index 5ef1077..4a01461 100644 --- a/extension/package.json +++ b/extension/package.json @@ -36,7 +36,8 @@ "Other" ], "activationEvents": [ - "*" + "*", + "onCommand:vscode-debug-visualizer.codeql-visualizer" ], "main": "./dist/extension.js", "contributes": { @@ -45,6 +46,10 @@ "command": "vscode-debug-visualizer.new-visualizer", "title": "Debug Visualizer: New View" }, + { + "command": "vscode-debug-visualizer.codeql-visualizer", + "title": "Debug Visualizer: Visualize CodeQL File" + }, { "command": "vscode-debug-visualizer.visualizer-set-expression", "title": "Debug Visualizer: Use Selection as Expression" diff --git a/extension/src/extension.ts b/extension/src/extension.ts index 5d51db9..205fb21 100644 --- a/extension/src/extension.ts +++ b/extension/src/extension.ts @@ -1,4 +1,4 @@ -import { window, ExtensionContext, commands } from "vscode"; +import { window, ExtensionContext, commands, extensions } from "vscode"; import { Disposable } from "@hediet/std/disposable"; import { enableHotReload, @@ -29,9 +29,11 @@ let fs = require('fs'); let codeQLVisViewOpened: boolean = false; export function activate(context: ExtensionContext) { - context.subscriptions.push( - hotRequireExportedFn(module, Extension, Extension => new Extension()) - ); + const command = 'vscode-debug-visualizer.codeql-visualizer' + const commandHandler = (path: string) => { + new Extension(path); + } + context.subscriptions.push(commands.registerCommand(command, commandHandler)); } export function deactivate() {} @@ -48,41 +50,29 @@ export class Extension { new InternalWebviewManager(this.server, this.config) ); - constructor() { + constructor(path: string) { if (getReloadCount(module) > 0) { const i = this.dispose.track(window.createStatusBarItem()); i.text = "reload" + getReloadCount(module); i.show(); } - // The API for creating graph - - - - fs.readFile(__dirname+'/../../../codeqlVisData.json', 'utf8', (err: any, data: any) =>{ - if (err){ - console.log(err); - } else { - - let obj = JSON.parse(data); //now it an object - console.log(obj); - - if (!codeQLVisViewOpened) { - this.views.createNew(); - codeQLVisViewOpened = true; - } - - this.dataSource.createCodeQLGraph(obj); - - }}); - + fs.readFile(path, 'utf8', (err: any, data: any) =>{ + if (err){ + console.log(err); + } else { + + let obj = JSON.parse(data); //now it an object + console.log(obj); + + if (!codeQLVisViewOpened) { + this.views.createNew(); + codeQLVisViewOpened = true; + } + this.dataSource.createCodeQLGraph(obj); - - - - - + }}); } } From c3e364d1aa800a3f2ca50cd5c439b2f9fe740333 Mon Sep 17 00:00:00 2001 From: Robert MacGillivray Date: Thu, 3 Dec 2020 01:35:12 -0700 Subject: [PATCH 11/17] Refresh Existing Webview Window Properly --- extension/src/extension.ts | 34 +++++++++---------- .../src/webview/InternalWebviewManager.ts | 6 ++++ 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/extension/src/extension.ts b/extension/src/extension.ts index 205fb21..3fd8364 100644 --- a/extension/src/extension.ts +++ b/extension/src/extension.ts @@ -26,19 +26,8 @@ import { ConfiguredEvaluationEngine, } from "./EvaluationWatchService/EvaluationEngine"; let fs = require('fs'); -let codeQLVisViewOpened: boolean = false; -export function activate(context: ExtensionContext) { - const command = 'vscode-debug-visualizer.codeql-visualizer' - const commandHandler = (path: string) => { - new Extension(path); - } - context.subscriptions.push(commands.registerCommand(command, commandHandler)); -} - -export function deactivate() {} - -export class Extension { +export class CodeQLVisExtension { public readonly dispose = Disposable.fn(); private readonly config = new Config(); @@ -50,7 +39,7 @@ export class Extension { new InternalWebviewManager(this.server, this.config) ); - constructor(path: string) { + public produceVis(path: string) { if (getReloadCount(module) > 0) { const i = this.dispose.track(window.createStatusBarItem()); i.text = "reload" + getReloadCount(module); @@ -66,13 +55,24 @@ export class Extension { let obj = JSON.parse(data); //now it an object console.log(obj); - if (!codeQLVisViewOpened) { - this.views.createNew(); - codeQLVisViewOpened = true; - } + this.views.createNew(); this.dataSource.createCodeQLGraph(obj); }}); } } +const extension: CodeQLVisExtension = new CodeQLVisExtension(); + +export function activate(context: ExtensionContext) { + const command = 'vscode-debug-visualizer.codeql-visualizer' + const commandHandler = (path: string) => { + console.log("Reading from path: " + path); + extension.produceVis(path); + } + context.subscriptions.push(commands.registerCommand(command, commandHandler)); +} + +export function deactivate() {} + + diff --git a/extension/src/webview/InternalWebviewManager.ts b/extension/src/webview/InternalWebviewManager.ts index 64535aa..0ae4210 100644 --- a/extension/src/webview/InternalWebviewManager.ts +++ b/extension/src/webview/InternalWebviewManager.ts @@ -3,6 +3,7 @@ import { WebviewServer } from "./WebviewServer"; import { Disposable } from "@hediet/std/disposable"; import { WindowWithWebviewData } from "../webviewContract"; import { Config } from "../Config"; +import webpack = require("webpack"); export const debugVisualizer = "debugVisualizer"; @@ -36,6 +37,11 @@ export class InternalWebviewManager { } public createNew(expression: string | undefined = undefined) { + // Get rid of the existing webviews since they'll just duplicate our updated visualization + for (const panel of this.openedWebviews.keys()) { + panel.dispose(); + } + const webviewPanel = window.createWebviewPanel( debugVisualizer, "CodeQL Visualizer", From 396130f1d898cfc9e5b0baa6b2d12e377317d371 Mon Sep 17 00:00:00 2001 From: Robert MacGillivray Date: Mon, 7 Dec 2020 01:09:18 -0700 Subject: [PATCH 12/17] Update package.json - changed some metadata to differentiate from the actual debug visualizer --- extension/package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/extension/package.json b/extension/package.json index 4a01461..f136515 100644 --- a/extension/package.json +++ b/extension/package.json @@ -1,10 +1,10 @@ { "name": "debug-visualizer", "private": true, - "displayName": "Debug Visualizer", - "description": "A visual watch window that lets you visualize your data structures while debugging.", + "displayName": "CodeQL Visualizer", + "description": "A visual watch window that lets you visualize CodeQL query data.", "icon": "docs/logo.drawio.png", - "version": "2.0.6", + "version": "416.0.0", "license": "GPL-3.0", "engines": { "vscode": "^1.46.0" @@ -63,7 +63,7 @@ } ], "configuration": { - "title": "Debug Visualizer", + "title": "CodeQL Visualizer", "properties": { "debugVisualizer.useChromeKioskMode": { "type": "boolean", From 28073ff29da4e3ab477e2ce0a11018a49db8d9b3 Mon Sep 17 00:00:00 2001 From: Robert MacGillivray Date: Mon, 7 Dec 2020 01:22:47 -0700 Subject: [PATCH 13/17] Create CMPUT-416_README.md --- CMPUT-416_README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 CMPUT-416_README.md diff --git a/CMPUT-416_README.md b/CMPUT-416_README.md new file mode 100644 index 0000000..f0a32a1 --- /dev/null +++ b/CMPUT-416_README.md @@ -0,0 +1,11 @@ +# How to Run +1. Download this extension's VSIX file [here](https://drive.google.com/file/d/1anBbOCuIVtiLCy3rwROPmjVB4wl4AyWz/view?usp=sharing) +1. Open [Visual Studio Code](https://code.visualstudio.com/download) +1. Navigate to the Extensions menu (it looks like 4 blocks, one of which has yet to be put in place) +1. Make sure you don't have an extension called "Debug Visualizer" + * If you do, uninstall it +1. Click the three horizontal dots in the top right of that menu +1. Select "Install from VSIX..." +1. Select the file you downloaded in the first step +1. Restart Visual Studio Code +1. You should see a new extension in the Extensions menu called "CodeQL Visualizer" with the ludicrous version number 416.0.0 From 97760d98ae0c05148cb0ff11243fe97ff652aafd Mon Sep 17 00:00:00 2001 From: Robert MacGillivray Date: Mon, 7 Dec 2020 01:25:05 -0700 Subject: [PATCH 14/17] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index f989f99..77c988e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # VS Code Debug Visualizer +### For CMPUT 416 +See [CMPUT-416_README.md](CMPUT-416_README.md) for installation instructions. This extension has been modified to support the primary project extension, found [here](https://github.com/CodeQL-Visualization/vscode-codeql) (the cmput416-visualization branch). + [![](https://img.shields.io/static/v1?style=social&label=Sponsor&message=%E2%9D%A4&logo=GitHub&color&link=%3Curl%3E)](https://github.com/sponsors/hediet) [![](https://img.shields.io/static/v1?style=social&label=Donate&message=%E2%9D%A4&logo=Paypal&color&link=%3Curl%3E)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=ZP5F38L4C88UY&source=url) [![](https://img.shields.io/twitter/follow/hediet_dev.svg?style=social)](https://twitter.com/intent/follow?screen_name=hediet_dev) From 1191ed07e7fd0685a17a5a47a125e52edf259b9b Mon Sep 17 00:00:00 2001 From: Robert MacGillivray Date: Mon, 7 Dec 2020 01:25:21 -0700 Subject: [PATCH 15/17] Update CMPUT-416_README.md --- CMPUT-416_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMPUT-416_README.md b/CMPUT-416_README.md index f0a32a1..ca1467a 100644 --- a/CMPUT-416_README.md +++ b/CMPUT-416_README.md @@ -3,7 +3,7 @@ 1. Open [Visual Studio Code](https://code.visualstudio.com/download) 1. Navigate to the Extensions menu (it looks like 4 blocks, one of which has yet to be put in place) 1. Make sure you don't have an extension called "Debug Visualizer" - * If you do, uninstall it + * If you do, uninstall it 1. Click the three horizontal dots in the top right of that menu 1. Select "Install from VSIX..." 1. Select the file you downloaded in the first step From 8d8c12f558d7bfa52b362a4cbf948395c9d56fce Mon Sep 17 00:00:00 2001 From: Robert MacGillivray Date: Mon, 7 Dec 2020 01:25:57 -0700 Subject: [PATCH 16/17] Update CMPUT-416_README.md --- CMPUT-416_README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/CMPUT-416_README.md b/CMPUT-416_README.md index ca1467a..aa1dde5 100644 --- a/CMPUT-416_README.md +++ b/CMPUT-416_README.md @@ -1,11 +1,11 @@ # How to Run -1. Download this extension's VSIX file [here](https://drive.google.com/file/d/1anBbOCuIVtiLCy3rwROPmjVB4wl4AyWz/view?usp=sharing) -1. Open [Visual Studio Code](https://code.visualstudio.com/download) -1. Navigate to the Extensions menu (it looks like 4 blocks, one of which has yet to be put in place) -1. Make sure you don't have an extension called "Debug Visualizer" - * If you do, uninstall it -1. Click the three horizontal dots in the top right of that menu -1. Select "Install from VSIX..." -1. Select the file you downloaded in the first step -1. Restart Visual Studio Code -1. You should see a new extension in the Extensions menu called "CodeQL Visualizer" with the ludicrous version number 416.0.0 +1. Download this extension's VSIX file [here](https://drive.google.com/file/d/1anBbOCuIVtiLCy3rwROPmjVB4wl4AyWz/view?usp=sharing). +1. Open [Visual Studio Code](https://code.visualstudio.com/download). +1. Navigate to the Extensions menu (it looks like 4 blocks, one of which has yet to be put in place). +1. Make sure you don't have an extension called "Debug Visualizer". + * If you do, uninstall it. +1. Click the three horizontal dots in the top right of that menu. +1. Select "Install from VSIX...". +1. Select the file you downloaded in the first step. +1. Restart Visual Studio Code. +1. You should see a new extension in the Extensions menu called "CodeQL Visualizer" with the ludicrous version number 416.0.0. From 03c673db8314dac48701ba0584a787e4112cc1c8 Mon Sep 17 00:00:00 2001 From: Robert MacGillivray Date: Mon, 7 Dec 2020 01:32:06 -0700 Subject: [PATCH 17/17] Update CMPUT-416_README.md --- CMPUT-416_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMPUT-416_README.md b/CMPUT-416_README.md index aa1dde5..a7349f7 100644 --- a/CMPUT-416_README.md +++ b/CMPUT-416_README.md @@ -1,4 +1,4 @@ -# How to Run +# Installation Instructions 1. Download this extension's VSIX file [here](https://drive.google.com/file/d/1anBbOCuIVtiLCy3rwROPmjVB4wl4AyWz/view?usp=sharing). 1. Open [Visual Studio Code](https://code.visualstudio.com/download). 1. Navigate to the Extensions menu (it looks like 4 blocks, one of which has yet to be put in place).