Merge remote-tracking branch 'origin/main' into koesie10/find-github-repository
This commit is contained in:
@@ -2,6 +2,15 @@
|
|||||||
|
|
||||||
## [UNRELEASED]
|
## [UNRELEASED]
|
||||||
|
|
||||||
|
- Add new CodeQL views for managing databases and queries:
|
||||||
|
1. A queries panel, to create and run queries in one place.
|
||||||
|
2. A language selector, to quickly determine the language compatibility of databases and queries.
|
||||||
|
|
||||||
|
For more information, see the [documentation](https://codeql.github.com/docs/codeql-for-visual-studio-code/analyzing-your-projects/#filtering-databases-and-queries-by-language).
|
||||||
|
- When adding a CodeQL database, we no longer add the database source folder to the workspace by default (since this caused bugs in single-folder workspaces). [#3047](https://github.com/github/vscode-codeql/pull/3047)
|
||||||
|
- You can manually add individual database source folders to the workspace with the "Add Database Source to Workspace" right-click command in the databases view.
|
||||||
|
- To restore the old behavior of adding all database source folders by default, set the `codeQL.addingDatabases.addDatabaseSourceToWorkspace` setting to `true`.
|
||||||
|
- Rename the `codeQL.databaseDownload.allowHttp` setting to `codeQL.addingDatabases.allowHttp`, so that database-related settings are grouped together in the Settings UI. [#3047](https://github.com/github/vscode-codeql/pull/3047) & [#3069](https://github.com/github/vscode-codeql/pull/3069)
|
||||||
- The "Sort by Language" action in the databases view now sorts by name within each language. [#3055](https://github.com/github/vscode-codeql/pull/3055)
|
- The "Sort by Language" action in the databases view now sorts by name within each language. [#3055](https://github.com/github/vscode-codeql/pull/3055)
|
||||||
|
|
||||||
## 1.9.4 - 6 November 2023
|
## 1.9.4 - 6 November 2023
|
||||||
|
|||||||
12
extensions/ql-vscode/package-lock.json
generated
12
extensions/ql-vscode/package-lock.json
generated
@@ -4392,9 +4392,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@octokit/openapi-types": {
|
"node_modules/@octokit/openapi-types": {
|
||||||
"version": "19.0.0",
|
"version": "19.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.2.tgz",
|
||||||
"integrity": "sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw=="
|
"integrity": "sha512-8li32fUDUeml/ACRp/njCWTsk5t17cfTM1jp9n08pBrqs5cDFJubtjsSnuz56r5Tad6jdEPJld7LxNp9dNcyjQ=="
|
||||||
},
|
},
|
||||||
"node_modules/@octokit/plugin-paginate-rest": {
|
"node_modules/@octokit/plugin-paginate-rest": {
|
||||||
"version": "9.0.0",
|
"version": "9.0.0",
|
||||||
@@ -35269,9 +35269,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@octokit/openapi-types": {
|
"@octokit/openapi-types": {
|
||||||
"version": "19.0.0",
|
"version": "19.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.2.tgz",
|
||||||
"integrity": "sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw=="
|
"integrity": "sha512-8li32fUDUeml/ACRp/njCWTsk5t17cfTM1jp9n08pBrqs5cDFJubtjsSnuz56r5Tad6jdEPJld7LxNp9dNcyjQ=="
|
||||||
},
|
},
|
||||||
"@octokit/plugin-paginate-rest": {
|
"@octokit/plugin-paginate-rest": {
|
||||||
"version": "9.0.0",
|
"version": "9.0.0",
|
||||||
|
|||||||
@@ -374,13 +374,23 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"title": "Downloading databases",
|
"title": "Adding databases",
|
||||||
"order": 6,
|
"order": 6,
|
||||||
"properties": {
|
"properties": {
|
||||||
"codeQL.databaseDownload.allowHttp": {
|
"codeQL.addingDatabases.allowHttp": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false,
|
"default": false,
|
||||||
"description": "Allow database to be downloaded via HTTP. Warning: enabling this option will allow downloading from insecure servers."
|
"description": "Allow databases to be downloaded via HTTP. Warning: enabling this option will allow downloading from insecure servers."
|
||||||
|
},
|
||||||
|
"codeQL.databaseDownload.allowHttp": {
|
||||||
|
"type": "boolean",
|
||||||
|
"markdownDeprecationMessage": "**Deprecated**: Please use `#codeQL.addingDatabases.allowHttp#` instead.",
|
||||||
|
"deprecationMessage": "Deprecated: Please use codeQL.addingDatabases.allowHttp instead."
|
||||||
|
},
|
||||||
|
"codeQL.addingDatabases.addDatabaseSourceToWorkspace": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false,
|
||||||
|
"markdownDescription": "When adding a CodeQL database, automatically add the database's source folder as a workspace folder. Warning: enabling this option in a single-folder workspace will cause the workspace to reload as a [multi-root workspace](https://code.visualstudio.com/docs/editor/multi-root-workspaces). This may cause query history and database lists to be reset."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -1678,10 +1688,6 @@
|
|||||||
"command": "codeQL.mockGitHubApiServer.unloadScenario",
|
"command": "codeQL.mockGitHubApiServer.unloadScenario",
|
||||||
"when": "config.codeQL.mockGitHubApiServer.enabled && codeQL.mockGitHubApiServer.scenarioLoaded"
|
"when": "config.codeQL.mockGitHubApiServer.enabled && codeQL.mockGitHubApiServer.scenarioLoaded"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"command": "codeQL.createQuery",
|
|
||||||
"when": "config.codeQL.codespacesTemplate || config.codeQL.canary && config.codeQL.queriesPanel"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"command": "codeQLTests.acceptOutputContextTestItem",
|
"command": "codeQLTests.acceptOutputContextTestItem",
|
||||||
"when": "false"
|
"when": "false"
|
||||||
@@ -1766,8 +1772,7 @@
|
|||||||
"ql-container": [
|
"ql-container": [
|
||||||
{
|
{
|
||||||
"id": "codeQLLanguageSelection",
|
"id": "codeQLLanguageSelection",
|
||||||
"name": "Language",
|
"name": "Language"
|
||||||
"when": "config.codeQL.canary && config.codeQL.showLanguageFilter"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "codeQLDatabases",
|
"id": "codeQLDatabases",
|
||||||
@@ -1775,8 +1780,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "codeQLQueries",
|
"id": "codeQLQueries",
|
||||||
"name": "Queries",
|
"name": "Queries"
|
||||||
"when": "config.codeQL.canary && config.codeQL.queriesPanel"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "codeQLVariantAnalysisRepositories",
|
"id": "codeQLVariantAnalysisRepositories",
|
||||||
|
|||||||
@@ -641,12 +641,32 @@ export function isCodespacesTemplate() {
|
|||||||
return !!CODESPACES_TEMPLATE.getValue<boolean>();
|
return !!CODESPACES_TEMPLATE.getValue<boolean>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated after v1.9.4. Can be removed in a few versions.
|
||||||
const DATABASE_DOWNLOAD_SETTING = new Setting("databaseDownload", ROOT_SETTING);
|
const DATABASE_DOWNLOAD_SETTING = new Setting("databaseDownload", ROOT_SETTING);
|
||||||
|
const DEPRECATED_ALLOW_HTTP_SETTING = new Setting(
|
||||||
|
"allowHttp",
|
||||||
|
DATABASE_DOWNLOAD_SETTING,
|
||||||
|
);
|
||||||
|
|
||||||
const ALLOW_HTTP_SETTING = new Setting("allowHttp", DATABASE_DOWNLOAD_SETTING);
|
const ADDING_DATABASES_SETTING = new Setting("addingDatabases", ROOT_SETTING);
|
||||||
|
|
||||||
|
const ALLOW_HTTP_SETTING = new Setting("allowHttp", ADDING_DATABASES_SETTING);
|
||||||
|
|
||||||
export function allowHttp(): boolean {
|
export function allowHttp(): boolean {
|
||||||
return ALLOW_HTTP_SETTING.getValue<boolean>() || false;
|
return (
|
||||||
|
ALLOW_HTTP_SETTING.getValue<boolean>() ||
|
||||||
|
DEPRECATED_ALLOW_HTTP_SETTING.getValue<boolean>() ||
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ADD_DATABASE_SOURCE_TO_WORKSPACE_SETTING = new Setting(
|
||||||
|
"addDatabaseSourceToWorkspace",
|
||||||
|
ADDING_DATABASES_SETTING,
|
||||||
|
);
|
||||||
|
|
||||||
|
export function addDatabaseSourceToWorkspace(): boolean {
|
||||||
|
return ADD_DATABASE_SOURCE_TO_WORKSPACE_SETTING.getValue<boolean>() || false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -690,15 +710,6 @@ export async function setAutogenerateQlPacks(choice: AutogenerateQLPacks) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* A flag indicating whether to show the queries panel in the QL view container.
|
|
||||||
*/
|
|
||||||
const QUERIES_PANEL = new Setting("queriesPanel", ROOT_SETTING);
|
|
||||||
|
|
||||||
export function showQueriesPanel(): boolean {
|
|
||||||
return !!QUERIES_PANEL.getValue<boolean>();
|
|
||||||
}
|
|
||||||
|
|
||||||
const MODEL_SETTING = new Setting("model", ROOT_SETTING);
|
const MODEL_SETTING = new Setting("model", ROOT_SETTING);
|
||||||
const FLOW_GENERATION = new Setting("flowGeneration", MODEL_SETTING);
|
const FLOW_GENERATION = new Setting("flowGeneration", MODEL_SETTING);
|
||||||
const LLM_GENERATION = new Setting("llmGeneration", MODEL_SETTING);
|
const LLM_GENERATION = new Setting("llmGeneration", MODEL_SETTING);
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
// Contains models and consts for the data we want to store in the database config.
|
// Contains models and consts for the data we want to store in the database config.
|
||||||
// Changes to these models should be done carefully and account for backwards compatibility of data.
|
// Changes to these models should be done carefully and account for backwards compatibility of data.
|
||||||
|
|
||||||
|
import { DatabaseOrigin } from "../local-databases/database-origin";
|
||||||
|
|
||||||
export const DB_CONFIG_VERSION = 1;
|
export const DB_CONFIG_VERSION = 1;
|
||||||
|
|
||||||
export interface DbConfig {
|
export interface DbConfig {
|
||||||
@@ -88,6 +90,7 @@ export interface LocalDatabase {
|
|||||||
name: string;
|
name: string;
|
||||||
dateAdded: number;
|
dateAdded: number;
|
||||||
language: string;
|
language: string;
|
||||||
|
origin: DatabaseOrigin;
|
||||||
storagePath: string;
|
storagePath: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,10 +29,11 @@ import {
|
|||||||
} from "../common/github-url-identifier-helper";
|
} from "../common/github-url-identifier-helper";
|
||||||
import { Credentials } from "../common/authentication";
|
import { Credentials } from "../common/authentication";
|
||||||
import { AppCommandManager } from "../common/commands";
|
import { AppCommandManager } from "../common/commands";
|
||||||
import { allowHttp } from "../config";
|
import { addDatabaseSourceToWorkspace, allowHttp } from "../config";
|
||||||
import { showAndLogInformationMessage } from "../common/logging";
|
import { showAndLogInformationMessage } from "../common/logging";
|
||||||
import { AppOctokit } from "../common/octokit";
|
import { AppOctokit } from "../common/octokit";
|
||||||
import { getLanguageDisplayName } from "../common/query-language";
|
import { getLanguageDisplayName } from "../common/query-language";
|
||||||
|
import { DatabaseOrigin } from "./local-databases/database-origin";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prompts a user to fetch a database from a remote location. Database is assumed to be an archive file.
|
* Prompts a user to fetch a database from a remote location. Database is assumed to be an archive file.
|
||||||
@@ -62,6 +63,10 @@ export async function promptImportInternetDatabase(
|
|||||||
databaseManager,
|
databaseManager,
|
||||||
storagePath,
|
storagePath,
|
||||||
undefined,
|
undefined,
|
||||||
|
{
|
||||||
|
type: "url",
|
||||||
|
url: databaseUrl,
|
||||||
|
},
|
||||||
progress,
|
progress,
|
||||||
cli,
|
cli,
|
||||||
);
|
);
|
||||||
@@ -99,7 +104,7 @@ export async function promptImportGithubDatabase(
|
|||||||
cli?: CodeQLCliServer,
|
cli?: CodeQLCliServer,
|
||||||
language?: string,
|
language?: string,
|
||||||
makeSelected = true,
|
makeSelected = true,
|
||||||
addSourceArchiveFolder = true,
|
addSourceArchiveFolder = addDatabaseSourceToWorkspace(),
|
||||||
): Promise<DatabaseItem | undefined> {
|
): Promise<DatabaseItem | undefined> {
|
||||||
const githubRepo = await askForGitHubRepo(progress);
|
const githubRepo = await askForGitHubRepo(progress);
|
||||||
if (!githubRepo) {
|
if (!githubRepo) {
|
||||||
@@ -178,7 +183,7 @@ export async function downloadGitHubDatabase(
|
|||||||
cli?: CodeQLCliServer,
|
cli?: CodeQLCliServer,
|
||||||
language?: string,
|
language?: string,
|
||||||
makeSelected = true,
|
makeSelected = true,
|
||||||
addSourceArchiveFolder = true,
|
addSourceArchiveFolder = addDatabaseSourceToWorkspace(),
|
||||||
): Promise<DatabaseItem | undefined> {
|
): Promise<DatabaseItem | undefined> {
|
||||||
const nwo = getNwoFromGitHubUrl(githubRepo) || githubRepo;
|
const nwo = getNwoFromGitHubUrl(githubRepo) || githubRepo;
|
||||||
if (!isValidGitHubNwo(nwo)) {
|
if (!isValidGitHubNwo(nwo)) {
|
||||||
@@ -199,7 +204,8 @@ export async function downloadGitHubDatabase(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { databaseUrl, name, owner } = result;
|
const { databaseUrl, name, owner, databaseId, databaseCreatedAt, commitOid } =
|
||||||
|
result;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The 'token' property of the token object returned by `octokit.auth()`.
|
* The 'token' property of the token object returned by `octokit.auth()`.
|
||||||
@@ -221,6 +227,13 @@ export async function downloadGitHubDatabase(
|
|||||||
databaseManager,
|
databaseManager,
|
||||||
storagePath,
|
storagePath,
|
||||||
`${owner}/${name}`,
|
`${owner}/${name}`,
|
||||||
|
{
|
||||||
|
type: "github",
|
||||||
|
repository: nwo,
|
||||||
|
databaseId,
|
||||||
|
databaseCreatedAt,
|
||||||
|
commitOid,
|
||||||
|
},
|
||||||
progress,
|
progress,
|
||||||
cli,
|
cli,
|
||||||
makeSelected,
|
makeSelected,
|
||||||
@@ -250,6 +263,10 @@ export async function importArchiveDatabase(
|
|||||||
databaseManager,
|
databaseManager,
|
||||||
storagePath,
|
storagePath,
|
||||||
undefined,
|
undefined,
|
||||||
|
{
|
||||||
|
type: "archive",
|
||||||
|
path: databaseUrl,
|
||||||
|
},
|
||||||
progress,
|
progress,
|
||||||
cli,
|
cli,
|
||||||
);
|
);
|
||||||
@@ -282,6 +299,7 @@ export async function importArchiveDatabase(
|
|||||||
* @param databaseManager the DatabaseManager
|
* @param databaseManager the DatabaseManager
|
||||||
* @param storagePath where to store the unzipped database.
|
* @param storagePath where to store the unzipped database.
|
||||||
* @param nameOverride a name for the database that overrides the default
|
* @param nameOverride a name for the database that overrides the default
|
||||||
|
* @param origin the origin of the database
|
||||||
* @param progress callback to send progress messages to
|
* @param progress callback to send progress messages to
|
||||||
* @param makeSelected make the new database selected in the databases panel (default: true)
|
* @param makeSelected make the new database selected in the databases panel (default: true)
|
||||||
* @param addSourceArchiveFolder whether to add a workspace folder containing the source archive to the workspace
|
* @param addSourceArchiveFolder whether to add a workspace folder containing the source archive to the workspace
|
||||||
@@ -292,10 +310,11 @@ async function databaseArchiveFetcher(
|
|||||||
databaseManager: DatabaseManager,
|
databaseManager: DatabaseManager,
|
||||||
storagePath: string,
|
storagePath: string,
|
||||||
nameOverride: string | undefined,
|
nameOverride: string | undefined,
|
||||||
|
origin: DatabaseOrigin,
|
||||||
progress: ProgressCallback,
|
progress: ProgressCallback,
|
||||||
cli?: CodeQLCliServer,
|
cli?: CodeQLCliServer,
|
||||||
makeSelected = true,
|
makeSelected = true,
|
||||||
addSourceArchiveFolder = true,
|
addSourceArchiveFolder = addDatabaseSourceToWorkspace(),
|
||||||
): Promise<DatabaseItem> {
|
): Promise<DatabaseItem> {
|
||||||
progress({
|
progress({
|
||||||
message: "Getting database",
|
message: "Getting database",
|
||||||
@@ -336,6 +355,7 @@ async function databaseArchiveFetcher(
|
|||||||
|
|
||||||
const item = await databaseManager.openDatabase(
|
const item = await databaseManager.openDatabase(
|
||||||
Uri.file(dbPath),
|
Uri.file(dbPath),
|
||||||
|
origin,
|
||||||
makeSelected,
|
makeSelected,
|
||||||
nameOverride,
|
nameOverride,
|
||||||
{
|
{
|
||||||
@@ -476,7 +496,7 @@ async function checkForFailingResponse(
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
// An error downloading the database. Attempt to extract the resaon behind it.
|
// An error downloading the database. Attempt to extract the reason behind it.
|
||||||
const text = await response.text();
|
const text = await response.text();
|
||||||
let msg: string;
|
let msg: string;
|
||||||
try {
|
try {
|
||||||
@@ -533,16 +553,19 @@ export async function convertGithubNwoToDatabaseUrl(
|
|||||||
databaseUrl: string;
|
databaseUrl: string;
|
||||||
owner: string;
|
owner: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
databaseId: number;
|
||||||
|
databaseCreatedAt: string;
|
||||||
|
commitOid: string | null;
|
||||||
}
|
}
|
||||||
| undefined
|
| undefined
|
||||||
> {
|
> {
|
||||||
try {
|
try {
|
||||||
const [owner, repo] = nwo.split("/");
|
const [owner, repo] = nwo.split("/");
|
||||||
|
|
||||||
const response = await octokit.request(
|
const response = await octokit.rest.codeScanning.listCodeqlDatabases({
|
||||||
"GET /repos/:owner/:repo/code-scanning/codeql/databases",
|
owner,
|
||||||
{ owner, repo },
|
repo,
|
||||||
);
|
});
|
||||||
|
|
||||||
const languages = response.data.map((db: any) => db.language);
|
const languages = response.data.map((db: any) => db.language);
|
||||||
|
|
||||||
@@ -553,10 +576,20 @@ export async function convertGithubNwoToDatabaseUrl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const databaseForLanguage = response.data.find(
|
||||||
|
(db: any) => db.language === language,
|
||||||
|
);
|
||||||
|
if (!databaseForLanguage) {
|
||||||
|
throw new Error(`No database found for language '${language}'`);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
databaseUrl: `https://api.github.com/repos/${owner}/${repo}/code-scanning/codeql/databases/${language}`,
|
databaseUrl: databaseForLanguage.url,
|
||||||
owner,
|
owner,
|
||||||
name: repo,
|
name: repo,
|
||||||
|
databaseId: databaseForLanguage.id,
|
||||||
|
databaseCreatedAt: databaseForLanguage.created_at,
|
||||||
|
commitOid: databaseForLanguage.commit_oid ?? null,
|
||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
void extLogger.log(`Error: ${getErrorMessage(e)}`);
|
void extLogger.log(`Error: ${getErrorMessage(e)}`);
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
// This file contains models that are used to represent the databases.
|
// This file contains models that are used to represent the databases.
|
||||||
|
|
||||||
|
import { DatabaseOrigin } from "./local-databases/database-origin";
|
||||||
|
|
||||||
export enum DbItemKind {
|
export enum DbItemKind {
|
||||||
RootLocal = "RootLocal",
|
RootLocal = "RootLocal",
|
||||||
LocalList = "LocalList",
|
LocalList = "LocalList",
|
||||||
@@ -38,6 +40,7 @@ export interface LocalDatabaseDbItem {
|
|||||||
databaseName: string;
|
databaseName: string;
|
||||||
dateAdded: number;
|
dateAdded: number;
|
||||||
language: string;
|
language: string;
|
||||||
|
origin: DatabaseOrigin;
|
||||||
storagePath: string;
|
storagePath: string;
|
||||||
parentListName?: string;
|
parentListName?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -197,6 +197,7 @@ function createLocalDb(
|
|||||||
databaseName: db.name,
|
databaseName: db.name,
|
||||||
dateAdded: db.dateAdded,
|
dateAdded: db.dateAdded,
|
||||||
language: db.language,
|
language: db.language,
|
||||||
|
origin: db.origin,
|
||||||
storagePath: db.storagePath,
|
storagePath: db.storagePath,
|
||||||
selected: !!selected,
|
selected: !!selected,
|
||||||
parentListName: listName,
|
parentListName: listName,
|
||||||
|
|||||||
@@ -367,6 +367,9 @@ export class DatabaseUI extends DisposableObject {
|
|||||||
|
|
||||||
await this.databaseManager.openDatabase(
|
await this.databaseManager.openDatabase(
|
||||||
uri,
|
uri,
|
||||||
|
{
|
||||||
|
type: "folder",
|
||||||
|
},
|
||||||
makeSelected,
|
makeSelected,
|
||||||
nameOverride,
|
nameOverride,
|
||||||
{
|
{
|
||||||
@@ -704,7 +707,9 @@ export class DatabaseUI extends DisposableObject {
|
|||||||
this.queryServer?.cliServer,
|
this.queryServer?.cliServer,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
await this.databaseManager.openDatabase(uri);
|
await this.databaseManager.openDatabase(uri, {
|
||||||
|
type: "folder",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// rethrow and let this be handled by default error handling.
|
// rethrow and let this be handled by default error handling.
|
||||||
@@ -819,7 +824,9 @@ export class DatabaseUI extends DisposableObject {
|
|||||||
if (byFolder) {
|
if (byFolder) {
|
||||||
const fixedUri = await this.fixDbUri(uri);
|
const fixedUri = await this.fixDbUri(uri);
|
||||||
// we are selecting a database folder
|
// we are selecting a database folder
|
||||||
return await this.databaseManager.openDatabase(fixedUri);
|
return await this.databaseManager.openDatabase(fixedUri, {
|
||||||
|
type: "folder",
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
// we are selecting a database archive. Must unzip into a workspace-controlled area
|
// we are selecting a database archive. Must unzip into a workspace-controlled area
|
||||||
// before importing.
|
// before importing.
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import { isLikelyDatabaseRoot } from "./db-contents-heuristics";
|
|||||||
import { stat } from "fs-extra";
|
import { stat } from "fs-extra";
|
||||||
import { containsPath, pathsEqual } from "../../common/files";
|
import { containsPath, pathsEqual } from "../../common/files";
|
||||||
import { DatabaseContents } from "./database-contents";
|
import { DatabaseContents } from "./database-contents";
|
||||||
|
import { DatabaseOrigin } from "./database-origin";
|
||||||
|
|
||||||
export class DatabaseItemImpl implements DatabaseItem {
|
export class DatabaseItemImpl implements DatabaseItem {
|
||||||
// These are only public in the implementation, they are readonly in the interface
|
// These are only public in the implementation, they are readonly in the interface
|
||||||
@@ -61,6 +62,10 @@ export class DatabaseItemImpl implements DatabaseItem {
|
|||||||
return this.options.dateAdded;
|
return this.options.dateAdded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get origin(): DatabaseOrigin | undefined {
|
||||||
|
return this.options.origin;
|
||||||
|
}
|
||||||
|
|
||||||
public resolveSourceFile(uriStr: string | undefined): vscode.Uri {
|
public resolveSourceFile(uriStr: string | undefined): vscode.Uri {
|
||||||
const sourceArchive = this.sourceArchive;
|
const sourceArchive = this.sourceArchive;
|
||||||
const uri = uriStr ? vscode.Uri.parse(uriStr, true) : undefined;
|
const uri = uriStr ? vscode.Uri.parse(uriStr, true) : undefined;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import vscode from "vscode";
|
|||||||
import * as cli from "../../codeql-cli/cli";
|
import * as cli from "../../codeql-cli/cli";
|
||||||
import { DatabaseContents } from "./database-contents";
|
import { DatabaseContents } from "./database-contents";
|
||||||
import { DatabaseOptions } from "./database-options";
|
import { DatabaseOptions } from "./database-options";
|
||||||
|
import { DatabaseOrigin } from "./database-origin";
|
||||||
|
|
||||||
/** An item in the list of available databases */
|
/** An item in the list of available databases */
|
||||||
export interface DatabaseItem {
|
export interface DatabaseItem {
|
||||||
@@ -25,6 +26,11 @@ export interface DatabaseItem {
|
|||||||
*/
|
*/
|
||||||
readonly dateAdded: number | undefined;
|
readonly dateAdded: number | undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The origin this database item was retrieved from or undefined if unknown.
|
||||||
|
*/
|
||||||
|
readonly origin: DatabaseOrigin | undefined;
|
||||||
|
|
||||||
/** If the database is invalid, describes why. */
|
/** If the database is invalid, describes why. */
|
||||||
readonly error: Error | undefined;
|
readonly error: Error | undefined;
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { QueryRunner } from "../../query-server";
|
|||||||
import * as cli from "../../codeql-cli/cli";
|
import * as cli from "../../codeql-cli/cli";
|
||||||
import { ProgressCallback, withProgress } from "../../common/vscode/progress";
|
import { ProgressCallback, withProgress } from "../../common/vscode/progress";
|
||||||
import {
|
import {
|
||||||
|
addDatabaseSourceToWorkspace,
|
||||||
getAutogenerateQlPacks,
|
getAutogenerateQlPacks,
|
||||||
isCodespacesTemplate,
|
isCodespacesTemplate,
|
||||||
setAutogenerateQlPacks,
|
setAutogenerateQlPacks,
|
||||||
@@ -34,6 +35,7 @@ import { DatabaseChangedEvent, DatabaseEventKind } from "./database-events";
|
|||||||
import { DatabaseResolver } from "./database-resolver";
|
import { DatabaseResolver } from "./database-resolver";
|
||||||
import { telemetryListener } from "../../common/vscode/telemetry";
|
import { telemetryListener } from "../../common/vscode/telemetry";
|
||||||
import { LanguageContextStore } from "../../language-context-store";
|
import { LanguageContextStore } from "../../language-context-store";
|
||||||
|
import { DatabaseOrigin } from "./database-origin";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the key in the workspaceState dictionary in which we
|
* The name of the key in the workspaceState dictionary in which we
|
||||||
@@ -115,7 +117,7 @@ export class DatabaseManager extends DisposableObject {
|
|||||||
this.languageContext.onLanguageContextChanged(async () => {
|
this.languageContext.onLanguageContextChanged(async () => {
|
||||||
if (
|
if (
|
||||||
this.currentDatabaseItem !== undefined &&
|
this.currentDatabaseItem !== undefined &&
|
||||||
!this.languageContext.isSelectedLanguage(
|
!this.languageContext.shouldInclude(
|
||||||
tryGetQueryLanguage(this.currentDatabaseItem.language),
|
tryGetQueryLanguage(this.currentDatabaseItem.language),
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
@@ -131,14 +133,19 @@ export class DatabaseManager extends DisposableObject {
|
|||||||
*/
|
*/
|
||||||
public async openDatabase(
|
public async openDatabase(
|
||||||
uri: vscode.Uri,
|
uri: vscode.Uri,
|
||||||
|
origin: DatabaseOrigin | undefined,
|
||||||
makeSelected = true,
|
makeSelected = true,
|
||||||
displayName?: string,
|
displayName?: string,
|
||||||
{
|
{
|
||||||
isTutorialDatabase = false,
|
isTutorialDatabase = false,
|
||||||
addSourceArchiveFolder = true,
|
addSourceArchiveFolder = addDatabaseSourceToWorkspace(),
|
||||||
}: OpenDatabaseOptions = {},
|
}: OpenDatabaseOptions = {},
|
||||||
): Promise<DatabaseItem> {
|
): Promise<DatabaseItem> {
|
||||||
const databaseItem = await this.createDatabaseItem(uri, displayName);
|
const databaseItem = await this.createDatabaseItem(
|
||||||
|
uri,
|
||||||
|
origin,
|
||||||
|
displayName,
|
||||||
|
);
|
||||||
|
|
||||||
return await this.addExistingDatabaseItem(
|
return await this.addExistingDatabaseItem(
|
||||||
databaseItem,
|
databaseItem,
|
||||||
@@ -158,7 +165,7 @@ export class DatabaseManager extends DisposableObject {
|
|||||||
databaseItem: DatabaseItemImpl,
|
databaseItem: DatabaseItemImpl,
|
||||||
makeSelected: boolean,
|
makeSelected: boolean,
|
||||||
isTutorialDatabase?: boolean,
|
isTutorialDatabase?: boolean,
|
||||||
addSourceArchiveFolder = true,
|
addSourceArchiveFolder = addDatabaseSourceToWorkspace(),
|
||||||
): Promise<DatabaseItem> {
|
): Promise<DatabaseItem> {
|
||||||
const existingItem = this.findDatabaseItem(databaseItem.databaseUri);
|
const existingItem = this.findDatabaseItem(databaseItem.databaseUri);
|
||||||
if (existingItem !== undefined) {
|
if (existingItem !== undefined) {
|
||||||
@@ -189,6 +196,7 @@ export class DatabaseManager extends DisposableObject {
|
|||||||
*/
|
*/
|
||||||
private async createDatabaseItem(
|
private async createDatabaseItem(
|
||||||
uri: vscode.Uri,
|
uri: vscode.Uri,
|
||||||
|
origin: DatabaseOrigin | undefined,
|
||||||
displayName: string | undefined,
|
displayName: string | undefined,
|
||||||
): Promise<DatabaseItemImpl> {
|
): Promise<DatabaseItemImpl> {
|
||||||
const contents = await DatabaseResolver.resolveDatabaseContents(uri);
|
const contents = await DatabaseResolver.resolveDatabaseContents(uri);
|
||||||
@@ -197,6 +205,7 @@ export class DatabaseManager extends DisposableObject {
|
|||||||
displayName,
|
displayName,
|
||||||
dateAdded: Date.now(),
|
dateAdded: Date.now(),
|
||||||
language: await this.getPrimaryLanguage(uri.fsPath),
|
language: await this.getPrimaryLanguage(uri.fsPath),
|
||||||
|
origin,
|
||||||
};
|
};
|
||||||
const databaseItem = new DatabaseItemImpl(uri, contents, fullOptions);
|
const databaseItem = new DatabaseItemImpl(uri, contents, fullOptions);
|
||||||
|
|
||||||
@@ -212,6 +221,7 @@ export class DatabaseManager extends DisposableObject {
|
|||||||
*/
|
*/
|
||||||
public async createOrOpenDatabaseItem(
|
public async createOrOpenDatabaseItem(
|
||||||
uri: vscode.Uri,
|
uri: vscode.Uri,
|
||||||
|
origin: DatabaseOrigin | undefined,
|
||||||
): Promise<DatabaseItem> {
|
): Promise<DatabaseItem> {
|
||||||
const existingItem = this.findDatabaseItem(uri);
|
const existingItem = this.findDatabaseItem(uri);
|
||||||
if (existingItem !== undefined) {
|
if (existingItem !== undefined) {
|
||||||
@@ -220,7 +230,7 @@ export class DatabaseManager extends DisposableObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We don't add this to the list automatically, but the user can add it later.
|
// We don't add this to the list automatically, but the user can add it later.
|
||||||
return this.createDatabaseItem(uri, undefined);
|
return this.createDatabaseItem(uri, origin, undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async createSkeletonPacks(databaseItem: DatabaseItem) {
|
public async createSkeletonPacks(databaseItem: DatabaseItem) {
|
||||||
@@ -355,6 +365,7 @@ export class DatabaseManager extends DisposableObject {
|
|||||||
let displayName: string | undefined = undefined;
|
let displayName: string | undefined = undefined;
|
||||||
let dateAdded = undefined;
|
let dateAdded = undefined;
|
||||||
let language = undefined;
|
let language = undefined;
|
||||||
|
let origin = undefined;
|
||||||
if (state.options) {
|
if (state.options) {
|
||||||
if (typeof state.options.displayName === "string") {
|
if (typeof state.options.displayName === "string") {
|
||||||
displayName = state.options.displayName;
|
displayName = state.options.displayName;
|
||||||
@@ -363,6 +374,7 @@ export class DatabaseManager extends DisposableObject {
|
|||||||
dateAdded = state.options.dateAdded;
|
dateAdded = state.options.dateAdded;
|
||||||
}
|
}
|
||||||
language = state.options.language;
|
language = state.options.language;
|
||||||
|
origin = state.options.origin;
|
||||||
}
|
}
|
||||||
|
|
||||||
const dbBaseUri = vscode.Uri.parse(state.uri, true);
|
const dbBaseUri = vscode.Uri.parse(state.uri, true);
|
||||||
@@ -375,6 +387,7 @@ export class DatabaseManager extends DisposableObject {
|
|||||||
displayName,
|
displayName,
|
||||||
dateAdded,
|
dateAdded,
|
||||||
language,
|
language,
|
||||||
|
origin,
|
||||||
};
|
};
|
||||||
const item = new DatabaseItemImpl(dbBaseUri, undefined, fullOptions);
|
const item = new DatabaseItemImpl(dbBaseUri, undefined, fullOptions);
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
|
import { DatabaseOrigin } from "./database-origin";
|
||||||
|
|
||||||
export interface DatabaseOptions {
|
export interface DatabaseOptions {
|
||||||
displayName?: string;
|
displayName?: string;
|
||||||
dateAdded?: number | undefined;
|
dateAdded?: number | undefined;
|
||||||
language?: string;
|
language?: string;
|
||||||
|
origin?: DatabaseOrigin;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FullDatabaseOptions extends DatabaseOptions {
|
export interface FullDatabaseOptions extends DatabaseOptions {
|
||||||
dateAdded: number | undefined;
|
dateAdded: number | undefined;
|
||||||
language: string | undefined;
|
language: string | undefined;
|
||||||
|
origin: DatabaseOrigin | undefined;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
interface DatabaseOriginFolder {
|
||||||
|
type: "folder";
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DatabaseOriginArchive {
|
||||||
|
type: "archive";
|
||||||
|
path: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DatabaseOriginGitHub {
|
||||||
|
type: "github";
|
||||||
|
repository: string;
|
||||||
|
databaseId: number;
|
||||||
|
databaseCreatedAt: string;
|
||||||
|
commitOid: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DatabaseOriginInternet {
|
||||||
|
type: "url";
|
||||||
|
url: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DatabaseOriginDebugger {
|
||||||
|
type: "debugger";
|
||||||
|
}
|
||||||
|
|
||||||
|
export type DatabaseOrigin =
|
||||||
|
| DatabaseOriginFolder
|
||||||
|
| DatabaseOriginArchive
|
||||||
|
| DatabaseOriginGitHub
|
||||||
|
| DatabaseOriginInternet
|
||||||
|
| DatabaseOriginDebugger;
|
||||||
@@ -105,7 +105,9 @@ class QLDebugAdapterTracker
|
|||||||
body: CodeQLProtocol.EvaluationStartedEvent["body"],
|
body: CodeQLProtocol.EvaluationStartedEvent["body"],
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const dbUri = Uri.file(this.configuration.database);
|
const dbUri = Uri.file(this.configuration.database);
|
||||||
const dbItem = await this.dbm.createOrOpenDatabaseItem(dbUri);
|
const dbItem = await this.dbm.createOrOpenDatabaseItem(dbUri, {
|
||||||
|
type: "debugger",
|
||||||
|
});
|
||||||
|
|
||||||
// When cancellation is requested from the query history view, we just stop the debug session.
|
// When cancellation is requested from the query history view, we just stop the debug session.
|
||||||
const tokenSource = new CancellationTokenSource();
|
const tokenSource = new CancellationTokenSource();
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { mkdir, writeFile } from "fs-extra";
|
import { ensureDir, writeFile } from "fs-extra";
|
||||||
import { dump } from "js-yaml";
|
import { dump } from "js-yaml";
|
||||||
import { dirname, join } from "path";
|
import { dirname, join } from "path";
|
||||||
import { Uri } from "vscode";
|
import { Uri } from "vscode";
|
||||||
@@ -76,7 +76,7 @@ export class QlPackGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async createWorkspaceFolder() {
|
private async createWorkspaceFolder() {
|
||||||
await mkdir(this.folderUri.fsPath);
|
await ensureDir(this.folderUri.fsPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async createQlPackYaml() {
|
private async createQlPackYaml() {
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { DisposableObject } from "../../common/disposable-object";
|
|||||||
import { MethodModelingViewProvider } from "./method-modeling-view-provider";
|
import { MethodModelingViewProvider } from "./method-modeling-view-provider";
|
||||||
import { Method } from "../method";
|
import { Method } from "../method";
|
||||||
import { ModelingStore } from "../modeling-store";
|
import { ModelingStore } from "../modeling-store";
|
||||||
import { ModelEditorViewTracker } from "../model-editor-view-tracker";
|
|
||||||
import { ModelConfigListener } from "../../config";
|
import { ModelConfigListener } from "../../config";
|
||||||
import { DatabaseItem } from "../../databases/local-databases";
|
import { DatabaseItem } from "../../databases/local-databases";
|
||||||
import { ModelingEvents } from "../modeling-events";
|
import { ModelingEvents } from "../modeling-events";
|
||||||
@@ -16,7 +15,6 @@ export class MethodModelingPanel extends DisposableObject {
|
|||||||
app: App,
|
app: App,
|
||||||
modelingStore: ModelingStore,
|
modelingStore: ModelingStore,
|
||||||
modelingEvents: ModelingEvents,
|
modelingEvents: ModelingEvents,
|
||||||
editorViewTracker: ModelEditorViewTracker,
|
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
@@ -29,7 +27,6 @@ export class MethodModelingPanel extends DisposableObject {
|
|||||||
app,
|
app,
|
||||||
modelingStore,
|
modelingStore,
|
||||||
modelingEvents,
|
modelingEvents,
|
||||||
editorViewTracker,
|
|
||||||
modelConfig,
|
modelConfig,
|
||||||
);
|
);
|
||||||
this.push(
|
this.push(
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import { Method } from "../method";
|
|||||||
import { ModelingStore } from "../modeling-store";
|
import { ModelingStore } from "../modeling-store";
|
||||||
import { AbstractWebviewViewProvider } from "../../common/vscode/abstract-webview-view-provider";
|
import { AbstractWebviewViewProvider } from "../../common/vscode/abstract-webview-view-provider";
|
||||||
import { assertNever } from "../../common/helpers-pure";
|
import { assertNever } from "../../common/helpers-pure";
|
||||||
import { ModelEditorViewTracker } from "../model-editor-view-tracker";
|
|
||||||
import { ModelConfigListener } from "../../config";
|
import { ModelConfigListener } from "../../config";
|
||||||
import { DatabaseItem } from "../../databases/local-databases";
|
import { DatabaseItem } from "../../databases/local-databases";
|
||||||
import { ModelingEvents } from "../modeling-events";
|
import { ModelingEvents } from "../modeling-events";
|
||||||
@@ -33,7 +32,6 @@ export class MethodModelingViewProvider extends AbstractWebviewViewProvider<
|
|||||||
app: App,
|
app: App,
|
||||||
private readonly modelingStore: ModelingStore,
|
private readonly modelingStore: ModelingStore,
|
||||||
private readonly modelingEvents: ModelingEvents,
|
private readonly modelingEvents: ModelingEvents,
|
||||||
private readonly editorViewTracker: ModelEditorViewTracker,
|
|
||||||
private readonly modelConfig: ModelConfigListener,
|
private readonly modelConfig: ModelConfigListener,
|
||||||
) {
|
) {
|
||||||
super(app, "method-modeling");
|
super(app, "method-modeling");
|
||||||
@@ -158,10 +156,10 @@ export class MethodModelingViewProvider extends AbstractWebviewViewProvider<
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const view = this.editorViewTracker.getView(
|
this.modelingEvents.fireRevealInModelEditorEvent(
|
||||||
this.databaseItem.databaseUri.toString(),
|
this.databaseItem.databaseUri.toString(),
|
||||||
|
method,
|
||||||
);
|
);
|
||||||
await view?.revealMethod(method);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private registerToModelingEvents(): void {
|
private registerToModelingEvents(): void {
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import { setUpPack } from "./model-editor-queries-setup";
|
|||||||
import { MethodModelingPanel } from "./method-modeling/method-modeling-panel";
|
import { MethodModelingPanel } from "./method-modeling/method-modeling-panel";
|
||||||
import { ModelingStore } from "./modeling-store";
|
import { ModelingStore } from "./modeling-store";
|
||||||
import { showResolvableLocation } from "../databases/local-databases/locations";
|
import { showResolvableLocation } from "../databases/local-databases/locations";
|
||||||
import { ModelEditorViewTracker } from "./model-editor-view-tracker";
|
|
||||||
import { ModelConfigListener } from "../config";
|
import { ModelConfigListener } from "../config";
|
||||||
import { ModelingEvents } from "./modeling-events";
|
import { ModelingEvents } from "./modeling-events";
|
||||||
import { getModelsAsDataLanguage } from "./languages";
|
import { getModelsAsDataLanguage } from "./languages";
|
||||||
@@ -30,7 +29,6 @@ export class ModelEditorModule extends DisposableObject {
|
|||||||
private readonly queryStorageDir: string;
|
private readonly queryStorageDir: string;
|
||||||
private readonly modelingStore: ModelingStore;
|
private readonly modelingStore: ModelingStore;
|
||||||
private readonly modelingEvents: ModelingEvents;
|
private readonly modelingEvents: ModelingEvents;
|
||||||
private readonly editorViewTracker: ModelEditorViewTracker<ModelEditorView>;
|
|
||||||
private readonly methodsUsagePanel: MethodsUsagePanel;
|
private readonly methodsUsagePanel: MethodsUsagePanel;
|
||||||
private readonly methodModelingPanel: MethodModelingPanel;
|
private readonly methodModelingPanel: MethodModelingPanel;
|
||||||
private readonly modelConfig: ModelConfigListener;
|
private readonly modelConfig: ModelConfigListener;
|
||||||
@@ -46,17 +44,11 @@ export class ModelEditorModule extends DisposableObject {
|
|||||||
this.queryStorageDir = join(baseQueryStorageDir, "model-editor-results");
|
this.queryStorageDir = join(baseQueryStorageDir, "model-editor-results");
|
||||||
this.modelingEvents = new ModelingEvents(app);
|
this.modelingEvents = new ModelingEvents(app);
|
||||||
this.modelingStore = new ModelingStore(this.modelingEvents);
|
this.modelingStore = new ModelingStore(this.modelingEvents);
|
||||||
this.editorViewTracker = new ModelEditorViewTracker();
|
|
||||||
this.methodsUsagePanel = this.push(
|
this.methodsUsagePanel = this.push(
|
||||||
new MethodsUsagePanel(this.modelingStore, this.modelingEvents, cliServer),
|
new MethodsUsagePanel(this.modelingStore, this.modelingEvents, cliServer),
|
||||||
);
|
);
|
||||||
this.methodModelingPanel = this.push(
|
this.methodModelingPanel = this.push(
|
||||||
new MethodModelingPanel(
|
new MethodModelingPanel(app, this.modelingStore, this.modelingEvents),
|
||||||
app,
|
|
||||||
this.modelingStore,
|
|
||||||
this.modelingEvents,
|
|
||||||
this.editorViewTracker,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
this.modelConfig = this.push(new ModelConfigListener());
|
this.modelConfig = this.push(new ModelConfigListener());
|
||||||
|
|
||||||
@@ -144,12 +136,10 @@ export class ModelEditorModule extends DisposableObject {
|
|||||||
|
|
||||||
const initialMode = definition.availableModes?.[0] ?? INITIAL_MODE;
|
const initialMode = definition.availableModes?.[0] ?? INITIAL_MODE;
|
||||||
|
|
||||||
const existingView = this.editorViewTracker.getView(
|
if (this.modelingStore.isDbOpen(db.databaseUri.toString())) {
|
||||||
db.databaseUri.toString(),
|
this.modelingEvents.fireFocusModelEditorEvent(
|
||||||
);
|
db.databaseUri.toString(),
|
||||||
if (existingView) {
|
);
|
||||||
await existingView.focusView();
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,12 +208,10 @@ export class ModelEditorModule extends DisposableObject {
|
|||||||
|
|
||||||
// Check again just before opening the editor to ensure no model editor has been opened between
|
// Check again just before opening the editor to ensure no model editor has been opened between
|
||||||
// our first check and now.
|
// our first check and now.
|
||||||
const existingView = this.editorViewTracker.getView(
|
if (this.modelingStore.isDbOpen(db.databaseUri.toString())) {
|
||||||
db.databaseUri.toString(),
|
this.modelingEvents.fireFocusModelEditorEvent(
|
||||||
);
|
db.databaseUri.toString(),
|
||||||
if (existingView) {
|
);
|
||||||
await existingView.focusView();
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,7 +219,6 @@ export class ModelEditorModule extends DisposableObject {
|
|||||||
this.app,
|
this.app,
|
||||||
this.modelingStore,
|
this.modelingStore,
|
||||||
this.modelingEvents,
|
this.modelingEvents,
|
||||||
this.editorViewTracker,
|
|
||||||
this.modelConfig,
|
this.modelConfig,
|
||||||
this.databaseManager,
|
this.databaseManager,
|
||||||
this.cliServer,
|
this.cliServer,
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
import { Method } from "./method";
|
|
||||||
|
|
||||||
interface ModelEditorViewInterface {
|
|
||||||
databaseUri: string;
|
|
||||||
|
|
||||||
revealMethod(method: Method): Promise<void>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ModelEditorViewTracker<
|
|
||||||
T extends ModelEditorViewInterface = ModelEditorViewInterface,
|
|
||||||
> {
|
|
||||||
private readonly views = new Map<string, T>();
|
|
||||||
|
|
||||||
constructor() {}
|
|
||||||
|
|
||||||
public registerView(view: T): void {
|
|
||||||
const databaseUri = view.databaseUri;
|
|
||||||
|
|
||||||
if (this.views.has(databaseUri)) {
|
|
||||||
throw new Error(`View for database ${databaseUri} already registered`);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.views.set(databaseUri, view);
|
|
||||||
}
|
|
||||||
|
|
||||||
public unregisterView(view: T): void {
|
|
||||||
this.views.delete(view.databaseUri);
|
|
||||||
}
|
|
||||||
|
|
||||||
public getView(databaseUri: string): T | undefined {
|
|
||||||
return this.views.get(databaseUri);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -44,7 +44,6 @@ import {
|
|||||||
import { AutoModeler } from "./auto-modeler";
|
import { AutoModeler } from "./auto-modeler";
|
||||||
import { telemetryListener } from "../common/vscode/telemetry";
|
import { telemetryListener } from "../common/vscode/telemetry";
|
||||||
import { ModelingStore } from "./modeling-store";
|
import { ModelingStore } from "./modeling-store";
|
||||||
import { ModelEditorViewTracker } from "./model-editor-view-tracker";
|
|
||||||
import { ModelingEvents } from "./modeling-events";
|
import { ModelingEvents } from "./modeling-events";
|
||||||
import { getModelsAsDataLanguage, ModelsAsDataLanguage } from "./languages";
|
import { getModelsAsDataLanguage, ModelsAsDataLanguage } from "./languages";
|
||||||
import { runGenerateQueries } from "./generate";
|
import { runGenerateQueries } from "./generate";
|
||||||
@@ -60,7 +59,6 @@ export class ModelEditorView extends AbstractWebview<
|
|||||||
protected readonly app: App,
|
protected readonly app: App,
|
||||||
private readonly modelingStore: ModelingStore,
|
private readonly modelingStore: ModelingStore,
|
||||||
private readonly modelingEvents: ModelingEvents,
|
private readonly modelingEvents: ModelingEvents,
|
||||||
private readonly viewTracker: ModelEditorViewTracker<ModelEditorView>,
|
|
||||||
private readonly modelConfig: ModelConfigListener,
|
private readonly modelConfig: ModelConfigListener,
|
||||||
private readonly databaseManager: DatabaseManager,
|
private readonly databaseManager: DatabaseManager,
|
||||||
private readonly cliServer: CodeQLCliServer,
|
private readonly cliServer: CodeQLCliServer,
|
||||||
@@ -79,8 +77,6 @@ export class ModelEditorView extends AbstractWebview<
|
|||||||
this.registerToModelingEvents();
|
this.registerToModelingEvents();
|
||||||
this.registerToModelConfigEvents();
|
this.registerToModelConfigEvents();
|
||||||
|
|
||||||
this.viewTracker.registerView(this);
|
|
||||||
|
|
||||||
this.autoModeler = new AutoModeler(
|
this.autoModeler = new AutoModeler(
|
||||||
app,
|
app,
|
||||||
cliServer,
|
cliServer,
|
||||||
@@ -166,7 +162,7 @@ export class ModelEditorView extends AbstractWebview<
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected onPanelDispose(): void {
|
protected onPanelDispose(): void {
|
||||||
this.viewTracker.unregisterView(this);
|
// Nothing to do
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async onMessage(msg: FromModelEditorMessage): Promise<void> {
|
protected async onMessage(msg: FromModelEditorMessage): Promise<void> {
|
||||||
@@ -573,12 +569,9 @@ export class ModelEditorView extends AbstractWebview<
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let existingView = this.viewTracker.getView(
|
const addedDbUri = addedDatabase.databaseUri.toString();
|
||||||
addedDatabase.databaseUri.toString(),
|
if (this.modelingStore.isDbOpen(addedDbUri)) {
|
||||||
);
|
this.modelingEvents.fireFocusModelEditorEvent(addedDbUri);
|
||||||
if (existingView) {
|
|
||||||
await existingView.focusView();
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -596,12 +589,8 @@ export class ModelEditorView extends AbstractWebview<
|
|||||||
|
|
||||||
// Check again just before opening the editor to ensure no model editor has been opened between
|
// Check again just before opening the editor to ensure no model editor has been opened between
|
||||||
// our first check and now.
|
// our first check and now.
|
||||||
existingView = this.viewTracker.getView(
|
if (this.modelingStore.isDbOpen(addedDbUri)) {
|
||||||
addedDatabase.databaseUri.toString(),
|
this.modelingEvents.fireFocusModelEditorEvent(addedDbUri);
|
||||||
);
|
|
||||||
if (existingView) {
|
|
||||||
await existingView.focusView();
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -609,7 +598,6 @@ export class ModelEditorView extends AbstractWebview<
|
|||||||
this.app,
|
this.app,
|
||||||
this.modelingStore,
|
this.modelingStore,
|
||||||
this.modelingEvents,
|
this.modelingEvents,
|
||||||
this.viewTracker,
|
|
||||||
this.modelConfig,
|
this.modelConfig,
|
||||||
this.databaseManager,
|
this.databaseManager,
|
||||||
this.cliServer,
|
this.cliServer,
|
||||||
@@ -742,6 +730,22 @@ export class ModelEditorView extends AbstractWebview<
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.push(
|
||||||
|
this.modelingEvents.onRevealInModelEditor(async (event) => {
|
||||||
|
if (event.dbUri === this.databaseItem.databaseUri.toString()) {
|
||||||
|
await this.revealMethod(event.method);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
this.push(
|
||||||
|
this.modelingEvents.onFocusModelEditor(async (event) => {
|
||||||
|
if (event.dbUri === this.databaseItem.databaseUri.toString()) {
|
||||||
|
await this.focusView();
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private registerToModelConfigEvents() {
|
private registerToModelConfigEvents() {
|
||||||
|
|||||||
@@ -126,3 +126,38 @@ export function isModelAccepted(
|
|||||||
modeledMethod.provenance !== "ai-generated"
|
modeledMethod.provenance !== "ai-generated"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the new provenance for a modeled method based on the current provenance.
|
||||||
|
* @param modeledMethod The modeled method if there is one.
|
||||||
|
* @returns The new provenance.
|
||||||
|
*/
|
||||||
|
export function calculateNewProvenance(
|
||||||
|
modeledMethod: ModeledMethod | undefined,
|
||||||
|
) {
|
||||||
|
if (!modeledMethod || !modeledMethodSupportsProvenance(modeledMethod)) {
|
||||||
|
// If nothing has been modeled or the modeled method does not support
|
||||||
|
// provenance, we assume that the user has entered it manually.
|
||||||
|
return "manual";
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (modeledMethod.provenance) {
|
||||||
|
case "df-generated":
|
||||||
|
// If the method has been generated and there has been a change, we assume
|
||||||
|
// that the user has manually edited it.
|
||||||
|
return "df-manual";
|
||||||
|
case "df-manual":
|
||||||
|
// If the method has had manual edits, we want the provenance to stay the same.
|
||||||
|
return "df-manual";
|
||||||
|
case "ai-generated":
|
||||||
|
// If the method has been generated and there has been a change, we assume
|
||||||
|
// that the user has manually edited it.
|
||||||
|
return "ai-manual";
|
||||||
|
case "ai-manual":
|
||||||
|
// If the method has had manual edits, we want the provenance to stay the same.
|
||||||
|
return "ai-manual";
|
||||||
|
default:
|
||||||
|
// The method has been modeled manually.
|
||||||
|
return "manual";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -48,6 +48,15 @@ interface InProgressMethodsChangedEvent {
|
|||||||
readonly methods: ReadonlySet<string>;
|
readonly methods: ReadonlySet<string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface RevealInModelEditorEvent {
|
||||||
|
dbUri: string;
|
||||||
|
method: Method;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FocusModelEditorEvent {
|
||||||
|
dbUri: string;
|
||||||
|
}
|
||||||
|
|
||||||
export class ModelingEvents extends DisposableObject {
|
export class ModelingEvents extends DisposableObject {
|
||||||
public readonly onActiveDbChanged: AppEvent<void>;
|
public readonly onActiveDbChanged: AppEvent<void>;
|
||||||
public readonly onDbOpened: AppEvent<DatabaseItem>;
|
public readonly onDbOpened: AppEvent<DatabaseItem>;
|
||||||
@@ -59,6 +68,8 @@ export class ModelingEvents extends DisposableObject {
|
|||||||
public readonly onModifiedMethodsChanged: AppEvent<ModifiedMethodsChangedEvent>;
|
public readonly onModifiedMethodsChanged: AppEvent<ModifiedMethodsChangedEvent>;
|
||||||
public readonly onSelectedMethodChanged: AppEvent<SelectedMethodChangedEvent>;
|
public readonly onSelectedMethodChanged: AppEvent<SelectedMethodChangedEvent>;
|
||||||
public readonly onInProgressMethodsChanged: AppEvent<InProgressMethodsChangedEvent>;
|
public readonly onInProgressMethodsChanged: AppEvent<InProgressMethodsChangedEvent>;
|
||||||
|
public readonly onRevealInModelEditor: AppEvent<RevealInModelEditorEvent>;
|
||||||
|
public readonly onFocusModelEditor: AppEvent<FocusModelEditorEvent>;
|
||||||
|
|
||||||
private readonly onActiveDbChangedEventEmitter: AppEventEmitter<void>;
|
private readonly onActiveDbChangedEventEmitter: AppEventEmitter<void>;
|
||||||
private readonly onDbOpenedEventEmitter: AppEventEmitter<DatabaseItem>;
|
private readonly onDbOpenedEventEmitter: AppEventEmitter<DatabaseItem>;
|
||||||
@@ -70,6 +81,8 @@ export class ModelingEvents extends DisposableObject {
|
|||||||
private readonly onModifiedMethodsChangedEventEmitter: AppEventEmitter<ModifiedMethodsChangedEvent>;
|
private readonly onModifiedMethodsChangedEventEmitter: AppEventEmitter<ModifiedMethodsChangedEvent>;
|
||||||
private readonly onSelectedMethodChangedEventEmitter: AppEventEmitter<SelectedMethodChangedEvent>;
|
private readonly onSelectedMethodChangedEventEmitter: AppEventEmitter<SelectedMethodChangedEvent>;
|
||||||
private readonly onInProgressMethodsChangedEventEmitter: AppEventEmitter<InProgressMethodsChangedEvent>;
|
private readonly onInProgressMethodsChangedEventEmitter: AppEventEmitter<InProgressMethodsChangedEvent>;
|
||||||
|
private readonly onRevealInModelEditorEventEmitter: AppEventEmitter<RevealInModelEditorEvent>;
|
||||||
|
private readonly onFocusModelEditorEventEmitter: AppEventEmitter<FocusModelEditorEvent>;
|
||||||
|
|
||||||
constructor(app: App) {
|
constructor(app: App) {
|
||||||
super();
|
super();
|
||||||
@@ -126,6 +139,16 @@ export class ModelingEvents extends DisposableObject {
|
|||||||
);
|
);
|
||||||
this.onInProgressMethodsChanged =
|
this.onInProgressMethodsChanged =
|
||||||
this.onInProgressMethodsChangedEventEmitter.event;
|
this.onInProgressMethodsChangedEventEmitter.event;
|
||||||
|
|
||||||
|
this.onRevealInModelEditorEventEmitter = this.push(
|
||||||
|
app.createEventEmitter<RevealInModelEditorEvent>(),
|
||||||
|
);
|
||||||
|
this.onRevealInModelEditor = this.onRevealInModelEditorEventEmitter.event;
|
||||||
|
|
||||||
|
this.onFocusModelEditorEventEmitter = this.push(
|
||||||
|
app.createEventEmitter<FocusModelEditorEvent>(),
|
||||||
|
);
|
||||||
|
this.onFocusModelEditor = this.onFocusModelEditorEventEmitter.event;
|
||||||
}
|
}
|
||||||
|
|
||||||
public fireActiveDbChangedEvent() {
|
public fireActiveDbChangedEvent() {
|
||||||
@@ -220,4 +243,17 @@ export class ModelingEvents extends DisposableObject {
|
|||||||
methods,
|
methods,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fireRevealInModelEditorEvent(dbUri: string, method: Method) {
|
||||||
|
this.onRevealInModelEditorEventEmitter.fire({
|
||||||
|
dbUri,
|
||||||
|
method,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public fireFocusModelEditorEvent(dbUri: string) {
|
||||||
|
this.onFocusModelEditorEventEmitter.fire({
|
||||||
|
dbUri,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,6 +112,10 @@ export class ModelingStore extends DisposableObject {
|
|||||||
return this.state.size > 0;
|
return this.state.size > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public isDbOpen(dbUri: string): boolean {
|
||||||
|
return this.state.has(dbUri);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the method for the given database item and method signature.
|
* Returns the method for the given database item and method signature.
|
||||||
* Returns undefined if no method exists with that signature.
|
* Returns undefined if no method exists with that signature.
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { CodeQLCliServer } from "../codeql-cli/cli";
|
import { CodeQLCliServer } from "../codeql-cli/cli";
|
||||||
import { extLogger } from "../common/logging/vscode";
|
import { extLogger } from "../common/logging/vscode";
|
||||||
import { App } from "../common/app";
|
import { App } from "../common/app";
|
||||||
import { isCanary, showQueriesPanel } from "../config";
|
|
||||||
import { DisposableObject } from "../common/disposable-object";
|
import { DisposableObject } from "../common/disposable-object";
|
||||||
import { QueriesPanel } from "./queries-panel";
|
import { QueriesPanel } from "./queries-panel";
|
||||||
import { QueryDiscovery } from "./query-discovery";
|
import { QueryDiscovery } from "./query-discovery";
|
||||||
@@ -41,11 +40,6 @@ export class QueriesModule extends DisposableObject {
|
|||||||
langauageContext: LanguageContextStore,
|
langauageContext: LanguageContextStore,
|
||||||
cliServer: CodeQLCliServer,
|
cliServer: CodeQLCliServer,
|
||||||
): void {
|
): void {
|
||||||
// Currently, we only want to expose the new panel when we are in canary mode
|
|
||||||
// and the user has enabled the "Show queries panel" flag.
|
|
||||||
if (!isCanary() || !showQueriesPanel()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
void extLogger.log("Initializing queries panel.");
|
void extLogger.log("Initializing queries panel.");
|
||||||
|
|
||||||
const queryPackDiscovery = new QueryPackDiscovery(cliServer);
|
const queryPackDiscovery = new QueryPackDiscovery(cliServer);
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ export class TestRunner extends DisposableObject {
|
|||||||
try {
|
try {
|
||||||
const reopenedDatabase = await this.databaseManager.openDatabase(
|
const reopenedDatabase = await this.databaseManager.openDatabase(
|
||||||
uri,
|
uri,
|
||||||
|
closedDatabase.origin,
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
await this.databaseManager.renameDatabaseItem(
|
await this.databaseManager.renameDatabaseItem(
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import * as React from "react";
|
|||||||
import { ChangeEvent, useCallback, useMemo } from "react";
|
import { ChangeEvent, useCallback, useMemo } from "react";
|
||||||
import {
|
import {
|
||||||
ModeledMethod,
|
ModeledMethod,
|
||||||
|
calculateNewProvenance,
|
||||||
isModelAccepted,
|
isModelAccepted,
|
||||||
modeledMethodSupportsInput,
|
modeledMethodSupportsInput,
|
||||||
} from "../../model-editor/modeled-method";
|
} from "../../model-editor/modeled-method";
|
||||||
@@ -53,6 +54,7 @@ export const ModelInputDropdown = ({
|
|||||||
|
|
||||||
onChange({
|
onChange({
|
||||||
...modeledMethod,
|
...modeledMethod,
|
||||||
|
provenance: calculateNewProvenance(modeledMethod),
|
||||||
input: target.value,
|
input: target.value,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
ModeledMethodKind,
|
ModeledMethodKind,
|
||||||
modeledMethodSupportsKind,
|
modeledMethodSupportsKind,
|
||||||
isModelAccepted,
|
isModelAccepted,
|
||||||
|
calculateNewProvenance,
|
||||||
} from "../../model-editor/modeled-method";
|
} from "../../model-editor/modeled-method";
|
||||||
import { getModelsAsDataLanguage } from "../../model-editor/languages";
|
import { getModelsAsDataLanguage } from "../../model-editor/languages";
|
||||||
import { QueryLanguage } from "../../common/query-language";
|
import { QueryLanguage } from "../../common/query-language";
|
||||||
@@ -52,6 +53,7 @@ export const ModelKindDropdown = ({
|
|||||||
|
|
||||||
onChange({
|
onChange({
|
||||||
...modeledMethod,
|
...modeledMethod,
|
||||||
|
provenance: calculateNewProvenance(modeledMethod),
|
||||||
kind,
|
kind,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import * as React from "react";
|
|||||||
import { ChangeEvent, useCallback, useMemo } from "react";
|
import { ChangeEvent, useCallback, useMemo } from "react";
|
||||||
import {
|
import {
|
||||||
ModeledMethod,
|
ModeledMethod,
|
||||||
|
calculateNewProvenance,
|
||||||
isModelAccepted,
|
isModelAccepted,
|
||||||
modeledMethodSupportsOutput,
|
modeledMethodSupportsOutput,
|
||||||
} from "../../model-editor/modeled-method";
|
} from "../../model-editor/modeled-method";
|
||||||
@@ -54,6 +55,7 @@ export const ModelOutputDropdown = ({
|
|||||||
|
|
||||||
onChange({
|
onChange({
|
||||||
...modeledMethod,
|
...modeledMethod,
|
||||||
|
provenance: calculateNewProvenance(modeledMethod),
|
||||||
output: target.value,
|
output: target.value,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { ChangeEvent, useCallback } from "react";
|
import { ChangeEvent, useCallback } from "react";
|
||||||
import {
|
import {
|
||||||
|
calculateNewProvenance,
|
||||||
isModelAccepted,
|
isModelAccepted,
|
||||||
ModeledMethod,
|
ModeledMethod,
|
||||||
modeledMethodSupportsProvenance,
|
|
||||||
ModeledMethodType,
|
ModeledMethodType,
|
||||||
Provenance,
|
|
||||||
} from "../../model-editor/modeled-method";
|
} from "../../model-editor/modeled-method";
|
||||||
import { Method } from "../../model-editor/method";
|
import { Method } from "../../model-editor/method";
|
||||||
import { createEmptyModeledMethod } from "../../model-editor/modeled-method-empty";
|
import { createEmptyModeledMethod } from "../../model-editor/modeled-method-empty";
|
||||||
@@ -43,15 +42,6 @@ export const ModelTypeDropdown = ({
|
|||||||
(e: ChangeEvent<HTMLSelectElement>) => {
|
(e: ChangeEvent<HTMLSelectElement>) => {
|
||||||
const modelsAsDataLanguage = getModelsAsDataLanguage(language);
|
const modelsAsDataLanguage = getModelsAsDataLanguage(language);
|
||||||
|
|
||||||
let newProvenance: Provenance = "manual";
|
|
||||||
if (modeledMethod && modeledMethodSupportsProvenance(modeledMethod)) {
|
|
||||||
if (modeledMethod.provenance === "df-generated") {
|
|
||||||
newProvenance = "df-manual";
|
|
||||||
} else if (modeledMethod.provenance === "ai-generated") {
|
|
||||||
newProvenance = "ai-manual";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const emptyModeledMethod = createEmptyModeledMethod(
|
const emptyModeledMethod = createEmptyModeledMethod(
|
||||||
e.target.value as ModeledMethodType,
|
e.target.value as ModeledMethodType,
|
||||||
method,
|
method,
|
||||||
@@ -67,7 +57,7 @@ export const ModelTypeDropdown = ({
|
|||||||
updatedModeledMethod.output = "ReturnValue";
|
updatedModeledMethod.output = "ReturnValue";
|
||||||
}
|
}
|
||||||
if ("provenance" in updatedModeledMethod) {
|
if ("provenance" in updatedModeledMethod) {
|
||||||
updatedModeledMethod.provenance = newProvenance;
|
updatedModeledMethod.provenance = calculateNewProvenance(modeledMethod);
|
||||||
}
|
}
|
||||||
if ("kind" in updatedModeledMethod) {
|
if ("kind" in updatedModeledMethod) {
|
||||||
updatedModeledMethod.kind = "value";
|
updatedModeledMethod.kind = "value";
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ describe(MethodRow.name, () => {
|
|||||||
input: "Argument[0]",
|
input: "Argument[0]",
|
||||||
output: "ReturnValue",
|
output: "ReturnValue",
|
||||||
kind: "taint",
|
kind: "taint",
|
||||||
provenance: "df-generated",
|
provenance: "manual",
|
||||||
};
|
};
|
||||||
const onChange = jest.fn();
|
const onChange = jest.fn();
|
||||||
|
|
||||||
@@ -111,6 +111,32 @@ describe(MethodRow.name, () => {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("changes the provenance when the kind is changed", async () => {
|
||||||
|
const modeledMethodWithGeneratedProvenance: ModeledMethod = {
|
||||||
|
...modeledMethod,
|
||||||
|
provenance: "df-generated",
|
||||||
|
};
|
||||||
|
render({ modeledMethods: [modeledMethodWithGeneratedProvenance] });
|
||||||
|
|
||||||
|
onChange.mockReset();
|
||||||
|
|
||||||
|
expect(screen.getByRole("combobox", { name: "Kind" })).toHaveValue("taint");
|
||||||
|
|
||||||
|
await userEvent.selectOptions(
|
||||||
|
screen.getByRole("combobox", { name: "Kind" }),
|
||||||
|
"value",
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(onChange).toHaveBeenCalledTimes(1);
|
||||||
|
expect(onChange).toHaveBeenCalledWith(method.signature, [
|
||||||
|
{
|
||||||
|
...modeledMethod,
|
||||||
|
kind: "value",
|
||||||
|
provenance: "df-manual",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
it("has the correct input options", () => {
|
it("has the correct input options", () => {
|
||||||
render();
|
render();
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[
|
[
|
||||||
"v2.15.1",
|
"v2.15.2",
|
||||||
"v2.14.6",
|
"v2.14.6",
|
||||||
"v2.13.5",
|
"v2.13.5",
|
||||||
"v2.12.7",
|
"v2.12.7",
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
import { mockedObject } from "../../vscode-tests/utils/mocking.helpers";
|
|
||||||
import { ModelEditorViewTracker } from "../../../src/model-editor/model-editor-view-tracker";
|
|
||||||
import { ModelEditorView } from "../../../src/model-editor/model-editor-view";
|
|
||||||
|
|
||||||
export function createMockModelEditorViewTracker({
|
|
||||||
registerView = jest.fn(),
|
|
||||||
unregisterView = jest.fn(),
|
|
||||||
getView = jest.fn(),
|
|
||||||
}: {
|
|
||||||
registerView?: ModelEditorViewTracker["registerView"];
|
|
||||||
unregisterView?: ModelEditorViewTracker["unregisterView"];
|
|
||||||
getView?: ModelEditorViewTracker["getView"];
|
|
||||||
} = {}): ModelEditorViewTracker<ModelEditorView> {
|
|
||||||
return mockedObject<ModelEditorViewTracker<ModelEditorView>>({
|
|
||||||
registerView,
|
|
||||||
unregisterView,
|
|
||||||
getView,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -10,6 +10,8 @@ export function createMockModelingEvents({
|
|||||||
onModeledMethodsChanged = jest.fn(),
|
onModeledMethodsChanged = jest.fn(),
|
||||||
onModifiedMethodsChanged = jest.fn(),
|
onModifiedMethodsChanged = jest.fn(),
|
||||||
onInProgressMethodsChanged = jest.fn(),
|
onInProgressMethodsChanged = jest.fn(),
|
||||||
|
onRevealInModelEditor = jest.fn(),
|
||||||
|
onFocusModelEditor = jest.fn(),
|
||||||
}: {
|
}: {
|
||||||
onActiveDbChanged?: ModelingEvents["onActiveDbChanged"];
|
onActiveDbChanged?: ModelingEvents["onActiveDbChanged"];
|
||||||
onDbClosed?: ModelingEvents["onDbClosed"];
|
onDbClosed?: ModelingEvents["onDbClosed"];
|
||||||
@@ -19,6 +21,8 @@ export function createMockModelingEvents({
|
|||||||
onModeledMethodsChanged?: ModelingEvents["onModeledMethodsChanged"];
|
onModeledMethodsChanged?: ModelingEvents["onModeledMethodsChanged"];
|
||||||
onModifiedMethodsChanged?: ModelingEvents["onModifiedMethodsChanged"];
|
onModifiedMethodsChanged?: ModelingEvents["onModifiedMethodsChanged"];
|
||||||
onInProgressMethodsChanged?: ModelingEvents["onInProgressMethodsChanged"];
|
onInProgressMethodsChanged?: ModelingEvents["onInProgressMethodsChanged"];
|
||||||
|
onRevealInModelEditor?: ModelingEvents["onRevealInModelEditor"];
|
||||||
|
onFocusModelEditor?: ModelingEvents["onFocusModelEditor"];
|
||||||
} = {}): ModelingEvents {
|
} = {}): ModelingEvents {
|
||||||
return mockedObject<ModelingEvents>({
|
return mockedObject<ModelingEvents>({
|
||||||
onActiveDbChanged,
|
onActiveDbChanged,
|
||||||
@@ -29,5 +33,7 @@ export function createMockModelingEvents({
|
|||||||
onModeledMethodsChanged,
|
onModeledMethodsChanged,
|
||||||
onModifiedMethodsChanged,
|
onModifiedMethodsChanged,
|
||||||
onInProgressMethodsChanged,
|
onInProgressMethodsChanged,
|
||||||
|
onRevealInModelEditor,
|
||||||
|
onFocusModelEditor,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ export function mockDbOptions(): FullDatabaseOptions {
|
|||||||
return {
|
return {
|
||||||
dateAdded: 123,
|
dateAdded: 123,
|
||||||
language: "",
|
language: "",
|
||||||
|
origin: {
|
||||||
|
type: "folder",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
SelectedDbItem,
|
SelectedDbItem,
|
||||||
DB_CONFIG_VERSION,
|
DB_CONFIG_VERSION,
|
||||||
} from "../../src/databases/config/db-config";
|
} from "../../src/databases/config/db-config";
|
||||||
|
import { DatabaseOrigin } from "../../src/databases/local-databases/database-origin";
|
||||||
|
|
||||||
export function createDbConfig({
|
export function createDbConfig({
|
||||||
remoteLists = [],
|
remoteLists = [],
|
||||||
@@ -45,16 +46,21 @@ export function createLocalDbConfigItem({
|
|||||||
dateAdded = faker.date.past().getTime(),
|
dateAdded = faker.date.past().getTime(),
|
||||||
language = `language${faker.number.int()}`,
|
language = `language${faker.number.int()}`,
|
||||||
storagePath = `storagePath${faker.number.int()}`,
|
storagePath = `storagePath${faker.number.int()}`,
|
||||||
|
origin = {
|
||||||
|
type: "folder",
|
||||||
|
},
|
||||||
}: {
|
}: {
|
||||||
name?: string;
|
name?: string;
|
||||||
dateAdded?: number;
|
dateAdded?: number;
|
||||||
language?: string;
|
language?: string;
|
||||||
storagePath?: string;
|
storagePath?: string;
|
||||||
|
origin?: DatabaseOrigin;
|
||||||
} = {}): LocalDatabase {
|
} = {}): LocalDatabase {
|
||||||
return {
|
return {
|
||||||
name,
|
name,
|
||||||
dateAdded,
|
dateAdded,
|
||||||
language,
|
language,
|
||||||
storagePath,
|
storagePath,
|
||||||
|
origin,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import {
|
|||||||
RootLocalDbItem,
|
RootLocalDbItem,
|
||||||
RootRemoteDbItem,
|
RootRemoteDbItem,
|
||||||
} from "../../src/databases/db-item";
|
} from "../../src/databases/db-item";
|
||||||
|
import { DatabaseOrigin } from "../../src/databases/local-databases/database-origin";
|
||||||
|
|
||||||
// Root Remote Db Items
|
// Root Remote Db Items
|
||||||
export function createRootRemoteDbItem({
|
export function createRootRemoteDbItem({
|
||||||
@@ -124,12 +125,16 @@ export function createLocalDatabaseDbItem({
|
|||||||
language = `language${faker.number.int()}`,
|
language = `language${faker.number.int()}`,
|
||||||
storagePath = `storagePath${faker.number.int()}`,
|
storagePath = `storagePath${faker.number.int()}`,
|
||||||
selected = false,
|
selected = false,
|
||||||
|
origin = {
|
||||||
|
type: "folder",
|
||||||
|
},
|
||||||
}: {
|
}: {
|
||||||
databaseName?: string;
|
databaseName?: string;
|
||||||
dateAdded?: number;
|
dateAdded?: number;
|
||||||
language?: string;
|
language?: string;
|
||||||
storagePath?: string;
|
storagePath?: string;
|
||||||
selected?: boolean;
|
selected?: boolean;
|
||||||
|
origin?: DatabaseOrigin;
|
||||||
} = {}): LocalDatabaseDbItem {
|
} = {}): LocalDatabaseDbItem {
|
||||||
return {
|
return {
|
||||||
kind: DbItemKind.LocalDatabase,
|
kind: DbItemKind.LocalDatabase,
|
||||||
@@ -138,6 +143,7 @@ export function createLocalDatabaseDbItem({
|
|||||||
dateAdded,
|
dateAdded,
|
||||||
language,
|
language,
|
||||||
storagePath,
|
storagePath,
|
||||||
|
origin,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,9 @@ describe("db item selection", () => {
|
|||||||
dateAdded: 1234,
|
dateAdded: 1234,
|
||||||
language: "javascript",
|
language: "javascript",
|
||||||
storagePath: "/foo/bar",
|
storagePath: "/foo/bar",
|
||||||
|
origin: {
|
||||||
|
type: "folder",
|
||||||
|
},
|
||||||
selected: true,
|
selected: true,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -337,12 +337,18 @@ describe("db tree creator", () => {
|
|||||||
dateAdded: 1668428293677,
|
dateAdded: 1668428293677,
|
||||||
language: QueryLanguage.Cpp,
|
language: QueryLanguage.Cpp,
|
||||||
storagePath: "/path/to/db1/",
|
storagePath: "/path/to/db1/",
|
||||||
|
origin: {
|
||||||
|
type: "folder",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "db2",
|
name: "db2",
|
||||||
dateAdded: 1668428472731,
|
dateAdded: 1668428472731,
|
||||||
language: "cpp",
|
language: "cpp",
|
||||||
storagePath: "/path/to/db2/",
|
storagePath: "/path/to/db2/",
|
||||||
|
origin: {
|
||||||
|
type: "folder",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -354,6 +360,9 @@ describe("db tree creator", () => {
|
|||||||
dateAdded: 1668428472731,
|
dateAdded: 1668428472731,
|
||||||
language: "ruby",
|
language: "ruby",
|
||||||
storagePath: "/path/to/db3/",
|
storagePath: "/path/to/db3/",
|
||||||
|
origin: {
|
||||||
|
type: "folder",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -380,6 +389,7 @@ describe("db tree creator", () => {
|
|||||||
databaseName: db.name,
|
databaseName: db.name,
|
||||||
dateAdded: db.dateAdded,
|
dateAdded: db.dateAdded,
|
||||||
language: db.language,
|
language: db.language,
|
||||||
|
origin: db.origin,
|
||||||
storagePath: db.storagePath,
|
storagePath: db.storagePath,
|
||||||
parentListName: dbConfig.databases.local.lists[0].name,
|
parentListName: dbConfig.databases.local.lists[0].name,
|
||||||
})),
|
})),
|
||||||
@@ -395,6 +405,7 @@ describe("db tree creator", () => {
|
|||||||
databaseName: db.name,
|
databaseName: db.name,
|
||||||
dateAdded: db.dateAdded,
|
dateAdded: db.dateAdded,
|
||||||
language: db.language,
|
language: db.language,
|
||||||
|
origin: db.origin,
|
||||||
storagePath: db.storagePath,
|
storagePath: db.storagePath,
|
||||||
parentListName: dbConfig.databases.local.lists[1].name,
|
parentListName: dbConfig.databases.local.lists[1].name,
|
||||||
})),
|
})),
|
||||||
@@ -409,12 +420,18 @@ describe("db tree creator", () => {
|
|||||||
dateAdded: 1668428293677,
|
dateAdded: 1668428293677,
|
||||||
language: "csharp",
|
language: "csharp",
|
||||||
storagePath: "/path/to/db1/",
|
storagePath: "/path/to/db1/",
|
||||||
|
origin: {
|
||||||
|
type: "folder",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "db2",
|
name: "db2",
|
||||||
dateAdded: 1668428472731,
|
dateAdded: 1668428472731,
|
||||||
language: "go",
|
language: "go",
|
||||||
storagePath: "/path/to/db2/",
|
storagePath: "/path/to/db2/",
|
||||||
|
origin: {
|
||||||
|
type: "folder",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
@@ -434,6 +451,7 @@ describe("db tree creator", () => {
|
|||||||
databaseName: dbConfig.databases.local.databases[0].name,
|
databaseName: dbConfig.databases.local.databases[0].name,
|
||||||
dateAdded: dbConfig.databases.local.databases[0].dateAdded,
|
dateAdded: dbConfig.databases.local.databases[0].dateAdded,
|
||||||
language: dbConfig.databases.local.databases[0].language,
|
language: dbConfig.databases.local.databases[0].language,
|
||||||
|
origin: dbConfig.databases.local.databases[0].origin,
|
||||||
storagePath: dbConfig.databases.local.databases[0].storagePath,
|
storagePath: dbConfig.databases.local.databases[0].storagePath,
|
||||||
});
|
});
|
||||||
expect(localDatabaseNodes[1]).toEqual({
|
expect(localDatabaseNodes[1]).toEqual({
|
||||||
@@ -442,6 +460,7 @@ describe("db tree creator", () => {
|
|||||||
databaseName: dbConfig.databases.local.databases[1].name,
|
databaseName: dbConfig.databases.local.databases[1].name,
|
||||||
dateAdded: dbConfig.databases.local.databases[1].dateAdded,
|
dateAdded: dbConfig.databases.local.databases[1].dateAdded,
|
||||||
language: dbConfig.databases.local.databases[1].language,
|
language: dbConfig.databases.local.databases[1].language,
|
||||||
|
origin: dbConfig.databases.local.databases[1].origin,
|
||||||
storagePath: dbConfig.databases.local.databases[1].storagePath,
|
storagePath: dbConfig.databases.local.databases[1].storagePath,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -186,12 +186,18 @@ describe("db panel rendering nodes", () => {
|
|||||||
dateAdded: 1668428293677,
|
dateAdded: 1668428293677,
|
||||||
language: QueryLanguage.Cpp,
|
language: QueryLanguage.Cpp,
|
||||||
storagePath: "/path/to/db1/",
|
storagePath: "/path/to/db1/",
|
||||||
|
origin: {
|
||||||
|
type: "folder",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "db2",
|
name: "db2",
|
||||||
dateAdded: 1668428472731,
|
dateAdded: 1668428472731,
|
||||||
language: QueryLanguage.Cpp,
|
language: QueryLanguage.Cpp,
|
||||||
storagePath: "/path/to/db2/",
|
storagePath: "/path/to/db2/",
|
||||||
|
origin: {
|
||||||
|
type: "folder",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -203,6 +209,9 @@ describe("db panel rendering nodes", () => {
|
|||||||
dateAdded: 1668428472731,
|
dateAdded: 1668428472731,
|
||||||
language: "ruby",
|
language: "ruby",
|
||||||
storagePath: "/path/to/db3/",
|
storagePath: "/path/to/db3/",
|
||||||
|
origin: {
|
||||||
|
type: "folder",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -238,6 +247,9 @@ describe("db panel rendering nodes", () => {
|
|||||||
language: QueryLanguage.Cpp,
|
language: QueryLanguage.Cpp,
|
||||||
storagePath: "/path/to/db1/",
|
storagePath: "/path/to/db1/",
|
||||||
selected: false,
|
selected: false,
|
||||||
|
origin: {
|
||||||
|
type: "folder",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
kind: DbItemKind.LocalDatabase,
|
kind: DbItemKind.LocalDatabase,
|
||||||
@@ -246,6 +258,9 @@ describe("db panel rendering nodes", () => {
|
|||||||
language: QueryLanguage.Cpp,
|
language: QueryLanguage.Cpp,
|
||||||
storagePath: "/path/to/db2/",
|
storagePath: "/path/to/db2/",
|
||||||
selected: false,
|
selected: false,
|
||||||
|
origin: {
|
||||||
|
type: "folder",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
checkLocalListItem(localListItems[1], "my-list-2", [
|
checkLocalListItem(localListItems[1], "my-list-2", [
|
||||||
@@ -256,6 +271,9 @@ describe("db panel rendering nodes", () => {
|
|||||||
language: "ruby",
|
language: "ruby",
|
||||||
storagePath: "/path/to/db3/",
|
storagePath: "/path/to/db3/",
|
||||||
selected: false,
|
selected: false,
|
||||||
|
origin: {
|
||||||
|
type: "folder",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
@@ -268,12 +286,18 @@ describe("db panel rendering nodes", () => {
|
|||||||
dateAdded: 1668428293677,
|
dateAdded: 1668428293677,
|
||||||
language: "csharp",
|
language: "csharp",
|
||||||
storagePath: "/path/to/db1/",
|
storagePath: "/path/to/db1/",
|
||||||
|
origin: {
|
||||||
|
type: "folder",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "db2",
|
name: "db2",
|
||||||
dateAdded: 1668428472731,
|
dateAdded: 1668428472731,
|
||||||
language: "go",
|
language: "go",
|
||||||
storagePath: "/path/to/db2/",
|
storagePath: "/path/to/db2/",
|
||||||
|
origin: {
|
||||||
|
type: "folder",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
@@ -306,6 +330,9 @@ describe("db panel rendering nodes", () => {
|
|||||||
language: "csharp",
|
language: "csharp",
|
||||||
storagePath: "/path/to/db1/",
|
storagePath: "/path/to/db1/",
|
||||||
selected: false,
|
selected: false,
|
||||||
|
origin: {
|
||||||
|
type: "folder",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
checkLocalDatabaseItem(localDatabaseItems[1], {
|
checkLocalDatabaseItem(localDatabaseItems[1], {
|
||||||
kind: DbItemKind.LocalDatabase,
|
kind: DbItemKind.LocalDatabase,
|
||||||
@@ -314,6 +341,9 @@ describe("db panel rendering nodes", () => {
|
|||||||
language: "go",
|
language: "go",
|
||||||
storagePath: "/path/to/db2/",
|
storagePath: "/path/to/db2/",
|
||||||
selected: false,
|
selected: false,
|
||||||
|
origin: {
|
||||||
|
type: "folder",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -597,6 +597,9 @@ describe("local databases", () => {
|
|||||||
const options: FullDatabaseOptions = {
|
const options: FullDatabaseOptions = {
|
||||||
dateAdded: 123,
|
dateAdded: 123,
|
||||||
language,
|
language,
|
||||||
|
origin: {
|
||||||
|
type: "folder",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
mockDbItem = createMockDB(dir, options);
|
mockDbItem = createMockDB(dir, options);
|
||||||
|
|
||||||
@@ -728,19 +731,41 @@ describe("local databases", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should resolve the database contents", async () => {
|
it("should resolve the database contents", async () => {
|
||||||
await databaseManager.openDatabase(mockDbItem.databaseUri);
|
await databaseManager.openDatabase(
|
||||||
|
mockDbItem.databaseUri,
|
||||||
|
mockDbItem.origin,
|
||||||
|
);
|
||||||
|
|
||||||
expect(resolveDatabaseContentsSpy).toBeCalledTimes(2);
|
expect(resolveDatabaseContentsSpy).toBeCalledTimes(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should set the database as the currently selected one", async () => {
|
it("should set the database as the currently selected one", async () => {
|
||||||
await databaseManager.openDatabase(mockDbItem.databaseUri);
|
await databaseManager.openDatabase(
|
||||||
|
mockDbItem.databaseUri,
|
||||||
|
mockDbItem.origin,
|
||||||
|
);
|
||||||
|
|
||||||
expect(setCurrentDatabaseItemSpy).toBeCalledTimes(1);
|
expect(setCurrentDatabaseItemSpy).toBeCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should add database source archive folder", async () => {
|
it("should not add database source archive folder when `codeQL.addingDatabases.addDatabaseSourceToWorkspace` is `false`", async () => {
|
||||||
await databaseManager.openDatabase(mockDbItem.databaseUri);
|
jest.spyOn(config, "addDatabaseSourceToWorkspace").mockReturnValue(false);
|
||||||
|
|
||||||
|
await databaseManager.openDatabase(
|
||||||
|
mockDbItem.databaseUri,
|
||||||
|
mockDbItem.origin,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(addDatabaseSourceArchiveFolderSpy).toBeCalledTimes(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should add database source archive folder when `codeQL.addingDatabases.addDatabaseSourceToWorkspace` is `true`", async () => {
|
||||||
|
jest.spyOn(config, "addDatabaseSourceToWorkspace").mockReturnValue(true);
|
||||||
|
|
||||||
|
await databaseManager.openDatabase(
|
||||||
|
mockDbItem.databaseUri,
|
||||||
|
mockDbItem.origin,
|
||||||
|
);
|
||||||
|
|
||||||
expect(addDatabaseSourceArchiveFolderSpy).toBeCalledTimes(1);
|
expect(addDatabaseSourceArchiveFolderSpy).toBeCalledTimes(1);
|
||||||
});
|
});
|
||||||
@@ -756,6 +781,7 @@ describe("local databases", () => {
|
|||||||
|
|
||||||
await databaseManager.openDatabase(
|
await databaseManager.openDatabase(
|
||||||
mockDbItem.databaseUri,
|
mockDbItem.databaseUri,
|
||||||
|
mockDbItem.origin,
|
||||||
makeSelected,
|
makeSelected,
|
||||||
nameOverride,
|
nameOverride,
|
||||||
{ isTutorialDatabase },
|
{ isTutorialDatabase },
|
||||||
@@ -769,7 +795,10 @@ describe("local databases", () => {
|
|||||||
it("should create a skeleton QL pack", async () => {
|
it("should create a skeleton QL pack", async () => {
|
||||||
jest.spyOn(config, "isCodespacesTemplate").mockReturnValue(true);
|
jest.spyOn(config, "isCodespacesTemplate").mockReturnValue(true);
|
||||||
|
|
||||||
await databaseManager.openDatabase(mockDbItem.databaseUri);
|
await databaseManager.openDatabase(
|
||||||
|
mockDbItem.databaseUri,
|
||||||
|
mockDbItem.origin,
|
||||||
|
);
|
||||||
|
|
||||||
expect(createSkeletonPacksSpy).toBeCalledTimes(1);
|
expect(createSkeletonPacksSpy).toBeCalledTimes(1);
|
||||||
});
|
});
|
||||||
@@ -780,7 +809,10 @@ describe("local databases", () => {
|
|||||||
it("should not create a skeleton QL pack", async () => {
|
it("should not create a skeleton QL pack", async () => {
|
||||||
jest.spyOn(config, "isCodespacesTemplate").mockReturnValue(false);
|
jest.spyOn(config, "isCodespacesTemplate").mockReturnValue(false);
|
||||||
|
|
||||||
await databaseManager.openDatabase(mockDbItem.databaseUri);
|
await databaseManager.openDatabase(
|
||||||
|
mockDbItem.databaseUri,
|
||||||
|
mockDbItem.origin,
|
||||||
|
);
|
||||||
expect(createSkeletonPacksSpy).toBeCalledTimes(0);
|
expect(createSkeletonPacksSpy).toBeCalledTimes(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -8,7 +8,11 @@ import {
|
|||||||
findDirWithFile,
|
findDirWithFile,
|
||||||
} from "../../../../src/databases/database-fetcher";
|
} from "../../../../src/databases/database-fetcher";
|
||||||
import * as Octokit from "@octokit/rest";
|
import * as Octokit from "@octokit/rest";
|
||||||
import { mockedQuickPickItem } from "../../utils/mocking.helpers";
|
import {
|
||||||
|
mockedObject,
|
||||||
|
mockedOctokitFunction,
|
||||||
|
mockedQuickPickItem,
|
||||||
|
} from "../../utils/mocking.helpers";
|
||||||
|
|
||||||
// These tests make API calls and may need extra time to complete.
|
// These tests make API calls and may need extra time to complete.
|
||||||
jest.setTimeout(10000);
|
jest.setTimeout(10000);
|
||||||
@@ -18,10 +22,17 @@ describe("database-fetcher", () => {
|
|||||||
let quickPickSpy: jest.SpiedFunction<typeof window.showQuickPick>;
|
let quickPickSpy: jest.SpiedFunction<typeof window.showQuickPick>;
|
||||||
|
|
||||||
const progressSpy = jest.fn();
|
const progressSpy = jest.fn();
|
||||||
const mockRequest = jest.fn();
|
const mockListCodeqlDatabases = mockedOctokitFunction<
|
||||||
const octokit: Octokit.Octokit = {
|
"codeScanning",
|
||||||
request: mockRequest,
|
"listCodeqlDatabases"
|
||||||
} as unknown as Octokit.Octokit;
|
>();
|
||||||
|
const octokit = mockedObject<Octokit.Octokit>({
|
||||||
|
rest: {
|
||||||
|
codeScanning: {
|
||||||
|
listCodeqlDatabases: mockListCodeqlDatabases,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
// We can't make the real octokit request (since we need credentials), so we mock the response.
|
// We can't make the real octokit request (since we need credentials), so we mock the response.
|
||||||
const successfullMockApiResponse = {
|
const successfullMockApiResponse = {
|
||||||
@@ -72,7 +83,7 @@ describe("database-fetcher", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should convert a GitHub nwo to a database url", async () => {
|
it("should convert a GitHub nwo to a database url", async () => {
|
||||||
mockRequest.mockResolvedValue(successfullMockApiResponse);
|
mockListCodeqlDatabases.mockResolvedValue(successfullMockApiResponse);
|
||||||
quickPickSpy.mockResolvedValue(
|
quickPickSpy.mockResolvedValue(
|
||||||
mockedQuickPickItem({
|
mockedQuickPickItem({
|
||||||
label: "JavaScript",
|
label: "JavaScript",
|
||||||
@@ -93,7 +104,7 @@ describe("database-fetcher", () => {
|
|||||||
const { databaseUrl, name, owner } = result;
|
const { databaseUrl, name, owner } = result;
|
||||||
|
|
||||||
expect(databaseUrl).toBe(
|
expect(databaseUrl).toBe(
|
||||||
"https://api.github.com/repos/github/codeql/code-scanning/codeql/databases/javascript",
|
"https://api.github.com/repositories/143040428/code-scanning/codeql/databases/javascript",
|
||||||
);
|
);
|
||||||
expect(name).toBe("codeql");
|
expect(name).toBe("codeql");
|
||||||
expect(owner).toBe("github");
|
expect(owner).toBe("github");
|
||||||
@@ -128,7 +139,7 @@ describe("database-fetcher", () => {
|
|||||||
},
|
},
|
||||||
status: 404,
|
status: 404,
|
||||||
};
|
};
|
||||||
mockRequest.mockResolvedValue(mockApiResponse);
|
mockListCodeqlDatabases.mockResolvedValue(mockApiResponse);
|
||||||
const githubRepo = "foo/bar-not-real";
|
const githubRepo = "foo/bar-not-real";
|
||||||
await expect(
|
await expect(
|
||||||
convertGithubNwoToDatabaseUrl(githubRepo, octokit, progressSpy),
|
convertGithubNwoToDatabaseUrl(githubRepo, octokit, progressSpy),
|
||||||
@@ -142,7 +153,7 @@ describe("database-fetcher", () => {
|
|||||||
data: [],
|
data: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
mockRequest.mockResolvedValue(mockApiResponse);
|
mockListCodeqlDatabases.mockResolvedValue(mockApiResponse);
|
||||||
const githubRepo = "foo/bar-with-no-dbs";
|
const githubRepo = "foo/bar-with-no-dbs";
|
||||||
await expect(
|
await expect(
|
||||||
convertGithubNwoToDatabaseUrl(githubRepo, octokit, progressSpy),
|
convertGithubNwoToDatabaseUrl(githubRepo, octokit, progressSpy),
|
||||||
@@ -153,7 +164,7 @@ describe("database-fetcher", () => {
|
|||||||
describe("when language is already provided", () => {
|
describe("when language is already provided", () => {
|
||||||
describe("when language is valid", () => {
|
describe("when language is valid", () => {
|
||||||
it("should not prompt the user", async () => {
|
it("should not prompt the user", async () => {
|
||||||
mockRequest.mockResolvedValue(successfullMockApiResponse);
|
mockListCodeqlDatabases.mockResolvedValue(successfullMockApiResponse);
|
||||||
const githubRepo = "github/codeql";
|
const githubRepo = "github/codeql";
|
||||||
await convertGithubNwoToDatabaseUrl(
|
await convertGithubNwoToDatabaseUrl(
|
||||||
githubRepo,
|
githubRepo,
|
||||||
@@ -167,7 +178,7 @@ describe("database-fetcher", () => {
|
|||||||
|
|
||||||
describe("when language is invalid", () => {
|
describe("when language is invalid", () => {
|
||||||
it("should prompt for language", async () => {
|
it("should prompt for language", async () => {
|
||||||
mockRequest.mockResolvedValue(successfullMockApiResponse);
|
mockListCodeqlDatabases.mockResolvedValue(successfullMockApiResponse);
|
||||||
const githubRepo = "github/codeql";
|
const githubRepo = "github/codeql";
|
||||||
await convertGithubNwoToDatabaseUrl(
|
await convertGithubNwoToDatabaseUrl(
|
||||||
githubRepo,
|
githubRepo,
|
||||||
@@ -182,7 +193,7 @@ describe("database-fetcher", () => {
|
|||||||
|
|
||||||
describe("when language is not provided", () => {
|
describe("when language is not provided", () => {
|
||||||
it("should prompt for language", async () => {
|
it("should prompt for language", async () => {
|
||||||
mockRequest.mockResolvedValue(successfullMockApiResponse);
|
mockListCodeqlDatabases.mockResolvedValue(successfullMockApiResponse);
|
||||||
const githubRepo = "github/codeql";
|
const githubRepo = "github/codeql";
|
||||||
await convertGithubNwoToDatabaseUrl(githubRepo, octokit, progressSpy);
|
await convertGithubNwoToDatabaseUrl(githubRepo, octokit, progressSpy);
|
||||||
expect(quickPickSpy).toHaveBeenCalled();
|
expect(quickPickSpy).toHaveBeenCalled();
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import { mockEmptyDatabaseManager } from "../query-testing/test-runner-helpers";
|
|||||||
import { QueryRunner } from "../../../../src/query-server";
|
import { QueryRunner } from "../../../../src/query-server";
|
||||||
import { ExtensionPack } from "../../../../src/model-editor/shared/extension-pack";
|
import { ExtensionPack } from "../../../../src/model-editor/shared/extension-pack";
|
||||||
import { createMockModelingStore } from "../../../__mocks__/model-editor/modelingStoreMock";
|
import { createMockModelingStore } from "../../../__mocks__/model-editor/modelingStoreMock";
|
||||||
import { createMockModelEditorViewTracker } from "../../../__mocks__/model-editor/modelEditorViewTrackerMock";
|
|
||||||
import { ModelConfigListener } from "../../../../src/config";
|
import { ModelConfigListener } from "../../../../src/config";
|
||||||
import { createMockModelingEvents } from "../../../__mocks__/model-editor/modelingEventsMock";
|
import { createMockModelingEvents } from "../../../__mocks__/model-editor/modelingEventsMock";
|
||||||
import { QueryLanguage } from "../../../../src/common/query-language";
|
import { QueryLanguage } from "../../../../src/common/query-language";
|
||||||
@@ -18,7 +17,6 @@ describe("ModelEditorView", () => {
|
|||||||
const app = createMockApp({});
|
const app = createMockApp({});
|
||||||
const modelingStore = createMockModelingStore();
|
const modelingStore = createMockModelingStore();
|
||||||
const modelingEvents = createMockModelingEvents();
|
const modelingEvents = createMockModelingEvents();
|
||||||
const viewTracker = createMockModelEditorViewTracker();
|
|
||||||
const modelConfig = mockedObject<ModelConfigListener>({
|
const modelConfig = mockedObject<ModelConfigListener>({
|
||||||
onDidChangeConfiguration: jest.fn(),
|
onDidChangeConfiguration: jest.fn(),
|
||||||
});
|
});
|
||||||
@@ -48,7 +46,6 @@ describe("ModelEditorView", () => {
|
|||||||
app,
|
app,
|
||||||
modelingStore,
|
modelingStore,
|
||||||
modelingEvents,
|
modelingEvents,
|
||||||
viewTracker,
|
|
||||||
modelConfig,
|
modelConfig,
|
||||||
databaseManager,
|
databaseManager,
|
||||||
cliServer,
|
cliServer,
|
||||||
|
|||||||
@@ -39,12 +39,18 @@ describe("test-runner", () => {
|
|||||||
const preTestDatabaseItem = new DatabaseItemImpl(
|
const preTestDatabaseItem = new DatabaseItemImpl(
|
||||||
Uri.file("/path/to/test/dir/dir.testproj"),
|
Uri.file("/path/to/test/dir/dir.testproj"),
|
||||||
undefined,
|
undefined,
|
||||||
mockedObject<FullDatabaseOptions>({ displayName: "custom display name" }),
|
mockedObject<FullDatabaseOptions>({
|
||||||
|
displayName: "custom display name",
|
||||||
|
origin: { type: "folder" },
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
const postTestDatabaseItem = new DatabaseItemImpl(
|
const postTestDatabaseItem = new DatabaseItemImpl(
|
||||||
Uri.file("/path/to/test/dir/dir.testproj"),
|
Uri.file("/path/to/test/dir/dir.testproj"),
|
||||||
undefined,
|
undefined,
|
||||||
mockedObject<FullDatabaseOptions>({ displayName: "default name" }),
|
mockedObject<FullDatabaseOptions>({
|
||||||
|
displayName: "default name",
|
||||||
|
origin: { type: "folder" },
|
||||||
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@@ -160,6 +166,7 @@ describe("test-runner", () => {
|
|||||||
expect(openDatabaseSpy).toBeCalledTimes(1);
|
expect(openDatabaseSpy).toBeCalledTimes(1);
|
||||||
expect(openDatabaseSpy).toBeCalledWith(
|
expect(openDatabaseSpy).toBeCalledWith(
|
||||||
preTestDatabaseItem.databaseUri,
|
preTestDatabaseItem.databaseUri,
|
||||||
|
preTestDatabaseItem.origin,
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { QuickPickItem, window, Uri } from "vscode";
|
import type { QuickPickItem, window, Uri } from "vscode";
|
||||||
import { DatabaseItem } from "../../../src/databases/local-databases";
|
import { DatabaseItem } from "../../../src/databases/local-databases";
|
||||||
|
import * as Octokit from "@octokit/rest";
|
||||||
|
|
||||||
export type DeepPartial<T> = T extends object
|
export type DeepPartial<T> = T extends object
|
||||||
? {
|
? {
|
||||||
@@ -57,6 +58,14 @@ export function mockedObject<T extends object>(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function mockedOctokitFunction<
|
||||||
|
Namespace extends keyof Octokit.Octokit["rest"],
|
||||||
|
Name extends keyof Octokit.Octokit["rest"][Namespace],
|
||||||
|
>(): Octokit.Octokit["rest"][Namespace][Name] & jest.Mock {
|
||||||
|
const fn = jest.fn();
|
||||||
|
return fn as unknown as Octokit.Octokit["rest"][Namespace][Name] & jest.Mock;
|
||||||
|
}
|
||||||
|
|
||||||
export function mockDatabaseItem(
|
export function mockDatabaseItem(
|
||||||
props: DeepPartial<DatabaseItem> = {},
|
props: DeepPartial<DatabaseItem> = {},
|
||||||
): DatabaseItem {
|
): DatabaseItem {
|
||||||
|
|||||||
Reference in New Issue
Block a user