From 07d54a21f27743d9126cd7d86c865c5a1eab41f4 Mon Sep 17 00:00:00 2001 From: shati-patel <42641846+shati-patel@users.noreply.github.com> Date: Thu, 1 Jun 2023 17:22:50 +0100 Subject: [PATCH 1/5] Make FileTreeNode accept additional data --- .../ql-vscode/src/common/file-tree-nodes.ts | 42 +++++++++++-------- .../src/queries-panel/query-discovery.ts | 2 +- .../src/query-testing/qltest-discovery.ts | 2 +- .../query-tree-data-provider.test.ts | 10 ++--- 4 files changed, 32 insertions(+), 24 deletions(-) diff --git a/extensions/ql-vscode/src/common/file-tree-nodes.ts b/extensions/ql-vscode/src/common/file-tree-nodes.ts index 3544265ca58..c2f92e48f58 100644 --- a/extensions/ql-vscode/src/common/file-tree-nodes.ts +++ b/extensions/ql-vscode/src/common/file-tree-nodes.ts @@ -4,8 +4,12 @@ import { env } from "vscode"; /** * A node in the tree of files. This will be either a `FileTreeDirectory` or a `FileTreeLeaf`. */ -export abstract class FileTreeNode { - constructor(private _path: string, private _name: string) {} +export abstract class FileTreeNode { + constructor( + private _path: string, + private _name: string, + private _data: T | undefined, + ) {} public get path(): string { return this._path; @@ -15,7 +19,11 @@ export abstract class FileTreeNode { return this._name; } - public abstract get children(): readonly FileTreeNode[]; + public get data(): T | undefined { + return this._data; + } + + public abstract get children(): ReadonlyArray>; public abstract finish(): void; } @@ -23,24 +31,24 @@ export abstract class FileTreeNode { /** * A directory containing one or more files or other directories. */ -export class FileTreeDirectory extends FileTreeNode { +export class FileTreeDirectory extends FileTreeNode { constructor( _path: string, _name: string, - private _children: FileTreeNode[] = [], + private _children: Array> = [], ) { - super(_path, _name); + super(_path, _name, undefined); } - public get children(): readonly FileTreeNode[] { + public get children(): ReadonlyArray> { return this._children; } - public addChild(child: FileTreeNode): void { + public addChild(child: FileTreeNode): void { this._children.push(child); } - public createDirectory(relativePath: string): FileTreeDirectory { + public createDirectory(relativePath: string): FileTreeDirectory { if (relativePath === ".") { return this; } @@ -66,7 +74,7 @@ export class FileTreeDirectory extends FileTreeNode { child.children[0] instanceof FileTreeDirectory ) { // collapse children - const replacement = new FileTreeDirectory( + const replacement = new FileTreeDirectory( child.children[0].path, `${child.name} / ${child.children[0].name}`, Array.from(child.children[0].children), @@ -76,12 +84,12 @@ export class FileTreeDirectory extends FileTreeNode { }); } - private createChildDirectory(name: string): FileTreeDirectory { + private createChildDirectory(name: string): FileTreeDirectory { const existingChild = this._children.find((child) => child.name === name); if (existingChild !== undefined) { - return existingChild as FileTreeDirectory; + return existingChild as FileTreeDirectory; } else { - const newChild = new FileTreeDirectory(join(this.path, name), name); + const newChild = new FileTreeDirectory(join(this.path, name), name); this.addChild(newChild); return newChild; } @@ -91,12 +99,12 @@ export class FileTreeDirectory extends FileTreeNode { /** * A single file. */ -export class FileTreeLeaf extends FileTreeNode { - constructor(_path: string, _name: string) { - super(_path, _name); +export class FileTreeLeaf extends FileTreeNode { + constructor(_path: string, _name: string, _data: T) { + super(_path, _name, _data); } - public get children(): readonly FileTreeNode[] { + public get children(): ReadonlyArray> { return []; } diff --git a/extensions/ql-vscode/src/queries-panel/query-discovery.ts b/extensions/ql-vscode/src/queries-panel/query-discovery.ts index f7b25ea097b..6d41b561cc4 100644 --- a/extensions/ql-vscode/src/queries-panel/query-discovery.ts +++ b/extensions/ql-vscode/src/queries-panel/query-discovery.ts @@ -130,7 +130,7 @@ export class QueryDiscovery const dirName = dirname(relativePath); const parentDirectory = rootDirectory.createDirectory(dirName); parentDirectory.addChild( - new FileTreeLeaf(queryPath, basename(queryPath)), + new FileTreeLeaf(queryPath, basename(queryPath), undefined), ); } diff --git a/extensions/ql-vscode/src/query-testing/qltest-discovery.ts b/extensions/ql-vscode/src/query-testing/qltest-discovery.ts index 5a9a4088f40..dee9dea2626 100644 --- a/extensions/ql-vscode/src/query-testing/qltest-discovery.ts +++ b/extensions/ql-vscode/src/query-testing/qltest-discovery.ts @@ -109,7 +109,7 @@ export class QLTestDiscovery extends Discovery { const dirName = dirname(relativePath); const parentDirectory = rootDirectory.createDirectory(dirName); parentDirectory.addChild( - new FileTreeLeaf(testPath, basename(testPath)), + new FileTreeLeaf(testPath, basename(testPath), undefined), ); } diff --git a/extensions/ql-vscode/test/vscode-tests/minimal-workspace/queries-panel/query-tree-data-provider.test.ts b/extensions/ql-vscode/test/vscode-tests/minimal-workspace/queries-panel/query-tree-data-provider.test.ts index 0805286893d..48426e99c44 100644 --- a/extensions/ql-vscode/test/vscode-tests/minimal-workspace/queries-panel/query-tree-data-provider.test.ts +++ b/extensions/ql-vscode/test/vscode-tests/minimal-workspace/queries-panel/query-tree-data-provider.test.ts @@ -33,12 +33,12 @@ describe("QueryTreeDataProvider", () => { queries: [ new FileTreeDirectory("dir1", "dir1", [ new FileTreeDirectory("dir1/dir2", "dir2", [ - new FileTreeLeaf("dir1/dir2/file1", "file1"), - new FileTreeLeaf("dir1/dir2/file1", "file2"), + new FileTreeLeaf("dir1/dir2/file1", "file1", undefined), + new FileTreeLeaf("dir1/dir2/file1", "file2", undefined), ]), ]), new FileTreeDirectory("dir3", "dir3", [ - new FileTreeLeaf("dir3/file3", "file3"), + new FileTreeLeaf("dir3/file3", "file3", undefined), ]), ], onDidChangeQueries: jest.fn(), @@ -71,7 +71,7 @@ describe("QueryTreeDataProvider", () => { const queryDiscoverer: QueryDiscoverer = { queries: [ new FileTreeDirectory("dir1", "dir1", [ - new FileTreeLeaf("dir1/file1", "file1"), + new FileTreeLeaf("dir1/file1", "file1", undefined), ]), ], onDidChangeQueries: onDidChangeQueriesEmitter.event, @@ -82,7 +82,7 @@ describe("QueryTreeDataProvider", () => { queryDiscoverer.queries?.push( new FileTreeDirectory("dir2", "dir2", [ - new FileTreeLeaf("dir2/file2", "file2"), + new FileTreeLeaf("dir2/file2", "file2", undefined), ]), ); onDidChangeQueriesEmitter.fire(); From d2c8db65e39cf6bb1f7e6b7ca6411215b17616a0 Mon Sep 17 00:00:00 2001 From: shati-patel <42641846+shati-patel@users.noreply.github.com> Date: Thu, 1 Jun 2023 17:25:17 +0100 Subject: [PATCH 2/5] Pass `language` data to the query tree view items --- .../ql-vscode/src/queries-panel/query-discovery.ts | 12 ++++++------ .../src/queries-panel/query-tree-data-provider.ts | 5 +++-- .../src/queries-panel/query-tree-view-item.ts | 2 ++ 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/extensions/ql-vscode/src/queries-panel/query-discovery.ts b/extensions/ql-vscode/src/queries-panel/query-discovery.ts index 6d41b561cc4..3b19debe384 100644 --- a/extensions/ql-vscode/src/queries-panel/query-discovery.ts +++ b/extensions/ql-vscode/src/queries-panel/query-discovery.ts @@ -18,7 +18,7 @@ export interface QueryDiscoveryResults { * A tree of directories and query files. * May have multiple roots because of multiple workspaces. */ - queries: FileTreeDirectory[]; + queries: Array>; /** * File system paths to watch. If any ql file changes in these directories @@ -49,7 +49,7 @@ export class QueryDiscovery this.push(this.watcher.onDidChange(this.refresh.bind(this))); } - public get queries(): FileTreeDirectory[] | undefined { + public get queries(): Array> | undefined { return this.results?.queries; } @@ -97,7 +97,7 @@ export class QueryDiscovery */ private async discoverQueries( workspaceFolders: readonly WorkspaceFolder[], - ): Promise { + ): Promise>> { const rootDirectories = []; for (const workspaceFolder of workspaceFolders) { const root = await this.discoverQueriesInWorkspace(workspaceFolder); @@ -110,7 +110,7 @@ export class QueryDiscovery private async discoverQueriesInWorkspace( workspaceFolder: WorkspaceFolder, - ): Promise { + ): Promise | undefined> { const fullPath = workspaceFolder.uri.fsPath; const name = workspaceFolder.name; @@ -124,13 +124,13 @@ export class QueryDiscovery return undefined; } - const rootDirectory = new FileTreeDirectory(fullPath, name); + const rootDirectory = new FileTreeDirectory(fullPath, name); for (const queryPath of resolvedQueries) { const relativePath = normalize(relative(fullPath, queryPath)); const dirName = dirname(relativePath); const parentDirectory = rootDirectory.createDirectory(dirName); parentDirectory.addChild( - new FileTreeLeaf(queryPath, basename(queryPath), undefined), + new FileTreeLeaf(queryPath, basename(queryPath), "language"), ); } diff --git a/extensions/ql-vscode/src/queries-panel/query-tree-data-provider.ts b/extensions/ql-vscode/src/queries-panel/query-tree-data-provider.ts index 0810ded8a63..b0bf7c79fd2 100644 --- a/extensions/ql-vscode/src/queries-panel/query-tree-data-provider.ts +++ b/extensions/ql-vscode/src/queries-panel/query-tree-data-provider.ts @@ -4,7 +4,7 @@ import { DisposableObject } from "../pure/disposable-object"; import { FileTreeNode } from "../common/file-tree-nodes"; export interface QueryDiscoverer { - readonly queries: FileTreeNode[] | undefined; + readonly queries: Array> | undefined; readonly onDidChangeQueries: Event; } @@ -40,11 +40,12 @@ export class QueryTreeDataProvider } private convertFileTreeNode( - fileTreeDirectory: FileTreeNode, + fileTreeDirectory: FileTreeNode, ): QueryTreeViewItem { return new QueryTreeViewItem( fileTreeDirectory.name, fileTreeDirectory.path, + fileTreeDirectory.data, fileTreeDirectory.children.map(this.convertFileTreeNode.bind(this)), ); } diff --git a/extensions/ql-vscode/src/queries-panel/query-tree-view-item.ts b/extensions/ql-vscode/src/queries-panel/query-tree-view-item.ts index 17caea32d63..8a14f8018dc 100644 --- a/extensions/ql-vscode/src/queries-panel/query-tree-view-item.ts +++ b/extensions/ql-vscode/src/queries-panel/query-tree-view-item.ts @@ -4,10 +4,12 @@ export class QueryTreeViewItem extends vscode.TreeItem { constructor( name: string, path: string, + language: string | undefined, public readonly children: QueryTreeViewItem[], ) { super(name); this.tooltip = path; + this.description = language; this.collapsibleState = this.children.length ? vscode.TreeItemCollapsibleState.Collapsed : vscode.TreeItemCollapsibleState.None; From 6a90658397f3d30e94c7bd1c4926e4cde22fdcb3 Mon Sep 17 00:00:00 2001 From: shati-patel <42641846+shati-patel@users.noreply.github.com> Date: Thu, 1 Jun 2023 17:26:26 +0100 Subject: [PATCH 3/5] Fix types in tests --- .../query-tree-data-provider.test.ts | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/extensions/ql-vscode/test/vscode-tests/minimal-workspace/queries-panel/query-tree-data-provider.test.ts b/extensions/ql-vscode/test/vscode-tests/minimal-workspace/queries-panel/query-tree-data-provider.test.ts index 48426e99c44..9719441518d 100644 --- a/extensions/ql-vscode/test/vscode-tests/minimal-workspace/queries-panel/query-tree-data-provider.test.ts +++ b/extensions/ql-vscode/test/vscode-tests/minimal-workspace/queries-panel/query-tree-data-provider.test.ts @@ -31,14 +31,22 @@ describe("QueryTreeDataProvider", () => { it("converts FileTreeNode to QueryTreeViewItem", async () => { const dataProvider = new QueryTreeDataProvider({ queries: [ - new FileTreeDirectory("dir1", "dir1", [ - new FileTreeDirectory("dir1/dir2", "dir2", [ - new FileTreeLeaf("dir1/dir2/file1", "file1", undefined), - new FileTreeLeaf("dir1/dir2/file1", "file2", undefined), + new FileTreeDirectory("dir1", "dir1", [ + new FileTreeDirectory("dir1/dir2", "dir2", [ + new FileTreeLeaf( + "dir1/dir2/file1", + "file1", + "javascript", + ), + new FileTreeLeaf( + "dir1/dir2/file1", + "file2", + "javascript", + ), ]), ]), - new FileTreeDirectory("dir3", "dir3", [ - new FileTreeLeaf("dir3/file3", "file3", undefined), + new FileTreeDirectory("dir3", "dir3", [ + new FileTreeLeaf("dir3/file3", "file3", "javascript"), ]), ], onDidChangeQueries: jest.fn(), @@ -70,8 +78,8 @@ describe("QueryTreeDataProvider", () => { const onDidChangeQueriesEmitter = new EventEmitter(); const queryDiscoverer: QueryDiscoverer = { queries: [ - new FileTreeDirectory("dir1", "dir1", [ - new FileTreeLeaf("dir1/file1", "file1", undefined), + new FileTreeDirectory("dir1", "dir1", [ + new FileTreeLeaf("dir1/file1", "file1", "javascript"), ]), ], onDidChangeQueries: onDidChangeQueriesEmitter.event, @@ -81,8 +89,8 @@ describe("QueryTreeDataProvider", () => { expect(dataProvider.getChildren().length).toEqual(1); queryDiscoverer.queries?.push( - new FileTreeDirectory("dir2", "dir2", [ - new FileTreeLeaf("dir2/file2", "file2", undefined), + new FileTreeDirectory("dir2", "dir2", [ + new FileTreeLeaf("dir2/file2", "file2", "javascript"), ]), ); onDidChangeQueriesEmitter.fire(); From c192495e90600b4393f2fa4d762851ae95a48272 Mon Sep 17 00:00:00 2001 From: shati-patel <42641846+shati-patel@users.noreply.github.com> Date: Fri, 2 Jun 2023 14:53:41 +0100 Subject: [PATCH 4/5] Make `data` param optional on `FileTreeLeaf` --- extensions/ql-vscode/src/common/file-tree-nodes.ts | 2 +- extensions/ql-vscode/src/query-testing/qltest-discovery.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/ql-vscode/src/common/file-tree-nodes.ts b/extensions/ql-vscode/src/common/file-tree-nodes.ts index c2f92e48f58..8fb2c5cf2bf 100644 --- a/extensions/ql-vscode/src/common/file-tree-nodes.ts +++ b/extensions/ql-vscode/src/common/file-tree-nodes.ts @@ -100,7 +100,7 @@ export class FileTreeDirectory extends FileTreeNode { * A single file. */ export class FileTreeLeaf extends FileTreeNode { - constructor(_path: string, _name: string, _data: T) { + constructor(_path: string, _name: string, _data?: T) { super(_path, _name, _data); } diff --git a/extensions/ql-vscode/src/query-testing/qltest-discovery.ts b/extensions/ql-vscode/src/query-testing/qltest-discovery.ts index dee9dea2626..5a9a4088f40 100644 --- a/extensions/ql-vscode/src/query-testing/qltest-discovery.ts +++ b/extensions/ql-vscode/src/query-testing/qltest-discovery.ts @@ -109,7 +109,7 @@ export class QLTestDiscovery extends Discovery { const dirName = dirname(relativePath); const parentDirectory = rootDirectory.createDirectory(dirName); parentDirectory.addChild( - new FileTreeLeaf(testPath, basename(testPath), undefined), + new FileTreeLeaf(testPath, basename(testPath)), ); } From 79d59bc259a3429acbeba7971d46272e7f2c581f Mon Sep 17 00:00:00 2001 From: shati-patel <42641846+shati-patel@users.noreply.github.com> Date: Fri, 2 Jun 2023 15:54:38 +0100 Subject: [PATCH 5/5] Make `data` param optional on `FileTreeNode` --- extensions/ql-vscode/src/common/file-tree-nodes.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/ql-vscode/src/common/file-tree-nodes.ts b/extensions/ql-vscode/src/common/file-tree-nodes.ts index 8fb2c5cf2bf..88a954e0e59 100644 --- a/extensions/ql-vscode/src/common/file-tree-nodes.ts +++ b/extensions/ql-vscode/src/common/file-tree-nodes.ts @@ -8,7 +8,7 @@ export abstract class FileTreeNode { constructor( private _path: string, private _name: string, - private _data: T | undefined, + private _data?: T, ) {} public get path(): string { @@ -37,7 +37,7 @@ export class FileTreeDirectory extends FileTreeNode { _name: string, private _children: Array> = [], ) { - super(_path, _name, undefined); + super(_path, _name); } public get children(): ReadonlyArray> {