Merge pull request #3020 from github/koesie10/refactor-predicates
Refactor model editor predicates
This commit is contained in:
@@ -18,6 +18,7 @@ import { Mode } from "./shared/mode";
|
|||||||
import { CancellationTokenSource } from "vscode";
|
import { CancellationTokenSource } from "vscode";
|
||||||
import { ModelingStore } from "./modeling-store";
|
import { ModelingStore } from "./modeling-store";
|
||||||
import { ModelConfigListener } from "../config";
|
import { ModelConfigListener } from "../config";
|
||||||
|
import { QueryLanguage } from "../common/query-language";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The auto-modeler holds state around auto-modeling jobs and allows
|
* The auto-modeler holds state around auto-modeling jobs and allows
|
||||||
@@ -36,6 +37,7 @@ export class AutoModeler {
|
|||||||
private readonly modelingStore: ModelingStore,
|
private readonly modelingStore: ModelingStore,
|
||||||
private readonly queryStorageDir: string,
|
private readonly queryStorageDir: string,
|
||||||
private readonly databaseItem: DatabaseItem,
|
private readonly databaseItem: DatabaseItem,
|
||||||
|
private readonly language: QueryLanguage,
|
||||||
private readonly addModeledMethods: (
|
private readonly addModeledMethods: (
|
||||||
modeledMethods: Record<string, ModeledMethod[]>,
|
modeledMethods: Record<string, ModeledMethod[]>,
|
||||||
) => Promise<void>,
|
) => Promise<void>,
|
||||||
@@ -202,7 +204,7 @@ export class AutoModeler {
|
|||||||
filename: "auto-model.yml",
|
filename: "auto-model.yml",
|
||||||
});
|
});
|
||||||
|
|
||||||
const loadedMethods = loadDataExtensionYaml(models);
|
const loadedMethods = loadDataExtensionYaml(models, this.language);
|
||||||
if (!loadedMethods) {
|
if (!loadedMethods) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { QueryRunner } from "../query-server";
|
|||||||
import { CodeQLCliServer } from "../codeql-cli/cli";
|
import { CodeQLCliServer } from "../codeql-cli/cli";
|
||||||
import { showAndLogExceptionWithTelemetry } from "../common/logging";
|
import { showAndLogExceptionWithTelemetry } from "../common/logging";
|
||||||
import { extLogger } from "../common/logging/vscode";
|
import { extLogger } from "../common/logging/vscode";
|
||||||
import { extensiblePredicateDefinitions } from "./predicates";
|
import { getModelsAsDataLanguage } from "./languages";
|
||||||
import { ProgressCallback } from "../common/vscode/progress";
|
import { ProgressCallback } from "../common/vscode/progress";
|
||||||
import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
|
import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
|
||||||
import { ModeledMethod, ModeledMethodType } from "./modeled-method";
|
import { ModeledMethod, ModeledMethodType } from "./modeled-method";
|
||||||
@@ -13,12 +13,14 @@ import { redactableError } from "../common/errors";
|
|||||||
import { telemetryListener } from "../common/vscode/telemetry";
|
import { telemetryListener } from "../common/vscode/telemetry";
|
||||||
import { runQuery } from "../local-queries/run-query";
|
import { runQuery } from "../local-queries/run-query";
|
||||||
import { resolveQueries } from "../local-queries";
|
import { resolveQueries } from "../local-queries";
|
||||||
|
import { QueryLanguage } from "../common/query-language";
|
||||||
|
|
||||||
type FlowModelOptions = {
|
type FlowModelOptions = {
|
||||||
cliServer: CodeQLCliServer;
|
cliServer: CodeQLCliServer;
|
||||||
queryRunner: QueryRunner;
|
queryRunner: QueryRunner;
|
||||||
queryStorageDir: string;
|
queryStorageDir: string;
|
||||||
databaseItem: DatabaseItem;
|
databaseItem: DatabaseItem;
|
||||||
|
language: QueryLanguage;
|
||||||
progress: ProgressCallback;
|
progress: ProgressCallback;
|
||||||
token: CancellationToken;
|
token: CancellationToken;
|
||||||
onResults: (results: ModeledMethod[]) => void | Promise<void>;
|
onResults: (results: ModeledMethod[]) => void | Promise<void>;
|
||||||
@@ -104,6 +106,7 @@ async function runSingleFlowQuery(
|
|||||||
queryRunner,
|
queryRunner,
|
||||||
queryStorageDir,
|
queryStorageDir,
|
||||||
databaseItem,
|
databaseItem,
|
||||||
|
language,
|
||||||
progress,
|
progress,
|
||||||
token,
|
token,
|
||||||
}: Omit<FlowModelOptions, "onResults">,
|
}: Omit<FlowModelOptions, "onResults">,
|
||||||
@@ -140,7 +143,9 @@ async function runSingleFlowQuery(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Interpret the results
|
// Interpret the results
|
||||||
const definition = extensiblePredicateDefinitions[type];
|
const modelsAsDataLanguage = getModelsAsDataLanguage(language);
|
||||||
|
|
||||||
|
const definition = modelsAsDataLanguage[type];
|
||||||
|
|
||||||
const bqrsPath = completedQuery.outputDir.bqrsPath;
|
const bqrsPath = completedQuery.outputDir.bqrsPath;
|
||||||
|
|
||||||
|
|||||||
2
extensions/ql-vscode/src/model-editor/languages/index.ts
Normal file
2
extensions/ql-vscode/src/model-editor/languages/index.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export * from "./languages";
|
||||||
|
export * from "./models-as-data";
|
||||||
18
extensions/ql-vscode/src/model-editor/languages/languages.ts
Normal file
18
extensions/ql-vscode/src/model-editor/languages/languages.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { QueryLanguage } from "../../common/query-language";
|
||||||
|
import { ModelsAsDataLanguage } from "./models-as-data";
|
||||||
|
import { staticLanguage } from "./static";
|
||||||
|
|
||||||
|
const languages: Partial<Record<QueryLanguage, ModelsAsDataLanguage>> = {
|
||||||
|
[QueryLanguage.CSharp]: staticLanguage,
|
||||||
|
[QueryLanguage.Java]: staticLanguage,
|
||||||
|
};
|
||||||
|
|
||||||
|
export function getModelsAsDataLanguage(
|
||||||
|
language: QueryLanguage,
|
||||||
|
): ModelsAsDataLanguage {
|
||||||
|
const definition = languages[language];
|
||||||
|
if (!definition) {
|
||||||
|
throw new Error(`No models-as-data definition for ${language}`);
|
||||||
|
}
|
||||||
|
return definition;
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import { ModeledMethod, ModeledMethodType } from "../modeled-method";
|
||||||
|
import { DataTuple } from "../model-extension-file";
|
||||||
|
|
||||||
|
type GenerateMethodDefinition = (method: ModeledMethod) => DataTuple[];
|
||||||
|
type ReadModeledMethod = (row: DataTuple[]) => ModeledMethod;
|
||||||
|
|
||||||
|
export type ModelsAsDataLanguageModelType = Exclude<ModeledMethodType, "none">;
|
||||||
|
|
||||||
|
export type ModelsAsDataLanguageModel = {
|
||||||
|
extensiblePredicate: string;
|
||||||
|
supportedKinds: string[];
|
||||||
|
generateMethodDefinition: GenerateMethodDefinition;
|
||||||
|
readModeledMethod: ReadModeledMethod;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ModelsAsDataLanguage = Record<
|
||||||
|
ModelsAsDataLanguageModelType,
|
||||||
|
ModelsAsDataLanguageModel
|
||||||
|
>;
|
||||||
25
extensions/ql-vscode/src/model-editor/languages/shared.ts
Normal file
25
extensions/ql-vscode/src/model-editor/languages/shared.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
export const sharedExtensiblePredicates = {
|
||||||
|
source: "sourceModel",
|
||||||
|
sink: "sinkModel",
|
||||||
|
summary: "summaryModel",
|
||||||
|
neutral: "neutralModel",
|
||||||
|
};
|
||||||
|
|
||||||
|
export const sharedKinds = {
|
||||||
|
source: ["local", "remote"],
|
||||||
|
sink: [
|
||||||
|
"code-injection",
|
||||||
|
"command-injection",
|
||||||
|
"file-content-store",
|
||||||
|
"html-injection",
|
||||||
|
"js-injection",
|
||||||
|
"ldap-injection",
|
||||||
|
"log-injection",
|
||||||
|
"path-injection",
|
||||||
|
"request-forgery",
|
||||||
|
"sql-injection",
|
||||||
|
"url-redirection",
|
||||||
|
],
|
||||||
|
summary: ["taint", "value"],
|
||||||
|
neutral: ["summary", "source", "sink"],
|
||||||
|
};
|
||||||
@@ -1,24 +1,16 @@
|
|||||||
import { ModeledMethod, ModeledMethodType, Provenance } from "./modeled-method";
|
import { ModelsAsDataLanguage } from "./models-as-data";
|
||||||
import { DataTuple } from "./model-extension-file";
|
import { ModeledMethodType, Provenance } from "../modeled-method";
|
||||||
|
import { DataTuple } from "../model-extension-file";
|
||||||
export type ExtensiblePredicateDefinition = {
|
import { sharedExtensiblePredicates, sharedKinds } from "./shared";
|
||||||
extensiblePredicate: string;
|
|
||||||
generateMethodDefinition: (method: ModeledMethod) => DataTuple[];
|
|
||||||
readModeledMethod: (row: DataTuple[]) => ModeledMethod;
|
|
||||||
|
|
||||||
supportedKinds?: string[];
|
|
||||||
};
|
|
||||||
|
|
||||||
function readRowToMethod(row: DataTuple[]): string {
|
function readRowToMethod(row: DataTuple[]): string {
|
||||||
return `${row[0]}.${row[1]}#${row[3]}${row[4]}`;
|
return `${row[0]}.${row[1]}#${row[3]}${row[4]}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const extensiblePredicateDefinitions: Record<
|
export const staticLanguage: ModelsAsDataLanguage = {
|
||||||
Exclude<ModeledMethodType, "none">,
|
|
||||||
ExtensiblePredicateDefinition
|
|
||||||
> = {
|
|
||||||
source: {
|
source: {
|
||||||
extensiblePredicate: "sourceModel",
|
extensiblePredicate: sharedExtensiblePredicates.source,
|
||||||
|
supportedKinds: sharedKinds.source,
|
||||||
// extensible predicate sourceModel(
|
// extensible predicate sourceModel(
|
||||||
// string package, string type, boolean subtypes, string name, string signature, string ext,
|
// string package, string type, boolean subtypes, string name, string signature, string ext,
|
||||||
// string output, string kind, string provenance
|
// string output, string kind, string provenance
|
||||||
@@ -35,7 +27,7 @@ export const extensiblePredicateDefinitions: Record<
|
|||||||
method.provenance,
|
method.provenance,
|
||||||
],
|
],
|
||||||
readModeledMethod: (row) => ({
|
readModeledMethod: (row) => ({
|
||||||
type: "source",
|
type: "source" as ModeledMethodType,
|
||||||
input: "",
|
input: "",
|
||||||
output: row[6] as string,
|
output: row[6] as string,
|
||||||
kind: row[7] as string,
|
kind: row[7] as string,
|
||||||
@@ -46,10 +38,10 @@ export const extensiblePredicateDefinitions: Record<
|
|||||||
methodName: row[3] as string,
|
methodName: row[3] as string,
|
||||||
methodParameters: row[4] as string,
|
methodParameters: row[4] as string,
|
||||||
}),
|
}),
|
||||||
supportedKinds: ["local", "remote"],
|
|
||||||
},
|
},
|
||||||
sink: {
|
sink: {
|
||||||
extensiblePredicate: "sinkModel",
|
extensiblePredicate: sharedExtensiblePredicates.sink,
|
||||||
|
supportedKinds: sharedKinds.sink,
|
||||||
// extensible predicate sinkModel(
|
// extensible predicate sinkModel(
|
||||||
// string package, string type, boolean subtypes, string name, string signature, string ext,
|
// string package, string type, boolean subtypes, string name, string signature, string ext,
|
||||||
// string input, string kind, string provenance
|
// string input, string kind, string provenance
|
||||||
@@ -77,22 +69,10 @@ export const extensiblePredicateDefinitions: Record<
|
|||||||
methodName: row[3] as string,
|
methodName: row[3] as string,
|
||||||
methodParameters: row[4] as string,
|
methodParameters: row[4] as string,
|
||||||
}),
|
}),
|
||||||
supportedKinds: [
|
|
||||||
"code-injection",
|
|
||||||
"command-injection",
|
|
||||||
"file-content-store",
|
|
||||||
"html-injection",
|
|
||||||
"js-injection",
|
|
||||||
"ldap-injection",
|
|
||||||
"log-injection",
|
|
||||||
"path-injection",
|
|
||||||
"request-forgery",
|
|
||||||
"sql-injection",
|
|
||||||
"url-redirection",
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
summary: {
|
summary: {
|
||||||
extensiblePredicate: "summaryModel",
|
extensiblePredicate: sharedExtensiblePredicates.summary,
|
||||||
|
supportedKinds: sharedKinds.summary,
|
||||||
// extensible predicate summaryModel(
|
// extensible predicate summaryModel(
|
||||||
// string package, string type, boolean subtypes, string name, string signature, string ext,
|
// string package, string type, boolean subtypes, string name, string signature, string ext,
|
||||||
// string input, string output, string kind, string provenance
|
// string input, string output, string kind, string provenance
|
||||||
@@ -121,10 +101,10 @@ export const extensiblePredicateDefinitions: Record<
|
|||||||
methodName: row[3] as string,
|
methodName: row[3] as string,
|
||||||
methodParameters: row[4] as string,
|
methodParameters: row[4] as string,
|
||||||
}),
|
}),
|
||||||
supportedKinds: ["taint", "value"],
|
|
||||||
},
|
},
|
||||||
neutral: {
|
neutral: {
|
||||||
extensiblePredicate: "neutralModel",
|
extensiblePredicate: sharedExtensiblePredicates.neutral,
|
||||||
|
supportedKinds: sharedKinds.neutral,
|
||||||
// extensible predicate neutralModel(
|
// extensible predicate neutralModel(
|
||||||
// string package, string type, string name, string signature, string kind, string provenance
|
// string package, string type, string name, string signature, string kind, string provenance
|
||||||
// );
|
// );
|
||||||
@@ -148,6 +128,5 @@ export const extensiblePredicateDefinitions: Record<
|
|||||||
methodName: row[2] as string,
|
methodName: row[2] as string,
|
||||||
methodParameters: row[3] as string,
|
methodParameters: row[3] as string,
|
||||||
}),
|
}),
|
||||||
supportedKinds: ["summary", "source", "sink"],
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -15,6 +15,10 @@ 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";
|
||||||
|
import {
|
||||||
|
QueryLanguage,
|
||||||
|
tryGetQueryLanguage,
|
||||||
|
} from "../../common/query-language";
|
||||||
|
|
||||||
export class MethodModelingViewProvider extends AbstractWebviewViewProvider<
|
export class MethodModelingViewProvider extends AbstractWebviewViewProvider<
|
||||||
ToMethodModelingMessage,
|
ToMethodModelingMessage,
|
||||||
@@ -24,6 +28,7 @@ export class MethodModelingViewProvider extends AbstractWebviewViewProvider<
|
|||||||
|
|
||||||
private method: Method | undefined = undefined;
|
private method: Method | undefined = undefined;
|
||||||
private databaseItem: DatabaseItem | undefined = undefined;
|
private databaseItem: DatabaseItem | undefined = undefined;
|
||||||
|
private language: QueryLanguage | undefined = undefined;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
app: App,
|
app: App,
|
||||||
@@ -45,6 +50,7 @@ export class MethodModelingViewProvider extends AbstractWebviewViewProvider<
|
|||||||
await this.postMessage({
|
await this.postMessage({
|
||||||
t: "setMethodModelingPanelViewState",
|
t: "setMethodModelingPanelViewState",
|
||||||
viewState: {
|
viewState: {
|
||||||
|
language: this.language,
|
||||||
showMultipleModels: this.modelConfig.showMultipleModels,
|
showMultipleModels: this.modelConfig.showMultipleModels,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -56,6 +62,7 @@ export class MethodModelingViewProvider extends AbstractWebviewViewProvider<
|
|||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
this.method = method;
|
this.method = method;
|
||||||
this.databaseItem = databaseItem;
|
this.databaseItem = databaseItem;
|
||||||
|
this.language = databaseItem && tryGetQueryLanguage(databaseItem.language);
|
||||||
|
|
||||||
if (this.isShowingView) {
|
if (this.isShowingView) {
|
||||||
await this.postMessage({
|
await this.postMessage({
|
||||||
@@ -70,6 +77,9 @@ export class MethodModelingViewProvider extends AbstractWebviewViewProvider<
|
|||||||
const selectedMethod = this.modelingStore.getSelectedMethodDetails();
|
const selectedMethod = this.modelingStore.getSelectedMethodDetails();
|
||||||
if (selectedMethod) {
|
if (selectedMethod) {
|
||||||
this.databaseItem = selectedMethod.databaseItem;
|
this.databaseItem = selectedMethod.databaseItem;
|
||||||
|
this.language = tryGetQueryLanguage(
|
||||||
|
selectedMethod.databaseItem.language,
|
||||||
|
);
|
||||||
this.method = selectedMethod.method;
|
this.method = selectedMethod.method;
|
||||||
|
|
||||||
await this.postMessage({
|
await this.postMessage({
|
||||||
@@ -185,6 +195,7 @@ export class MethodModelingViewProvider extends AbstractWebviewViewProvider<
|
|||||||
if (this.webviewView) {
|
if (this.webviewView) {
|
||||||
this.method = e.method;
|
this.method = e.method;
|
||||||
this.databaseItem = e.databaseItem;
|
this.databaseItem = e.databaseItem;
|
||||||
|
this.language = tryGetQueryLanguage(e.databaseItem.language);
|
||||||
|
|
||||||
await this.postMessage({
|
await this.postMessage({
|
||||||
t: "setSelectedMethod",
|
t: "setSelectedMethod",
|
||||||
|
|||||||
@@ -233,6 +233,7 @@ export class ModelEditorModule extends DisposableObject {
|
|||||||
queryDir,
|
queryDir,
|
||||||
db,
|
db,
|
||||||
modelFile,
|
modelFile,
|
||||||
|
language,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.modelingEvents.onDbClosed(async (dbUri) => {
|
this.modelingEvents.onDbClosed(async (dbUri) => {
|
||||||
|
|||||||
@@ -38,7 +38,10 @@ import { ModelConfigListener } from "../config";
|
|||||||
import { INITIAL_MODE, Mode } from "./shared/mode";
|
import { INITIAL_MODE, Mode } from "./shared/mode";
|
||||||
import { loadModeledMethods, saveModeledMethods } from "./modeled-method-fs";
|
import { loadModeledMethods, saveModeledMethods } from "./modeled-method-fs";
|
||||||
import { pickExtensionPack } from "./extension-pack-picker";
|
import { pickExtensionPack } from "./extension-pack-picker";
|
||||||
import { getLanguageDisplayName } from "../common/query-language";
|
import {
|
||||||
|
getLanguageDisplayName,
|
||||||
|
QueryLanguage,
|
||||||
|
} from "../common/query-language";
|
||||||
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";
|
||||||
@@ -64,6 +67,8 @@ export class ModelEditorView extends AbstractWebview<
|
|||||||
private readonly queryDir: string,
|
private readonly queryDir: string,
|
||||||
private readonly databaseItem: DatabaseItem,
|
private readonly databaseItem: DatabaseItem,
|
||||||
private readonly extensionPack: ExtensionPack,
|
private readonly extensionPack: ExtensionPack,
|
||||||
|
// The language is equal to databaseItem.language but is properly typed as QueryLanguage
|
||||||
|
private readonly language: QueryLanguage,
|
||||||
initialMode: Mode = INITIAL_MODE,
|
initialMode: Mode = INITIAL_MODE,
|
||||||
) {
|
) {
|
||||||
super(app);
|
super(app);
|
||||||
@@ -82,6 +87,7 @@ export class ModelEditorView extends AbstractWebview<
|
|||||||
modelingStore,
|
modelingStore,
|
||||||
queryStorageDir,
|
queryStorageDir,
|
||||||
databaseItem,
|
databaseItem,
|
||||||
|
language,
|
||||||
async (modeledMethods) => {
|
async (modeledMethods) => {
|
||||||
this.addModeledMethods(modeledMethods);
|
this.addModeledMethods(modeledMethods);
|
||||||
},
|
},
|
||||||
@@ -218,7 +224,7 @@ export class ModelEditorView extends AbstractWebview<
|
|||||||
});
|
});
|
||||||
await saveModeledMethods(
|
await saveModeledMethods(
|
||||||
this.extensionPack,
|
this.extensionPack,
|
||||||
this.databaseItem.language,
|
this.language,
|
||||||
methods,
|
methods,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
mode,
|
mode,
|
||||||
@@ -367,6 +373,7 @@ export class ModelEditorView extends AbstractWebview<
|
|||||||
t: "setModelEditorViewState",
|
t: "setModelEditorViewState",
|
||||||
viewState: {
|
viewState: {
|
||||||
extensionPack: this.extensionPack,
|
extensionPack: this.extensionPack,
|
||||||
|
language: this.language,
|
||||||
showFlowGeneration: this.modelConfig.flowGeneration,
|
showFlowGeneration: this.modelConfig.flowGeneration,
|
||||||
showLlmButton,
|
showLlmButton,
|
||||||
showMultipleModels: this.modelConfig.showMultipleModels,
|
showMultipleModels: this.modelConfig.showMultipleModels,
|
||||||
@@ -394,6 +401,7 @@ export class ModelEditorView extends AbstractWebview<
|
|||||||
try {
|
try {
|
||||||
const modeledMethods = await loadModeledMethods(
|
const modeledMethods = await loadModeledMethods(
|
||||||
this.extensionPack,
|
this.extensionPack,
|
||||||
|
this.language,
|
||||||
this.cliServer,
|
this.cliServer,
|
||||||
this.app.logger,
|
this.app.logger,
|
||||||
);
|
);
|
||||||
@@ -458,6 +466,14 @@ export class ModelEditorView extends AbstractWebview<
|
|||||||
if (!addedDatabase) {
|
if (!addedDatabase) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (addedDatabase.language !== this.language) {
|
||||||
|
void showAndLogErrorMessage(
|
||||||
|
this.app.logger,
|
||||||
|
`The selected database is for ${addedDatabase.language}, but the current database is for ${this.language}.`,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
progress({
|
progress({
|
||||||
@@ -472,6 +488,7 @@ export class ModelEditorView extends AbstractWebview<
|
|||||||
queryRunner: this.queryRunner,
|
queryRunner: this.queryRunner,
|
||||||
queryStorageDir: this.queryStorageDir,
|
queryStorageDir: this.queryStorageDir,
|
||||||
databaseItem: addedDatabase ?? this.databaseItem,
|
databaseItem: addedDatabase ?? this.databaseItem,
|
||||||
|
language: this.language,
|
||||||
onResults: async (modeledMethods) => {
|
onResults: async (modeledMethods) => {
|
||||||
const modeledMethodsByName: Record<string, ModeledMethod[]> = {};
|
const modeledMethodsByName: Record<string, ModeledMethod[]> = {};
|
||||||
|
|
||||||
@@ -579,6 +596,7 @@ export class ModelEditorView extends AbstractWebview<
|
|||||||
this.queryDir,
|
this.queryDir,
|
||||||
addedDatabase,
|
addedDatabase,
|
||||||
modelFile,
|
modelFile,
|
||||||
|
this.language,
|
||||||
Mode.Framework,
|
Mode.Framework,
|
||||||
);
|
);
|
||||||
await view.openView();
|
await view.openView();
|
||||||
|
|||||||
@@ -10,10 +10,11 @@ import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
|
|||||||
import { load as loadYaml } from "js-yaml";
|
import { load as loadYaml } from "js-yaml";
|
||||||
import { CodeQLCliServer } from "../codeql-cli/cli";
|
import { CodeQLCliServer } from "../codeql-cli/cli";
|
||||||
import { pathsEqual } from "../common/files";
|
import { pathsEqual } from "../common/files";
|
||||||
|
import { QueryLanguage } from "../common/query-language";
|
||||||
|
|
||||||
export async function saveModeledMethods(
|
export async function saveModeledMethods(
|
||||||
extensionPack: ExtensionPack,
|
extensionPack: ExtensionPack,
|
||||||
language: string,
|
language: QueryLanguage,
|
||||||
methods: readonly Method[],
|
methods: readonly Method[],
|
||||||
modeledMethods: Readonly<Record<string, readonly ModeledMethod[]>>,
|
modeledMethods: Readonly<Record<string, readonly ModeledMethod[]>>,
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
@@ -22,6 +23,7 @@ export async function saveModeledMethods(
|
|||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const existingModeledMethods = await loadModeledMethodFiles(
|
const existingModeledMethods = await loadModeledMethodFiles(
|
||||||
extensionPack,
|
extensionPack,
|
||||||
|
language,
|
||||||
cliServer,
|
cliServer,
|
||||||
logger,
|
logger,
|
||||||
);
|
);
|
||||||
@@ -43,6 +45,7 @@ export async function saveModeledMethods(
|
|||||||
|
|
||||||
async function loadModeledMethodFiles(
|
async function loadModeledMethodFiles(
|
||||||
extensionPack: ExtensionPack,
|
extensionPack: ExtensionPack,
|
||||||
|
language: QueryLanguage,
|
||||||
cliServer: CodeQLCliServer,
|
cliServer: CodeQLCliServer,
|
||||||
logger: NotificationLogger,
|
logger: NotificationLogger,
|
||||||
): Promise<Record<string, Record<string, ModeledMethod[]>>> {
|
): Promise<Record<string, Record<string, ModeledMethod[]>>> {
|
||||||
@@ -60,7 +63,7 @@ async function loadModeledMethodFiles(
|
|||||||
filename: modelFile,
|
filename: modelFile,
|
||||||
});
|
});
|
||||||
|
|
||||||
const modeledMethods = loadDataExtensionYaml(data);
|
const modeledMethods = loadDataExtensionYaml(data, language);
|
||||||
if (!modeledMethods) {
|
if (!modeledMethods) {
|
||||||
void showAndLogErrorMessage(
|
void showAndLogErrorMessage(
|
||||||
logger,
|
logger,
|
||||||
@@ -76,6 +79,7 @@ async function loadModeledMethodFiles(
|
|||||||
|
|
||||||
export async function loadModeledMethods(
|
export async function loadModeledMethods(
|
||||||
extensionPack: ExtensionPack,
|
extensionPack: ExtensionPack,
|
||||||
|
language: QueryLanguage,
|
||||||
cliServer: CodeQLCliServer,
|
cliServer: CodeQLCliServer,
|
||||||
logger: NotificationLogger,
|
logger: NotificationLogger,
|
||||||
): Promise<Record<string, ModeledMethod[]>> {
|
): Promise<Record<string, ModeledMethod[]>> {
|
||||||
@@ -83,6 +87,7 @@ export async function loadModeledMethods(
|
|||||||
|
|
||||||
const modeledMethodsByFile = await loadModeledMethodFiles(
|
const modeledMethodsByFile = await loadModeledMethodFiles(
|
||||||
extensionPack,
|
extensionPack,
|
||||||
|
language,
|
||||||
cliServer,
|
cliServer,
|
||||||
logger,
|
logger,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import { ExtensionPack } from "./extension-pack";
|
import { ExtensionPack } from "./extension-pack";
|
||||||
import { Mode } from "./mode";
|
import { Mode } from "./mode";
|
||||||
|
import { QueryLanguage } from "../../common/query-language";
|
||||||
|
|
||||||
export interface ModelEditorViewState {
|
export interface ModelEditorViewState {
|
||||||
extensionPack: ExtensionPack;
|
extensionPack: ExtensionPack;
|
||||||
|
language: QueryLanguage;
|
||||||
showFlowGeneration: boolean;
|
showFlowGeneration: boolean;
|
||||||
showLlmButton: boolean;
|
showLlmButton: boolean;
|
||||||
showMultipleModels: boolean;
|
showMultipleModels: boolean;
|
||||||
@@ -11,5 +13,6 @@ export interface ModelEditorViewState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface MethodModelingPanelViewState {
|
export interface MethodModelingPanelViewState {
|
||||||
|
language: QueryLanguage | undefined;
|
||||||
showMultipleModels: boolean;
|
showMultipleModels: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,21 +3,22 @@ import Ajv from "ajv";
|
|||||||
import { Method } from "./method";
|
import { Method } from "./method";
|
||||||
import { ModeledMethod, ModeledMethodType } from "./modeled-method";
|
import { ModeledMethod, ModeledMethodType } from "./modeled-method";
|
||||||
import {
|
import {
|
||||||
ExtensiblePredicateDefinition,
|
getModelsAsDataLanguage,
|
||||||
extensiblePredicateDefinitions,
|
ModelsAsDataLanguageModel,
|
||||||
} from "./predicates";
|
} from "./languages";
|
||||||
|
|
||||||
import * as modelExtensionFileSchema from "./model-extension-file.schema.json";
|
import * as modelExtensionFileSchema from "./model-extension-file.schema.json";
|
||||||
import { Mode } from "./shared/mode";
|
import { Mode } from "./shared/mode";
|
||||||
import { assertNever } from "../common/helpers-pure";
|
import { assertNever } from "../common/helpers-pure";
|
||||||
import { ModelExtensionFile } from "./model-extension-file";
|
import { ModelExtensionFile } from "./model-extension-file";
|
||||||
|
import { QueryLanguage } from "../common/query-language";
|
||||||
|
|
||||||
const ajv = new Ajv({ allErrors: true, allowUnionTypes: true });
|
const ajv = new Ajv({ allErrors: true, allowUnionTypes: true });
|
||||||
const modelExtensionFileSchemaValidate = ajv.compile(modelExtensionFileSchema);
|
const modelExtensionFileSchemaValidate = ajv.compile(modelExtensionFileSchema);
|
||||||
|
|
||||||
function createDataProperty(
|
function createDataProperty(
|
||||||
methods: readonly ModeledMethod[],
|
methods: readonly ModeledMethod[],
|
||||||
definition: ExtensiblePredicateDefinition,
|
definition: ModelsAsDataLanguageModel,
|
||||||
) {
|
) {
|
||||||
if (methods.length === 0) {
|
if (methods.length === 0) {
|
||||||
return " []";
|
return " []";
|
||||||
@@ -34,9 +35,11 @@ function createDataProperty(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function createDataExtensionYaml(
|
export function createDataExtensionYaml(
|
||||||
language: string,
|
language: QueryLanguage,
|
||||||
modeledMethods: readonly ModeledMethod[],
|
modeledMethods: readonly ModeledMethod[],
|
||||||
) {
|
) {
|
||||||
|
const modelsAsDataLanguage = getModelsAsDataLanguage(language);
|
||||||
|
|
||||||
const methodsByType: Record<
|
const methodsByType: Record<
|
||||||
Exclude<ModeledMethodType, "none">,
|
Exclude<ModeledMethodType, "none">,
|
||||||
ModeledMethod[]
|
ModeledMethod[]
|
||||||
@@ -53,7 +56,7 @@ export function createDataExtensionYaml(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const extensions = Object.entries(extensiblePredicateDefinitions).map(
|
const extensions = Object.entries(modelsAsDataLanguage).map(
|
||||||
([type, definition]) => ` - addsTo:
|
([type, definition]) => ` - addsTo:
|
||||||
pack: codeql/${language}-all
|
pack: codeql/${language}-all
|
||||||
extensible: ${definition.extensiblePredicate}
|
extensible: ${definition.extensiblePredicate}
|
||||||
@@ -69,7 +72,7 @@ ${extensions.join("\n")}`;
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function createDataExtensionYamls(
|
export function createDataExtensionYamls(
|
||||||
language: string,
|
language: QueryLanguage,
|
||||||
methods: readonly Method[],
|
methods: readonly Method[],
|
||||||
newModeledMethods: Readonly<Record<string, readonly ModeledMethod[]>>,
|
newModeledMethods: Readonly<Record<string, readonly ModeledMethod[]>>,
|
||||||
existingModeledMethods: Readonly<
|
existingModeledMethods: Readonly<
|
||||||
@@ -98,7 +101,7 @@ export function createDataExtensionYamls(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function createDataExtensionYamlsByGrouping(
|
function createDataExtensionYamlsByGrouping(
|
||||||
language: string,
|
language: QueryLanguage,
|
||||||
methods: readonly Method[],
|
methods: readonly Method[],
|
||||||
newModeledMethods: Readonly<Record<string, readonly ModeledMethod[]>>,
|
newModeledMethods: Readonly<Record<string, readonly ModeledMethod[]>>,
|
||||||
existingModeledMethods: Readonly<
|
existingModeledMethods: Readonly<
|
||||||
@@ -153,7 +156,7 @@ function createDataExtensionYamlsByGrouping(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function createDataExtensionYamlsForApplicationMode(
|
export function createDataExtensionYamlsForApplicationMode(
|
||||||
language: string,
|
language: QueryLanguage,
|
||||||
methods: readonly Method[],
|
methods: readonly Method[],
|
||||||
newModeledMethods: Readonly<Record<string, readonly ModeledMethod[]>>,
|
newModeledMethods: Readonly<Record<string, readonly ModeledMethod[]>>,
|
||||||
existingModeledMethods: Readonly<
|
existingModeledMethods: Readonly<
|
||||||
@@ -170,7 +173,7 @@ export function createDataExtensionYamlsForApplicationMode(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function createDataExtensionYamlsForFrameworkMode(
|
export function createDataExtensionYamlsForFrameworkMode(
|
||||||
language: string,
|
language: QueryLanguage,
|
||||||
methods: readonly Method[],
|
methods: readonly Method[],
|
||||||
newModeledMethods: Readonly<Record<string, readonly ModeledMethod[]>>,
|
newModeledMethods: Readonly<Record<string, readonly ModeledMethod[]>>,
|
||||||
existingModeledMethods: Readonly<
|
existingModeledMethods: Readonly<
|
||||||
@@ -240,11 +243,14 @@ function validateModelExtensionFile(data: unknown): data is ModelExtensionFile {
|
|||||||
|
|
||||||
export function loadDataExtensionYaml(
|
export function loadDataExtensionYaml(
|
||||||
data: unknown,
|
data: unknown,
|
||||||
|
language: QueryLanguage,
|
||||||
): Record<string, ModeledMethod[]> | undefined {
|
): Record<string, ModeledMethod[]> | undefined {
|
||||||
if (!validateModelExtensionFile(data)) {
|
if (!validateModelExtensionFile(data)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const modelsAsDataLanguage = getModelsAsDataLanguage(language);
|
||||||
|
|
||||||
const extensions = data.extensions;
|
const extensions = data.extensions;
|
||||||
|
|
||||||
const modeledMethods: Record<string, ModeledMethod[]> = {};
|
const modeledMethods: Record<string, ModeledMethod[]> = {};
|
||||||
@@ -254,7 +260,7 @@ export function loadDataExtensionYaml(
|
|||||||
const extensible = addsTo.extensible;
|
const extensible = addsTo.extensible;
|
||||||
const data = extension.data;
|
const data = extension.data;
|
||||||
|
|
||||||
const definition = Object.values(extensiblePredicateDefinitions).find(
|
const definition = Object.values(modelsAsDataLanguage).find(
|
||||||
(definition) => definition.extensiblePredicate === extensible,
|
(definition) => definition.extensiblePredicate === extensible,
|
||||||
);
|
);
|
||||||
if (!definition) {
|
if (!definition) {
|
||||||
|
|||||||
@@ -2,10 +2,9 @@ import * as React from "react";
|
|||||||
|
|
||||||
import { Meta, StoryFn } from "@storybook/react";
|
import { Meta, StoryFn } from "@storybook/react";
|
||||||
|
|
||||||
import { Mode } from "../../model-editor/shared/mode";
|
|
||||||
import { LibraryRow as LibraryRowComponent } from "../../view/model-editor/LibraryRow";
|
import { LibraryRow as LibraryRowComponent } from "../../view/model-editor/LibraryRow";
|
||||||
import { CallClassification } from "../../model-editor/method";
|
import { CallClassification } from "../../model-editor/method";
|
||||||
import { createMockExtensionPack } from "../../../test/factories/model-editor/extension-pack";
|
import { createMockModelEditorViewState } from "../../../test/factories/model-editor/view-state";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: "CodeQL Model Editor/Library Row",
|
title: "CodeQL Model Editor/Library Row",
|
||||||
@@ -219,13 +218,10 @@ LibraryRow.args = {
|
|||||||
},
|
},
|
||||||
modifiedSignatures: new Set(["org.sql2o.Sql2o#Sql2o(String)"]),
|
modifiedSignatures: new Set(["org.sql2o.Sql2o#Sql2o(String)"]),
|
||||||
inProgressMethods: new Set(),
|
inProgressMethods: new Set(),
|
||||||
viewState: {
|
viewState: createMockModelEditorViewState({
|
||||||
extensionPack: createMockExtensionPack(),
|
|
||||||
showFlowGeneration: true,
|
showFlowGeneration: true,
|
||||||
showLlmButton: true,
|
showLlmButton: true,
|
||||||
showMultipleModels: true,
|
showMultipleModels: true,
|
||||||
mode: Mode.Application,
|
}),
|
||||||
sourceArchiveAvailable: true,
|
|
||||||
},
|
|
||||||
hideModeledMethods: false,
|
hideModeledMethods: false,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,10 +10,8 @@ import {
|
|||||||
MULTIPLE_MODELS_GRID_TEMPLATE_COLUMNS,
|
MULTIPLE_MODELS_GRID_TEMPLATE_COLUMNS,
|
||||||
SINGLE_MODEL_GRID_TEMPLATE_COLUMNS,
|
SINGLE_MODEL_GRID_TEMPLATE_COLUMNS,
|
||||||
} from "../../view/model-editor/ModeledMethodDataGrid";
|
} from "../../view/model-editor/ModeledMethodDataGrid";
|
||||||
import { ModelEditorViewState } from "../../model-editor/shared/view-state";
|
|
||||||
import { createMockExtensionPack } from "../../../test/factories/model-editor/extension-pack";
|
|
||||||
import { Mode } from "../../model-editor/shared/mode";
|
|
||||||
import { DataGrid } from "../../view/common/DataGrid";
|
import { DataGrid } from "../../view/common/DataGrid";
|
||||||
|
import { createMockModelEditorViewState } from "../../../test/factories/model-editor/view-state";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: "CodeQL Model Editor/Method Row",
|
title: "CodeQL Model Editor/Method Row",
|
||||||
@@ -99,14 +97,11 @@ const modeledMethod: ModeledMethod = {
|
|||||||
methodParameters: "()",
|
methodParameters: "()",
|
||||||
};
|
};
|
||||||
|
|
||||||
const viewState: ModelEditorViewState = {
|
const viewState = createMockModelEditorViewState({
|
||||||
extensionPack: createMockExtensionPack(),
|
|
||||||
showFlowGeneration: true,
|
showFlowGeneration: true,
|
||||||
showLlmButton: true,
|
showLlmButton: true,
|
||||||
showMultipleModels: true,
|
showMultipleModels: true,
|
||||||
mode: Mode.Application,
|
});
|
||||||
sourceArchiveAvailable: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
export const Unmodeled = Template.bind({});
|
export const Unmodeled = Template.bind({});
|
||||||
Unmodeled.args = {
|
Unmodeled.args = {
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ import * as React from "react";
|
|||||||
|
|
||||||
import { Meta, StoryFn } from "@storybook/react";
|
import { Meta, StoryFn } from "@storybook/react";
|
||||||
|
|
||||||
import { Mode } from "../../model-editor/shared/mode";
|
|
||||||
import { ModelEditor as ModelEditorComponent } from "../../view/model-editor/ModelEditor";
|
import { ModelEditor as ModelEditorComponent } from "../../view/model-editor/ModelEditor";
|
||||||
import { CallClassification } from "../../model-editor/method";
|
import { CallClassification } from "../../model-editor/method";
|
||||||
|
import { createMockModelEditorViewState } from "../../../test/factories/model-editor/view-state";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: "CodeQL Model Editor/CodeQL Model Editor",
|
title: "CodeQL Model Editor/CodeQL Model Editor",
|
||||||
@@ -17,7 +17,7 @@ const Template: StoryFn<typeof ModelEditorComponent> = (args) => (
|
|||||||
|
|
||||||
export const ModelEditor = Template.bind({});
|
export const ModelEditor = Template.bind({});
|
||||||
ModelEditor.args = {
|
ModelEditor.args = {
|
||||||
initialViewState: {
|
initialViewState: createMockModelEditorViewState({
|
||||||
extensionPack: {
|
extensionPack: {
|
||||||
path: "/home/user/vscode-codeql-starter/codeql-custom-queries-java/sql2o",
|
path: "/home/user/vscode-codeql-starter/codeql-custom-queries-java/sql2o",
|
||||||
yamlPath:
|
yamlPath:
|
||||||
@@ -31,9 +31,7 @@ ModelEditor.args = {
|
|||||||
showFlowGeneration: true,
|
showFlowGeneration: true,
|
||||||
showLlmButton: true,
|
showLlmButton: true,
|
||||||
showMultipleModels: true,
|
showMultipleModels: true,
|
||||||
mode: Mode.Application,
|
}),
|
||||||
sourceArchiveAvailable: true,
|
|
||||||
},
|
|
||||||
initialMethods: [
|
initialMethods: [
|
||||||
{
|
{
|
||||||
library: "sql2o",
|
library: "sql2o",
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { ModeledMethod } from "../../model-editor/modeled-method";
|
|||||||
import { VSCodeTag } from "@vscode/webview-ui-toolkit/react";
|
import { VSCodeTag } from "@vscode/webview-ui-toolkit/react";
|
||||||
import { ReviewInEditorButton } from "./ReviewInEditorButton";
|
import { ReviewInEditorButton } from "./ReviewInEditorButton";
|
||||||
import { ModeledMethodsPanel } from "./ModeledMethodsPanel";
|
import { ModeledMethodsPanel } from "./ModeledMethodsPanel";
|
||||||
|
import { QueryLanguage } from "../../common/query-language";
|
||||||
|
|
||||||
const Container = styled.div`
|
const Container = styled.div`
|
||||||
padding-top: 0.5rem;
|
padding-top: 0.5rem;
|
||||||
@@ -49,6 +50,7 @@ const UnsavedTag = ({ modelingStatus }: { modelingStatus: ModelingStatus }) => (
|
|||||||
);
|
);
|
||||||
|
|
||||||
export type MethodModelingProps = {
|
export type MethodModelingProps = {
|
||||||
|
language: QueryLanguage;
|
||||||
modelingStatus: ModelingStatus;
|
modelingStatus: ModelingStatus;
|
||||||
method: Method;
|
method: Method;
|
||||||
modeledMethods: ModeledMethod[];
|
modeledMethods: ModeledMethod[];
|
||||||
@@ -58,6 +60,7 @@ export type MethodModelingProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const MethodModeling = ({
|
export const MethodModeling = ({
|
||||||
|
language,
|
||||||
modelingStatus,
|
modelingStatus,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
method,
|
method,
|
||||||
@@ -77,6 +80,7 @@ export const MethodModeling = ({
|
|||||||
<MethodName {...method} />
|
<MethodName {...method} />
|
||||||
</DependencyContainer>
|
</DependencyContainer>
|
||||||
<ModeledMethodsPanel
|
<ModeledMethodsPanel
|
||||||
|
language={language}
|
||||||
method={method}
|
method={method}
|
||||||
modeledMethods={modeledMethods}
|
modeledMethods={modeledMethods}
|
||||||
showMultipleModels={showMultipleModels}
|
showMultipleModels={showMultipleModels}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { ModelInputDropdown } from "../model-editor/ModelInputDropdown";
|
|||||||
import { ModelOutputDropdown } from "../model-editor/ModelOutputDropdown";
|
import { ModelOutputDropdown } from "../model-editor/ModelOutputDropdown";
|
||||||
import { ModelKindDropdown } from "../model-editor/ModelKindDropdown";
|
import { ModelKindDropdown } from "../model-editor/ModelKindDropdown";
|
||||||
import { InProgressDropdown } from "../model-editor/InProgressDropdown";
|
import { InProgressDropdown } from "../model-editor/InProgressDropdown";
|
||||||
|
import { QueryLanguage } from "../../common/query-language";
|
||||||
|
|
||||||
const Container = styled.div`
|
const Container = styled.div`
|
||||||
padding-top: 0.5rem;
|
padding-top: 0.5rem;
|
||||||
@@ -23,6 +24,7 @@ const Name = styled.span`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export type MethodModelingInputsProps = {
|
export type MethodModelingInputsProps = {
|
||||||
|
language: QueryLanguage;
|
||||||
method: Method;
|
method: Method;
|
||||||
modeledMethod: ModeledMethod | undefined;
|
modeledMethod: ModeledMethod | undefined;
|
||||||
isModelingInProgress: boolean;
|
isModelingInProgress: boolean;
|
||||||
@@ -30,6 +32,7 @@ export type MethodModelingInputsProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const MethodModelingInputs = ({
|
export const MethodModelingInputs = ({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethod,
|
modeledMethod,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -79,7 +82,7 @@ export const MethodModelingInputs = ({
|
|||||||
{isModelingInProgress ? (
|
{isModelingInProgress ? (
|
||||||
<InProgressDropdown />
|
<InProgressDropdown />
|
||||||
) : (
|
) : (
|
||||||
<ModelKindDropdown {...inputProps} />
|
<ModelKindDropdown language={language} {...inputProps} />
|
||||||
)}
|
)}
|
||||||
</Input>
|
</Input>
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ export function MethodModelingView({ initialViewState }: Props): JSX.Element {
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
if (!inModelingMode) {
|
if (!inModelingMode || !viewState?.language) {
|
||||||
return <NotInModelingMode />;
|
return <NotInModelingMode />;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,6 +105,7 @@ export function MethodModelingView({ initialViewState }: Props): JSX.Element {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<MethodModeling
|
<MethodModeling
|
||||||
|
language={viewState?.language}
|
||||||
modelingStatus={modelingStatus}
|
modelingStatus={modelingStatus}
|
||||||
method={method}
|
method={method}
|
||||||
modeledMethods={modeledMethods}
|
modeledMethods={modeledMethods}
|
||||||
|
|||||||
@@ -6,8 +6,10 @@ import { Method } from "../../model-editor/method";
|
|||||||
import { styled } from "styled-components";
|
import { styled } from "styled-components";
|
||||||
import { MultipleModeledMethodsPanel } from "./MultipleModeledMethodsPanel";
|
import { MultipleModeledMethodsPanel } from "./MultipleModeledMethodsPanel";
|
||||||
import { convertToLegacyModeledMethod } from "../../model-editor/shared/modeled-methods-legacy";
|
import { convertToLegacyModeledMethod } from "../../model-editor/shared/modeled-methods-legacy";
|
||||||
|
import { QueryLanguage } from "../../common/query-language";
|
||||||
|
|
||||||
export type ModeledMethodsPanelProps = {
|
export type ModeledMethodsPanelProps = {
|
||||||
|
language: QueryLanguage;
|
||||||
method: Method;
|
method: Method;
|
||||||
modeledMethods: ModeledMethod[];
|
modeledMethods: ModeledMethod[];
|
||||||
isModelingInProgress: boolean;
|
isModelingInProgress: boolean;
|
||||||
@@ -20,6 +22,7 @@ const SingleMethodModelingInputs = styled(MethodModelingInputs)`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export const ModeledMethodsPanel = ({
|
export const ModeledMethodsPanel = ({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -36,6 +39,7 @@ export const ModeledMethodsPanel = ({
|
|||||||
if (!showMultipleModels) {
|
if (!showMultipleModels) {
|
||||||
return (
|
return (
|
||||||
<SingleMethodModelingInputs
|
<SingleMethodModelingInputs
|
||||||
|
language={language}
|
||||||
method={method}
|
method={method}
|
||||||
modeledMethod={convertToLegacyModeledMethod(modeledMethods)}
|
modeledMethod={convertToLegacyModeledMethod(modeledMethods)}
|
||||||
isModelingInProgress={isModelingInProgress}
|
isModelingInProgress={isModelingInProgress}
|
||||||
@@ -46,6 +50,7 @@ export const ModeledMethodsPanel = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<MultipleModeledMethodsPanel
|
<MultipleModeledMethodsPanel
|
||||||
|
language={language}
|
||||||
method={method}
|
method={method}
|
||||||
modeledMethods={modeledMethods}
|
modeledMethods={modeledMethods}
|
||||||
isModelingInProgress={isModelingInProgress}
|
isModelingInProgress={isModelingInProgress}
|
||||||
|
|||||||
@@ -12,8 +12,10 @@ import { VSCodeButton } from "@vscode/webview-ui-toolkit/react";
|
|||||||
import { Codicon } from "../common";
|
import { Codicon } from "../common";
|
||||||
import { validateModeledMethods } from "../../model-editor/shared/validation";
|
import { validateModeledMethods } from "../../model-editor/shared/validation";
|
||||||
import { ModeledMethodAlert } from "./ModeledMethodAlert";
|
import { ModeledMethodAlert } from "./ModeledMethodAlert";
|
||||||
|
import { QueryLanguage } from "../../common/query-language";
|
||||||
|
|
||||||
export type MultipleModeledMethodsPanelProps = {
|
export type MultipleModeledMethodsPanelProps = {
|
||||||
|
language: QueryLanguage;
|
||||||
method: Method;
|
method: Method;
|
||||||
modeledMethods: ModeledMethod[];
|
modeledMethods: ModeledMethod[];
|
||||||
isModelingInProgress: boolean;
|
isModelingInProgress: boolean;
|
||||||
@@ -53,6 +55,7 @@ const ModificationActions = styled.div`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
export const MultipleModeledMethodsPanel = ({
|
export const MultipleModeledMethodsPanel = ({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -150,6 +153,7 @@ export const MultipleModeledMethodsPanel = ({
|
|||||||
)}
|
)}
|
||||||
{modeledMethods.length > 0 ? (
|
{modeledMethods.length > 0 ? (
|
||||||
<MethodModelingInputs
|
<MethodModelingInputs
|
||||||
|
language={language}
|
||||||
method={method}
|
method={method}
|
||||||
modeledMethod={modeledMethods[selectedIndex]}
|
modeledMethod={modeledMethods[selectedIndex]}
|
||||||
isModelingInProgress={isModelingInProgress}
|
isModelingInProgress={isModelingInProgress}
|
||||||
@@ -157,6 +161,7 @@ export const MultipleModeledMethodsPanel = ({
|
|||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<MethodModelingInputs
|
<MethodModelingInputs
|
||||||
|
language={language}
|
||||||
method={method}
|
method={method}
|
||||||
modeledMethod={undefined}
|
modeledMethod={undefined}
|
||||||
isModelingInProgress={isModelingInProgress}
|
isModelingInProgress={isModelingInProgress}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { render as reactRender, screen } from "@testing-library/react";
|
|||||||
import { MethodModeling, MethodModelingProps } from "../MethodModeling";
|
import { MethodModeling, MethodModelingProps } from "../MethodModeling";
|
||||||
import { createMethod } from "../../../../test/factories/model-editor/method-factories";
|
import { createMethod } from "../../../../test/factories/model-editor/method-factories";
|
||||||
import { createModeledMethod } from "../../../../test/factories/model-editor/modeled-method-factories";
|
import { createModeledMethod } from "../../../../test/factories/model-editor/modeled-method-factories";
|
||||||
|
import { QueryLanguage } from "../../../common/query-language";
|
||||||
|
|
||||||
describe(MethodModeling.name, () => {
|
describe(MethodModeling.name, () => {
|
||||||
const render = (props: MethodModelingProps) =>
|
const render = (props: MethodModelingProps) =>
|
||||||
@@ -15,6 +16,7 @@ describe(MethodModeling.name, () => {
|
|||||||
const onChange = jest.fn();
|
const onChange = jest.fn();
|
||||||
|
|
||||||
render({
|
render({
|
||||||
|
language: QueryLanguage.Java,
|
||||||
modelingStatus: "saved",
|
modelingStatus: "saved",
|
||||||
method,
|
method,
|
||||||
modeledMethods: [modeledMethod],
|
modeledMethods: [modeledMethod],
|
||||||
|
|||||||
@@ -7,11 +7,13 @@ import {
|
|||||||
} from "../MethodModelingInputs";
|
} from "../MethodModelingInputs";
|
||||||
import { createMethod } from "../../../../test/factories/model-editor/method-factories";
|
import { createMethod } from "../../../../test/factories/model-editor/method-factories";
|
||||||
import { createModeledMethod } from "../../../../test/factories/model-editor/modeled-method-factories";
|
import { createModeledMethod } from "../../../../test/factories/model-editor/modeled-method-factories";
|
||||||
|
import { QueryLanguage } from "../../../common/query-language";
|
||||||
|
|
||||||
describe(MethodModelingInputs.name, () => {
|
describe(MethodModelingInputs.name, () => {
|
||||||
const render = (props: MethodModelingInputsProps) =>
|
const render = (props: MethodModelingInputsProps) =>
|
||||||
reactRender(<MethodModelingInputs {...props} />);
|
reactRender(<MethodModelingInputs {...props} />);
|
||||||
|
|
||||||
|
const language = QueryLanguage.Java;
|
||||||
const method = createMethod();
|
const method = createMethod();
|
||||||
const modeledMethod = createModeledMethod();
|
const modeledMethod = createModeledMethod();
|
||||||
const isModelingInProgress = false;
|
const isModelingInProgress = false;
|
||||||
@@ -19,6 +21,7 @@ describe(MethodModelingInputs.name, () => {
|
|||||||
|
|
||||||
it("renders the method modeling inputs", () => {
|
it("renders the method modeling inputs", () => {
|
||||||
render({
|
render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethod,
|
modeledMethod,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -44,6 +47,7 @@ describe(MethodModelingInputs.name, () => {
|
|||||||
|
|
||||||
it("allows changing the type", async () => {
|
it("allows changing the type", async () => {
|
||||||
render({
|
render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethod,
|
modeledMethod,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -65,6 +69,7 @@ describe(MethodModelingInputs.name, () => {
|
|||||||
|
|
||||||
it("sets other dropdowns when model type is changed", () => {
|
it("sets other dropdowns when model type is changed", () => {
|
||||||
const { rerender } = render({
|
const { rerender } = render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethod,
|
modeledMethod,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -77,6 +82,7 @@ describe(MethodModelingInputs.name, () => {
|
|||||||
|
|
||||||
rerender(
|
rerender(
|
||||||
<MethodModelingInputs
|
<MethodModelingInputs
|
||||||
|
language={language}
|
||||||
method={method}
|
method={method}
|
||||||
modeledMethod={updatedModeledMethod}
|
modeledMethod={updatedModeledMethod}
|
||||||
isModelingInProgress={isModelingInProgress}
|
isModelingInProgress={isModelingInProgress}
|
||||||
@@ -105,6 +111,7 @@ describe(MethodModelingInputs.name, () => {
|
|||||||
|
|
||||||
it("sets in progress dropdowns when modeling is in progress", () => {
|
it("sets in progress dropdowns when modeling is in progress", () => {
|
||||||
render({
|
render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethod,
|
modeledMethod,
|
||||||
isModelingInProgress: true,
|
isModelingInProgress: true,
|
||||||
|
|||||||
@@ -6,11 +6,13 @@ import {
|
|||||||
ModeledMethodsPanel,
|
ModeledMethodsPanel,
|
||||||
ModeledMethodsPanelProps,
|
ModeledMethodsPanelProps,
|
||||||
} from "../ModeledMethodsPanel";
|
} from "../ModeledMethodsPanel";
|
||||||
|
import { QueryLanguage } from "../../../common/query-language";
|
||||||
|
|
||||||
describe(ModeledMethodsPanel.name, () => {
|
describe(ModeledMethodsPanel.name, () => {
|
||||||
const render = (props: ModeledMethodsPanelProps) =>
|
const render = (props: ModeledMethodsPanelProps) =>
|
||||||
reactRender(<ModeledMethodsPanel {...props} />);
|
reactRender(<ModeledMethodsPanel {...props} />);
|
||||||
|
|
||||||
|
const language = QueryLanguage.Java;
|
||||||
const method = createMethod();
|
const method = createMethod();
|
||||||
const modeledMethods = [createModeledMethod(), createModeledMethod()];
|
const modeledMethods = [createModeledMethod(), createModeledMethod()];
|
||||||
const isModelingInProgress = false;
|
const isModelingInProgress = false;
|
||||||
@@ -21,6 +23,7 @@ describe(ModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("renders the method modeling inputs", () => {
|
it("renders the method modeling inputs", () => {
|
||||||
render({
|
render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -33,6 +36,7 @@ describe(ModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("does not render the pagination", () => {
|
it("does not render the pagination", () => {
|
||||||
render({
|
render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -52,6 +56,7 @@ describe(ModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("renders the method modeling inputs once", () => {
|
it("renders the method modeling inputs once", () => {
|
||||||
render({
|
render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -64,6 +69,7 @@ describe(ModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("renders the pagination", () => {
|
it("renders the pagination", () => {
|
||||||
render({
|
render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
|
|||||||
@@ -8,11 +8,13 @@ import {
|
|||||||
} from "../MultipleModeledMethodsPanel";
|
} from "../MultipleModeledMethodsPanel";
|
||||||
import userEvent from "@testing-library/user-event";
|
import userEvent from "@testing-library/user-event";
|
||||||
import { ModeledMethod } from "../../../model-editor/modeled-method";
|
import { ModeledMethod } from "../../../model-editor/modeled-method";
|
||||||
|
import { QueryLanguage } from "../../../common/query-language";
|
||||||
|
|
||||||
describe(MultipleModeledMethodsPanel.name, () => {
|
describe(MultipleModeledMethodsPanel.name, () => {
|
||||||
const render = (props: MultipleModeledMethodsPanelProps) =>
|
const render = (props: MultipleModeledMethodsPanelProps) =>
|
||||||
reactRender(<MultipleModeledMethodsPanel {...props} />);
|
reactRender(<MultipleModeledMethodsPanel {...props} />);
|
||||||
|
|
||||||
|
const language = QueryLanguage.Java;
|
||||||
const method = createMethod();
|
const method = createMethod();
|
||||||
const isModelingInProgress = false;
|
const isModelingInProgress = false;
|
||||||
const onChange = jest.fn<void, [string, ModeledMethod[]]>();
|
const onChange = jest.fn<void, [string, ModeledMethod[]]>();
|
||||||
@@ -22,6 +24,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("renders the method modeling inputs once", () => {
|
it("renders the method modeling inputs once", () => {
|
||||||
render({
|
render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -38,6 +41,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("disables all pagination", () => {
|
it("disables all pagination", () => {
|
||||||
render({
|
render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -58,6 +62,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("cannot add or delete modeling", () => {
|
it("cannot add or delete modeling", () => {
|
||||||
render({
|
render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -88,6 +93,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("renders the method modeling inputs once", () => {
|
it("renders the method modeling inputs once", () => {
|
||||||
render({
|
render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -104,6 +110,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("disables all pagination", () => {
|
it("disables all pagination", () => {
|
||||||
render({
|
render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -123,6 +130,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("cannot delete modeling", () => {
|
it("cannot delete modeling", () => {
|
||||||
render({
|
render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -138,6 +146,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("can add modeling", async () => {
|
it("can add modeling", async () => {
|
||||||
render({
|
render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -165,6 +174,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("changes selection to the newly added modeling", async () => {
|
it("changes selection to the newly added modeling", async () => {
|
||||||
const { rerender } = render({
|
const { rerender } = render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -175,6 +185,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
rerender(
|
rerender(
|
||||||
<MultipleModeledMethodsPanel
|
<MultipleModeledMethodsPanel
|
||||||
|
language={language}
|
||||||
method={method}
|
method={method}
|
||||||
modeledMethods={
|
modeledMethods={
|
||||||
onChange.mock.calls[onChange.mock.calls.length - 1][1]
|
onChange.mock.calls[onChange.mock.calls.length - 1][1]
|
||||||
@@ -208,6 +219,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("renders the method modeling inputs once", () => {
|
it("renders the method modeling inputs once", () => {
|
||||||
render({
|
render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -224,6 +236,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("renders the pagination", () => {
|
it("renders the pagination", () => {
|
||||||
render({
|
render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -237,6 +250,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("disables the correct pagination", async () => {
|
it("disables the correct pagination", async () => {
|
||||||
render({
|
render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -255,6 +269,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("can use the pagination", async () => {
|
it("can use the pagination", async () => {
|
||||||
render({
|
render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -290,6 +305,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("correctly updates selected pagination index when the number of models decreases", async () => {
|
it("correctly updates selected pagination index when the number of models decreases", async () => {
|
||||||
const { rerender } = render({
|
const { rerender } = render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -300,6 +316,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
rerender(
|
rerender(
|
||||||
<MultipleModeledMethodsPanel
|
<MultipleModeledMethodsPanel
|
||||||
|
language={language}
|
||||||
method={method}
|
method={method}
|
||||||
modeledMethods={[modeledMethods[1]]}
|
modeledMethods={[modeledMethods[1]]}
|
||||||
isModelingInProgress={isModelingInProgress}
|
isModelingInProgress={isModelingInProgress}
|
||||||
@@ -317,6 +334,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("does not show errors", () => {
|
it("does not show errors", () => {
|
||||||
render({
|
render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -328,6 +346,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("can update the first modeling", async () => {
|
it("can update the first modeling", async () => {
|
||||||
render({
|
render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -359,6 +378,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("can update the second modeling", async () => {
|
it("can update the second modeling", async () => {
|
||||||
render({
|
render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -392,6 +412,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("can delete modeling", async () => {
|
it("can delete modeling", async () => {
|
||||||
render({
|
render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -408,6 +429,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("can add modeling", async () => {
|
it("can add modeling", async () => {
|
||||||
render({
|
render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -435,6 +457,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("shows an error when adding a neutral modeling", async () => {
|
it("shows an error when adding a neutral modeling", async () => {
|
||||||
const { rerender } = render({
|
const { rerender } = render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -445,6 +468,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
rerender(
|
rerender(
|
||||||
<MultipleModeledMethodsPanel
|
<MultipleModeledMethodsPanel
|
||||||
|
language={language}
|
||||||
method={method}
|
method={method}
|
||||||
modeledMethods={
|
modeledMethods={
|
||||||
onChange.mock.calls[onChange.mock.calls.length - 1][1]
|
onChange.mock.calls[onChange.mock.calls.length - 1][1]
|
||||||
@@ -464,6 +488,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
rerender(
|
rerender(
|
||||||
<MultipleModeledMethodsPanel
|
<MultipleModeledMethodsPanel
|
||||||
|
language={language}
|
||||||
method={method}
|
method={method}
|
||||||
modeledMethods={
|
modeledMethods={
|
||||||
onChange.mock.calls[onChange.mock.calls.length - 1][1]
|
onChange.mock.calls[onChange.mock.calls.length - 1][1]
|
||||||
@@ -481,6 +506,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
rerender(
|
rerender(
|
||||||
<MultipleModeledMethodsPanel
|
<MultipleModeledMethodsPanel
|
||||||
|
language={language}
|
||||||
method={method}
|
method={method}
|
||||||
modeledMethods={
|
modeledMethods={
|
||||||
onChange.mock.calls[onChange.mock.calls.length - 1][1]
|
onChange.mock.calls[onChange.mock.calls.length - 1][1]
|
||||||
@@ -498,6 +524,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("changes selection to the newly added modeling", async () => {
|
it("changes selection to the newly added modeling", async () => {
|
||||||
const { rerender } = render({
|
const { rerender } = render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -510,6 +537,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
rerender(
|
rerender(
|
||||||
<MultipleModeledMethodsPanel
|
<MultipleModeledMethodsPanel
|
||||||
|
language={language}
|
||||||
method={method}
|
method={method}
|
||||||
modeledMethods={
|
modeledMethods={
|
||||||
onChange.mock.calls[onChange.mock.calls.length - 1][1]
|
onChange.mock.calls[onChange.mock.calls.length - 1][1]
|
||||||
@@ -550,6 +578,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("can use the pagination", async () => {
|
it("can use the pagination", async () => {
|
||||||
render({
|
render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -639,6 +668,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("preserves selection when a modeling other than the selected modeling is removed", async () => {
|
it("preserves selection when a modeling other than the selected modeling is removed", async () => {
|
||||||
const { rerender } = render({
|
const { rerender } = render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -649,6 +679,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
rerender(
|
rerender(
|
||||||
<MultipleModeledMethodsPanel
|
<MultipleModeledMethodsPanel
|
||||||
|
language={language}
|
||||||
method={method}
|
method={method}
|
||||||
modeledMethods={modeledMethods.slice(0, 2)}
|
modeledMethods={modeledMethods.slice(0, 2)}
|
||||||
isModelingInProgress={isModelingInProgress}
|
isModelingInProgress={isModelingInProgress}
|
||||||
@@ -661,6 +692,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("reduces selection when the selected modeling is removed", async () => {
|
it("reduces selection when the selected modeling is removed", async () => {
|
||||||
const { rerender } = render({
|
const { rerender } = render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -673,6 +705,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
rerender(
|
rerender(
|
||||||
<MultipleModeledMethodsPanel
|
<MultipleModeledMethodsPanel
|
||||||
|
language={language}
|
||||||
method={method}
|
method={method}
|
||||||
modeledMethods={modeledMethods.slice(0, 2)}
|
modeledMethods={modeledMethods.slice(0, 2)}
|
||||||
isModelingInProgress={isModelingInProgress}
|
isModelingInProgress={isModelingInProgress}
|
||||||
@@ -704,6 +737,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("can add modeling", () => {
|
it("can add modeling", () => {
|
||||||
render({
|
render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -717,6 +751,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("can delete first modeling", async () => {
|
it("can delete first modeling", async () => {
|
||||||
render({
|
render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -733,6 +768,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("can delete second modeling", async () => {
|
it("can delete second modeling", async () => {
|
||||||
render({
|
render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -750,6 +786,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("can add modeling after deleting second modeling", async () => {
|
it("can add modeling after deleting second modeling", async () => {
|
||||||
const { rerender } = render({
|
const { rerender } = render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -766,6 +803,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
rerender(
|
rerender(
|
||||||
<MultipleModeledMethodsPanel
|
<MultipleModeledMethodsPanel
|
||||||
|
language={language}
|
||||||
method={method}
|
method={method}
|
||||||
modeledMethods={modeledMethods.slice(0, 1)}
|
modeledMethods={modeledMethods.slice(0, 1)}
|
||||||
isModelingInProgress={isModelingInProgress}
|
isModelingInProgress={isModelingInProgress}
|
||||||
@@ -806,6 +844,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("shows errors", () => {
|
it("shows errors", () => {
|
||||||
render({
|
render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
@@ -817,6 +856,7 @@ describe(MultipleModeledMethodsPanel.name, () => {
|
|||||||
|
|
||||||
it("shows the correct error message", async () => {
|
it("shows the correct error message", async () => {
|
||||||
render({
|
render({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModelingInProgress,
|
isModelingInProgress,
|
||||||
|
|||||||
@@ -262,6 +262,7 @@ const ModelableMethodRow = forwardRef<HTMLElement | undefined, MethodRowProps>(
|
|||||||
</DataGridCell>
|
</DataGridCell>
|
||||||
<DataGridCell>
|
<DataGridCell>
|
||||||
<ModelKindDropdown
|
<ModelKindDropdown
|
||||||
|
language={viewState.language}
|
||||||
method={method}
|
method={method}
|
||||||
modeledMethod={modeledMethod}
|
modeledMethod={modeledMethod}
|
||||||
onChange={modeledMethodChangedHandlers[index]}
|
onChange={modeledMethodChangedHandlers[index]}
|
||||||
|
|||||||
@@ -6,24 +6,29 @@ import type {
|
|||||||
} from "../../model-editor/modeled-method";
|
} from "../../model-editor/modeled-method";
|
||||||
import { Dropdown } from "../common/Dropdown";
|
import { Dropdown } from "../common/Dropdown";
|
||||||
import { Method } from "../../model-editor/method";
|
import { Method } from "../../model-editor/method";
|
||||||
import { extensiblePredicateDefinitions } from "../../model-editor/predicates";
|
import { getModelsAsDataLanguage } from "../../model-editor/languages";
|
||||||
|
import { QueryLanguage } from "../../common/query-language";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
language: QueryLanguage;
|
||||||
method: Method;
|
method: Method;
|
||||||
modeledMethod: ModeledMethod | undefined;
|
modeledMethod: ModeledMethod | undefined;
|
||||||
onChange: (modeledMethod: ModeledMethod) => void;
|
onChange: (modeledMethod: ModeledMethod) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ModelKindDropdown = ({
|
export const ModelKindDropdown = ({
|
||||||
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethod,
|
modeledMethod,
|
||||||
onChange,
|
onChange,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const predicate = useMemo(() => {
|
const predicate = useMemo(() => {
|
||||||
|
const modelsAsDataLanguage = getModelsAsDataLanguage(language);
|
||||||
|
|
||||||
return modeledMethod?.type && modeledMethod.type !== "none"
|
return modeledMethod?.type && modeledMethod.type !== "none"
|
||||||
? extensiblePredicateDefinitions[modeledMethod.type]
|
? modelsAsDataLanguage[modeledMethod.type]
|
||||||
: undefined;
|
: undefined;
|
||||||
}, [modeledMethod?.type]);
|
}, [language, modeledMethod?.type]);
|
||||||
|
|
||||||
const kinds = useMemo(() => predicate?.supportedKinds || [], [predicate]);
|
const kinds = useMemo(() => predicate?.supportedKinds || [], [predicate]);
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,10 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { render, screen } from "@testing-library/react";
|
import { render, screen } from "@testing-library/react";
|
||||||
import { HiddenMethodsRow } from "../HiddenMethodsRow";
|
import { HiddenMethodsRow } from "../HiddenMethodsRow";
|
||||||
import { createMockExtensionPack } from "../../../../test/factories/model-editor/extension-pack";
|
import { createMockModelEditorViewState } from "../../../../test/factories/model-editor/view-state";
|
||||||
import { ModelEditorViewState } from "../../../model-editor/shared/view-state";
|
|
||||||
import { Mode } from "../../../model-editor/shared/mode";
|
|
||||||
|
|
||||||
describe(HiddenMethodsRow.name, () => {
|
describe(HiddenMethodsRow.name, () => {
|
||||||
const viewState: ModelEditorViewState = {
|
const viewState = createMockModelEditorViewState();
|
||||||
mode: Mode.Application,
|
|
||||||
showFlowGeneration: false,
|
|
||||||
showLlmButton: false,
|
|
||||||
showMultipleModels: false,
|
|
||||||
extensionPack: createMockExtensionPack(),
|
|
||||||
sourceArchiveAvailable: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
it("does not render with 0 hidden methods", () => {
|
it("does not render with 0 hidden methods", () => {
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
|
|||||||
@@ -2,10 +2,8 @@ import * as React from "react";
|
|||||||
import { render as reactRender, screen } from "@testing-library/react";
|
import { render as reactRender, screen } from "@testing-library/react";
|
||||||
import { createMethod } from "../../../../test/factories/model-editor/method-factories";
|
import { createMethod } from "../../../../test/factories/model-editor/method-factories";
|
||||||
import { LibraryRow, LibraryRowProps } from "../LibraryRow";
|
import { LibraryRow, LibraryRowProps } from "../LibraryRow";
|
||||||
import { createMockExtensionPack } from "../../../../test/factories/model-editor/extension-pack";
|
|
||||||
import { Mode } from "../../../model-editor/shared/mode";
|
|
||||||
import { ModelEditorViewState } from "../../../model-editor/shared/view-state";
|
|
||||||
import userEvent from "@testing-library/user-event";
|
import userEvent from "@testing-library/user-event";
|
||||||
|
import { createMockModelEditorViewState } from "../../../../test/factories/model-editor/view-state";
|
||||||
|
|
||||||
describe(LibraryRow.name, () => {
|
describe(LibraryRow.name, () => {
|
||||||
const method = createMethod();
|
const method = createMethod();
|
||||||
@@ -15,14 +13,7 @@ describe(LibraryRow.name, () => {
|
|||||||
const onStopGenerateFromLlmClick = jest.fn();
|
const onStopGenerateFromLlmClick = jest.fn();
|
||||||
const onModelDependencyClick = jest.fn();
|
const onModelDependencyClick = jest.fn();
|
||||||
|
|
||||||
const viewState: ModelEditorViewState = {
|
const viewState = createMockModelEditorViewState();
|
||||||
mode: Mode.Application,
|
|
||||||
showFlowGeneration: false,
|
|
||||||
showLlmButton: false,
|
|
||||||
showMultipleModels: false,
|
|
||||||
extensionPack: createMockExtensionPack(),
|
|
||||||
sourceArchiveAvailable: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
const render = (props: Partial<LibraryRowProps> = {}) =>
|
const render = (props: Partial<LibraryRowProps> = {}) =>
|
||||||
reactRender(
|
reactRender(
|
||||||
|
|||||||
@@ -5,12 +5,10 @@ import {
|
|||||||
screen,
|
screen,
|
||||||
} from "@testing-library/react";
|
} from "@testing-library/react";
|
||||||
import { createMethod } from "../../../../test/factories/model-editor/method-factories";
|
import { createMethod } from "../../../../test/factories/model-editor/method-factories";
|
||||||
import { Mode } from "../../../model-editor/shared/mode";
|
|
||||||
import { MethodRow, MethodRowProps } from "../MethodRow";
|
import { MethodRow, MethodRowProps } from "../MethodRow";
|
||||||
import { ModeledMethod } from "../../../model-editor/modeled-method";
|
import { ModeledMethod } from "../../../model-editor/modeled-method";
|
||||||
import userEvent from "@testing-library/user-event";
|
import userEvent from "@testing-library/user-event";
|
||||||
import { ModelEditorViewState } from "../../../model-editor/shared/view-state";
|
import { createMockModelEditorViewState } from "../../../../test/factories/model-editor/view-state";
|
||||||
import { createMockExtensionPack } from "../../../../test/factories/model-editor/extension-pack";
|
|
||||||
|
|
||||||
describe(MethodRow.name, () => {
|
describe(MethodRow.name, () => {
|
||||||
const method = createMethod({
|
const method = createMethod({
|
||||||
@@ -33,14 +31,7 @@ describe(MethodRow.name, () => {
|
|||||||
};
|
};
|
||||||
const onChange = jest.fn();
|
const onChange = jest.fn();
|
||||||
|
|
||||||
const viewState: ModelEditorViewState = {
|
const viewState = createMockModelEditorViewState();
|
||||||
mode: Mode.Application,
|
|
||||||
showFlowGeneration: false,
|
|
||||||
showLlmButton: false,
|
|
||||||
showMultipleModels: false,
|
|
||||||
extensionPack: createMockExtensionPack(),
|
|
||||||
sourceArchiveAvailable: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
const render = (props: Partial<MethodRowProps> = {}) =>
|
const render = (props: Partial<MethodRowProps> = {}) =>
|
||||||
reactRender(
|
reactRender(
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { ModelKindDropdown } from "../ModelKindDropdown";
|
|||||||
import userEvent from "@testing-library/user-event";
|
import userEvent from "@testing-library/user-event";
|
||||||
import { createMethod } from "../../../../test/factories/model-editor/method-factories";
|
import { createMethod } from "../../../../test/factories/model-editor/method-factories";
|
||||||
import { createModeledMethod } from "../../../../test/factories/model-editor/modeled-method-factories";
|
import { createModeledMethod } from "../../../../test/factories/model-editor/modeled-method-factories";
|
||||||
|
import { QueryLanguage } from "../../../common/query-language";
|
||||||
|
|
||||||
describe(ModelKindDropdown.name, () => {
|
describe(ModelKindDropdown.name, () => {
|
||||||
const onChange = jest.fn();
|
const onChange = jest.fn();
|
||||||
@@ -21,6 +22,7 @@ describe(ModelKindDropdown.name, () => {
|
|||||||
|
|
||||||
render(
|
render(
|
||||||
<ModelKindDropdown
|
<ModelKindDropdown
|
||||||
|
language={QueryLanguage.Java}
|
||||||
method={method}
|
method={method}
|
||||||
modeledMethod={modeledMethod}
|
modeledMethod={modeledMethod}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
@@ -45,6 +47,7 @@ describe(ModelKindDropdown.name, () => {
|
|||||||
|
|
||||||
const { rerender } = render(
|
const { rerender } = render(
|
||||||
<ModelKindDropdown
|
<ModelKindDropdown
|
||||||
|
language={QueryLanguage.Java}
|
||||||
method={method}
|
method={method}
|
||||||
modeledMethod={modeledMethod}
|
modeledMethod={modeledMethod}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
@@ -62,6 +65,7 @@ describe(ModelKindDropdown.name, () => {
|
|||||||
|
|
||||||
rerender(
|
rerender(
|
||||||
<ModelKindDropdown
|
<ModelKindDropdown
|
||||||
|
language={QueryLanguage.Java}
|
||||||
method={method}
|
method={method}
|
||||||
modeledMethod={updatedModeledMethod}
|
modeledMethod={updatedModeledMethod}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
@@ -79,6 +83,7 @@ describe(ModelKindDropdown.name, () => {
|
|||||||
|
|
||||||
render(
|
render(
|
||||||
<ModelKindDropdown
|
<ModelKindDropdown
|
||||||
|
language={QueryLanguage.Java}
|
||||||
method={method}
|
method={method}
|
||||||
modeledMethod={modeledMethod}
|
modeledMethod={modeledMethod}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
@@ -102,6 +107,7 @@ describe(ModelKindDropdown.name, () => {
|
|||||||
|
|
||||||
render(
|
render(
|
||||||
<ModelKindDropdown
|
<ModelKindDropdown
|
||||||
|
language={QueryLanguage.Java}
|
||||||
method={method}
|
method={method}
|
||||||
modeledMethod={modeledMethod}
|
modeledMethod={modeledMethod}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
@@ -120,6 +126,7 @@ describe(ModelKindDropdown.name, () => {
|
|||||||
|
|
||||||
render(
|
render(
|
||||||
<ModelKindDropdown
|
<ModelKindDropdown
|
||||||
|
language={QueryLanguage.Java}
|
||||||
method={method}
|
method={method}
|
||||||
modeledMethod={modeledMethod}
|
modeledMethod={modeledMethod}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { render as reactRender, screen } from "@testing-library/react";
|
import { render as reactRender, screen } from "@testing-library/react";
|
||||||
import { createMethod } from "../../../../test/factories/model-editor/method-factories";
|
import { createMethod } from "../../../../test/factories/model-editor/method-factories";
|
||||||
import { Mode } from "../../../model-editor/shared/mode";
|
|
||||||
import {
|
import {
|
||||||
ModeledMethodDataGrid,
|
ModeledMethodDataGrid,
|
||||||
ModeledMethodDataGridProps,
|
ModeledMethodDataGridProps,
|
||||||
} from "../ModeledMethodDataGrid";
|
} from "../ModeledMethodDataGrid";
|
||||||
import { ModelEditorViewState } from "../../../model-editor/shared/view-state";
|
import { createMockModelEditorViewState } from "../../../../test/factories/model-editor/view-state";
|
||||||
import { createMockExtensionPack } from "../../../../test/factories/model-editor/extension-pack";
|
|
||||||
|
|
||||||
describe(ModeledMethodDataGrid.name, () => {
|
describe(ModeledMethodDataGrid.name, () => {
|
||||||
const method1 = createMethod({
|
const method1 = createMethod({
|
||||||
@@ -42,14 +40,7 @@ describe(ModeledMethodDataGrid.name, () => {
|
|||||||
});
|
});
|
||||||
const onChange = jest.fn();
|
const onChange = jest.fn();
|
||||||
|
|
||||||
const viewState: ModelEditorViewState = {
|
const viewState = createMockModelEditorViewState();
|
||||||
mode: Mode.Application,
|
|
||||||
showFlowGeneration: false,
|
|
||||||
showLlmButton: false,
|
|
||||||
showMultipleModels: false,
|
|
||||||
extensionPack: createMockExtensionPack(),
|
|
||||||
sourceArchiveAvailable: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
const render = (props: Partial<ModeledMethodDataGridProps> = {}) =>
|
const render = (props: Partial<ModeledMethodDataGridProps> = {}) =>
|
||||||
reactRender(
|
reactRender(
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { render as reactRender, screen } from "@testing-library/react";
|
import { render as reactRender, screen } from "@testing-library/react";
|
||||||
import { createMethod } from "../../../../test/factories/model-editor/method-factories";
|
import { createMethod } from "../../../../test/factories/model-editor/method-factories";
|
||||||
import { createMockExtensionPack } from "../../../../test/factories/model-editor/extension-pack";
|
|
||||||
import { Mode } from "../../../model-editor/shared/mode";
|
|
||||||
import { ModelEditorViewState } from "../../../model-editor/shared/view-state";
|
|
||||||
import {
|
import {
|
||||||
ModeledMethodsList,
|
ModeledMethodsList,
|
||||||
ModeledMethodsListProps,
|
ModeledMethodsListProps,
|
||||||
} from "../ModeledMethodsList";
|
} from "../ModeledMethodsList";
|
||||||
|
import { createMockModelEditorViewState } from "../../../../test/factories/model-editor/view-state";
|
||||||
|
|
||||||
describe(ModeledMethodsList.name, () => {
|
describe(ModeledMethodsList.name, () => {
|
||||||
const method1 = createMethod({
|
const method1 = createMethod({
|
||||||
@@ -43,14 +41,7 @@ describe(ModeledMethodsList.name, () => {
|
|||||||
const onStopGenerateFromLlmClick = jest.fn();
|
const onStopGenerateFromLlmClick = jest.fn();
|
||||||
const onModelDependencyClick = jest.fn();
|
const onModelDependencyClick = jest.fn();
|
||||||
|
|
||||||
const viewState: ModelEditorViewState = {
|
const viewState = createMockModelEditorViewState();
|
||||||
mode: Mode.Application,
|
|
||||||
showFlowGeneration: false,
|
|
||||||
showLlmButton: false,
|
|
||||||
showMultipleModels: false,
|
|
||||||
extensionPack: createMockExtensionPack(),
|
|
||||||
sourceArchiveAvailable: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
const render = (props: Partial<ModeledMethodsListProps> = {}) =>
|
const render = (props: Partial<ModeledMethodsListProps> = {}) =>
|
||||||
reactRender(
|
reactRender(
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import { ModelEditorViewState } from "../../../src/model-editor/shared/view-state";
|
||||||
|
import { Mode } from "../../../src/model-editor/shared/mode";
|
||||||
|
import { createMockExtensionPack } from "./extension-pack";
|
||||||
|
import { QueryLanguage } from "../../../src/common/query-language";
|
||||||
|
|
||||||
|
export function createMockModelEditorViewState(
|
||||||
|
data: Partial<ModelEditorViewState> = {},
|
||||||
|
): ModelEditorViewState {
|
||||||
|
return {
|
||||||
|
language: QueryLanguage.Java,
|
||||||
|
mode: Mode.Application,
|
||||||
|
showFlowGeneration: false,
|
||||||
|
showLlmButton: false,
|
||||||
|
showMultipleModels: false,
|
||||||
|
extensionPack: createMockExtensionPack(),
|
||||||
|
sourceArchiveAvailable: true,
|
||||||
|
...data,
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -7,10 +7,11 @@ import {
|
|||||||
loadDataExtensionYaml,
|
loadDataExtensionYaml,
|
||||||
} from "../../../src/model-editor/yaml";
|
} from "../../../src/model-editor/yaml";
|
||||||
import { CallClassification } from "../../../src/model-editor/method";
|
import { CallClassification } from "../../../src/model-editor/method";
|
||||||
|
import { QueryLanguage } from "../../../src/common/query-language";
|
||||||
|
|
||||||
describe("createDataExtensionYaml", () => {
|
describe("createDataExtensionYaml", () => {
|
||||||
it("creates the correct YAML file", () => {
|
it("creates the correct YAML file", () => {
|
||||||
const yaml = createDataExtensionYaml("java", [
|
const yaml = createDataExtensionYaml(QueryLanguage.Java, [
|
||||||
{
|
{
|
||||||
type: "sink",
|
type: "sink",
|
||||||
input: "Argument[0]",
|
input: "Argument[0]",
|
||||||
@@ -50,7 +51,7 @@ describe("createDataExtensionYaml", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("includes the correct language", () => {
|
it("includes the correct language", () => {
|
||||||
const yaml = createDataExtensionYaml("csharp", []);
|
const yaml = createDataExtensionYaml(QueryLanguage.CSharp, []);
|
||||||
|
|
||||||
expect(yaml).toEqual(`extensions:
|
expect(yaml).toEqual(`extensions:
|
||||||
- addsTo:
|
- addsTo:
|
||||||
@@ -79,7 +80,7 @@ describe("createDataExtensionYaml", () => {
|
|||||||
describe("createDataExtensionYamlsForApplicationMode", () => {
|
describe("createDataExtensionYamlsForApplicationMode", () => {
|
||||||
it("creates the correct YAML files when there are no existing modeled methods", () => {
|
it("creates the correct YAML files when there are no existing modeled methods", () => {
|
||||||
const yaml = createDataExtensionYamlsForApplicationMode(
|
const yaml = createDataExtensionYamlsForApplicationMode(
|
||||||
"java",
|
QueryLanguage.Java,
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
library: "sql2o",
|
library: "sql2o",
|
||||||
@@ -323,7 +324,7 @@ describe("createDataExtensionYamlsForApplicationMode", () => {
|
|||||||
|
|
||||||
it("creates the correct YAML files when there are existing modeled methods", () => {
|
it("creates the correct YAML files when there are existing modeled methods", () => {
|
||||||
const yaml = createDataExtensionYamlsForApplicationMode(
|
const yaml = createDataExtensionYamlsForApplicationMode(
|
||||||
"java",
|
QueryLanguage.Java,
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
library: "sql2o",
|
library: "sql2o",
|
||||||
@@ -618,7 +619,7 @@ describe("createDataExtensionYamlsForApplicationMode", () => {
|
|||||||
describe("createDataExtensionYamlsForFrameworkMode", () => {
|
describe("createDataExtensionYamlsForFrameworkMode", () => {
|
||||||
it("creates the correct YAML files when there are no existing modeled methods", () => {
|
it("creates the correct YAML files when there are no existing modeled methods", () => {
|
||||||
const yaml = createDataExtensionYamlsForFrameworkMode(
|
const yaml = createDataExtensionYamlsForFrameworkMode(
|
||||||
"java",
|
QueryLanguage.Java,
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
library: "sql2o",
|
library: "sql2o",
|
||||||
@@ -774,7 +775,7 @@ describe("createDataExtensionYamlsForFrameworkMode", () => {
|
|||||||
|
|
||||||
it("creates the correct YAML files when there are existing modeled methods", () => {
|
it("creates the correct YAML files when there are existing modeled methods", () => {
|
||||||
const yaml = createDataExtensionYamlsForFrameworkMode(
|
const yaml = createDataExtensionYamlsForFrameworkMode(
|
||||||
"java",
|
QueryLanguage.Java,
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
library: "sql2o",
|
library: "sql2o",
|
||||||
@@ -980,38 +981,41 @@ describe("createDataExtensionYamlsForFrameworkMode", () => {
|
|||||||
|
|
||||||
describe("loadDataExtensionYaml", () => {
|
describe("loadDataExtensionYaml", () => {
|
||||||
it("loads the YAML file", () => {
|
it("loads the YAML file", () => {
|
||||||
const data = loadDataExtensionYaml({
|
const data = loadDataExtensionYaml(
|
||||||
extensions: [
|
{
|
||||||
{
|
extensions: [
|
||||||
addsTo: { pack: "codeql/java-all", extensible: "sourceModel" },
|
{
|
||||||
data: [],
|
addsTo: { pack: "codeql/java-all", extensible: "sourceModel" },
|
||||||
},
|
data: [],
|
||||||
{
|
},
|
||||||
addsTo: { pack: "codeql/java-all", extensible: "sinkModel" },
|
{
|
||||||
data: [
|
addsTo: { pack: "codeql/java-all", extensible: "sinkModel" },
|
||||||
[
|
data: [
|
||||||
"org.sql2o",
|
[
|
||||||
"Connection",
|
"org.sql2o",
|
||||||
true,
|
"Connection",
|
||||||
"createQuery",
|
true,
|
||||||
"(String)",
|
"createQuery",
|
||||||
"",
|
"(String)",
|
||||||
"Argument[0]",
|
"",
|
||||||
"sql",
|
"Argument[0]",
|
||||||
"manual",
|
"sql",
|
||||||
|
"manual",
|
||||||
|
],
|
||||||
],
|
],
|
||||||
],
|
},
|
||||||
},
|
{
|
||||||
{
|
addsTo: { pack: "codeql/java-all", extensible: "summaryModel" },
|
||||||
addsTo: { pack: "codeql/java-all", extensible: "summaryModel" },
|
data: [],
|
||||||
data: [],
|
},
|
||||||
},
|
{
|
||||||
{
|
addsTo: { pack: "codeql/java-all", extensible: "neutralModel" },
|
||||||
addsTo: { pack: "codeql/java-all", extensible: "neutralModel" },
|
data: [],
|
||||||
data: [],
|
},
|
||||||
},
|
],
|
||||||
],
|
},
|
||||||
});
|
QueryLanguage.Java,
|
||||||
|
);
|
||||||
|
|
||||||
expect(data).toEqual({
|
expect(data).toEqual({
|
||||||
"org.sql2o.Connection#createQuery(String)": [
|
"org.sql2o.Connection#createQuery(String)": [
|
||||||
@@ -1033,13 +1037,16 @@ describe("loadDataExtensionYaml", () => {
|
|||||||
|
|
||||||
it("returns undefined if given a string", () => {
|
it("returns undefined if given a string", () => {
|
||||||
expect(() =>
|
expect(() =>
|
||||||
loadDataExtensionYaml(`extensions:
|
loadDataExtensionYaml(
|
||||||
|
`extensions:
|
||||||
- addsTo:
|
- addsTo:
|
||||||
pack: codeql/java-all
|
pack: codeql/java-all
|
||||||
extensible: sinkModel
|
extensible: sinkModel
|
||||||
data:
|
data:
|
||||||
- ["org.sql2o","Connection",true,"createQuery","(String)","","Argument[0]","sql","manual"]
|
- ["org.sql2o","Connection",true,"createQuery","(String)","","Argument[0]","sql","manual"]
|
||||||
`),
|
`,
|
||||||
|
QueryLanguage.Java,
|
||||||
|
),
|
||||||
).toThrow("Invalid data extension YAML: must be object");
|
).toThrow("Invalid data extension YAML: must be object");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { ExtensionPack } from "../../../../src/model-editor/shared/extension-pac
|
|||||||
import { join } from "path";
|
import { join } from "path";
|
||||||
import { extLogger } from "../../../../src/common/logging/vscode";
|
import { extLogger } from "../../../../src/common/logging/vscode";
|
||||||
import { homedir } from "os";
|
import { homedir } from "os";
|
||||||
|
import { QueryLanguage } from "../../../../src/common/query-language";
|
||||||
|
|
||||||
const dummyExtensionPackContents = `
|
const dummyExtensionPackContents = `
|
||||||
name: dummy/pack
|
name: dummy/pack
|
||||||
@@ -192,6 +193,7 @@ describe("modeled-method-fs", () => {
|
|||||||
|
|
||||||
const modeledMethods = await loadModeledMethods(
|
const modeledMethods = await loadModeledMethods(
|
||||||
makeExtensionPack(extensionPackPath),
|
makeExtensionPack(extensionPackPath),
|
||||||
|
QueryLanguage.Java,
|
||||||
cli,
|
cli,
|
||||||
extLogger,
|
extLogger,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { createMockModelingStore } from "../../../__mocks__/model-editor/modelin
|
|||||||
import { createMockModelEditorViewTracker } from "../../../__mocks__/model-editor/modelEditorViewTrackerMock";
|
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";
|
||||||
|
|
||||||
describe("ModelEditorView", () => {
|
describe("ModelEditorView", () => {
|
||||||
const app = createMockApp({});
|
const app = createMockApp({});
|
||||||
@@ -56,6 +57,7 @@ describe("ModelEditorView", () => {
|
|||||||
queryDir,
|
queryDir,
|
||||||
databaseItem,
|
databaseItem,
|
||||||
extensionPack,
|
extensionPack,
|
||||||
|
QueryLanguage.Java,
|
||||||
mode,
|
mode,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user