Improve user experience when no database is selected (#3214)
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
## [UNRELEASED]
|
## [UNRELEASED]
|
||||||
|
|
||||||
|
- If you run a query without having selected a database, we show a more intuitive prompt to help you select a database. [#3214](https://github.com/github/vscode-codeql/pull/3214)
|
||||||
- Add a prompt for downloading a GitHub database when opening a GitHub repository. [#3138](https://github.com/github/vscode-codeql/pull/3138)
|
- Add a prompt for downloading a GitHub database when opening a GitHub repository. [#3138](https://github.com/github/vscode-codeql/pull/3138)
|
||||||
- Avoid showing a popup when hovering over source elements in database source files. [#3125](https://github.com/github/vscode-codeql/pull/3125)
|
- Avoid showing a popup when hovering over source elements in database source files. [#3125](https://github.com/github/vscode-codeql/pull/3125)
|
||||||
- Add comparison of alerts when comparing query results. This allows viewing path explanations for differences in alerts. [#3113](https://github.com/github/vscode-codeql/pull/3113)
|
- Add comparison of alerts when comparing query results. This allows viewing path explanations for differences in alerts. [#3113](https://github.com/github/vscode-codeql/pull/3113)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import type {
|
|||||||
ProviderResult,
|
ProviderResult,
|
||||||
TreeDataProvider,
|
TreeDataProvider,
|
||||||
CancellationToken,
|
CancellationToken,
|
||||||
|
QuickPickItem,
|
||||||
} from "vscode";
|
} from "vscode";
|
||||||
import {
|
import {
|
||||||
EventEmitter,
|
EventEmitter,
|
||||||
@@ -28,7 +29,11 @@ import type {
|
|||||||
ProgressCallback,
|
ProgressCallback,
|
||||||
ProgressContext,
|
ProgressContext,
|
||||||
} from "../common/vscode/progress";
|
} from "../common/vscode/progress";
|
||||||
import { withInheritedProgress, withProgress } from "../common/vscode/progress";
|
import {
|
||||||
|
UserCancellationException,
|
||||||
|
withInheritedProgress,
|
||||||
|
withProgress,
|
||||||
|
} from "../common/vscode/progress";
|
||||||
import {
|
import {
|
||||||
isLikelyDatabaseRoot,
|
isLikelyDatabaseRoot,
|
||||||
isLikelyDbLanguageFolder,
|
isLikelyDbLanguageFolder,
|
||||||
@@ -52,7 +57,10 @@ import {
|
|||||||
createMultiSelectionCommand,
|
createMultiSelectionCommand,
|
||||||
createSingleSelectionCommand,
|
createSingleSelectionCommand,
|
||||||
} from "../common/vscode/selection-commands";
|
} from "../common/vscode/selection-commands";
|
||||||
import { tryGetQueryLanguage } from "../common/query-language";
|
import {
|
||||||
|
getLanguageDisplayName,
|
||||||
|
tryGetQueryLanguage,
|
||||||
|
} from "../common/query-language";
|
||||||
import type { LanguageContextStore } from "../language-context-store";
|
import type { LanguageContextStore } from "../language-context-store";
|
||||||
|
|
||||||
enum SortOrder {
|
enum SortOrder {
|
||||||
@@ -227,6 +235,18 @@ async function chooseDatabaseDir(byFolder: boolean): Promise<Uri | undefined> {
|
|||||||
return getFirst(chosen);
|
return getFirst(chosen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface DatabaseSelectionQuickPickItem extends QuickPickItem {
|
||||||
|
databaseKind: "new" | "existing";
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DatabaseQuickPickItem extends QuickPickItem {
|
||||||
|
databaseItem: DatabaseItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DatabaseImportQuickPickItems extends QuickPickItem {
|
||||||
|
importType: "URL" | "github" | "archive" | "folder";
|
||||||
|
}
|
||||||
|
|
||||||
export class DatabaseUI extends DisposableObject {
|
export class DatabaseUI extends DisposableObject {
|
||||||
private treeDataProvider: DatabaseTreeDataProvider;
|
private treeDataProvider: DatabaseTreeDataProvider;
|
||||||
|
|
||||||
@@ -794,13 +814,120 @@ export class DatabaseUI extends DisposableObject {
|
|||||||
* notification if it tries to perform any long-running operations.
|
* notification if it tries to perform any long-running operations.
|
||||||
*/
|
*/
|
||||||
private async getDatabaseItemInternal(
|
private async getDatabaseItemInternal(
|
||||||
progress: ProgressContext | undefined,
|
progressContext: ProgressContext | undefined,
|
||||||
): Promise<DatabaseItem | undefined> {
|
): Promise<DatabaseItem | undefined> {
|
||||||
if (this.databaseManager.currentDatabaseItem === undefined) {
|
if (this.databaseManager.currentDatabaseItem === undefined) {
|
||||||
await this.chooseAndSetDatabase(false, progress);
|
progressContext?.progress({
|
||||||
|
maxStep: 2,
|
||||||
|
step: 1,
|
||||||
|
message: "Choosing database",
|
||||||
|
});
|
||||||
|
await this.promptForDatabase();
|
||||||
|
}
|
||||||
|
return this.databaseManager.currentDatabaseItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async promptForDatabase(): Promise<void> {
|
||||||
|
const quickPickItems: DatabaseSelectionQuickPickItem[] = [
|
||||||
|
{
|
||||||
|
label: "$(database) Existing database",
|
||||||
|
detail: "Select an existing database from your workspace",
|
||||||
|
alwaysShow: true,
|
||||||
|
databaseKind: "existing",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "$(arrow-down) New database",
|
||||||
|
detail: "Import a new database from the cloud or your local machine",
|
||||||
|
alwaysShow: true,
|
||||||
|
databaseKind: "new",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const selectedOption =
|
||||||
|
await window.showQuickPick<DatabaseSelectionQuickPickItem>(
|
||||||
|
quickPickItems,
|
||||||
|
{
|
||||||
|
placeHolder: "Select an option",
|
||||||
|
ignoreFocusOut: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!selectedOption) {
|
||||||
|
throw new UserCancellationException("No database selected", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.databaseManager.currentDatabaseItem;
|
if (selectedOption.databaseKind === "existing") {
|
||||||
|
await this.selectExistingDatabase();
|
||||||
|
} else if (selectedOption.databaseKind === "new") {
|
||||||
|
await this.importNewDatabase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async selectExistingDatabase() {
|
||||||
|
const dbItems: DatabaseQuickPickItem[] =
|
||||||
|
this.databaseManager.databaseItems.map((dbItem) => ({
|
||||||
|
label: dbItem.name,
|
||||||
|
description: getLanguageDisplayName(dbItem.language),
|
||||||
|
databaseItem: dbItem,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const selectedDatabase = await window.showQuickPick(dbItems, {
|
||||||
|
placeHolder: "Select a database",
|
||||||
|
ignoreFocusOut: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!selectedDatabase) {
|
||||||
|
throw new UserCancellationException("No database selected", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.databaseManager.setCurrentDatabaseItem(
|
||||||
|
selectedDatabase.databaseItem,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async importNewDatabase() {
|
||||||
|
const importOptions: DatabaseImportQuickPickItems[] = [
|
||||||
|
{
|
||||||
|
label: "$(github) GitHub",
|
||||||
|
detail: "Import a database from a GitHub repository",
|
||||||
|
alwaysShow: true,
|
||||||
|
importType: "github",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "$(link) URL",
|
||||||
|
detail: "Import a database archive or folder from a remote URL",
|
||||||
|
alwaysShow: true,
|
||||||
|
importType: "URL",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "$(file-zip) Archive",
|
||||||
|
detail: "Import a database from a local ZIP archive",
|
||||||
|
alwaysShow: true,
|
||||||
|
importType: "archive",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "$(folder) Folder",
|
||||||
|
detail: "Import a database from a local folder",
|
||||||
|
alwaysShow: true,
|
||||||
|
importType: "folder",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const selectedImportOption =
|
||||||
|
await window.showQuickPick<DatabaseImportQuickPickItems>(importOptions, {
|
||||||
|
placeHolder: "Import a database from...",
|
||||||
|
ignoreFocusOut: true,
|
||||||
|
});
|
||||||
|
if (!selectedImportOption) {
|
||||||
|
throw new UserCancellationException("No database selected", true);
|
||||||
|
}
|
||||||
|
if (selectedImportOption.importType === "github") {
|
||||||
|
await this.handleChooseDatabaseGithub();
|
||||||
|
} else if (selectedImportOption.importType === "URL") {
|
||||||
|
await this.handleChooseDatabaseInternet();
|
||||||
|
} else if (selectedImportOption.importType === "archive") {
|
||||||
|
await this.handleChooseDatabaseArchive();
|
||||||
|
} else if (selectedImportOption.importType === "folder") {
|
||||||
|
await this.handleChooseDatabaseFolder();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -3,12 +3,7 @@ import type {
|
|||||||
ProgressUpdate,
|
ProgressUpdate,
|
||||||
} from "../common/vscode/progress";
|
} from "../common/vscode/progress";
|
||||||
import { withProgress } from "../common/vscode/progress";
|
import { withProgress } from "../common/vscode/progress";
|
||||||
import type {
|
import type { CancellationToken, Range, TabInputText } from "vscode";
|
||||||
CancellationToken,
|
|
||||||
QuickPickItem,
|
|
||||||
Range,
|
|
||||||
TabInputText,
|
|
||||||
} from "vscode";
|
|
||||||
import { CancellationTokenSource, Uri, window } from "vscode";
|
import { CancellationTokenSource, Uri, window } from "vscode";
|
||||||
import {
|
import {
|
||||||
TeeLogger,
|
TeeLogger,
|
||||||
@@ -23,7 +18,10 @@ import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
|
|||||||
import { displayQuickQuery } from "./quick-query";
|
import { displayQuickQuery } from "./quick-query";
|
||||||
import type { CoreCompletedQuery, QueryRunner } from "../query-server";
|
import type { CoreCompletedQuery, QueryRunner } from "../query-server";
|
||||||
import type { QueryHistoryManager } from "../query-history/query-history-manager";
|
import type { QueryHistoryManager } from "../query-history/query-history-manager";
|
||||||
import type { DatabaseUI } from "../databases/local-databases-ui";
|
import type {
|
||||||
|
DatabaseQuickPickItem,
|
||||||
|
DatabaseUI,
|
||||||
|
} from "../databases/local-databases-ui";
|
||||||
import type { ResultsView } from "./results-view";
|
import type { ResultsView } from "./results-view";
|
||||||
import type {
|
import type {
|
||||||
DatabaseItem,
|
DatabaseItem,
|
||||||
@@ -55,10 +53,6 @@ import { tryGetQueryLanguage } from "../common/query-language";
|
|||||||
import type { LanguageContextStore } from "../language-context-store";
|
import type { LanguageContextStore } from "../language-context-store";
|
||||||
import type { ExtensionApp } from "../common/vscode/vscode-app";
|
import type { ExtensionApp } from "../common/vscode/vscode-app";
|
||||||
|
|
||||||
interface DatabaseQuickPickItem extends QuickPickItem {
|
|
||||||
databaseItem: DatabaseItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum QuickEvalType {
|
export enum QuickEvalType {
|
||||||
None,
|
None,
|
||||||
QuickEval,
|
QuickEval,
|
||||||
|
|||||||
Reference in New Issue
Block a user