diff --git a/extensions/ql-vscode/src/databases/db-item-selection.ts b/extensions/ql-vscode/src/databases/db-item-selection.ts new file mode 100644 index 00000000000..9ddc9bdc8ac --- /dev/null +++ b/extensions/ql-vscode/src/databases/db-item-selection.ts @@ -0,0 +1,44 @@ +import { DbItem, DbItemKind, LocalDbItem, RemoteDbItem } from "./db-item"; + +export function getSelectedDbItem(dbItems: DbItem[]): DbItem | undefined { + for (const dbItem of dbItems) { + if ( + dbItem.kind === DbItemKind.RootRemote || + dbItem.kind === DbItemKind.RootLocal + ) { + for (const child of dbItem.children) { + const selectedItem = extractSelected(child); + if (selectedItem) return selectedItem; + } + } else { + const selectedItem = extractSelected(dbItem); + if (selectedItem) return selectedItem; + } + } + return undefined; +} + +function extractSelected( + dbItem: RemoteDbItem | LocalDbItem, +): DbItem | undefined { + if (dbItem.selected) { + return dbItem; + } + switch (dbItem.kind) { + case DbItemKind.LocalList: + for (const database of dbItem.databases) { + if (database.selected) { + return database; + } + } + break; + case DbItemKind.RemoteUserDefinedList: + for (const repo of dbItem.repos) { + if (repo.selected) { + return repo; + } + } + break; + } + return undefined; +} diff --git a/extensions/ql-vscode/src/databases/db-manager.ts b/extensions/ql-vscode/src/databases/db-manager.ts index 32317c99c51..a4d499a82fc 100644 --- a/extensions/ql-vscode/src/databases/db-manager.ts +++ b/extensions/ql-vscode/src/databases/db-manager.ts @@ -3,6 +3,7 @@ import { AppEvent, AppEventEmitter } from "../common/events"; import { ValueResult } from "../common/value-result"; import { DbConfigStore } from "./config/db-config-store"; import { DbItem } from "./db-item"; +import { getSelectedDbItem } from "./db-item-selection"; import { createLocalTree, createRemoteTree } from "./db-tree-creator"; export class DbManager { @@ -18,6 +19,16 @@ export class DbManager { }); } + public getSelectedDbItem(): DbItem | undefined { + const dbItems = this.getDbItems(); + + if (dbItems.isFailure) { + return undefined; + } + + return getSelectedDbItem(dbItems.value); + } + public getDbItems(): ValueResult { const configResult = this.dbConfigStore.getConfig(); if (configResult.isFailure) { diff --git a/extensions/ql-vscode/test/pure-tests/databases/db-item-selection.test.ts b/extensions/ql-vscode/test/pure-tests/databases/db-item-selection.test.ts new file mode 100644 index 00000000000..b41e5553359 --- /dev/null +++ b/extensions/ql-vscode/test/pure-tests/databases/db-item-selection.test.ts @@ -0,0 +1,278 @@ +import { DbItem, DbItemKind } from "../../../src/databases/db-item"; +import { getSelectedDbItem } from "../../../src/databases/db-item-selection"; +describe("db item selection", () => { + it("should return undefined if no item is selected", () => { + const dbItems: DbItem[] = [ + { + kind: DbItemKind.RootRemote, + children: [ + { + kind: DbItemKind.RemoteSystemDefinedList, + listName: "top_10", + listDisplayName: "Top 10 repositories", + listDescription: "Top 10 repositories of a language", + selected: false, + }, + { + kind: DbItemKind.RemoteSystemDefinedList, + listName: "top_100", + listDisplayName: "Top 100 repositories", + listDescription: "Top 100 repositories of a language", + selected: false, + }, + { + kind: DbItemKind.RemoteOwner, + ownerName: "github", + selected: false, + }, + { + kind: DbItemKind.RemoteUserDefinedList, + listName: "my list", + repos: [ + { + kind: DbItemKind.RemoteRepo, + repoFullName: "owner1/repo2", + selected: false, + }, + { + kind: DbItemKind.RemoteRepo, + repoFullName: "owner1/repo3", + selected: false, + }, + ], + selected: false, + }, + ], + }, + { + kind: DbItemKind.RootLocal, + children: [ + { + kind: DbItemKind.LocalList, + listName: "list-1", + databases: [ + { + kind: DbItemKind.LocalDatabase, + databaseName: "db1", + dateAdded: 1234, + language: "javascript", + storagePath: "/foo/bar", + selected: false, + }, + { + kind: DbItemKind.LocalDatabase, + databaseName: "db2", + dateAdded: 1234, + language: "javascript", + storagePath: "/foo/bar", + selected: false, + }, + ], + selected: false, + }, + { + kind: DbItemKind.LocalDatabase, + databaseName: "db3", + dateAdded: 1234, + language: "javascript", + storagePath: "/foo/bar", + selected: false, + }, + ], + }, + ]; + + expect(getSelectedDbItem(dbItems)).toBeUndefined(); + }); + + it("should return correct local database item from DbItem list", () => { + const dbItems: DbItem[] = [ + { + kind: DbItemKind.RootLocal, + children: [ + { + kind: DbItemKind.LocalList, + listName: "list-1", + databases: [ + { + kind: DbItemKind.LocalDatabase, + databaseName: "db1", + dateAdded: 1234, + language: "javascript", + storagePath: "/foo/bar", + selected: false, + }, + { + kind: DbItemKind.LocalDatabase, + databaseName: "db2", + dateAdded: 1234, + language: "javascript", + storagePath: "/foo/bar", + selected: true, + }, + ], + selected: false, + }, + { + kind: DbItemKind.LocalDatabase, + databaseName: "db3", + dateAdded: 1234, + language: "javascript", + storagePath: "/foo/bar", + selected: false, + }, + ], + }, + ]; + + expect(getSelectedDbItem(dbItems)).toEqual({ + kind: DbItemKind.LocalDatabase, + databaseName: "db2", + dateAdded: 1234, + language: "javascript", + storagePath: "/foo/bar", + selected: true, + }); + }); + + it("should return correct remote database list item from DbItem list", () => { + const dbItems: DbItem[] = [ + { + kind: DbItemKind.RootRemote, + children: [ + { + kind: DbItemKind.RemoteSystemDefinedList, + listName: "top_10", + listDisplayName: "Top 10 repositories", + listDescription: "Top 10 repositories of a language", + selected: false, + }, + { + kind: DbItemKind.RemoteOwner, + ownerName: "github", + selected: false, + }, + { + kind: DbItemKind.RemoteUserDefinedList, + listName: "my list", + repos: [ + { + kind: DbItemKind.RemoteRepo, + repoFullName: "owner1/repo2", + selected: false, + }, + { + kind: DbItemKind.RemoteRepo, + repoFullName: "owner1/repo3", + selected: false, + }, + ], + selected: true, + }, + ], + }, + ]; + + expect(getSelectedDbItem(dbItems)).toEqual({ + kind: DbItemKind.RemoteUserDefinedList, + listName: "my list", + repos: [ + { + kind: DbItemKind.RemoteRepo, + repoFullName: "owner1/repo2", + selected: false, + }, + { + kind: DbItemKind.RemoteRepo, + repoFullName: "owner1/repo3", + selected: false, + }, + ], + selected: true, + }); + }); + + it("should handle arbitrary list of db items", () => { + const dbItems: DbItem[] = [ + { + kind: DbItemKind.RootRemote, + children: [ + { + kind: DbItemKind.RemoteSystemDefinedList, + listName: "top_10", + listDisplayName: "Top 10 repositories", + listDescription: "Top 10 repositories of a language", + selected: false, + }, + { + kind: DbItemKind.RemoteOwner, + ownerName: "github", + selected: false, + }, + { + kind: DbItemKind.RemoteUserDefinedList, + listName: "my list", + repos: [ + { + kind: DbItemKind.RemoteRepo, + repoFullName: "owner1/repo2", + selected: false, + }, + { + kind: DbItemKind.RemoteRepo, + repoFullName: "owner1/repo3", + selected: false, + }, + ], + selected: false, + }, + ], + }, + { + kind: DbItemKind.RemoteSystemDefinedList, + listName: "top_10", + listDisplayName: "Top 10 repositories", + listDescription: "Top 10 repositories of a language", + selected: true, + }, + ]; + + expect(getSelectedDbItem(dbItems)).toEqual({ + kind: DbItemKind.RemoteSystemDefinedList, + listName: "top_10", + listDisplayName: "Top 10 repositories", + listDescription: "Top 10 repositories of a language", + selected: true, + }); + }); + + it("should handle empty db item lists", () => { + const dbItems: DbItem[] = [ + { + kind: DbItemKind.RootRemote, + children: [ + { + kind: DbItemKind.RemoteSystemDefinedList, + listName: "top_10", + listDisplayName: "Top 10 repositories", + listDescription: "Top 10 repositories of a language", + selected: false, + }, + { + kind: DbItemKind.RemoteOwner, + ownerName: "github", + selected: false, + }, + { + kind: DbItemKind.RemoteUserDefinedList, + listName: "my list", + repos: [], + selected: false, + }, + ], + }, + ]; + + expect(getSelectedDbItem(dbItems)).toBeUndefined(); + }); +});