Add model editor view tracker
This is used for registering which model editor views are currently active. This will be used to determine which view to send the "reveal method" command to. It can also be used in the future to limit the number of instances of the model editor that can be opened for a database. This uses the same pattern as variant analyses with a separate interface for the view to avoid having circular dependencies.
This commit is contained in:
@@ -20,12 +20,14 @@ import { setUpPack } from "./model-editor-queries";
|
||||
import { MethodModelingPanel } from "./method-modeling/method-modeling-panel";
|
||||
import { ModelingStore } from "./modeling-store";
|
||||
import { showResolvableLocation } from "../databases/local-databases/locations";
|
||||
import { ModelEditorViewTracker } from "./model-editor-view-tracker";
|
||||
|
||||
const SUPPORTED_LANGUAGES: string[] = ["java", "csharp"];
|
||||
|
||||
export class ModelEditorModule extends DisposableObject {
|
||||
private readonly queryStorageDir: string;
|
||||
private readonly modelingStore: ModelingStore;
|
||||
private readonly editorViewTracker: ModelEditorViewTracker<ModelEditorView>;
|
||||
private readonly methodsUsagePanel: MethodsUsagePanel;
|
||||
private readonly methodModelingPanel: MethodModelingPanel;
|
||||
|
||||
@@ -39,6 +41,7 @@ export class ModelEditorModule extends DisposableObject {
|
||||
super();
|
||||
this.queryStorageDir = join(baseQueryStorageDir, "model-editor-results");
|
||||
this.modelingStore = new ModelingStore(app);
|
||||
this.editorViewTracker = new ModelEditorViewTracker();
|
||||
this.methodsUsagePanel = this.push(
|
||||
new MethodsUsagePanel(this.modelingStore, cliServer),
|
||||
);
|
||||
@@ -148,6 +151,7 @@ export class ModelEditorModule extends DisposableObject {
|
||||
const view = new ModelEditorView(
|
||||
this.app,
|
||||
this.modelingStore,
|
||||
this.editorViewTracker,
|
||||
this.databaseManager,
|
||||
this.cliServer,
|
||||
this.queryRunner,
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
interface ModelEditorViewInterface {
|
||||
databaseUri: string;
|
||||
}
|
||||
|
||||
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)) {
|
||||
this.views.set(databaseUri, []);
|
||||
}
|
||||
|
||||
this.views.get(databaseUri)?.push(view);
|
||||
}
|
||||
|
||||
public unregisterView(view: T): void {
|
||||
const views = this.views.get(view.databaseUri);
|
||||
if (!views) {
|
||||
return;
|
||||
}
|
||||
|
||||
const index = views.indexOf(view);
|
||||
if (index !== -1) {
|
||||
views.splice(index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public getViews(databaseUri: string): T[] {
|
||||
return this.views.get(databaseUri) ?? [];
|
||||
}
|
||||
}
|
||||
@@ -42,6 +42,7 @@ import { getLanguageDisplayName } from "../common/query-language";
|
||||
import { AutoModeler } from "./auto-modeler";
|
||||
import { telemetryListener } from "../common/vscode/telemetry";
|
||||
import { ModelingStore } from "./modeling-store";
|
||||
import { ModelEditorViewTracker } from "./model-editor-view-tracker";
|
||||
|
||||
export class ModelEditorView extends AbstractWebview<
|
||||
ToModelEditorMessage,
|
||||
@@ -52,6 +53,7 @@ export class ModelEditorView extends AbstractWebview<
|
||||
public constructor(
|
||||
protected readonly app: App,
|
||||
private readonly modelingStore: ModelingStore,
|
||||
private readonly viewTracker: ModelEditorViewTracker<ModelEditorView>,
|
||||
private readonly databaseManager: DatabaseManager,
|
||||
private readonly cliServer: CodeQLCliServer,
|
||||
private readonly queryRunner: QueryRunner,
|
||||
@@ -66,6 +68,8 @@ export class ModelEditorView extends AbstractWebview<
|
||||
this.modelingStore.initializeStateForDb(databaseItem);
|
||||
this.registerToModelingStoreEvents();
|
||||
|
||||
this.viewTracker.registerView(this);
|
||||
|
||||
this.autoModeler = new AutoModeler(
|
||||
app,
|
||||
cliServer,
|
||||
@@ -181,7 +185,7 @@ export class ModelEditorView extends AbstractWebview<
|
||||
}
|
||||
|
||||
protected onPanelDispose(): void {
|
||||
// Nothing to do here
|
||||
this.viewTracker.unregisterView(this);
|
||||
}
|
||||
|
||||
protected async onMessage(msg: FromModelEditorMessage): Promise<void> {
|
||||
@@ -338,6 +342,10 @@ export class ModelEditorView extends AbstractWebview<
|
||||
]);
|
||||
}
|
||||
|
||||
public get databaseUri(): string {
|
||||
return this.databaseItem.databaseUri.toString();
|
||||
}
|
||||
|
||||
private async setViewState(): Promise<void> {
|
||||
const showLlmButton =
|
||||
this.databaseItem.language === "java" && showLlmGeneration();
|
||||
@@ -497,6 +505,7 @@ export class ModelEditorView extends AbstractWebview<
|
||||
const view = new ModelEditorView(
|
||||
this.app,
|
||||
this.modelingStore,
|
||||
this.viewTracker,
|
||||
this.databaseManager,
|
||||
this.cliServer,
|
||||
this.queryRunner,
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
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(),
|
||||
getViews = jest.fn(),
|
||||
}: {
|
||||
registerView?: ModelEditorViewTracker["registerView"];
|
||||
unregisterView?: ModelEditorViewTracker["unregisterView"];
|
||||
getViews?: ModelEditorViewTracker["getViews"];
|
||||
} = {}): ModelEditorViewTracker<ModelEditorView> {
|
||||
return mockedObject<ModelEditorViewTracker<ModelEditorView>>({
|
||||
registerView,
|
||||
unregisterView,
|
||||
getViews,
|
||||
});
|
||||
}
|
||||
@@ -9,10 +9,12 @@ import { mockEmptyDatabaseManager } from "../query-testing/test-runner-helpers";
|
||||
import { QueryRunner } from "../../../../src/query-server";
|
||||
import { ExtensionPack } from "../../../../src/model-editor/shared/extension-pack";
|
||||
import { createMockModelingStore } from "../../../__mocks__/model-editor/modelingStoreMock";
|
||||
import { createMockModelEditorViewTracker } from "../../../__mocks__/model-editor/modelEditorViewTrackerMock";
|
||||
|
||||
describe("ModelEditorView", () => {
|
||||
const app = createMockApp({});
|
||||
const modelingStore = createMockModelingStore();
|
||||
const viewTracker = createMockModelEditorViewTracker();
|
||||
const databaseManager = mockEmptyDatabaseManager();
|
||||
const cliServer = mockedObject<CodeQLCliServer>({});
|
||||
const queryRunner = mockedObject<QueryRunner>({});
|
||||
@@ -38,6 +40,7 @@ describe("ModelEditorView", () => {
|
||||
view = new ModelEditorView(
|
||||
app,
|
||||
modelingStore,
|
||||
viewTracker,
|
||||
databaseManager,
|
||||
cliServer,
|
||||
queryRunner,
|
||||
|
||||
Reference in New Issue
Block a user