diff --git a/extensions/ql-vscode/src/databases-ui.ts b/extensions/ql-vscode/src/databases-ui.ts index 50d5c14fdc3..e8b9ffd8a31 100644 --- a/extensions/ql-vscode/src/databases-ui.ts +++ b/extensions/ql-vscode/src/databases-ui.ts @@ -378,21 +378,28 @@ export class DatabaseUI extends DisposableObject { handleRemoveOrphanedDatabases = async (): Promise => { logger.log('Removing orphaned databases from workspace storage.'); - let dbDirs = - // read directory - (await fs.readdir(this.storagePath, { withFileTypes: true })) - // remove non-directories - .filter(dirent => dirent.isDirectory()) - // get the full path - .map(dirent => path.join(this.storagePath, dirent.name)) - // remove databases still in workspace - .filter(dbDir => { - const dbUri = Uri.file(dbDir); - return this.databaseManager.databaseItems.every(item => item.databaseUri.fsPath !== dbUri.fsPath); - }); - - // remove non-databases - dbDirs = await asyncFilter(dbDirs, isLikelyDatabaseRoot); + let dbDirs = undefined; + + try { + dbDirs = + // read directory + (await fs.readdir(this.storagePath, { withFileTypes: true })) + // remove non-directories + .filter(dirent => dirent.isDirectory()) + // get the full path + .map(dirent => path.join(this.storagePath, dirent.name)) + // remove databases still in workspace + .filter(dbDir => { + const dbUri = Uri.file(dbDir); + return this.databaseManager.databaseItems.every(item => item.databaseUri.fsPath !== dbUri.fsPath); + }); + + // remove non-databases + dbDirs = await asyncFilter(dbDirs, isLikelyDatabaseRoot); + } catch (e) { + logger.log(`Not able to find the storage path '${e.message}'. Ignoring request to remove orphaned database directories.`); + return; + } if (!dbDirs.length) { logger.log('No orphaned databases found.'); diff --git a/extensions/ql-vscode/src/discovery.ts b/extensions/ql-vscode/src/discovery.ts index bdad6b22aca..cc89e2fe969 100644 --- a/extensions/ql-vscode/src/discovery.ts +++ b/extensions/ql-vscode/src/discovery.ts @@ -1,5 +1,5 @@ import { DisposableObject } from './vscode-utils/disposable-object'; -import { showAndLogErrorMessage } from './helpers'; +import { logger } from './logging'; /** * Base class for "discovery" operations, which scan the file system to find specific kinds of @@ -62,7 +62,7 @@ export abstract class Discovery extends DisposableObject { }); discoveryPromise.catch(err => { - showAndLogErrorMessage(`${this.name} failed. Reason: ${err.message}`); + logger.log(`${this.name} failed. Reason: ${err.message}`); }); discoveryPromise.finally(() => { diff --git a/extensions/ql-vscode/src/helpers.ts b/extensions/ql-vscode/src/helpers.ts index cb05510568c..ecfea422a4f 100644 --- a/extensions/ql-vscode/src/helpers.ts +++ b/extensions/ql-vscode/src/helpers.ts @@ -123,15 +123,16 @@ export function commandRunner( try { return await task(...args); } catch (e) { + const errorMessage = `${e.message || e} (${commandId})`; if (e instanceof UserCancellationException) { // User has cancelled this action manually if (e.silent) { - logger.log(e.message); + logger.log(errorMessage); } else { - showAndLogWarningMessage(e.message); + showAndLogWarningMessage(errorMessage); } } else { - showAndLogErrorMessage(e.message || e); + showAndLogErrorMessage(errorMessage); } return undefined; } @@ -161,15 +162,16 @@ export function commandRunnerWithProgress( try { return await withProgress(progressOptionsWithDefaults, task, ...args); } catch (e) { + const errorMessage = `${e.message || e} (${commandId})`; if (e instanceof UserCancellationException) { // User has cancelled this action manually if (e.silent) { - logger.log(e.message); + logger.log(errorMessage); } else { - showAndLogWarningMessage(e.message); + showAndLogWarningMessage(errorMessage); } } else { - showAndLogErrorMessage(e.message || e); + showAndLogErrorMessage(errorMessage); } return undefined; } diff --git a/extensions/ql-vscode/src/qltest-discovery.ts b/extensions/ql-vscode/src/qltest-discovery.ts index 50bb3ee863b..0cda0be3d80 100644 --- a/extensions/ql-vscode/src/qltest-discovery.ts +++ b/extensions/ql-vscode/src/qltest-discovery.ts @@ -3,6 +3,7 @@ import { Discovery } from './discovery'; import { EventEmitter, Event, Uri, RelativePattern, WorkspaceFolder, env } from 'vscode'; import { MultiFileSystemWatcher } from './vscode-utils/multi-file-system-watcher'; import { CodeQLCliServer } from './cli'; +import * as fs from 'fs-extra'; /** * A node in the tree of tests. This will be either a `QLTestDirectory` or a `QLTestFile`. @@ -180,19 +181,21 @@ export class QLTestDiscovery extends Discovery { private async discoverTests(): Promise { const fullPath = this.workspaceFolder.uri.fsPath; const name = this.workspaceFolder.name; - const resolvedTests = (await this.cliServer.resolveTests(fullPath)) - .filter((testPath) => !QLTestDiscovery.ignoreTestPath(testPath)); - const rootDirectory = new QLTestDirectory(fullPath, name); - for (const testPath of resolvedTests) { - const relativePath = path.normalize(path.relative(fullPath, testPath)); - const dirName = path.dirname(relativePath); - const parentDirectory = rootDirectory.createDirectory(dirName); - parentDirectory.addChild(new QLTestFile(testPath, path.basename(testPath))); - } - rootDirectory.finish(); + // Don't try discovery on workspace folders that don't exist on the filesystem + if ((await fs.pathExists(fullPath))) { + const resolvedTests = (await this.cliServer.resolveTests(fullPath)) + .filter((testPath) => !QLTestDiscovery.ignoreTestPath(testPath)); + for (const testPath of resolvedTests) { + const relativePath = path.normalize(path.relative(fullPath, testPath)); + const dirName = path.dirname(relativePath); + const parentDirectory = rootDirectory.createDirectory(dirName); + parentDirectory.addChild(new QLTestFile(testPath, path.basename(testPath))); + } + rootDirectory.finish(); + } return rootDirectory; }