Merge branch 'main' into aeisenberg/avoid-double-restart
This commit is contained in:
Коммит
a9edb36242
|
@ -173,6 +173,8 @@ Note that this test requires the feature flag: `codeQL.model.llmGeneration`
|
|||
|
||||
#### Test Case 4: Model as dependency
|
||||
|
||||
Note that this test requires the feature flag: `codeQL.model.flowGeneration`
|
||||
|
||||
1. Click "Model as dependency"
|
||||
- Check that grouping are now per package (e.g. `com.alipay.sofa.rraft.option` or `com.google.protobuf`)
|
||||
2. Click "Generate".
|
||||
|
|
|
@ -4,6 +4,13 @@
|
|||
|
||||
- Fix a bug where the query server was restarted twice after configuration changes. [#2884](https://github.com/github/vscode-codeql/pull/2884).
|
||||
|
||||
## 1.9.1 - 29 September 2023
|
||||
|
||||
- Add warning when using a VS Code version older than 1.82.0. [#2854](https://github.com/github/vscode-codeql/pull/2854)
|
||||
- Fix a bug when parsing large evaluation log summaries. [#2858](https://github.com/github/vscode-codeql/pull/2858)
|
||||
- Right-align and format numbers in raw result tables. [#2864](https://github.com/github/vscode-codeql/pull/2864)
|
||||
- Remove rate limit warning notifications when using Code Search to add repositories to a variant analysis list. [#2812](https://github.com/github/vscode-codeql/pull/2812)
|
||||
|
||||
## 1.9.0 - 19 September 2023
|
||||
|
||||
- Release the [CodeQL model editor](https://codeql.github.com/docs/codeql/codeql-for-visual-studio-code/using-the-codeql-model-editor) to create CodeQL model packs for Java frameworks. Open the editor using the "CodeQL: Open CodeQL Model Editor (Beta)" command. [#2823](https://github.com/github/vscode-codeql/pull/2823)
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "vscode-codeql",
|
||||
"version": "1.9.1",
|
||||
"version": "1.9.2",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "vscode-codeql",
|
||||
"version": "1.9.1",
|
||||
"version": "1.9.2",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"description": "CodeQL for Visual Studio Code",
|
||||
"author": "GitHub",
|
||||
"private": true,
|
||||
"version": "1.9.1",
|
||||
"version": "1.9.2",
|
||||
"publisher": "GitHub",
|
||||
"license": "MIT",
|
||||
"icon": "media/VS-marketplace-CodeQL-icon.png",
|
||||
|
@ -1870,11 +1870,11 @@
|
|||
"codeQLDatabases.languages": [
|
||||
{
|
||||
"command": "codeQLDatabases.displayAllLanguages",
|
||||
"when": "codeQLDatabases.languageFilter != All"
|
||||
"when": "codeQLDatabases.languageFilter"
|
||||
},
|
||||
{
|
||||
"command": "codeQLDatabases.displayAllLanguagesSelected",
|
||||
"when": "codeQLDatabases.languageFilter == All"
|
||||
"when": "!codeQLDatabases.languageFilter"
|
||||
},
|
||||
{
|
||||
"command": "codeQLDatabases.displayCpp",
|
||||
|
|
|
@ -62,3 +62,9 @@ export const dbSchemeToLanguage: Record<string, QueryLanguage> = {
|
|||
export function isQueryLanguage(language: string): language is QueryLanguage {
|
||||
return Object.values(QueryLanguage).includes(language as QueryLanguage);
|
||||
}
|
||||
|
||||
export function tryGetQueryLanguage(
|
||||
language: string,
|
||||
): QueryLanguage | undefined {
|
||||
return isQueryLanguage(language) ? language : undefined;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import {
|
|||
import { join } from "path";
|
||||
|
||||
import { App } from "../app";
|
||||
import { DisposableObject, DisposeHandler } from "../disposable-object";
|
||||
import { Disposable } from "../disposable-object";
|
||||
import { tmpDir } from "../../tmp-dir";
|
||||
import { getHtmlForWebview, WebviewMessage, WebviewKind } from "./webview-html";
|
||||
|
||||
|
@ -27,16 +27,16 @@ export type WebviewPanelConfig = {
|
|||
export abstract class AbstractWebview<
|
||||
ToMessage extends WebviewMessage,
|
||||
FromMessage extends WebviewMessage,
|
||||
> extends DisposableObject {
|
||||
> {
|
||||
protected panel: WebviewPanel | undefined;
|
||||
protected panelLoaded = false;
|
||||
protected panelLoadedCallBacks: Array<() => void> = [];
|
||||
|
||||
private panelResolves?: Array<(panel: WebviewPanel) => void>;
|
||||
|
||||
constructor(protected readonly app: App) {
|
||||
super();
|
||||
}
|
||||
private disposables: Disposable[] = [];
|
||||
|
||||
constructor(protected readonly app: App) {}
|
||||
|
||||
public async restoreView(panel: WebviewPanel): Promise<void> {
|
||||
this.panel = panel;
|
||||
|
@ -101,6 +101,7 @@ export abstract class AbstractWebview<
|
|||
this.panel = undefined;
|
||||
this.panelLoaded = false;
|
||||
this.onPanelDispose();
|
||||
this.disposeAll();
|
||||
}, null),
|
||||
);
|
||||
|
||||
|
@ -150,8 +151,27 @@ export abstract class AbstractWebview<
|
|||
return panel.webview.postMessage(msg);
|
||||
}
|
||||
|
||||
public dispose(disposeHandler?: DisposeHandler) {
|
||||
public dispose() {
|
||||
this.panel?.dispose();
|
||||
super.dispose(disposeHandler);
|
||||
this.disposeAll();
|
||||
}
|
||||
|
||||
private disposeAll() {
|
||||
while (this.disposables.length > 0) {
|
||||
const disposable = this.disposables.pop()!;
|
||||
disposable.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds `obj` to a list of objects to dispose when the panel is disposed. Objects added by `push` are
|
||||
* disposed in reverse order of being added.
|
||||
* @param obj The object to take ownership of.
|
||||
*/
|
||||
protected push<T extends Disposable>(obj: T): T {
|
||||
if (obj !== undefined) {
|
||||
this.disposables.push(obj);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,8 @@ import {
|
|||
createMultiSelectionCommand,
|
||||
createSingleSelectionCommand,
|
||||
} from "../common/vscode/selection-commands";
|
||||
import { QueryLanguage } from "../common/query-language";
|
||||
import { QueryLanguage, tryGetQueryLanguage } from "../common/query-language";
|
||||
import { LanguageContextStore } from "../language-context-store";
|
||||
|
||||
enum SortOrder {
|
||||
NameAsc = "NameAsc",
|
||||
|
@ -60,8 +61,6 @@ enum SortOrder {
|
|||
DateAddedDesc = "DateAddedDesc",
|
||||
}
|
||||
|
||||
type LanguageFilter = QueryLanguage | "All";
|
||||
|
||||
/**
|
||||
* Tree data provider for the databases view.
|
||||
*/
|
||||
|
@ -70,14 +69,16 @@ class DatabaseTreeDataProvider
|
|||
implements TreeDataProvider<DatabaseItem>
|
||||
{
|
||||
private _sortOrder = SortOrder.NameAsc;
|
||||
private _languageFilter = "All" as LanguageFilter;
|
||||
|
||||
private readonly _onDidChangeTreeData = this.push(
|
||||
new EventEmitter<DatabaseItem | undefined>(),
|
||||
);
|
||||
private currentDatabaseItem: DatabaseItem | undefined;
|
||||
|
||||
constructor(private databaseManager: DatabaseManager) {
|
||||
constructor(
|
||||
private databaseManager: DatabaseManager,
|
||||
private languageContext: LanguageContextStore,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.currentDatabaseItem = databaseManager.currentDatabaseItem;
|
||||
|
@ -92,6 +93,11 @@ class DatabaseTreeDataProvider
|
|||
this.handleDidChangeCurrentDatabaseItem.bind(this),
|
||||
),
|
||||
);
|
||||
this.push(
|
||||
this.languageContext.onLanguageContextChanged(async () => {
|
||||
this._onDidChangeTreeData.fire(undefined);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
public get onDidChangeTreeData(): Event<DatabaseItem | undefined> {
|
||||
|
@ -137,11 +143,9 @@ class DatabaseTreeDataProvider
|
|||
if (element === undefined) {
|
||||
// Filter items by language
|
||||
const displayItems = this.databaseManager.databaseItems.filter((item) => {
|
||||
if (this.languageFilter === "All") {
|
||||
return true;
|
||||
} else {
|
||||
return item.language === this.languageFilter;
|
||||
}
|
||||
return this.languageContext.shouldInclude(
|
||||
tryGetQueryLanguage(item.language),
|
||||
);
|
||||
});
|
||||
|
||||
// Sort items
|
||||
|
@ -178,15 +182,6 @@ class DatabaseTreeDataProvider
|
|||
this._sortOrder = newSortOrder;
|
||||
this._onDidChangeTreeData.fire(undefined);
|
||||
}
|
||||
|
||||
public get languageFilter() {
|
||||
return this._languageFilter;
|
||||
}
|
||||
|
||||
public set languageFilter(newLanguageFilter: LanguageFilter) {
|
||||
this._languageFilter = newLanguageFilter;
|
||||
this._onDidChangeTreeData.fire(undefined);
|
||||
}
|
||||
}
|
||||
|
||||
/** Gets the first element in the given list, if any, or undefined if the list is empty or undefined. */
|
||||
|
@ -223,6 +218,7 @@ export class DatabaseUI extends DisposableObject {
|
|||
public constructor(
|
||||
private app: App,
|
||||
private databaseManager: DatabaseManager,
|
||||
private languageContext: LanguageContextStore,
|
||||
private readonly queryServer: QueryRunner | undefined,
|
||||
private readonly storagePath: string,
|
||||
readonly extensionPath: string,
|
||||
|
@ -230,7 +226,7 @@ export class DatabaseUI extends DisposableObject {
|
|||
super();
|
||||
|
||||
this.treeDataProvider = this.push(
|
||||
new DatabaseTreeDataProvider(databaseManager),
|
||||
new DatabaseTreeDataProvider(databaseManager, languageContext),
|
||||
);
|
||||
this.push(
|
||||
window.createTreeView("codeQLDatabases", {
|
||||
|
@ -269,7 +265,7 @@ export class DatabaseUI extends DisposableObject {
|
|||
"codeQLDatabases.sortByName": this.handleSortByName.bind(this),
|
||||
"codeQLDatabases.sortByDateAdded": this.handleSortByDateAdded.bind(this),
|
||||
"codeQLDatabases.displayAllLanguages":
|
||||
this.handleChangeLanguageFilter.bind(this, "All"),
|
||||
this.handleClearLanguageFilter.bind(this),
|
||||
"codeQLDatabases.displayCpp": this.handleChangeLanguageFilter.bind(
|
||||
this,
|
||||
QueryLanguage.Cpp,
|
||||
|
@ -303,7 +299,7 @@ export class DatabaseUI extends DisposableObject {
|
|||
QueryLanguage.Swift,
|
||||
),
|
||||
"codeQLDatabases.displayAllLanguagesSelected":
|
||||
this.handleChangeLanguageFilter.bind(this, "All"),
|
||||
this.handleClearLanguageFilter.bind(this),
|
||||
"codeQLDatabases.displayCppSelected":
|
||||
this.handleChangeLanguageFilter.bind(this, QueryLanguage.Cpp),
|
||||
"codeQLDatabases.displayCsharpSelected":
|
||||
|
@ -612,13 +608,12 @@ export class DatabaseUI extends DisposableObject {
|
|||
}
|
||||
}
|
||||
|
||||
private async handleChangeLanguageFilter(languageFilter: LanguageFilter) {
|
||||
this.treeDataProvider.languageFilter = languageFilter;
|
||||
await this.app.commands.execute(
|
||||
"setContext",
|
||||
"codeQLDatabases.languageFilter",
|
||||
languageFilter,
|
||||
);
|
||||
private async handleClearLanguageFilter() {
|
||||
await this.languageContext.clearLanguageContext();
|
||||
}
|
||||
|
||||
private async handleChangeLanguageFilter(languageFilter: QueryLanguage) {
|
||||
await this.languageContext.setLanguageContext(languageFilter);
|
||||
}
|
||||
|
||||
private async handleUpgradeCurrentDatabase(): Promise<void> {
|
||||
|
|
|
@ -135,6 +135,7 @@ import { TestManagerBase } from "./query-testing/test-manager-base";
|
|||
import { NewQueryRunner, QueryRunner, QueryServerClient } from "./query-server";
|
||||
import { QueriesModule } from "./queries-panel/queries-module";
|
||||
import { OpenReferencedFileCodeLensProvider } from "./local-queries/open-referenced-file-code-lens-provider";
|
||||
import { LanguageContextStore } from "./language-context-store";
|
||||
|
||||
/**
|
||||
* extension.ts
|
||||
|
@ -774,10 +775,15 @@ async function activateWithInstalledDistribution(
|
|||
void dbm.loadPersistedState();
|
||||
|
||||
ctx.subscriptions.push(dbm);
|
||||
|
||||
void extLogger.log("Initializing language context.");
|
||||
const languageContext = new LanguageContextStore(app);
|
||||
|
||||
void extLogger.log("Initializing database panel.");
|
||||
const databaseUI = new DatabaseUI(
|
||||
app,
|
||||
dbm,
|
||||
languageContext,
|
||||
qs,
|
||||
getContextStoragePath(ctx),
|
||||
ctx.extensionPath,
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
import { App } from "./common/app";
|
||||
import { DisposableObject } from "./common/disposable-object";
|
||||
import { AppEvent, AppEventEmitter } from "./common/events";
|
||||
import { QueryLanguage } from "./common/query-language";
|
||||
|
||||
type LanguageFilter = QueryLanguage | "All";
|
||||
|
||||
export class LanguageContextStore extends DisposableObject {
|
||||
public readonly onLanguageContextChanged: AppEvent<void>;
|
||||
private readonly onLanguageContextChangedEmitter: AppEventEmitter<void>;
|
||||
|
||||
private languageFilter: LanguageFilter;
|
||||
|
||||
constructor(private readonly app: App) {
|
||||
super();
|
||||
// State initialization
|
||||
this.languageFilter = "All";
|
||||
|
||||
// Set up event emitters
|
||||
this.onLanguageContextChangedEmitter = this.push(
|
||||
app.createEventEmitter<void>(),
|
||||
);
|
||||
this.onLanguageContextChanged = this.onLanguageContextChangedEmitter.event;
|
||||
}
|
||||
|
||||
public async clearLanguageContext() {
|
||||
this.languageFilter = "All";
|
||||
this.onLanguageContextChangedEmitter.fire();
|
||||
await this.app.commands.execute(
|
||||
"setContext",
|
||||
"codeQLDatabases.languageFilter",
|
||||
"",
|
||||
);
|
||||
}
|
||||
|
||||
public async setLanguageContext(language: QueryLanguage) {
|
||||
this.languageFilter = language;
|
||||
this.onLanguageContextChangedEmitter.fire();
|
||||
await this.app.commands.execute(
|
||||
"setContext",
|
||||
"codeQLDatabases.languageFilter",
|
||||
language,
|
||||
);
|
||||
}
|
||||
|
||||
public shouldInclude(language: QueryLanguage | undefined): boolean {
|
||||
return this.languageFilter === "All" || this.languageFilter === language;
|
||||
}
|
||||
}
|
|
@ -75,6 +75,7 @@ import { telemetryListener } from "../common/vscode/telemetry";
|
|||
import { redactableError } from "../common/errors";
|
||||
import { ResultsViewCommands } from "../common/commands";
|
||||
import { App } from "../common/app";
|
||||
import { Disposable } from "../common/disposable-object";
|
||||
|
||||
/**
|
||||
* results-view.ts
|
||||
|
@ -157,6 +158,12 @@ function numInterpretedPages(
|
|||
return Math.ceil(n / pageSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* The results view is used for displaying the results of a local query. It is a singleton; only 1 results view exists
|
||||
* in the extension. It is created when the extension is activated and disposed of when the extension is deactivated.
|
||||
* There can be multiple panels linked to this view over the lifetime of the extension, but there is only ever 1 panel
|
||||
* active at a time.
|
||||
*/
|
||||
export class ResultsView extends AbstractWebview<
|
||||
IntoResultsViewMsg,
|
||||
FromResultsViewMsg
|
||||
|
@ -168,6 +175,9 @@ export class ResultsView extends AbstractWebview<
|
|||
"codeql-query-results",
|
||||
);
|
||||
|
||||
// Event listeners that should be disposed of when the view is disposed.
|
||||
private disposableEventListeners: Disposable[] = [];
|
||||
|
||||
constructor(
|
||||
app: App,
|
||||
private databaseManager: DatabaseManager,
|
||||
|
@ -176,14 +186,16 @@ export class ResultsView extends AbstractWebview<
|
|||
private labelProvider: HistoryItemLabelProvider,
|
||||
) {
|
||||
super(app);
|
||||
this.push(this._diagnosticCollection);
|
||||
this.push(
|
||||
|
||||
// We can't use this.push for these two event listeners because they need to be disposed of when the view is
|
||||
// disposed, not when the panel is disposed. The results view is a singleton, so we shouldn't be calling this.push.
|
||||
this.disposableEventListeners.push(
|
||||
vscode.window.onDidChangeTextEditorSelection(
|
||||
this.handleSelectionChange.bind(this),
|
||||
),
|
||||
);
|
||||
|
||||
this.push(
|
||||
this.disposableEventListeners.push(
|
||||
this.databaseManager.onDidChangeDatabaseItem(({ kind }) => {
|
||||
if (kind === DatabaseEventKind.Remove) {
|
||||
this._diagnosticCollection.clear();
|
||||
|
@ -981,4 +993,12 @@ export class ResultsView extends AbstractWebview<
|
|||
editor.setDecorations(shownLocationLineDecoration, []);
|
||||
}
|
||||
}
|
||||
|
||||
dispose() {
|
||||
super.dispose();
|
||||
|
||||
this._diagnosticCollection.dispose();
|
||||
this.disposableEventListeners.forEach((d) => d.dispose());
|
||||
this.disposableEventListeners = [];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,10 +27,12 @@ const DependencyContainer = styled.div`
|
|||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 0.5em;
|
||||
background-color: var(--vscode-textBlockQuote-background);
|
||||
background-color: var(--vscode-editor-background);
|
||||
border: 0.05rem solid var(--vscode-panelSection-border);
|
||||
border-radius: 0.3rem;
|
||||
border-color: var(--vscode-textBlockQuote-border);
|
||||
padding: 0.5rem;
|
||||
word-wrap: break-word;
|
||||
word-break: break-all;
|
||||
`;
|
||||
|
||||
export type MethodModelingProps = {
|
||||
|
|
|
@ -99,6 +99,11 @@ describe("local-databases-ui", () => {
|
|||
/**/
|
||||
},
|
||||
} as any,
|
||||
{
|
||||
onLanguageContextChanged: () => {
|
||||
/**/
|
||||
},
|
||||
} as any,
|
||||
{} as any,
|
||||
storageDir,
|
||||
storageDir,
|
||||
|
|
Загрузка…
Ссылка в новой задаче