Remove automodel-related functionality
This commit is contained in:
@@ -560,16 +560,6 @@ interface SetModifiedMethodsMessage {
|
|||||||
methodSignatures: string[];
|
methodSignatures: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SetInProgressMethodsMessage {
|
|
||||||
t: "setInProgressMethods";
|
|
||||||
methods: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface SetProcessedByAutoModelMethodsMessage {
|
|
||||||
t: "setProcessedByAutoModelMethods";
|
|
||||||
methods: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface SwitchModeMessage {
|
interface SwitchModeMessage {
|
||||||
t: "switchMode";
|
t: "switchMode";
|
||||||
mode: Mode;
|
mode: Mode;
|
||||||
@@ -601,17 +591,6 @@ interface GenerateMethodMessage {
|
|||||||
t: "generateMethod";
|
t: "generateMethod";
|
||||||
}
|
}
|
||||||
|
|
||||||
interface GenerateMethodsFromLlmMessage {
|
|
||||||
t: "generateMethodsFromLlm";
|
|
||||||
packageName: string;
|
|
||||||
methodSignatures: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface StopGeneratingMethodsFromLlmMessage {
|
|
||||||
t: "stopGeneratingMethodsFromLlm";
|
|
||||||
packageName: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface StartModelEvaluationMessage {
|
interface StartModelEvaluationMessage {
|
||||||
t: "startModelEvaluation";
|
t: "startModelEvaluation";
|
||||||
}
|
}
|
||||||
@@ -649,16 +628,6 @@ interface SetInModelingModeMessage {
|
|||||||
inModelingMode: boolean;
|
inModelingMode: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SetInProgressMessage {
|
|
||||||
t: "setInProgress";
|
|
||||||
inProgress: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface SetProcessedByAutoModelMessage {
|
|
||||||
t: "setProcessedByAutoModel";
|
|
||||||
processedByAutoModel: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface RevealMethodMessage {
|
interface RevealMethodMessage {
|
||||||
t: "revealMethod";
|
t: "revealMethod";
|
||||||
methodSignature: string;
|
methodSignature: string;
|
||||||
@@ -679,8 +648,6 @@ export type ToModelEditorMessage =
|
|||||||
| SetMethodsMessage
|
| SetMethodsMessage
|
||||||
| SetModeledAndModifiedMethodsMessage
|
| SetModeledAndModifiedMethodsMessage
|
||||||
| SetModifiedMethodsMessage
|
| SetModifiedMethodsMessage
|
||||||
| SetInProgressMethodsMessage
|
|
||||||
| SetProcessedByAutoModelMethodsMessage
|
|
||||||
| RevealMethodMessage
|
| RevealMethodMessage
|
||||||
| SetAccessPathSuggestionsMessage
|
| SetAccessPathSuggestionsMessage
|
||||||
| SetModelEvaluationRunMessage;
|
| SetModelEvaluationRunMessage;
|
||||||
@@ -694,8 +661,6 @@ export type FromModelEditorMessage =
|
|||||||
| JumpToMethodMessage
|
| JumpToMethodMessage
|
||||||
| SaveModeledMethods
|
| SaveModeledMethods
|
||||||
| GenerateMethodMessage
|
| GenerateMethodMessage
|
||||||
| GenerateMethodsFromLlmMessage
|
|
||||||
| StopGeneratingMethodsFromLlmMessage
|
|
||||||
| ModelDependencyMessage
|
| ModelDependencyMessage
|
||||||
| HideModeledMethodsMessage
|
| HideModeledMethodsMessage
|
||||||
| SetMultipleModeledMethodsMessage
|
| SetMultipleModeledMethodsMessage
|
||||||
@@ -738,8 +703,6 @@ interface SetSelectedMethodMessage {
|
|||||||
method: Method;
|
method: Method;
|
||||||
modeledMethods: ModeledMethod[];
|
modeledMethods: ModeledMethod[];
|
||||||
isModified: boolean;
|
isModified: boolean;
|
||||||
isInProgress: boolean;
|
|
||||||
processedByAutoModel: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ToMethodModelingMessage =
|
export type ToMethodModelingMessage =
|
||||||
@@ -748,9 +711,7 @@ export type ToMethodModelingMessage =
|
|||||||
| SetMethodModifiedMessage
|
| SetMethodModifiedMessage
|
||||||
| SetNoMethodSelectedMessage
|
| SetNoMethodSelectedMessage
|
||||||
| SetSelectedMethodMessage
|
| SetSelectedMethodMessage
|
||||||
| SetInModelingModeMessage
|
| SetInModelingModeMessage;
|
||||||
| SetInProgressMessage
|
|
||||||
| SetProcessedByAutoModelMessage;
|
|
||||||
|
|
||||||
interface SetModelAlertsViewStateMessage {
|
interface SetModelAlertsViewStateMessage {
|
||||||
t: "setModelAlertsViewState";
|
t: "setModelAlertsViewState";
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ export enum RequestKind {
|
|||||||
GetVariantAnalysisRepo = "getVariantAnalysisRepo",
|
GetVariantAnalysisRepo = "getVariantAnalysisRepo",
|
||||||
GetVariantAnalysisRepoResult = "getVariantAnalysisRepoResult",
|
GetVariantAnalysisRepoResult = "getVariantAnalysisRepoResult",
|
||||||
CodeSearch = "codeSearch",
|
CodeSearch = "codeSearch",
|
||||||
AutoModel = "autoModel",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BasicErrorResponse {
|
export interface BasicErrorResponse {
|
||||||
@@ -92,31 +91,13 @@ interface CodeSearchRequest {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AutoModelResponse {
|
|
||||||
models: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface AutoModelRequest {
|
|
||||||
request: {
|
|
||||||
kind: RequestKind.AutoModel;
|
|
||||||
body?: {
|
|
||||||
candidates: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
response: {
|
|
||||||
status: number;
|
|
||||||
body?: AutoModelResponse | BasicErrorResponse;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export type GitHubApiRequest =
|
export type GitHubApiRequest =
|
||||||
| GetRepoRequest
|
| GetRepoRequest
|
||||||
| SubmitVariantAnalysisRequest
|
| SubmitVariantAnalysisRequest
|
||||||
| GetVariantAnalysisRequest
|
| GetVariantAnalysisRequest
|
||||||
| GetVariantAnalysisRepoRequest
|
| GetVariantAnalysisRepoRequest
|
||||||
| GetVariantAnalysisRepoResultRequest
|
| GetVariantAnalysisRepoResultRequest
|
||||||
| CodeSearchRequest
|
| CodeSearchRequest;
|
||||||
| AutoModelRequest;
|
|
||||||
|
|
||||||
export const isGetRepoRequest = (
|
export const isGetRepoRequest = (
|
||||||
request: GitHubApiRequest,
|
request: GitHubApiRequest,
|
||||||
@@ -146,8 +127,3 @@ export const isCodeSearchRequest = (
|
|||||||
request: GitHubApiRequest,
|
request: GitHubApiRequest,
|
||||||
): request is CodeSearchRequest =>
|
): request is CodeSearchRequest =>
|
||||||
request.request.kind === RequestKind.CodeSearch;
|
request.request.kind === RequestKind.CodeSearch;
|
||||||
|
|
||||||
export const isAutoModelRequest = (
|
|
||||||
request: GitHubApiRequest,
|
|
||||||
): request is AutoModelRequest =>
|
|
||||||
request.request.kind === RequestKind.AutoModel;
|
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import { DisposableObject } from "../disposable-object";
|
|||||||
import { gzipDecode } from "../zlib";
|
import { gzipDecode } from "../zlib";
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
AutoModelResponse,
|
|
||||||
BasicErrorResponse,
|
BasicErrorResponse,
|
||||||
CodeSearchResponse,
|
CodeSearchResponse,
|
||||||
GetVariantAnalysisRepoResultRequest,
|
GetVariantAnalysisRepoResultRequest,
|
||||||
@@ -265,23 +264,6 @@ async function createGitHubApiRequest(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const autoModelMatch = url.match(
|
|
||||||
/\/repos\/github\/codeql\/code-scanning\/codeql\/auto-model/,
|
|
||||||
);
|
|
||||||
if (autoModelMatch) {
|
|
||||||
return {
|
|
||||||
request: {
|
|
||||||
kind: RequestKind.AutoModel,
|
|
||||||
},
|
|
||||||
response: {
|
|
||||||
status,
|
|
||||||
body: await jsonResponseBody<
|
|
||||||
BasicErrorResponse | AutoModelResponse | undefined
|
|
||||||
>(response),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import type { RequestHandler } from "msw";
|
|||||||
import { http } from "msw";
|
import { http } from "msw";
|
||||||
import type { GitHubApiRequest } from "./gh-api-request";
|
import type { GitHubApiRequest } from "./gh-api-request";
|
||||||
import {
|
import {
|
||||||
isAutoModelRequest,
|
|
||||||
isCodeSearchRequest,
|
isCodeSearchRequest,
|
||||||
isGetRepoRequest,
|
isGetRepoRequest,
|
||||||
isGetVariantAnalysisRepoRequest,
|
isGetVariantAnalysisRepoRequest,
|
||||||
@@ -41,7 +40,6 @@ export async function createRequestHandlers(
|
|||||||
createGetVariantAnalysisRepoRequestHandler(requests),
|
createGetVariantAnalysisRepoRequestHandler(requests),
|
||||||
createGetVariantAnalysisRepoResultRequestHandler(requests),
|
createGetVariantAnalysisRepoResultRequestHandler(requests),
|
||||||
createCodeSearchRequestHandler(requests),
|
createCodeSearchRequestHandler(requests),
|
||||||
createAutoModelRequestHandler(requests),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
return handlers;
|
return handlers;
|
||||||
@@ -230,29 +228,3 @@ function createCodeSearchRequestHandler(
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function createAutoModelRequestHandler(
|
|
||||||
requests: GitHubApiRequest[],
|
|
||||||
): RequestHandler {
|
|
||||||
const autoModelRequests = requests.filter(isAutoModelRequest);
|
|
||||||
let requestIndex = 0;
|
|
||||||
|
|
||||||
// During automodeling there can be multiple API requests for each batch
|
|
||||||
// of candidates we want to model. We need to return different responses for each request,
|
|
||||||
// so keep an index of the request and return the appropriate response.
|
|
||||||
return http.post(
|
|
||||||
`${baseUrl}/repos/github/codeql/code-scanning/codeql/auto-model`,
|
|
||||||
() => {
|
|
||||||
const request = autoModelRequests[requestIndex];
|
|
||||||
|
|
||||||
if (requestIndex < autoModelRequests.length - 1) {
|
|
||||||
// If there are more requests to come, increment the index.
|
|
||||||
requestIndex++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return jsonResponse(request.response.body, {
|
|
||||||
status: request.response.status,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"request": {
|
|
||||||
"kind": "autoModel"
|
|
||||||
},
|
|
||||||
"response": {
|
|
||||||
"status": 200,
|
|
||||||
"body": {
|
|
||||||
"models": "extensions:\n- addsTo: {extensible: sinkModel, pack: codeql/java-all}\n data:\n - [javax.servlet.http, HttpServletResponse, true, sendRedirect, (String), '', 'Argument[this]',\n request-forgery, ai-generated]\n - [javax.servlet.http, HttpServletResponse, true, sendRedirect, (String), '', 'Argument[0]',\n request-forgery, ai-generated]\n"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"request": {
|
|
||||||
"kind": "autoModel"
|
|
||||||
},
|
|
||||||
"response": {
|
|
||||||
"status": 200,
|
|
||||||
"body": {
|
|
||||||
"models": "extensions:\n- addsTo: {extensible: sinkModel, pack: codeql/java-all}\n data:\n - [javax.servlet, MultipartConfigElement, true, MultipartConfigElement, (String),\n '', 'Argument[0]', request-forgery, ai-generated]\n"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
This scenario is best when modeling the `javax.servlet-api` package.
|
|
||||||
@@ -1,10 +1,5 @@
|
|||||||
import { promisify } from "util";
|
import { promisify } from "util";
|
||||||
import { gzip, gunzip } from "zlib";
|
import { gunzip } from "zlib";
|
||||||
|
|
||||||
/**
|
|
||||||
* Promisified version of zlib.gzip
|
|
||||||
*/
|
|
||||||
export const gzipEncode = promisify(gzip);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Promisified version of zlib.gunzip
|
* Promisified version of zlib.gunzip
|
||||||
|
|||||||
@@ -828,15 +828,6 @@ export async function setAutogenerateQlPacks(choice: AutogenerateQLPacks) {
|
|||||||
|
|
||||||
const MODEL_SETTING = new Setting("model", ROOT_SETTING);
|
const MODEL_SETTING = new Setting("model", ROOT_SETTING);
|
||||||
const FLOW_GENERATION = new Setting("flowGeneration", MODEL_SETTING);
|
const FLOW_GENERATION = new Setting("flowGeneration", MODEL_SETTING);
|
||||||
const LLM_GENERATION = new Setting("llmGeneration", MODEL_SETTING);
|
|
||||||
const LLM_GENERATION_BATCH_SIZE = new Setting(
|
|
||||||
"llmGenerationBatchSize",
|
|
||||||
MODEL_SETTING,
|
|
||||||
);
|
|
||||||
const LLM_GENERATION_DEV_ENDPOINT = new Setting(
|
|
||||||
"llmGenerationDevEndpoint",
|
|
||||||
MODEL_SETTING,
|
|
||||||
);
|
|
||||||
const MODEL_EVALUATION = new Setting("evaluation", MODEL_SETTING);
|
const MODEL_EVALUATION = new Setting("evaluation", MODEL_SETTING);
|
||||||
const MODEL_PACK_LOCATION = new Setting("packLocation", MODEL_SETTING);
|
const MODEL_PACK_LOCATION = new Setting("packLocation", MODEL_SETTING);
|
||||||
const MODEL_PACK_NAME = new Setting("packName", MODEL_SETTING);
|
const MODEL_PACK_NAME = new Setting("packName", MODEL_SETTING);
|
||||||
@@ -850,7 +841,6 @@ export type ModelConfigPackVariables = {
|
|||||||
|
|
||||||
export interface ModelConfig {
|
export interface ModelConfig {
|
||||||
flowGeneration: boolean;
|
flowGeneration: boolean;
|
||||||
llmGeneration: boolean;
|
|
||||||
getPackLocation(
|
getPackLocation(
|
||||||
languageId: string,
|
languageId: string,
|
||||||
variables: ModelConfigPackVariables,
|
variables: ModelConfigPackVariables,
|
||||||
@@ -870,26 +860,6 @@ export class ModelConfigListener extends ConfigListener implements ModelConfig {
|
|||||||
return !!FLOW_GENERATION.getValue<boolean>();
|
return !!FLOW_GENERATION.getValue<boolean>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public get llmGeneration(): boolean {
|
|
||||||
return !!LLM_GENERATION.getValue<boolean>() && !hasEnterpriseUri();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Limits the number of candidates we send to the model in each request to avoid long requests.
|
|
||||||
* Note that the model may return fewer than this number of candidates.
|
|
||||||
*/
|
|
||||||
public get llmGenerationBatchSize(): number {
|
|
||||||
return LLM_GENERATION_BATCH_SIZE.getValue<number | null>() || 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The URL of the endpoint to use for LLM generation. This should only be set
|
|
||||||
* if you want to test against a dev server.
|
|
||||||
*/
|
|
||||||
public get llmGenerationDevEndpoint(): string | undefined {
|
|
||||||
return LLM_GENERATION_DEV_ENDPOINT.getValue<string | undefined>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public get modelEvaluation(): boolean {
|
public get modelEvaluation(): boolean {
|
||||||
return !!MODEL_EVALUATION.getValue<boolean>();
|
return !!MODEL_EVALUATION.getValue<boolean>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,65 +0,0 @@
|
|||||||
import type { Credentials } from "../common/authentication";
|
|
||||||
import type { OctokitResponse } from "@octokit/types";
|
|
||||||
import fetch from "node-fetch";
|
|
||||||
import type { ModelConfigListener } from "../config";
|
|
||||||
|
|
||||||
export enum AutomodelMode {
|
|
||||||
Unspecified = "AUTOMODEL_MODE_UNSPECIFIED",
|
|
||||||
Framework = "AUTOMODEL_MODE_FRAMEWORK",
|
|
||||||
Application = "AUTOMODEL_MODE_APPLICATION",
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ModelRequest {
|
|
||||||
mode: AutomodelMode;
|
|
||||||
// Base64-encoded GZIP-compressed SARIF log
|
|
||||||
candidates: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ModelResponse {
|
|
||||||
models: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function autoModel(
|
|
||||||
credentials: Credentials,
|
|
||||||
request: ModelRequest,
|
|
||||||
modelingConfig: ModelConfigListener,
|
|
||||||
): Promise<ModelResponse> {
|
|
||||||
const devEndpoint = modelingConfig.llmGenerationDevEndpoint;
|
|
||||||
if (devEndpoint) {
|
|
||||||
return callAutoModelDevEndpoint(devEndpoint, request);
|
|
||||||
} else {
|
|
||||||
const octokit = await credentials.getOctokit();
|
|
||||||
|
|
||||||
const response: OctokitResponse<ModelResponse> = await octokit.request(
|
|
||||||
"POST /repos/github/codeql/code-scanning/codeql/auto-model",
|
|
||||||
{
|
|
||||||
data: request,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
return response.data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function callAutoModelDevEndpoint(
|
|
||||||
endpoint: string,
|
|
||||||
request: ModelRequest,
|
|
||||||
): Promise<ModelResponse> {
|
|
||||||
const json = JSON.stringify(request);
|
|
||||||
const response = await fetch(endpoint, {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: json,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(
|
|
||||||
`Error calling auto-model API: ${response.status} ${response.statusText}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = await response.json();
|
|
||||||
return data as ModelResponse;
|
|
||||||
}
|
|
||||||
@@ -1,233 +0,0 @@
|
|||||||
import type { CodeQLCliServer, SourceInfo } from "../codeql-cli/cli";
|
|
||||||
import type { CoreCompletedQuery, QueryRunner } from "../query-server";
|
|
||||||
import type { DatabaseItem } from "../databases/local-databases";
|
|
||||||
import type { ProgressCallback } from "../common/vscode/progress";
|
|
||||||
import type { Log } from "sarif";
|
|
||||||
import type { Mode } from "./shared/mode";
|
|
||||||
import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
|
|
||||||
import { interpretResultsSarif } from "../query-results";
|
|
||||||
import { join } from "path";
|
|
||||||
import { dir } from "tmp-promise";
|
|
||||||
import { writeFile, outputFile } from "fs-extra";
|
|
||||||
import { dump as dumpYaml } from "js-yaml";
|
|
||||||
import type { MethodSignature } from "./method";
|
|
||||||
import { runQuery } from "../local-queries/run-query";
|
|
||||||
import type { QueryMetadata } from "../common/interface-types";
|
|
||||||
import type { CancellationTokenSource } from "vscode";
|
|
||||||
import { resolveQueries } from "../local-queries";
|
|
||||||
import { modeTag } from "./mode-tag";
|
|
||||||
|
|
||||||
type AutoModelQueriesOptions = {
|
|
||||||
mode: Mode;
|
|
||||||
candidateMethods: MethodSignature[];
|
|
||||||
cliServer: CodeQLCliServer;
|
|
||||||
queryRunner: QueryRunner;
|
|
||||||
databaseItem: DatabaseItem;
|
|
||||||
queryStorageDir: string;
|
|
||||||
|
|
||||||
progress: ProgressCallback;
|
|
||||||
cancellationTokenSource: CancellationTokenSource;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type AutoModelQueriesResult = {
|
|
||||||
candidates: Log;
|
|
||||||
};
|
|
||||||
|
|
||||||
export async function runAutoModelQueries({
|
|
||||||
mode,
|
|
||||||
candidateMethods,
|
|
||||||
cliServer,
|
|
||||||
queryRunner,
|
|
||||||
databaseItem,
|
|
||||||
queryStorageDir,
|
|
||||||
progress,
|
|
||||||
cancellationTokenSource,
|
|
||||||
}: AutoModelQueriesOptions): Promise<AutoModelQueriesResult | undefined> {
|
|
||||||
// First, resolve the query that we want to run.
|
|
||||||
const queryPath = await resolveAutomodelQuery(
|
|
||||||
cliServer,
|
|
||||||
databaseItem,
|
|
||||||
"candidates",
|
|
||||||
mode,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Generate a pack containing the candidate filters
|
|
||||||
const { packDir: filterPackDir, cleanup: cleanupFilterPack } =
|
|
||||||
await generateCandidateFilterPack(databaseItem.language, candidateMethods);
|
|
||||||
|
|
||||||
const additionalPacks = [...getOnDiskWorkspaceFolders(), filterPackDir];
|
|
||||||
const extensionPacks = Object.keys(
|
|
||||||
await cliServer.resolveQlpacks(additionalPacks, true),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Run the actual query
|
|
||||||
const completedQuery = await runQuery({
|
|
||||||
queryRunner,
|
|
||||||
databaseItem,
|
|
||||||
queryPath,
|
|
||||||
queryStorageDir,
|
|
||||||
additionalPacks,
|
|
||||||
extensionPacks,
|
|
||||||
progress,
|
|
||||||
token: cancellationTokenSource.token,
|
|
||||||
});
|
|
||||||
|
|
||||||
await cleanupFilterPack();
|
|
||||||
|
|
||||||
if (!completedQuery) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get metadata for the query. This is required to interpret the results. We already know the kind is problem
|
|
||||||
// (because of the constraint in resolveQueries), so we don't need any more checks on the metadata.
|
|
||||||
const metadata = await cliServer.resolveMetadata(queryPath);
|
|
||||||
|
|
||||||
// CodeQL needs to have access to the database to be able to retrieve the
|
|
||||||
// snippets from it. The source location prefix is used to determine the
|
|
||||||
// base path of the database.
|
|
||||||
const sourceLocationPrefix =
|
|
||||||
await databaseItem.getSourceLocationPrefix(cliServer);
|
|
||||||
const sourceArchiveUri = databaseItem.sourceArchive;
|
|
||||||
const sourceInfo =
|
|
||||||
sourceArchiveUri === undefined
|
|
||||||
? undefined
|
|
||||||
: {
|
|
||||||
sourceArchive: sourceArchiveUri.fsPath,
|
|
||||||
sourceLocationPrefix,
|
|
||||||
};
|
|
||||||
|
|
||||||
const candidates = await interpretAutomodelResults(
|
|
||||||
cliServer,
|
|
||||||
completedQuery,
|
|
||||||
metadata,
|
|
||||||
sourceInfo,
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
candidates,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async function resolveAutomodelQuery(
|
|
||||||
cliServer: CodeQLCliServer,
|
|
||||||
databaseItem: DatabaseItem,
|
|
||||||
queryTag: string,
|
|
||||||
mode: Mode,
|
|
||||||
): Promise<string> {
|
|
||||||
const packsToSearch = [`codeql/${databaseItem.language}-automodel-queries`];
|
|
||||||
|
|
||||||
// First, resolve the query that we want to run.
|
|
||||||
// All queries are tagged like this:
|
|
||||||
// internal extract automodel <mode> <queryTag>
|
|
||||||
// Example: internal extract automodel framework-mode candidates
|
|
||||||
const queries = await resolveQueries(
|
|
||||||
cliServer,
|
|
||||||
packsToSearch,
|
|
||||||
`Extract automodel ${queryTag}`,
|
|
||||||
{
|
|
||||||
kind: "problem",
|
|
||||||
"tags contain all": ["automodel", modeTag(mode), ...queryTag.split(" ")],
|
|
||||||
},
|
|
||||||
);
|
|
||||||
if (queries.length > 1) {
|
|
||||||
throw new Error(
|
|
||||||
`Found multiple auto model queries for ${mode} ${queryTag}. Can't continue`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (queries.length === 0) {
|
|
||||||
throw new Error(
|
|
||||||
`Did not found any auto model queries for ${mode} ${queryTag}. Can't continue`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return queries[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
type CandidateFilterPackResult = {
|
|
||||||
packDir: string;
|
|
||||||
cleanup: () => Promise<void>;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* generateCandidateFilterPack will create a temporary extension pack.
|
|
||||||
* This pack will contain a filter that will restrict the automodel queries
|
|
||||||
* to the specified candidate methods only.
|
|
||||||
* This is done using the `extensible` predicate "automodelCandidateFilter".
|
|
||||||
* @param language
|
|
||||||
* @param candidateMethods
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
export async function generateCandidateFilterPack(
|
|
||||||
language: string,
|
|
||||||
candidateMethods: MethodSignature[],
|
|
||||||
): Promise<CandidateFilterPackResult> {
|
|
||||||
// Pack resides in a temporary directory, to not pollute the workspace.
|
|
||||||
const { path: packDir, cleanup } = await dir({ unsafeCleanup: true });
|
|
||||||
|
|
||||||
const syntheticConfigPack = {
|
|
||||||
name: "codeql/automodel-filter",
|
|
||||||
version: "0.0.0",
|
|
||||||
library: true,
|
|
||||||
extensionTargets: {
|
|
||||||
[`codeql/${language}-automodel-queries`]: "*",
|
|
||||||
},
|
|
||||||
dataExtensions: ["filter.yml"],
|
|
||||||
};
|
|
||||||
|
|
||||||
const qlpackFile = join(packDir, "codeql-pack.yml");
|
|
||||||
await outputFile(qlpackFile, dumpYaml(syntheticConfigPack), "utf8");
|
|
||||||
|
|
||||||
// The predicate has the following defintion:
|
|
||||||
// extensible predicate automodelCandidateFilter(string package, string type, string name, string signature)
|
|
||||||
const dataRows = candidateMethods.map((method) => [
|
|
||||||
method.packageName,
|
|
||||||
method.typeName,
|
|
||||||
method.methodName,
|
|
||||||
method.methodParameters,
|
|
||||||
]);
|
|
||||||
|
|
||||||
const filter = {
|
|
||||||
extensions: [
|
|
||||||
{
|
|
||||||
addsTo: {
|
|
||||||
pack: `codeql/${language}-automodel-queries`,
|
|
||||||
extensible: "automodelCandidateFilter",
|
|
||||||
},
|
|
||||||
data: dataRows,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
const filterFile = join(packDir, "filter.yml");
|
|
||||||
await writeFile(filterFile, dumpYaml(filter), "utf8");
|
|
||||||
|
|
||||||
return {
|
|
||||||
packDir,
|
|
||||||
cleanup,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async function interpretAutomodelResults(
|
|
||||||
cliServer: CodeQLCliServer,
|
|
||||||
completedQuery: CoreCompletedQuery,
|
|
||||||
metadata: QueryMetadata,
|
|
||||||
sourceInfo: SourceInfo | undefined,
|
|
||||||
): Promise<Log> {
|
|
||||||
const interpretedResultsPath = join(
|
|
||||||
completedQuery.outputDir.querySaveDir,
|
|
||||||
"results.sarif",
|
|
||||||
);
|
|
||||||
|
|
||||||
const { ...sarif } = await interpretResultsSarif(
|
|
||||||
cliServer,
|
|
||||||
metadata,
|
|
||||||
{
|
|
||||||
resultsPath: completedQuery.outputDir.bqrsPath,
|
|
||||||
interpretedResultsPath,
|
|
||||||
},
|
|
||||||
sourceInfo,
|
|
||||||
["--sarif-add-snippets"],
|
|
||||||
);
|
|
||||||
|
|
||||||
return sarif;
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
import type { ModelRequest } from "./auto-model-api";
|
|
||||||
import { AutomodelMode } from "./auto-model-api";
|
|
||||||
import { Mode } from "./shared/mode";
|
|
||||||
import type { AutoModelQueriesResult } from "./auto-model-codeml-queries";
|
|
||||||
import { assertNever } from "../common/helpers-pure";
|
|
||||||
import type { Log } from "sarif";
|
|
||||||
import { gzipEncode } from "../common/zlib";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode a SARIF log to the format expected by the server: JSON, GZIP-compressed, base64-encoded
|
|
||||||
* @param log SARIF log to encode
|
|
||||||
* @returns base64-encoded GZIP-compressed SARIF log
|
|
||||||
*/
|
|
||||||
export async function encodeSarif(log: Log): Promise<string> {
|
|
||||||
const json = JSON.stringify(log);
|
|
||||||
const buffer = Buffer.from(json, "utf-8");
|
|
||||||
const compressed = await gzipEncode(buffer);
|
|
||||||
return compressed.toString("base64");
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function createAutoModelRequest(
|
|
||||||
mode: Mode,
|
|
||||||
result: AutoModelQueriesResult,
|
|
||||||
): Promise<ModelRequest> {
|
|
||||||
let requestMode: AutomodelMode;
|
|
||||||
switch (mode) {
|
|
||||||
case Mode.Application:
|
|
||||||
requestMode = AutomodelMode.Application;
|
|
||||||
break;
|
|
||||||
case Mode.Framework:
|
|
||||||
requestMode = AutomodelMode.Framework;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assertNever(mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
mode: requestMode,
|
|
||||||
candidates: await encodeSarif(result.candidates),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,249 +0,0 @@
|
|||||||
import type { Method, MethodSignature } from "./method";
|
|
||||||
import type { ModeledMethod } from "./modeled-method";
|
|
||||||
import { load as loadYaml } from "js-yaml";
|
|
||||||
import type { ProgressCallback } from "../common/vscode/progress";
|
|
||||||
import { withProgress } from "../common/vscode/progress";
|
|
||||||
import { createAutoModelRequest } from "./auto-model";
|
|
||||||
import { getCandidates } from "./shared/auto-model-candidates";
|
|
||||||
import { runAutoModelQueries } from "./auto-model-codeml-queries";
|
|
||||||
import { loadDataExtensionYaml } from "./yaml";
|
|
||||||
import type { ModelRequest, ModelResponse } from "./auto-model-api";
|
|
||||||
import { autoModel } from "./auto-model-api";
|
|
||||||
import { RequestError } from "@octokit/request-error";
|
|
||||||
import { showAndLogExceptionWithTelemetry } from "../common/logging";
|
|
||||||
import { redactableError } from "../common/errors";
|
|
||||||
import type { App } from "../common/app";
|
|
||||||
import type { CodeQLCliServer } from "../codeql-cli/cli";
|
|
||||||
import type { QueryRunner } from "../query-server";
|
|
||||||
import type { DatabaseItem } from "../databases/local-databases";
|
|
||||||
import type { Mode } from "./shared/mode";
|
|
||||||
import { CancellationTokenSource } from "vscode";
|
|
||||||
import type { ModelingStore } from "./modeling-store";
|
|
||||||
import type { ModelConfigListener } from "../config";
|
|
||||||
import type { QueryLanguage } from "../common/query-language";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The auto-modeler holds state around auto-modeling jobs and allows
|
|
||||||
* starting and stopping them.
|
|
||||||
*/
|
|
||||||
export class AutoModeler {
|
|
||||||
// Keep track of auto-modeling jobs that are in progress
|
|
||||||
// so that we can stop them.
|
|
||||||
private readonly jobs: Map<string, CancellationTokenSource>;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private readonly app: App,
|
|
||||||
private readonly cliServer: CodeQLCliServer,
|
|
||||||
private readonly queryRunner: QueryRunner,
|
|
||||||
private readonly modelConfig: ModelConfigListener,
|
|
||||||
private readonly modelingStore: ModelingStore,
|
|
||||||
private readonly queryStorageDir: string,
|
|
||||||
private readonly databaseItem: DatabaseItem,
|
|
||||||
private readonly language: QueryLanguage,
|
|
||||||
private readonly addModeledMethods: (
|
|
||||||
modeledMethods: Record<string, ModeledMethod[]>,
|
|
||||||
) => Promise<void>,
|
|
||||||
) {
|
|
||||||
this.jobs = new Map<string, CancellationTokenSource>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Models the given package's external API usages, except
|
|
||||||
* the ones that are already modeled.
|
|
||||||
* @param packageName The name of the package to model.
|
|
||||||
* @param methods The methods.
|
|
||||||
* @param modeledMethods The currently modeled methods.
|
|
||||||
* @param mode The mode we are modeling in.
|
|
||||||
*/
|
|
||||||
public async startModeling(
|
|
||||||
packageName: string,
|
|
||||||
methods: readonly Method[],
|
|
||||||
modeledMethods: Record<string, readonly ModeledMethod[]>,
|
|
||||||
processedByAutoModelMethods: Set<string>,
|
|
||||||
mode: Mode,
|
|
||||||
): Promise<void> {
|
|
||||||
if (this.jobs.has(packageName)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const cancellationTokenSource = new CancellationTokenSource();
|
|
||||||
this.jobs.set(packageName, cancellationTokenSource);
|
|
||||||
|
|
||||||
try {
|
|
||||||
await this.modelPackage(
|
|
||||||
packageName,
|
|
||||||
methods,
|
|
||||||
modeledMethods,
|
|
||||||
processedByAutoModelMethods,
|
|
||||||
mode,
|
|
||||||
cancellationTokenSource,
|
|
||||||
);
|
|
||||||
} finally {
|
|
||||||
this.jobs.delete(packageName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stops modeling the given package.
|
|
||||||
* @param packageName The name of the package to stop modeling.
|
|
||||||
*/
|
|
||||||
public async stopModeling(packageName: string): Promise<void> {
|
|
||||||
void this.app.logger.log(`Stopping modeling for package ${packageName}`);
|
|
||||||
const cancellationTokenSource = this.jobs.get(packageName);
|
|
||||||
if (cancellationTokenSource) {
|
|
||||||
cancellationTokenSource.cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stops all in-progress modeling jobs.
|
|
||||||
*/
|
|
||||||
public async stopAllModeling(): Promise<void> {
|
|
||||||
for (const cancellationTokenSource of this.jobs.values()) {
|
|
||||||
cancellationTokenSource.cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async modelPackage(
|
|
||||||
packageName: string,
|
|
||||||
methods: readonly Method[],
|
|
||||||
modeledMethods: Record<string, readonly ModeledMethod[]>,
|
|
||||||
processedByAutoModelMethods: Set<string>,
|
|
||||||
mode: Mode,
|
|
||||||
cancellationTokenSource: CancellationTokenSource,
|
|
||||||
): Promise<void> {
|
|
||||||
void this.app.logger.log(`Modeling package ${packageName}`);
|
|
||||||
|
|
||||||
const candidateBatchSize = this.modelConfig.llmGenerationBatchSize;
|
|
||||||
|
|
||||||
await withProgress(async (progress) => {
|
|
||||||
// Fetch the candidates to send to the model
|
|
||||||
const allCandidateMethods = getCandidates(
|
|
||||||
mode,
|
|
||||||
methods,
|
|
||||||
modeledMethods,
|
|
||||||
processedByAutoModelMethods,
|
|
||||||
);
|
|
||||||
|
|
||||||
// If there are no candidates, there is nothing to model and we just return
|
|
||||||
if (allCandidateMethods.length === 0) {
|
|
||||||
void this.app.logger.log("No candidates to model. Stopping.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find number of slices to make
|
|
||||||
const batchNumber = Math.ceil(
|
|
||||||
allCandidateMethods.length / candidateBatchSize,
|
|
||||||
);
|
|
||||||
try {
|
|
||||||
for (let i = 0; i < batchNumber; i++) {
|
|
||||||
// Check if we should stop
|
|
||||||
if (cancellationTokenSource.token.isCancellationRequested) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
const start = i * candidateBatchSize;
|
|
||||||
const end = start + candidateBatchSize;
|
|
||||||
const candidatesToProcess = allCandidateMethods.slice(start, end);
|
|
||||||
const candidateSignatures = candidatesToProcess.map(
|
|
||||||
(c) => c.signature,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Let the UI know which candidates we are modeling
|
|
||||||
this.modelingStore.addInProgressMethods(
|
|
||||||
this.databaseItem,
|
|
||||||
candidateSignatures,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Kick off the process to model the slice of candidates
|
|
||||||
await this.modelCandidates(
|
|
||||||
candidatesToProcess,
|
|
||||||
mode,
|
|
||||||
progress,
|
|
||||||
cancellationTokenSource,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Let the UI know which candidates we are done modeling
|
|
||||||
this.modelingStore.removeInProgressMethods(
|
|
||||||
this.databaseItem,
|
|
||||||
candidateSignatures,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Let the UI know which methods have been sent to the LLM
|
|
||||||
this.modelingStore.addProcessedByAutoModelMethods(
|
|
||||||
this.databaseItem,
|
|
||||||
candidateSignatures,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
// Clear out in progress methods in case anything went wrong
|
|
||||||
this.modelingStore.removeInProgressMethods(
|
|
||||||
this.databaseItem,
|
|
||||||
allCandidateMethods.map((c) => c.signature),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private async modelCandidates(
|
|
||||||
candidateMethods: MethodSignature[],
|
|
||||||
mode: Mode,
|
|
||||||
progress: ProgressCallback,
|
|
||||||
cancellationTokenSource: CancellationTokenSource,
|
|
||||||
): Promise<void> {
|
|
||||||
void this.app.logger.log("Executing auto-model queries");
|
|
||||||
|
|
||||||
const usages = await runAutoModelQueries({
|
|
||||||
mode,
|
|
||||||
candidateMethods,
|
|
||||||
cliServer: this.cliServer,
|
|
||||||
queryRunner: this.queryRunner,
|
|
||||||
queryStorageDir: this.queryStorageDir,
|
|
||||||
databaseItem: this.databaseItem,
|
|
||||||
progress: (update) => progress({ ...update }),
|
|
||||||
cancellationTokenSource,
|
|
||||||
});
|
|
||||||
if (!usages) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const request = await createAutoModelRequest(mode, usages);
|
|
||||||
|
|
||||||
void this.app.logger.log("Calling auto-model API");
|
|
||||||
|
|
||||||
const response = await this.callAutoModelApi(request);
|
|
||||||
if (!response) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const models = loadYaml(response.models, {
|
|
||||||
filename: "auto-model.yml",
|
|
||||||
});
|
|
||||||
|
|
||||||
const loadedMethods = loadDataExtensionYaml(models, this.language);
|
|
||||||
if (!loadedMethods) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.addModeledMethods(loadedMethods);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async callAutoModelApi(
|
|
||||||
request: ModelRequest,
|
|
||||||
): Promise<ModelResponse | null> {
|
|
||||||
try {
|
|
||||||
return await autoModel(this.app.credentials, request, this.modelConfig);
|
|
||||||
} catch (e) {
|
|
||||||
if (e instanceof RequestError && e.status === 429) {
|
|
||||||
void showAndLogExceptionWithTelemetry(
|
|
||||||
this.app.logger,
|
|
||||||
this.app.telemetry,
|
|
||||||
redactableError`Rate limit hit, please try again soon.`,
|
|
||||||
);
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -70,8 +70,6 @@ export class MethodModelingViewProvider extends AbstractWebviewViewProvider<
|
|||||||
method: Method,
|
method: Method,
|
||||||
modeledMethods: readonly ModeledMethod[],
|
modeledMethods: readonly ModeledMethod[],
|
||||||
isModified: boolean,
|
isModified: boolean,
|
||||||
isInProgress: boolean,
|
|
||||||
processedByAutoModel: boolean,
|
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
this.method = method;
|
this.method = method;
|
||||||
this.databaseItem = databaseItem;
|
this.databaseItem = databaseItem;
|
||||||
@@ -82,8 +80,6 @@ export class MethodModelingViewProvider extends AbstractWebviewViewProvider<
|
|||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModified,
|
isModified,
|
||||||
isInProgress,
|
|
||||||
processedByAutoModel,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,8 +100,6 @@ export class MethodModelingViewProvider extends AbstractWebviewViewProvider<
|
|||||||
selectedMethod.method,
|
selectedMethod.method,
|
||||||
selectedMethod.modeledMethods,
|
selectedMethod.modeledMethods,
|
||||||
selectedMethod.isModified,
|
selectedMethod.isModified,
|
||||||
selectedMethod.isInProgress,
|
|
||||||
selectedMethod.processedByAutoModel,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -203,8 +197,6 @@ export class MethodModelingViewProvider extends AbstractWebviewViewProvider<
|
|||||||
e.method,
|
e.method,
|
||||||
e.modeledMethods,
|
e.modeledMethods,
|
||||||
e.isModified,
|
e.isModified,
|
||||||
e.isInProgress,
|
|
||||||
e.processedByAutoModel,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
@@ -232,36 +224,6 @@ export class MethodModelingViewProvider extends AbstractWebviewViewProvider<
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.push(
|
|
||||||
this.modelingEvents.onInProgressMethodsChanged(async (e) => {
|
|
||||||
if (this.method && this.databaseItem) {
|
|
||||||
const dbUri = this.databaseItem.databaseUri.toString();
|
|
||||||
if (e.dbUri === dbUri) {
|
|
||||||
const inProgress = e.methods.has(this.method.signature);
|
|
||||||
await this.postMessage({
|
|
||||||
t: "setInProgress",
|
|
||||||
inProgress,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
this.push(
|
|
||||||
this.modelingEvents.onProcessedByAutoModelMethodsChanged(async (e) => {
|
|
||||||
if (this.method && this.databaseItem) {
|
|
||||||
const dbUri = this.databaseItem.databaseUri.toString();
|
|
||||||
if (e.dbUri === dbUri) {
|
|
||||||
const processedByAutoModel = e.methods.has(this.method.signature);
|
|
||||||
await this.postMessage({
|
|
||||||
t: "setProcessedByAutoModel",
|
|
||||||
processedByAutoModel,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private registerToModelConfigEvents(): void {
|
private registerToModelConfigEvents(): void {
|
||||||
|
|||||||
@@ -204,7 +204,6 @@ export class ModelEditorModule extends DisposableObject {
|
|||||||
this.app.logger,
|
this.app.logger,
|
||||||
queryDir,
|
queryDir,
|
||||||
language,
|
language,
|
||||||
this.modelConfig,
|
|
||||||
initialMode,
|
initialMode,
|
||||||
);
|
);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import {
|
|||||||
syntheticQueryPackName,
|
syntheticQueryPackName,
|
||||||
} from "./model-editor-queries";
|
} from "./model-editor-queries";
|
||||||
import type { CodeQLCliServer } from "../codeql-cli/cli";
|
import type { CodeQLCliServer } from "../codeql-cli/cli";
|
||||||
import type { ModelConfig } from "../config";
|
|
||||||
import type { Mode } from "./shared/mode";
|
import type { Mode } from "./shared/mode";
|
||||||
import type { NotificationLogger } from "../common/logging";
|
import type { NotificationLogger } from "../common/logging";
|
||||||
|
|
||||||
@@ -30,7 +29,6 @@ import type { NotificationLogger } from "../common/logging";
|
|||||||
* @param logger The logger to use.
|
* @param logger The logger to use.
|
||||||
* @param queryDir The directory to set up.
|
* @param queryDir The directory to set up.
|
||||||
* @param language The language to use for the queries.
|
* @param language The language to use for the queries.
|
||||||
* @param modelConfig The model config to use.
|
|
||||||
* @param initialMode The initial mode to use to check the existence of the queries.
|
* @param initialMode The initial mode to use to check the existence of the queries.
|
||||||
* @returns true if the setup was successful, false otherwise.
|
* @returns true if the setup was successful, false otherwise.
|
||||||
*/
|
*/
|
||||||
@@ -39,7 +37,6 @@ export async function setUpPack(
|
|||||||
logger: NotificationLogger,
|
logger: NotificationLogger,
|
||||||
queryDir: string,
|
queryDir: string,
|
||||||
language: QueryLanguage,
|
language: QueryLanguage,
|
||||||
modelConfig: ModelConfig,
|
|
||||||
initialMode: Mode,
|
initialMode: Mode,
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
// Download the required query packs
|
// Download the required query packs
|
||||||
@@ -91,10 +88,5 @@ export async function setUpPack(
|
|||||||
await cliServer.packInstall(queryDir);
|
await cliServer.packInstall(queryDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Download any other required packs
|
|
||||||
if (language === "java" && modelConfig.llmGeneration) {
|
|
||||||
await cliServer.packDownload([`codeql/${language}-automodel-queries`]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ import {
|
|||||||
import { pickExtensionPack } from "./extension-pack-picker";
|
import { pickExtensionPack } from "./extension-pack-picker";
|
||||||
import type { QueryLanguage } from "../common/query-language";
|
import type { QueryLanguage } from "../common/query-language";
|
||||||
import { getLanguageDisplayName } from "../common/query-language";
|
import { getLanguageDisplayName } from "../common/query-language";
|
||||||
import { AutoModeler } from "./auto-modeler";
|
|
||||||
import { telemetryListener } from "../common/vscode/telemetry";
|
import { telemetryListener } from "../common/vscode/telemetry";
|
||||||
import type { ModelingStore } from "./modeling-store";
|
import type { ModelingStore } from "./modeling-store";
|
||||||
import type { ModelingEvents } from "./modeling-events";
|
import type { ModelingEvents } from "./modeling-events";
|
||||||
@@ -77,7 +76,6 @@ export class ModelEditorView extends AbstractWebview<
|
|||||||
ToModelEditorMessage,
|
ToModelEditorMessage,
|
||||||
FromModelEditorMessage
|
FromModelEditorMessage
|
||||||
> {
|
> {
|
||||||
private readonly autoModeler: AutoModeler;
|
|
||||||
private readonly modelEvaluator: ModelEvaluator;
|
private readonly modelEvaluator: ModelEvaluator;
|
||||||
private readonly languageDefinition: ModelsAsDataLanguage;
|
private readonly languageDefinition: ModelsAsDataLanguage;
|
||||||
// Cancellation token source that can be used for passing into long-running operations. Should only
|
// Cancellation token source that can be used for passing into long-running operations. Should only
|
||||||
@@ -114,19 +112,6 @@ export class ModelEditorView extends AbstractWebview<
|
|||||||
this.registerToModelingEvents();
|
this.registerToModelingEvents();
|
||||||
this.registerToModelConfigEvents();
|
this.registerToModelConfigEvents();
|
||||||
|
|
||||||
this.autoModeler = new AutoModeler(
|
|
||||||
app,
|
|
||||||
cliServer,
|
|
||||||
queryRunner,
|
|
||||||
this.modelConfig,
|
|
||||||
modelingStore,
|
|
||||||
queryStorageDir,
|
|
||||||
databaseItem,
|
|
||||||
language,
|
|
||||||
async (modeledMethods) => {
|
|
||||||
this.addModeledMethods(modeledMethods);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
this.languageDefinition = getModelsAsDataLanguage(language);
|
this.languageDefinition = getModelsAsDataLanguage(language);
|
||||||
|
|
||||||
this.modelEvaluator = new ModelEvaluator(
|
this.modelEvaluator = new ModelEvaluator(
|
||||||
@@ -317,21 +302,6 @@ export class ModelEditorView extends AbstractWebview<
|
|||||||
"model-editor-generate-modeled-methods",
|
"model-editor-generate-modeled-methods",
|
||||||
);
|
);
|
||||||
|
|
||||||
break;
|
|
||||||
case "generateMethodsFromLlm":
|
|
||||||
await this.generateModeledMethodsFromLlm(
|
|
||||||
msg.packageName,
|
|
||||||
msg.methodSignatures,
|
|
||||||
);
|
|
||||||
void telemetryListener?.sendUIInteraction(
|
|
||||||
"model-editor-generate-methods-from-llm",
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case "stopGeneratingMethodsFromLlm":
|
|
||||||
await this.autoModeler.stopModeling(msg.packageName);
|
|
||||||
void telemetryListener?.sendUIInteraction(
|
|
||||||
"model-editor-stop-generating-methods-from-llm",
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case "modelDependency":
|
case "modelDependency":
|
||||||
await this.modelDependency();
|
await this.modelDependency();
|
||||||
@@ -438,9 +408,6 @@ export class ModelEditorView extends AbstractWebview<
|
|||||||
this.modelConfig.flowGeneration) &&
|
this.modelConfig.flowGeneration) &&
|
||||||
!!modelsAsDataLanguage.modelGeneration;
|
!!modelsAsDataLanguage.modelGeneration;
|
||||||
|
|
||||||
const showLlmButton =
|
|
||||||
this.databaseItem.language === "java" && this.modelConfig.llmGeneration;
|
|
||||||
|
|
||||||
const showEvaluationUi = this.modelConfig.modelEvaluation;
|
const showEvaluationUi = this.modelConfig.modelEvaluation;
|
||||||
|
|
||||||
const sourceArchiveAvailable =
|
const sourceArchiveAvailable =
|
||||||
@@ -456,7 +423,6 @@ export class ModelEditorView extends AbstractWebview<
|
|||||||
extensionPack: this.extensionPack,
|
extensionPack: this.extensionPack,
|
||||||
language: this.language,
|
language: this.language,
|
||||||
showGenerateButton,
|
showGenerateButton,
|
||||||
showLlmButton,
|
|
||||||
showEvaluationUi,
|
showEvaluationUi,
|
||||||
mode: this.modelingStore.getMode(this.databaseItem),
|
mode: this.modelingStore.getMode(this.databaseItem),
|
||||||
showModeSwitchButton,
|
showModeSwitchButton,
|
||||||
@@ -805,33 +771,6 @@ export class ModelEditorView extends AbstractWebview<
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async generateModeledMethodsFromLlm(
|
|
||||||
packageName: string,
|
|
||||||
methodSignatures: string[],
|
|
||||||
): Promise<void> {
|
|
||||||
const methods = this.modelingStore.getMethods(
|
|
||||||
this.databaseItem,
|
|
||||||
methodSignatures,
|
|
||||||
);
|
|
||||||
const modeledMethods = this.modelingStore.getModeledMethods(
|
|
||||||
this.databaseItem,
|
|
||||||
methodSignatures,
|
|
||||||
);
|
|
||||||
const processedByAutoModelMethods =
|
|
||||||
this.modelingStore.getProcessedByAutoModelMethods(
|
|
||||||
this.databaseItem,
|
|
||||||
methodSignatures,
|
|
||||||
);
|
|
||||||
const mode = this.modelingStore.getMode(this.databaseItem);
|
|
||||||
await this.autoModeler.startModeling(
|
|
||||||
packageName,
|
|
||||||
methods,
|
|
||||||
modeledMethods,
|
|
||||||
processedByAutoModelMethods,
|
|
||||||
mode,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async modelDependency(): Promise<void> {
|
private async modelDependency(): Promise<void> {
|
||||||
return withProgress(
|
return withProgress(
|
||||||
async (progress, token) => {
|
async (progress, token) => {
|
||||||
@@ -983,30 +922,6 @@ export class ModelEditorView extends AbstractWebview<
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
this.push(
|
|
||||||
this.modelingEvents.onInProgressMethodsChanged(async (event) => {
|
|
||||||
if (event.dbUri === this.databaseItem.databaseUri.toString()) {
|
|
||||||
await this.postMessage({
|
|
||||||
t: "setInProgressMethods",
|
|
||||||
methods: Array.from(event.methods),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
this.push(
|
|
||||||
this.modelingEvents.onProcessedByAutoModelMethodsChanged(
|
|
||||||
async (event) => {
|
|
||||||
if (event.dbUri === this.databaseItem.databaseUri.toString()) {
|
|
||||||
await this.postMessage({
|
|
||||||
t: "setProcessedByAutoModelMethods",
|
|
||||||
methods: Array.from(event.methods),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
this.push(
|
this.push(
|
||||||
this.modelingEvents.onRevealInModelEditor(async (event) => {
|
this.modelingEvents.onRevealInModelEditor(async (event) => {
|
||||||
if (event.dbUri === this.databaseItem.databaseUri.toString()) {
|
if (event.dbUri === this.databaseItem.databaseUri.toString()) {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { assertNever } from "../common/helpers-pure";
|
import { assertNever } from "../common/helpers-pure";
|
||||||
import type { MethodSignature } from "./method";
|
import type { MethodSignature } from "./method";
|
||||||
import type { ModelingStatus } from "./shared/modeling-status";
|
|
||||||
|
|
||||||
export type ModeledMethodType =
|
export type ModeledMethodType =
|
||||||
| "none"
|
| "none"
|
||||||
@@ -15,10 +14,6 @@ export type Provenance =
|
|||||||
| "df-generated"
|
| "df-generated"
|
||||||
// Generated by the dataflow model and manually edited
|
// Generated by the dataflow model and manually edited
|
||||||
| "df-manual"
|
| "df-manual"
|
||||||
// Generated by the auto-model
|
|
||||||
| "ai-generated"
|
|
||||||
// Generated by the auto-model and manually edited
|
|
||||||
| "ai-manual"
|
|
||||||
// Entered by the user in the editor manually
|
// Entered by the user in the editor manually
|
||||||
| "manual";
|
| "manual";
|
||||||
|
|
||||||
@@ -112,30 +107,6 @@ export function modeledMethodSupportsProvenance(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isModelPending(
|
|
||||||
modeledMethod: ModeledMethod | undefined,
|
|
||||||
modelingStatus: ModelingStatus,
|
|
||||||
processedByAutoModel: boolean,
|
|
||||||
): boolean {
|
|
||||||
if (
|
|
||||||
(!modeledMethod || modeledMethod.type === "none") &&
|
|
||||||
processedByAutoModel
|
|
||||||
) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!modeledMethod) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
modelingStatus === "unsaved" &&
|
|
||||||
modeledMethod.type !== "none" &&
|
|
||||||
modeledMethodSupportsProvenance(modeledMethod) &&
|
|
||||||
modeledMethod.provenance === "ai-generated"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the new provenance for a modeled method based on the current provenance.
|
* Calculates the new provenance for a modeled method based on the current provenance.
|
||||||
* @param modeledMethod The modeled method if there is one.
|
* @param modeledMethod The modeled method if there is one.
|
||||||
@@ -158,13 +129,6 @@ export function calculateNewProvenance(
|
|||||||
case "df-manual":
|
case "df-manual":
|
||||||
// If the method has had manual edits, we want the provenance to stay the same.
|
// If the method has had manual edits, we want the provenance to stay the same.
|
||||||
return "df-manual";
|
return "df-manual";
|
||||||
case "ai-generated":
|
|
||||||
// If the method has been generated and there has been a change, we assume
|
|
||||||
// that the user has manually edited it.
|
|
||||||
return "ai-manual";
|
|
||||||
case "ai-manual":
|
|
||||||
// If the method has had manual edits, we want the provenance to stay the same.
|
|
||||||
return "ai-manual";
|
|
||||||
default:
|
default:
|
||||||
// The method has been modeled manually.
|
// The method has been modeled manually.
|
||||||
return "manual";
|
return "manual";
|
||||||
|
|||||||
@@ -37,18 +37,6 @@ interface SelectedMethodChangedEvent {
|
|||||||
readonly usage: Usage;
|
readonly usage: Usage;
|
||||||
readonly modeledMethods: readonly ModeledMethod[];
|
readonly modeledMethods: readonly ModeledMethod[];
|
||||||
readonly isModified: boolean;
|
readonly isModified: boolean;
|
||||||
readonly isInProgress: boolean;
|
|
||||||
readonly processedByAutoModel: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface InProgressMethodsChangedEvent {
|
|
||||||
readonly dbUri: string;
|
|
||||||
readonly methods: ReadonlySet<string>;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ProcessedByAutoModelMethodsChangedEvent {
|
|
||||||
readonly dbUri: string;
|
|
||||||
readonly methods: ReadonlySet<string>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ModelEvaluationRunChangedEvent {
|
interface ModelEvaluationRunChangedEvent {
|
||||||
@@ -83,8 +71,6 @@ export class ModelingEvents extends DisposableObject {
|
|||||||
public readonly onModeChanged: AppEvent<ModeChangedEvent>;
|
public readonly onModeChanged: AppEvent<ModeChangedEvent>;
|
||||||
public readonly onModeledAndModifiedMethodsChanged: AppEvent<ModeledAndModifiedMethodsChangedEvent>;
|
public readonly onModeledAndModifiedMethodsChanged: AppEvent<ModeledAndModifiedMethodsChangedEvent>;
|
||||||
public readonly onSelectedMethodChanged: AppEvent<SelectedMethodChangedEvent>;
|
public readonly onSelectedMethodChanged: AppEvent<SelectedMethodChangedEvent>;
|
||||||
public readonly onInProgressMethodsChanged: AppEvent<InProgressMethodsChangedEvent>;
|
|
||||||
public readonly onProcessedByAutoModelMethodsChanged: AppEvent<ProcessedByAutoModelMethodsChangedEvent>;
|
|
||||||
public readonly onModelEvaluationRunChanged: AppEvent<ModelEvaluationRunChangedEvent>;
|
public readonly onModelEvaluationRunChanged: AppEvent<ModelEvaluationRunChangedEvent>;
|
||||||
public readonly onRevealInModelEditor: AppEvent<RevealInModelEditorEvent>;
|
public readonly onRevealInModelEditor: AppEvent<RevealInModelEditorEvent>;
|
||||||
public readonly onFocusModelEditor: AppEvent<FocusModelEditorEvent>;
|
public readonly onFocusModelEditor: AppEvent<FocusModelEditorEvent>;
|
||||||
@@ -99,8 +85,6 @@ export class ModelingEvents extends DisposableObject {
|
|||||||
private readonly onModeChangedEventEmitter: AppEventEmitter<ModeChangedEvent>;
|
private readonly onModeChangedEventEmitter: AppEventEmitter<ModeChangedEvent>;
|
||||||
private readonly onModeledAndModifiedMethodsChangedEventEmitter: AppEventEmitter<ModeledAndModifiedMethodsChangedEvent>;
|
private readonly onModeledAndModifiedMethodsChangedEventEmitter: AppEventEmitter<ModeledAndModifiedMethodsChangedEvent>;
|
||||||
private readonly onSelectedMethodChangedEventEmitter: AppEventEmitter<SelectedMethodChangedEvent>;
|
private readonly onSelectedMethodChangedEventEmitter: AppEventEmitter<SelectedMethodChangedEvent>;
|
||||||
private readonly onInProgressMethodsChangedEventEmitter: AppEventEmitter<InProgressMethodsChangedEvent>;
|
|
||||||
private readonly onProcessedByAutoModelMethodsChangedEventEmitter: AppEventEmitter<ProcessedByAutoModelMethodsChangedEvent>;
|
|
||||||
private readonly onModelEvaluationRunChangedEventEmitter: AppEventEmitter<ModelEvaluationRunChangedEvent>;
|
private readonly onModelEvaluationRunChangedEventEmitter: AppEventEmitter<ModelEvaluationRunChangedEvent>;
|
||||||
private readonly onRevealInModelEditorEventEmitter: AppEventEmitter<RevealInModelEditorEvent>;
|
private readonly onRevealInModelEditorEventEmitter: AppEventEmitter<RevealInModelEditorEvent>;
|
||||||
private readonly onFocusModelEditorEventEmitter: AppEventEmitter<FocusModelEditorEvent>;
|
private readonly onFocusModelEditorEventEmitter: AppEventEmitter<FocusModelEditorEvent>;
|
||||||
@@ -151,18 +135,6 @@ export class ModelingEvents extends DisposableObject {
|
|||||||
this.onSelectedMethodChanged =
|
this.onSelectedMethodChanged =
|
||||||
this.onSelectedMethodChangedEventEmitter.event;
|
this.onSelectedMethodChangedEventEmitter.event;
|
||||||
|
|
||||||
this.onInProgressMethodsChangedEventEmitter = this.push(
|
|
||||||
app.createEventEmitter<InProgressMethodsChangedEvent>(),
|
|
||||||
);
|
|
||||||
this.onInProgressMethodsChanged =
|
|
||||||
this.onInProgressMethodsChangedEventEmitter.event;
|
|
||||||
|
|
||||||
this.onProcessedByAutoModelMethodsChangedEventEmitter = this.push(
|
|
||||||
app.createEventEmitter<ProcessedByAutoModelMethodsChangedEvent>(),
|
|
||||||
);
|
|
||||||
this.onProcessedByAutoModelMethodsChanged =
|
|
||||||
this.onProcessedByAutoModelMethodsChangedEventEmitter.event;
|
|
||||||
|
|
||||||
this.onModelEvaluationRunChangedEventEmitter = this.push(
|
this.onModelEvaluationRunChangedEventEmitter = this.push(
|
||||||
app.createEventEmitter<ModelEvaluationRunChangedEvent>(),
|
app.createEventEmitter<ModelEvaluationRunChangedEvent>(),
|
||||||
);
|
);
|
||||||
@@ -254,8 +226,6 @@ export class ModelingEvents extends DisposableObject {
|
|||||||
usage: Usage,
|
usage: Usage,
|
||||||
modeledMethods: ModeledMethod[],
|
modeledMethods: ModeledMethod[],
|
||||||
isModified: boolean,
|
isModified: boolean,
|
||||||
isInProgress: boolean,
|
|
||||||
processedByAutoModel: boolean,
|
|
||||||
) {
|
) {
|
||||||
this.onSelectedMethodChangedEventEmitter.fire({
|
this.onSelectedMethodChangedEventEmitter.fire({
|
||||||
databaseItem,
|
databaseItem,
|
||||||
@@ -263,28 +233,6 @@ export class ModelingEvents extends DisposableObject {
|
|||||||
usage,
|
usage,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModified,
|
isModified,
|
||||||
isInProgress,
|
|
||||||
processedByAutoModel,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public fireInProgressMethodsChangedEvent(
|
|
||||||
dbUri: string,
|
|
||||||
methods: ReadonlySet<string>,
|
|
||||||
) {
|
|
||||||
this.onInProgressMethodsChangedEventEmitter.fire({
|
|
||||||
dbUri,
|
|
||||||
methods,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public fireProcessedByAutoModelMethodsChangedEvent(
|
|
||||||
dbUri: string,
|
|
||||||
methods: ReadonlySet<string>,
|
|
||||||
) {
|
|
||||||
this.onProcessedByAutoModelMethodsChangedEventEmitter.fire({
|
|
||||||
dbUri,
|
|
||||||
methods,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,6 @@ interface InternalDbModelingState {
|
|||||||
mode: Mode;
|
mode: Mode;
|
||||||
modeledMethods: Record<string, ModeledMethod[]>;
|
modeledMethods: Record<string, ModeledMethod[]>;
|
||||||
modifiedMethodSignatures: Set<string>;
|
modifiedMethodSignatures: Set<string>;
|
||||||
inProgressMethods: Set<string>;
|
|
||||||
processedByAutoModelMethods: Set<string>;
|
|
||||||
selectedMethod: Method | undefined;
|
selectedMethod: Method | undefined;
|
||||||
selectedUsage: Usage | undefined;
|
selectedUsage: Usage | undefined;
|
||||||
modelEvaluationRun: ModelEvaluationRun | undefined;
|
modelEvaluationRun: ModelEvaluationRun | undefined;
|
||||||
@@ -30,8 +28,6 @@ export interface DbModelingState {
|
|||||||
readonly mode: Mode;
|
readonly mode: Mode;
|
||||||
readonly modeledMethods: Readonly<Record<string, readonly ModeledMethod[]>>;
|
readonly modeledMethods: Readonly<Record<string, readonly ModeledMethod[]>>;
|
||||||
readonly modifiedMethodSignatures: ReadonlySet<string>;
|
readonly modifiedMethodSignatures: ReadonlySet<string>;
|
||||||
readonly inProgressMethods: ReadonlySet<string>;
|
|
||||||
readonly processedByAutoModelMethods: ReadonlySet<string>;
|
|
||||||
readonly selectedMethod: Method | undefined;
|
readonly selectedMethod: Method | undefined;
|
||||||
readonly selectedUsage: Usage | undefined;
|
readonly selectedUsage: Usage | undefined;
|
||||||
readonly modelEvaluationRun: ModelEvaluationRun | undefined;
|
readonly modelEvaluationRun: ModelEvaluationRun | undefined;
|
||||||
@@ -44,8 +40,6 @@ export interface SelectedMethodDetails {
|
|||||||
readonly usage: Usage | undefined;
|
readonly usage: Usage | undefined;
|
||||||
readonly modeledMethods: readonly ModeledMethod[];
|
readonly modeledMethods: readonly ModeledMethod[];
|
||||||
readonly isModified: boolean;
|
readonly isModified: boolean;
|
||||||
readonly isInProgress: boolean;
|
|
||||||
readonly processedByAutoModel: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ModelingStore extends DisposableObject {
|
export class ModelingStore extends DisposableObject {
|
||||||
@@ -68,10 +62,8 @@ export class ModelingStore extends DisposableObject {
|
|||||||
mode,
|
mode,
|
||||||
modeledMethods: {},
|
modeledMethods: {},
|
||||||
modifiedMethodSignatures: new Set(),
|
modifiedMethodSignatures: new Set(),
|
||||||
processedByAutoModelMethods: new Set(),
|
|
||||||
selectedMethod: undefined,
|
selectedMethod: undefined,
|
||||||
selectedUsage: undefined,
|
selectedUsage: undefined,
|
||||||
inProgressMethods: new Set(),
|
|
||||||
modelEvaluationRun: undefined,
|
modelEvaluationRun: undefined,
|
||||||
isModelAlertsViewOpen: false,
|
isModelAlertsViewOpen: false,
|
||||||
});
|
});
|
||||||
@@ -160,7 +152,6 @@ export class ModelingStore extends DisposableObject {
|
|||||||
methods,
|
methods,
|
||||||
state.modeledMethods,
|
state.modeledMethods,
|
||||||
state.modifiedMethodSignatures,
|
state.modifiedMethodSignatures,
|
||||||
state.processedByAutoModelMethods,
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -171,7 +162,6 @@ export class ModelingStore extends DisposableObject {
|
|||||||
state.methods,
|
state.methods,
|
||||||
state.modeledMethods,
|
state.modeledMethods,
|
||||||
state.modifiedMethodSignatures,
|
state.modifiedMethodSignatures,
|
||||||
state.processedByAutoModelMethods,
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -308,75 +298,15 @@ export class ModelingStore extends DisposableObject {
|
|||||||
|
|
||||||
const modeledMethods = dbState.modeledMethods[method.signature] ?? [];
|
const modeledMethods = dbState.modeledMethods[method.signature] ?? [];
|
||||||
const isModified = dbState.modifiedMethodSignatures.has(method.signature);
|
const isModified = dbState.modifiedMethodSignatures.has(method.signature);
|
||||||
const isInProgress = dbState.inProgressMethods.has(method.signature);
|
|
||||||
const processedByAutoModel = dbState.processedByAutoModelMethods.has(
|
|
||||||
method.signature,
|
|
||||||
);
|
|
||||||
this.modelingEvents.fireSelectedMethodChangedEvent(
|
this.modelingEvents.fireSelectedMethodChangedEvent(
|
||||||
dbItem,
|
dbItem,
|
||||||
method,
|
method,
|
||||||
usage,
|
usage,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
isModified,
|
isModified,
|
||||||
isInProgress,
|
|
||||||
processedByAutoModel,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public addInProgressMethods(
|
|
||||||
dbItem: DatabaseItem,
|
|
||||||
inProgressMethods: string[],
|
|
||||||
) {
|
|
||||||
this.changeInProgressMethods(dbItem, (state) => {
|
|
||||||
state.inProgressMethods = new Set([
|
|
||||||
...state.inProgressMethods,
|
|
||||||
...inProgressMethods,
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public removeInProgressMethods(
|
|
||||||
dbItem: DatabaseItem,
|
|
||||||
methodSignatures: string[],
|
|
||||||
) {
|
|
||||||
this.changeInProgressMethods(dbItem, (state) => {
|
|
||||||
state.inProgressMethods = new Set(
|
|
||||||
Array.from(state.inProgressMethods).filter(
|
|
||||||
(s) => !methodSignatures.includes(s),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public getProcessedByAutoModelMethods(
|
|
||||||
dbItem: DatabaseItem,
|
|
||||||
methodSignatures?: string[],
|
|
||||||
): Set<string> {
|
|
||||||
const processedByAutoModelMethods =
|
|
||||||
this.getState(dbItem).processedByAutoModelMethods;
|
|
||||||
if (!methodSignatures) {
|
|
||||||
return processedByAutoModelMethods;
|
|
||||||
}
|
|
||||||
return new Set(
|
|
||||||
Array.from(processedByAutoModelMethods).filter((x) =>
|
|
||||||
methodSignatures.includes(x),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public addProcessedByAutoModelMethods(
|
|
||||||
dbItem: DatabaseItem,
|
|
||||||
processedByAutoModelMethods: string[],
|
|
||||||
) {
|
|
||||||
this.changeProcessedByAutoModelMethods(dbItem, (state) => {
|
|
||||||
state.processedByAutoModelMethods = new Set([
|
|
||||||
...state.processedByAutoModelMethods,
|
|
||||||
...processedByAutoModelMethods,
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
this.updateMethodSorting(dbItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
public updateModelEvaluationRun(
|
public updateModelEvaluationRun(
|
||||||
dbItem: DatabaseItem,
|
dbItem: DatabaseItem,
|
||||||
evaluationRun: ModelEvaluationRun | undefined,
|
evaluationRun: ModelEvaluationRun | undefined,
|
||||||
@@ -405,10 +335,6 @@ export class ModelingStore extends DisposableObject {
|
|||||||
isModified: dbState.modifiedMethodSignatures.has(
|
isModified: dbState.modifiedMethodSignatures.has(
|
||||||
selectedMethod.signature,
|
selectedMethod.signature,
|
||||||
),
|
),
|
||||||
isInProgress: dbState.inProgressMethods.has(selectedMethod.signature),
|
|
||||||
processedByAutoModel: dbState.processedByAutoModelMethods.has(
|
|
||||||
selectedMethod.signature,
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -460,34 +386,6 @@ export class ModelingStore extends DisposableObject {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private changeInProgressMethods(
|
|
||||||
dbItem: DatabaseItem,
|
|
||||||
updateState: (state: InternalDbModelingState) => void,
|
|
||||||
) {
|
|
||||||
const state = this.getState(dbItem);
|
|
||||||
|
|
||||||
updateState(state);
|
|
||||||
|
|
||||||
this.modelingEvents.fireInProgressMethodsChangedEvent(
|
|
||||||
dbItem.databaseUri.toString(),
|
|
||||||
state.inProgressMethods,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private changeProcessedByAutoModelMethods(
|
|
||||||
dbItem: DatabaseItem,
|
|
||||||
updateState: (state: InternalDbModelingState) => void,
|
|
||||||
) {
|
|
||||||
const state = this.getState(dbItem);
|
|
||||||
|
|
||||||
updateState(state);
|
|
||||||
|
|
||||||
this.modelingEvents.fireProcessedByAutoModelMethodsChangedEvent(
|
|
||||||
dbItem.databaseUri.toString(),
|
|
||||||
state.processedByAutoModelMethods,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private changeModelEvaluationRun(
|
private changeModelEvaluationRun(
|
||||||
dbItem: DatabaseItem,
|
dbItem: DatabaseItem,
|
||||||
updateState: (state: InternalDbModelingState) => void,
|
updateState: (state: InternalDbModelingState) => void,
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
import type { Method, MethodSignature } from "../method";
|
|
||||||
import type { ModeledMethod } from "../modeled-method";
|
|
||||||
import type { Mode } from "./mode";
|
|
||||||
import { groupMethods, sortGroupNames } from "./sorting";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the candidates that the model should be run on. This includes limiting the number of
|
|
||||||
* candidates to the candidate limit and filtering out anything that is already modeled and respecting
|
|
||||||
* the order in the UI.
|
|
||||||
* @param mode Whether it is application or framework mode.
|
|
||||||
* @param methods all methods.
|
|
||||||
* @param modeledMethodsBySignature the currently modeled methods.
|
|
||||||
* @returns list of modeled methods that are candidates for modeling.
|
|
||||||
*/
|
|
||||||
|
|
||||||
export function getCandidates(
|
|
||||||
mode: Mode,
|
|
||||||
methods: readonly Method[],
|
|
||||||
modeledMethodsBySignature: Record<string, readonly ModeledMethod[]>,
|
|
||||||
processedByAutoModelMethods: Set<string>,
|
|
||||||
): MethodSignature[] {
|
|
||||||
const candidateMethods = methods.filter((method) => {
|
|
||||||
// Filter out any methods already processed by auto-model
|
|
||||||
if (processedByAutoModelMethods.has(method.signature)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const modeledMethods: ModeledMethod[] = [
|
|
||||||
...(modeledMethodsBySignature[method.signature] ?? []),
|
|
||||||
];
|
|
||||||
|
|
||||||
// Anything that is modeled is not a candidate
|
|
||||||
if (modeledMethods.some((m) => m.type !== "none")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// A method that is supported is modeled outside of the model file, so it is not a candidate.
|
|
||||||
if (method.supported) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Sort the same way as the UI so we send the first ones listed in the UI first
|
|
||||||
const grouped = groupMethods(candidateMethods, mode);
|
|
||||||
return sortGroupNames(grouped).flatMap((name) => grouped[name]);
|
|
||||||
}
|
|
||||||
@@ -47,7 +47,6 @@ export function sortMethods(
|
|||||||
methods: readonly Method[],
|
methods: readonly Method[],
|
||||||
modeledMethodsMap: Record<string, readonly ModeledMethod[]>,
|
modeledMethodsMap: Record<string, readonly ModeledMethod[]>,
|
||||||
modifiedSignatures: ReadonlySet<string>,
|
modifiedSignatures: ReadonlySet<string>,
|
||||||
processedByAutoModelMethods: ReadonlySet<string>,
|
|
||||||
): Method[] {
|
): Method[] {
|
||||||
const sortedMethods = [...methods];
|
const sortedMethods = [...methods];
|
||||||
sortedMethods.sort((a, b) => {
|
sortedMethods.sort((a, b) => {
|
||||||
@@ -56,13 +55,11 @@ export function sortMethods(
|
|||||||
a,
|
a,
|
||||||
modeledMethodsMap[a.signature] ?? [],
|
modeledMethodsMap[a.signature] ?? [],
|
||||||
modifiedSignatures.has(a.signature),
|
modifiedSignatures.has(a.signature),
|
||||||
processedByAutoModelMethods.has(a.signature),
|
|
||||||
);
|
);
|
||||||
const methodBPrimarySortOrdinal = getMethodPrimarySortOrdinal(
|
const methodBPrimarySortOrdinal = getMethodPrimarySortOrdinal(
|
||||||
b,
|
b,
|
||||||
modeledMethodsMap[b.signature] ?? [],
|
modeledMethodsMap[b.signature] ?? [],
|
||||||
modifiedSignatures.has(b.signature),
|
modifiedSignatures.has(b.signature),
|
||||||
processedByAutoModelMethods.has(b.signature),
|
|
||||||
);
|
);
|
||||||
if (methodAPrimarySortOrdinal !== methodBPrimarySortOrdinal) {
|
if (methodAPrimarySortOrdinal !== methodBPrimarySortOrdinal) {
|
||||||
return methodAPrimarySortOrdinal - methodBPrimarySortOrdinal;
|
return methodAPrimarySortOrdinal - methodBPrimarySortOrdinal;
|
||||||
@@ -82,32 +79,25 @@ export function sortMethods(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Assigns numbers to the following classes of methods:
|
* Assigns numbers to the following classes of methods:
|
||||||
* - Unsaved positive AutoModel predictions => 0
|
* - Unsaved manual models + unmodeled methods => 0
|
||||||
* - Negative AutoModel predictions => 1
|
* - Saved models from this model pack (AutoModel and manual) => 1
|
||||||
* - Unsaved manual models + unmodeled methods => 2
|
* - Methods not modelable in this model pack => 2
|
||||||
* - Saved models from this model pack (AutoModel and manual) => 3
|
|
||||||
* - Methods not modelable in this model pack => 4
|
|
||||||
*/
|
*/
|
||||||
function getMethodPrimarySortOrdinal(
|
function getMethodPrimarySortOrdinal(
|
||||||
method: Method,
|
method: Method,
|
||||||
modeledMethods: readonly ModeledMethod[],
|
modeledMethods: readonly ModeledMethod[],
|
||||||
isUnsaved: boolean,
|
isUnsaved: boolean,
|
||||||
isProcessedByAutoModel: boolean,
|
|
||||||
): number {
|
): number {
|
||||||
const canBeModeled = canMethodBeModeled(method, modeledMethods, isUnsaved);
|
const canBeModeled = canMethodBeModeled(method, modeledMethods, isUnsaved);
|
||||||
const isModeled = modeledMethods.length > 0;
|
const isModeled = modeledMethods.length > 0;
|
||||||
if (canBeModeled) {
|
if (canBeModeled) {
|
||||||
if (isModeled && isUnsaved && isProcessedByAutoModel) {
|
if ((isModeled && isUnsaved) || !isModeled) {
|
||||||
return 0;
|
return 0;
|
||||||
} else if (!isModeled && isProcessedByAutoModel) {
|
|
||||||
return 1;
|
|
||||||
} else if ((isModeled && isUnsaved) || !isModeled) {
|
|
||||||
return 2;
|
|
||||||
} else {
|
} else {
|
||||||
return 3;
|
return 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return 4;
|
return 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ export interface ModelEditorViewState {
|
|||||||
extensionPack: ExtensionPack;
|
extensionPack: ExtensionPack;
|
||||||
language: QueryLanguage;
|
language: QueryLanguage;
|
||||||
showGenerateButton: boolean;
|
showGenerateButton: boolean;
|
||||||
showLlmButton: boolean;
|
|
||||||
showEvaluationUi: boolean;
|
showEvaluationUi: boolean;
|
||||||
mode: Mode;
|
mode: Mode;
|
||||||
showModeSwitchButton: boolean;
|
showModeSwitchButton: boolean;
|
||||||
|
|||||||
@@ -53,20 +53,3 @@ FullyModeledMethod.args = {
|
|||||||
method,
|
method,
|
||||||
modeledMethod,
|
modeledMethod,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ModelingInProgress = Template.bind({});
|
|
||||||
ModelingInProgress.args = {
|
|
||||||
method,
|
|
||||||
modeledMethod,
|
|
||||||
isModelingInProgress: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
const generatedModeledMethod = createSinkModeledMethod({
|
|
||||||
provenance: "ai-generated",
|
|
||||||
});
|
|
||||||
export const ModelingNotAccepted = Template.bind({});
|
|
||||||
ModelingNotAccepted.args = {
|
|
||||||
method,
|
|
||||||
modeledMethod: generatedModeledMethod,
|
|
||||||
modelPending: true,
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
import type { Meta, StoryFn } from "@storybook/react";
|
|
||||||
|
|
||||||
import { InProgressDropdown as InProgressDropdownComponent } from "../../view/model-editor/InProgressDropdown";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
title: "CodeQL Model Editor/In Progress Dropdown",
|
|
||||||
component: InProgressDropdownComponent,
|
|
||||||
} as Meta<typeof InProgressDropdownComponent>;
|
|
||||||
|
|
||||||
const Template: StoryFn<typeof InProgressDropdownComponent> = (args) => (
|
|
||||||
<InProgressDropdownComponent />
|
|
||||||
);
|
|
||||||
|
|
||||||
export const InProgressDropdown = Template.bind({});
|
|
||||||
@@ -220,10 +220,8 @@ LibraryRow.args = {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
modifiedSignatures: new Set(["org.sql2o.Sql2o#Sql2o(String)"]),
|
modifiedSignatures: new Set(["org.sql2o.Sql2o#Sql2o(String)"]),
|
||||||
inProgressMethods: new Set(),
|
|
||||||
viewState: createMockModelEditorViewState({
|
viewState: createMockModelEditorViewState({
|
||||||
showGenerateButton: true,
|
showGenerateButton: true,
|
||||||
showLlmButton: true,
|
|
||||||
}),
|
}),
|
||||||
hideModeledMethods: false,
|
hideModeledMethods: false,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -96,7 +96,6 @@ const modeledMethod: ModeledMethod = {
|
|||||||
|
|
||||||
const viewState = createMockModelEditorViewState({
|
const viewState = createMockModelEditorViewState({
|
||||||
showGenerateButton: true,
|
showGenerateButton: true,
|
||||||
showLlmButton: true,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export const Unmodeled = Template.bind({});
|
export const Unmodeled = Template.bind({});
|
||||||
@@ -146,15 +145,6 @@ AlreadyModeled.args = {
|
|||||||
viewState,
|
viewState,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ModelingInProgress = Template.bind({});
|
|
||||||
ModelingInProgress.args = {
|
|
||||||
method,
|
|
||||||
modeledMethods: [modeledMethod],
|
|
||||||
modelingInProgress: true,
|
|
||||||
methodCanBeModeled: true,
|
|
||||||
viewState,
|
|
||||||
};
|
|
||||||
|
|
||||||
export const MultipleModelings = Template.bind({});
|
export const MultipleModelings = Template.bind({});
|
||||||
MultipleModelings.args = {
|
MultipleModelings.args = {
|
||||||
method,
|
method,
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ ModelEditor.args = {
|
|||||||
dataExtensions: [],
|
dataExtensions: [],
|
||||||
},
|
},
|
||||||
showGenerateButton: true,
|
showGenerateButton: true,
|
||||||
showLlmButton: true,
|
|
||||||
}),
|
}),
|
||||||
initialMethods: [
|
initialMethods: [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -55,8 +55,6 @@ export type MethodModelingProps = {
|
|||||||
modelingStatus: ModelingStatus;
|
modelingStatus: ModelingStatus;
|
||||||
method: Method;
|
method: Method;
|
||||||
modeledMethods: ModeledMethod[];
|
modeledMethods: ModeledMethod[];
|
||||||
isModelingInProgress: boolean;
|
|
||||||
isProcessedByAutoModel: boolean;
|
|
||||||
onChange: (methodSignature: string, modeledMethods: ModeledMethod[]) => void;
|
onChange: (methodSignature: string, modeledMethods: ModeledMethod[]) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -66,8 +64,6 @@ export const MethodModeling = ({
|
|||||||
modelingStatus,
|
modelingStatus,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
method,
|
method,
|
||||||
isModelingInProgress,
|
|
||||||
isProcessedByAutoModel,
|
|
||||||
onChange,
|
onChange,
|
||||||
}: MethodModelingProps): React.JSX.Element => {
|
}: MethodModelingProps): React.JSX.Element => {
|
||||||
return (
|
return (
|
||||||
@@ -86,9 +82,6 @@ export const MethodModeling = ({
|
|||||||
modelConfig={modelConfig}
|
modelConfig={modelConfig}
|
||||||
method={method}
|
method={method}
|
||||||
modeledMethods={modeledMethods}
|
modeledMethods={modeledMethods}
|
||||||
isModelingInProgress={isModelingInProgress}
|
|
||||||
isProcessedByAutoModel={isProcessedByAutoModel}
|
|
||||||
modelingStatus={modelingStatus}
|
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
/>
|
/>
|
||||||
<ReviewInEditorButton method={method} />
|
<ReviewInEditorButton method={method} />
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import { ModelTypeDropdown } from "../model-editor/ModelTypeDropdown";
|
|||||||
import { ModelInputDropdown } from "../model-editor/ModelInputDropdown";
|
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 type { QueryLanguage } from "../../common/query-language";
|
import type { QueryLanguage } from "../../common/query-language";
|
||||||
import type { ModelConfig } from "../../model-editor/languages";
|
import type { ModelConfig } from "../../model-editor/languages";
|
||||||
|
|
||||||
@@ -28,8 +27,6 @@ export type MethodModelingInputsProps = {
|
|||||||
modelConfig: ModelConfig;
|
modelConfig: ModelConfig;
|
||||||
method: Method;
|
method: Method;
|
||||||
modeledMethod: ModeledMethod | undefined;
|
modeledMethod: ModeledMethod | undefined;
|
||||||
modelPending: boolean;
|
|
||||||
isModelingInProgress: boolean;
|
|
||||||
onChange: (modeledMethod: ModeledMethod) => void;
|
onChange: (modeledMethod: ModeledMethod) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -38,15 +35,12 @@ export const MethodModelingInputs = ({
|
|||||||
modelConfig,
|
modelConfig,
|
||||||
method,
|
method,
|
||||||
modeledMethod,
|
modeledMethod,
|
||||||
modelPending,
|
|
||||||
isModelingInProgress,
|
|
||||||
onChange,
|
onChange,
|
||||||
}: MethodModelingInputsProps): React.JSX.Element => {
|
}: MethodModelingInputsProps): React.JSX.Element => {
|
||||||
const inputProps = {
|
const inputProps = {
|
||||||
language,
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethod,
|
modeledMethod,
|
||||||
modelPending,
|
|
||||||
onChange,
|
onChange,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -55,41 +49,25 @@ export const MethodModelingInputs = ({
|
|||||||
<Container>
|
<Container>
|
||||||
<Input>
|
<Input>
|
||||||
<Name>Model Type</Name>
|
<Name>Model Type</Name>
|
||||||
{isModelingInProgress ? (
|
<ModelTypeDropdown modelConfig={modelConfig} {...inputProps} />
|
||||||
<InProgressDropdown />
|
|
||||||
) : (
|
|
||||||
<ModelTypeDropdown modelConfig={modelConfig} {...inputProps} />
|
|
||||||
)}
|
|
||||||
</Input>
|
</Input>
|
||||||
</Container>
|
</Container>
|
||||||
<Container>
|
<Container>
|
||||||
<Input>
|
<Input>
|
||||||
<Name>Input</Name>
|
<Name>Input</Name>
|
||||||
{isModelingInProgress ? (
|
<ModelInputDropdown {...inputProps} />
|
||||||
<InProgressDropdown />
|
|
||||||
) : (
|
|
||||||
<ModelInputDropdown {...inputProps} />
|
|
||||||
)}
|
|
||||||
</Input>
|
</Input>
|
||||||
</Container>
|
</Container>
|
||||||
<Container>
|
<Container>
|
||||||
<Input>
|
<Input>
|
||||||
<Name>Output</Name>
|
<Name>Output</Name>
|
||||||
{isModelingInProgress ? (
|
<ModelOutputDropdown {...inputProps} />
|
||||||
<InProgressDropdown />
|
|
||||||
) : (
|
|
||||||
<ModelOutputDropdown {...inputProps} />
|
|
||||||
)}
|
|
||||||
</Input>
|
</Input>
|
||||||
</Container>
|
</Container>
|
||||||
<Container>
|
<Container>
|
||||||
<Input>
|
<Input>
|
||||||
<Name>Kind</Name>
|
<Name>Kind</Name>
|
||||||
{isModelingInProgress ? (
|
<ModelKindDropdown {...inputProps} />
|
||||||
<InProgressDropdown />
|
|
||||||
) : (
|
|
||||||
<ModelKindDropdown {...inputProps} />
|
|
||||||
)}
|
|
||||||
</Input>
|
</Input>
|
||||||
</Container>
|
</Container>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -31,12 +31,6 @@ export function MethodModelingView({
|
|||||||
|
|
||||||
const [isMethodModified, setIsMethodModified] = useState<boolean>(false);
|
const [isMethodModified, setIsMethodModified] = useState<boolean>(false);
|
||||||
|
|
||||||
const [isModelingInProgress, setIsModelingInProgress] =
|
|
||||||
useState<boolean>(false);
|
|
||||||
|
|
||||||
const [isProcessedByAutoModel, setIsProcessedByAutoModel] =
|
|
||||||
useState<boolean>(false);
|
|
||||||
|
|
||||||
const modelingStatus = useMemo(
|
const modelingStatus = useMemo(
|
||||||
() => getModelingStatus(modeledMethods, isMethodModified),
|
() => getModelingStatus(modeledMethods, isMethodModified),
|
||||||
[modeledMethods, isMethodModified],
|
[modeledMethods, isMethodModified],
|
||||||
@@ -63,21 +57,11 @@ export function MethodModelingView({
|
|||||||
setMethod(undefined);
|
setMethod(undefined);
|
||||||
setModeledMethods([]);
|
setModeledMethods([]);
|
||||||
setIsMethodModified(false);
|
setIsMethodModified(false);
|
||||||
setIsModelingInProgress(false);
|
|
||||||
setIsProcessedByAutoModel(false);
|
|
||||||
break;
|
break;
|
||||||
case "setSelectedMethod":
|
case "setSelectedMethod":
|
||||||
setMethod(msg.method);
|
setMethod(msg.method);
|
||||||
setModeledMethods(msg.modeledMethods);
|
setModeledMethods(msg.modeledMethods);
|
||||||
setIsMethodModified(msg.isModified);
|
setIsMethodModified(msg.isModified);
|
||||||
setIsModelingInProgress(msg.isInProgress);
|
|
||||||
setIsProcessedByAutoModel(msg.processedByAutoModel);
|
|
||||||
break;
|
|
||||||
case "setInProgress":
|
|
||||||
setIsModelingInProgress(msg.inProgress);
|
|
||||||
break;
|
|
||||||
case "setProcessedByAutoModel":
|
|
||||||
setIsProcessedByAutoModel(msg.processedByAutoModel);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assertNever(msg);
|
assertNever(msg);
|
||||||
@@ -125,8 +109,6 @@ export function MethodModelingView({
|
|||||||
modelingStatus={modelingStatus}
|
modelingStatus={modelingStatus}
|
||||||
method={method}
|
method={method}
|
||||||
modeledMethods={modeledMethods}
|
modeledMethods={modeledMethods}
|
||||||
isModelingInProgress={isModelingInProgress}
|
|
||||||
isProcessedByAutoModel={isProcessedByAutoModel}
|
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||||
import type { Method } from "../../model-editor/method";
|
import type { Method } from "../../model-editor/method";
|
||||||
import type { ModeledMethod } from "../../model-editor/modeled-method";
|
import type { ModeledMethod } from "../../model-editor/modeled-method";
|
||||||
import { isModelPending } from "../../model-editor/modeled-method";
|
|
||||||
import {
|
import {
|
||||||
canAddNewModeledMethod,
|
canAddNewModeledMethod,
|
||||||
canRemoveModeledMethod,
|
canRemoveModeledMethod,
|
||||||
@@ -15,7 +14,6 @@ import { ModeledMethodAlert } from "./ModeledMethodAlert";
|
|||||||
import type { QueryLanguage } from "../../common/query-language";
|
import type { QueryLanguage } from "../../common/query-language";
|
||||||
import { createEmptyModeledMethod } from "../../model-editor/modeled-method-empty";
|
import { createEmptyModeledMethod } from "../../model-editor/modeled-method-empty";
|
||||||
import { sendTelemetry } from "../common/telemetry";
|
import { sendTelemetry } from "../common/telemetry";
|
||||||
import type { ModelingStatus } from "../../model-editor/shared/modeling-status";
|
|
||||||
import type { ModelConfig } from "../../model-editor/languages";
|
import type { ModelConfig } from "../../model-editor/languages";
|
||||||
|
|
||||||
export type MultipleModeledMethodsPanelProps = {
|
export type MultipleModeledMethodsPanelProps = {
|
||||||
@@ -23,9 +21,6 @@ export type MultipleModeledMethodsPanelProps = {
|
|||||||
modelConfig: ModelConfig;
|
modelConfig: ModelConfig;
|
||||||
method: Method;
|
method: Method;
|
||||||
modeledMethods: ModeledMethod[];
|
modeledMethods: ModeledMethod[];
|
||||||
modelingStatus: ModelingStatus;
|
|
||||||
isModelingInProgress: boolean;
|
|
||||||
isProcessedByAutoModel: boolean;
|
|
||||||
onChange: (methodSignature: string, modeledMethods: ModeledMethod[]) => void;
|
onChange: (methodSignature: string, modeledMethods: ModeledMethod[]) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -66,9 +61,6 @@ export const MultipleModeledMethodsPanel = ({
|
|||||||
modelConfig,
|
modelConfig,
|
||||||
method,
|
method,
|
||||||
modeledMethods,
|
modeledMethods,
|
||||||
modelingStatus,
|
|
||||||
isModelingInProgress,
|
|
||||||
isProcessedByAutoModel,
|
|
||||||
onChange,
|
onChange,
|
||||||
}: MultipleModeledMethodsPanelProps) => {
|
}: MultipleModeledMethodsPanelProps) => {
|
||||||
const [selectedIndex, setSelectedIndex] = useState<number>(0);
|
const [selectedIndex, setSelectedIndex] = useState<number>(0);
|
||||||
@@ -163,12 +155,6 @@ export const MultipleModeledMethodsPanel = ({
|
|||||||
modelConfig={modelConfig}
|
modelConfig={modelConfig}
|
||||||
method={method}
|
method={method}
|
||||||
modeledMethod={modeledMethods[selectedIndex]}
|
modeledMethod={modeledMethods[selectedIndex]}
|
||||||
modelPending={isModelPending(
|
|
||||||
modeledMethods[selectedIndex],
|
|
||||||
modelingStatus,
|
|
||||||
isProcessedByAutoModel,
|
|
||||||
)}
|
|
||||||
isModelingInProgress={isModelingInProgress}
|
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
@@ -177,12 +163,6 @@ export const MultipleModeledMethodsPanel = ({
|
|||||||
modelConfig={modelConfig}
|
modelConfig={modelConfig}
|
||||||
method={method}
|
method={method}
|
||||||
modeledMethod={undefined}
|
modeledMethod={undefined}
|
||||||
modelPending={isModelPending(
|
|
||||||
modeledMethods[selectedIndex],
|
|
||||||
modelingStatus,
|
|
||||||
isProcessedByAutoModel,
|
|
||||||
)}
|
|
||||||
isModelingInProgress={isModelingInProgress}
|
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -13,8 +13,6 @@ describe(MethodModeling.name, () => {
|
|||||||
it("renders method modeling panel", () => {
|
it("renders method modeling panel", () => {
|
||||||
const method = createMethod();
|
const method = createMethod();
|
||||||
const modeledMethod = createSinkModeledMethod();
|
const modeledMethod = createSinkModeledMethod();
|
||||||
const isModelingInProgress = false;
|
|
||||||
const isProcessedByAutoModel = false;
|
|
||||||
const onChange = jest.fn();
|
const onChange = jest.fn();
|
||||||
|
|
||||||
render({
|
render({
|
||||||
@@ -23,8 +21,6 @@ describe(MethodModeling.name, () => {
|
|||||||
modelingStatus: "saved",
|
modelingStatus: "saved",
|
||||||
method,
|
method,
|
||||||
modeledMethods: [modeledMethod],
|
modeledMethods: [modeledMethod],
|
||||||
isModelingInProgress,
|
|
||||||
isProcessedByAutoModel,
|
|
||||||
onChange,
|
onChange,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ describe(MethodModelingInputs.name, () => {
|
|||||||
const language = QueryLanguage.Java;
|
const language = QueryLanguage.Java;
|
||||||
const method = createMethod();
|
const method = createMethod();
|
||||||
const modeledMethod = createSinkModeledMethod();
|
const modeledMethod = createSinkModeledMethod();
|
||||||
const modelPending = false;
|
|
||||||
const isModelingInProgress = false;
|
|
||||||
const modelConfig = defaultModelConfig;
|
const modelConfig = defaultModelConfig;
|
||||||
const onChange = jest.fn();
|
const onChange = jest.fn();
|
||||||
|
|
||||||
@@ -28,8 +26,6 @@ describe(MethodModelingInputs.name, () => {
|
|||||||
language,
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethod,
|
modeledMethod,
|
||||||
modelPending,
|
|
||||||
isModelingInProgress,
|
|
||||||
modelConfig,
|
modelConfig,
|
||||||
onChange,
|
onChange,
|
||||||
});
|
});
|
||||||
@@ -56,8 +52,6 @@ describe(MethodModelingInputs.name, () => {
|
|||||||
language,
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethod,
|
modeledMethod,
|
||||||
modelPending,
|
|
||||||
isModelingInProgress,
|
|
||||||
modelConfig,
|
modelConfig,
|
||||||
onChange,
|
onChange,
|
||||||
});
|
});
|
||||||
@@ -80,8 +74,6 @@ describe(MethodModelingInputs.name, () => {
|
|||||||
language,
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethod,
|
modeledMethod,
|
||||||
modelPending,
|
|
||||||
isModelingInProgress,
|
|
||||||
modelConfig,
|
modelConfig,
|
||||||
onChange,
|
onChange,
|
||||||
});
|
});
|
||||||
@@ -96,8 +88,6 @@ describe(MethodModelingInputs.name, () => {
|
|||||||
language={language}
|
language={language}
|
||||||
method={method}
|
method={method}
|
||||||
modeledMethod={updatedModeledMethod}
|
modeledMethod={updatedModeledMethod}
|
||||||
modelPending={modelPending}
|
|
||||||
isModelingInProgress={isModelingInProgress}
|
|
||||||
modelConfig={modelConfig}
|
modelConfig={modelConfig}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
/>,
|
/>,
|
||||||
@@ -121,32 +111,4 @@ describe(MethodModelingInputs.name, () => {
|
|||||||
expect(modelOutputDropdown).toHaveValue("ReturnValue");
|
expect(modelOutputDropdown).toHaveValue("ReturnValue");
|
||||||
expect(modelKindDropdown).toHaveValue("local");
|
expect(modelKindDropdown).toHaveValue("local");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("sets in progress dropdowns when modeling is in progress", () => {
|
|
||||||
render({
|
|
||||||
language,
|
|
||||||
method,
|
|
||||||
modeledMethod,
|
|
||||||
modelPending,
|
|
||||||
isModelingInProgress: true,
|
|
||||||
modelConfig,
|
|
||||||
onChange,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Check that all the labels are rendered.
|
|
||||||
expect(screen.getByText("Model Type")).toBeInTheDocument();
|
|
||||||
expect(screen.getByText("Input")).toBeInTheDocument();
|
|
||||||
expect(screen.getByText("Output")).toBeInTheDocument();
|
|
||||||
expect(screen.getByText("Kind")).toBeInTheDocument();
|
|
||||||
|
|
||||||
// Check that all the dropdowns are rendered.
|
|
||||||
const dropdowns = screen.getAllByRole("combobox");
|
|
||||||
expect(dropdowns.length).toBe(4);
|
|
||||||
|
|
||||||
// Check that all the dropdowns are disabled and indicate have the value "Thinking...".
|
|
||||||
dropdowns.forEach((dropdown) => {
|
|
||||||
expect(dropdown).toBeDisabled();
|
|
||||||
expect(dropdown).toHaveValue("Thinking...");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -10,25 +10,18 @@ import { MultipleModeledMethodsPanel } from "../MultipleModeledMethodsPanel";
|
|||||||
import { userEvent } from "@testing-library/user-event";
|
import { userEvent } from "@testing-library/user-event";
|
||||||
import type { ModeledMethod } from "../../../model-editor/modeled-method";
|
import type { ModeledMethod } from "../../../model-editor/modeled-method";
|
||||||
import { QueryLanguage } from "../../../common/query-language";
|
import { QueryLanguage } from "../../../common/query-language";
|
||||||
import type { ModelingStatus } from "../../../model-editor/shared/modeling-status";
|
|
||||||
import { defaultModelConfig } from "../../../model-editor/languages";
|
import { defaultModelConfig } from "../../../model-editor/languages";
|
||||||
|
|
||||||
describe(MultipleModeledMethodsPanel.name, () => {
|
describe(MultipleModeledMethodsPanel.name, () => {
|
||||||
const language = QueryLanguage.Java;
|
const language = QueryLanguage.Java;
|
||||||
const method = createMethod();
|
const method = createMethod();
|
||||||
const isModelingInProgress = false;
|
|
||||||
const isProcessedByAutoModel = false;
|
|
||||||
const modelingStatus: ModelingStatus = "unmodeled";
|
|
||||||
const onChange = jest.fn<void, [string, ModeledMethod[]]>();
|
const onChange = jest.fn<void, [string, ModeledMethod[]]>();
|
||||||
const modelConfig = defaultModelConfig;
|
const modelConfig = defaultModelConfig;
|
||||||
|
|
||||||
const baseProps = {
|
const baseProps = {
|
||||||
language,
|
language,
|
||||||
method,
|
method,
|
||||||
modelingStatus,
|
|
||||||
isModelingInProgress,
|
|
||||||
modelConfig,
|
modelConfig,
|
||||||
isProcessedByAutoModel,
|
|
||||||
onChange,
|
onChange,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
import { styled } from "styled-components";
|
|
||||||
import { Dropdown } from "../common/Dropdown";
|
|
||||||
|
|
||||||
const StyledDropdown = styled(Dropdown)`
|
|
||||||
font-style: italic;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const InProgressDropdown = () => {
|
|
||||||
return (
|
|
||||||
<StyledDropdown
|
|
||||||
value="Thinking..."
|
|
||||||
options={[]}
|
|
||||||
disabled={true}
|
|
||||||
disabledPlaceholder="Thinking..."
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
import { styled } from "styled-components";
|
import { styled } from "styled-components";
|
||||||
import { Dropdown } from "../common/Dropdown";
|
import { Dropdown } from "../common/Dropdown";
|
||||||
|
|
||||||
export const InputDropdown = styled(Dropdown)<{ $pending: boolean }>`
|
export const InputDropdown = styled(Dropdown)``;
|
||||||
font-style: ${(props) => (props.$pending ? "italic" : "normal")};
|
|
||||||
`;
|
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import {
|
|||||||
} from "@vscode/webview-ui-toolkit/react";
|
} from "@vscode/webview-ui-toolkit/react";
|
||||||
import type { ModelEditorViewState } from "../../model-editor/shared/view-state";
|
import type { ModelEditorViewState } from "../../model-editor/shared/view-state";
|
||||||
import type { AccessPathSuggestionOptions } from "../../model-editor/suggestions";
|
import type { AccessPathSuggestionOptions } from "../../model-editor/suggestions";
|
||||||
import { getCandidates } from "../../model-editor/shared/auto-model-candidates";
|
|
||||||
import type { ModelEvaluationRunState } from "../../model-editor/shared/model-evaluation-run-state";
|
import type { ModelEvaluationRunState } from "../../model-editor/shared/model-evaluation-run-state";
|
||||||
|
|
||||||
const LibraryContainer = styled.div`
|
const LibraryContainer = styled.div`
|
||||||
@@ -75,8 +74,6 @@ export type LibraryRowProps = {
|
|||||||
modeledMethodsMap: Record<string, ModeledMethod[]>;
|
modeledMethodsMap: Record<string, ModeledMethod[]>;
|
||||||
modifiedSignatures: Set<string>;
|
modifiedSignatures: Set<string>;
|
||||||
selectedSignatures: Set<string>;
|
selectedSignatures: Set<string>;
|
||||||
inProgressMethods: Set<string>;
|
|
||||||
processedByAutoModelMethods: Set<string>;
|
|
||||||
viewState: ModelEditorViewState;
|
viewState: ModelEditorViewState;
|
||||||
hideModeledMethods: boolean;
|
hideModeledMethods: boolean;
|
||||||
revealedMethodSignature: string | null;
|
revealedMethodSignature: string | null;
|
||||||
@@ -85,11 +82,6 @@ export type LibraryRowProps = {
|
|||||||
onChange: (methodSignature: string, modeledMethods: ModeledMethod[]) => void;
|
onChange: (methodSignature: string, modeledMethods: ModeledMethod[]) => void;
|
||||||
onMethodClick: (methodSignature: string) => void;
|
onMethodClick: (methodSignature: string) => void;
|
||||||
onSaveModelClick: (methodSignatures: string[]) => void;
|
onSaveModelClick: (methodSignatures: string[]) => void;
|
||||||
onGenerateFromLlmClick: (
|
|
||||||
dependencyName: string,
|
|
||||||
methodSignatures: string[],
|
|
||||||
) => void;
|
|
||||||
onStopGenerateFromLlmClick: (dependencyName: string) => void;
|
|
||||||
onGenerateFromSourceClick: () => void;
|
onGenerateFromSourceClick: () => void;
|
||||||
onModelDependencyClick: () => void;
|
onModelDependencyClick: () => void;
|
||||||
};
|
};
|
||||||
@@ -101,8 +93,6 @@ export const LibraryRow = ({
|
|||||||
modeledMethodsMap,
|
modeledMethodsMap,
|
||||||
modifiedSignatures,
|
modifiedSignatures,
|
||||||
selectedSignatures,
|
selectedSignatures,
|
||||||
inProgressMethods,
|
|
||||||
processedByAutoModelMethods,
|
|
||||||
viewState,
|
viewState,
|
||||||
hideModeledMethods,
|
hideModeledMethods,
|
||||||
revealedMethodSignature,
|
revealedMethodSignature,
|
||||||
@@ -111,8 +101,6 @@ export const LibraryRow = ({
|
|||||||
onChange,
|
onChange,
|
||||||
onMethodClick,
|
onMethodClick,
|
||||||
onSaveModelClick,
|
onSaveModelClick,
|
||||||
onGenerateFromLlmClick,
|
|
||||||
onStopGenerateFromLlmClick,
|
|
||||||
onGenerateFromSourceClick,
|
onGenerateFromSourceClick,
|
||||||
onModelDependencyClick,
|
onModelDependencyClick,
|
||||||
}: LibraryRowProps) => {
|
}: LibraryRowProps) => {
|
||||||
@@ -134,27 +122,6 @@ export const LibraryRow = ({
|
|||||||
}
|
}
|
||||||
}, [methods, revealedMethodSignature]);
|
}, [methods, revealedMethodSignature]);
|
||||||
|
|
||||||
const handleModelWithAI = useCallback(
|
|
||||||
async (e: React.MouseEvent) => {
|
|
||||||
onGenerateFromLlmClick(
|
|
||||||
title,
|
|
||||||
methods.map((m) => m.signature),
|
|
||||||
);
|
|
||||||
e.stopPropagation();
|
|
||||||
e.preventDefault();
|
|
||||||
},
|
|
||||||
[title, methods, onGenerateFromLlmClick],
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleStopModelWithAI = useCallback(
|
|
||||||
async (e: React.MouseEvent) => {
|
|
||||||
onStopGenerateFromLlmClick(title);
|
|
||||||
e.stopPropagation();
|
|
||||||
e.preventDefault();
|
|
||||||
},
|
|
||||||
[title, onStopGenerateFromLlmClick],
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleModelFromSource = useCallback(
|
const handleModelFromSource = useCallback(
|
||||||
async (e: React.MouseEvent) => {
|
async (e: React.MouseEvent) => {
|
||||||
onGenerateFromSourceClick();
|
onGenerateFromSourceClick();
|
||||||
@@ -186,21 +153,6 @@ export const LibraryRow = ({
|
|||||||
return methods.some((method) => modifiedSignatures.has(method.signature));
|
return methods.some((method) => modifiedSignatures.has(method.signature));
|
||||||
}, [methods, modifiedSignatures]);
|
}, [methods, modifiedSignatures]);
|
||||||
|
|
||||||
const canStopAutoModeling = useMemo(() => {
|
|
||||||
return methods.some((method) => inProgressMethods.has(method.signature));
|
|
||||||
}, [methods, inProgressMethods]);
|
|
||||||
|
|
||||||
const modelWithAIDisabled = useMemo(() => {
|
|
||||||
return (
|
|
||||||
getCandidates(
|
|
||||||
viewState.mode,
|
|
||||||
methods,
|
|
||||||
modeledMethodsMap,
|
|
||||||
processedByAutoModelMethods,
|
|
||||||
).length === 0
|
|
||||||
);
|
|
||||||
}, [methods, modeledMethodsMap, processedByAutoModelMethods, viewState.mode]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LibraryContainer>
|
<LibraryContainer>
|
||||||
<TitleContainer onClick={toggleExpanded} aria-expanded={isExpanded}>
|
<TitleContainer onClick={toggleExpanded} aria-expanded={isExpanded}>
|
||||||
@@ -219,22 +171,6 @@ export const LibraryRow = ({
|
|||||||
</ModeledPercentage>
|
</ModeledPercentage>
|
||||||
{hasUnsavedChanges ? <VSCodeTag>UNSAVED</VSCodeTag> : null}
|
{hasUnsavedChanges ? <VSCodeTag>UNSAVED</VSCodeTag> : null}
|
||||||
</NameContainer>
|
</NameContainer>
|
||||||
{viewState.showLlmButton && !canStopAutoModeling && (
|
|
||||||
<VSCodeButton
|
|
||||||
appearance="icon"
|
|
||||||
disabled={modelWithAIDisabled}
|
|
||||||
onClick={handleModelWithAI}
|
|
||||||
>
|
|
||||||
<Codicon name="lightbulb-autofix" label="Model with AI" />
|
|
||||||
Model with AI
|
|
||||||
</VSCodeButton>
|
|
||||||
)}
|
|
||||||
{viewState.showLlmButton && canStopAutoModeling && (
|
|
||||||
<VSCodeButton appearance="icon" onClick={handleStopModelWithAI}>
|
|
||||||
<Codicon name="debug-stop" label="Stop model with AI" />
|
|
||||||
Stop
|
|
||||||
</VSCodeButton>
|
|
||||||
)}
|
|
||||||
{viewState.showGenerateButton &&
|
{viewState.showGenerateButton &&
|
||||||
viewState.mode === Mode.Application && (
|
viewState.mode === Mode.Application && (
|
||||||
<VSCodeButton appearance="icon" onClick={handleModelFromSource}>
|
<VSCodeButton appearance="icon" onClick={handleModelFromSource}>
|
||||||
@@ -257,8 +193,6 @@ export const LibraryRow = ({
|
|||||||
modeledMethodsMap={modeledMethodsMap}
|
modeledMethodsMap={modeledMethodsMap}
|
||||||
modifiedSignatures={modifiedSignatures}
|
modifiedSignatures={modifiedSignatures}
|
||||||
selectedSignatures={selectedSignatures}
|
selectedSignatures={selectedSignatures}
|
||||||
inProgressMethods={inProgressMethods}
|
|
||||||
processedByAutoModelMethods={processedByAutoModelMethods}
|
|
||||||
viewState={viewState}
|
viewState={viewState}
|
||||||
hideModeledMethods={hideModeledMethods}
|
hideModeledMethods={hideModeledMethods}
|
||||||
revealedMethodSignature={revealedMethodSignature}
|
revealedMethodSignature={revealedMethodSignature}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import {
|
|||||||
VSCodeBadge,
|
VSCodeBadge,
|
||||||
VSCodeButton,
|
VSCodeButton,
|
||||||
VSCodeLink,
|
VSCodeLink,
|
||||||
VSCodeProgressRing,
|
|
||||||
} from "@vscode/webview-ui-toolkit/react";
|
} from "@vscode/webview-ui-toolkit/react";
|
||||||
import {
|
import {
|
||||||
forwardRef,
|
forwardRef,
|
||||||
@@ -17,13 +16,11 @@ import { vscode } from "../vscode-api";
|
|||||||
|
|
||||||
import type { Method } from "../../model-editor/method";
|
import type { Method } from "../../model-editor/method";
|
||||||
import type { ModeledMethod } from "../../model-editor/modeled-method";
|
import type { ModeledMethod } from "../../model-editor/modeled-method";
|
||||||
import { isModelPending } from "../../model-editor/modeled-method";
|
|
||||||
import { ModelKindDropdown } from "./ModelKindDropdown";
|
import { ModelKindDropdown } from "./ModelKindDropdown";
|
||||||
import { Mode } from "../../model-editor/shared/mode";
|
import { Mode } from "../../model-editor/shared/mode";
|
||||||
import { MethodClassifications } from "./MethodClassifications";
|
import { MethodClassifications } from "./MethodClassifications";
|
||||||
import { getModelingStatus } from "../../model-editor/shared/modeling-status";
|
import { getModelingStatus } from "../../model-editor/shared/modeling-status";
|
||||||
import { ModelingStatusIndicator } from "./ModelingStatusIndicator";
|
import { ModelingStatusIndicator } from "./ModelingStatusIndicator";
|
||||||
import { InProgressDropdown } from "./InProgressDropdown";
|
|
||||||
import { MethodName } from "./MethodName";
|
import { MethodName } from "./MethodName";
|
||||||
import { ModelTypeDropdown } from "./ModelTypeDropdown";
|
import { ModelTypeDropdown } from "./ModelTypeDropdown";
|
||||||
import { ModelInputDropdown } from "./ModelInputDropdown";
|
import { ModelInputDropdown } from "./ModelInputDropdown";
|
||||||
@@ -66,12 +63,6 @@ const ViewLink = styled(VSCodeLink)`
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ProgressRing = styled(VSCodeProgressRing)`
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
margin-left: auto;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const CodiconRow = styled(VSCodeButton)`
|
const CodiconRow = styled(VSCodeButton)`
|
||||||
min-height: calc(var(--input-height) * 1px);
|
min-height: calc(var(--input-height) * 1px);
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -83,8 +74,6 @@ export type MethodRowProps = {
|
|||||||
modeledMethods: ModeledMethod[];
|
modeledMethods: ModeledMethod[];
|
||||||
methodIsUnsaved: boolean;
|
methodIsUnsaved: boolean;
|
||||||
methodIsSelected: boolean;
|
methodIsSelected: boolean;
|
||||||
modelingInProgress: boolean;
|
|
||||||
processedByAutoModel: boolean;
|
|
||||||
viewState: ModelEditorViewState;
|
viewState: ModelEditorViewState;
|
||||||
revealedMethodSignature: string | null;
|
revealedMethodSignature: string | null;
|
||||||
inputAccessPathSuggestions?: AccessPathOption[];
|
inputAccessPathSuggestions?: AccessPathOption[];
|
||||||
@@ -122,7 +111,6 @@ const ModelableMethodRow = forwardRef<HTMLElement | undefined, MethodRowProps>(
|
|||||||
modeledMethods: modeledMethodsProp,
|
modeledMethods: modeledMethodsProp,
|
||||||
methodIsUnsaved,
|
methodIsUnsaved,
|
||||||
methodIsSelected,
|
methodIsSelected,
|
||||||
processedByAutoModel,
|
|
||||||
viewState,
|
viewState,
|
||||||
revealedMethodSignature,
|
revealedMethodSignature,
|
||||||
inputAccessPathSuggestions,
|
inputAccessPathSuggestions,
|
||||||
@@ -269,140 +257,105 @@ const ModelableMethodRow = forwardRef<HTMLElement | undefined, MethodRowProps>(
|
|||||||
>
|
>
|
||||||
View
|
View
|
||||||
</ViewLink>
|
</ViewLink>
|
||||||
{props.modelingInProgress && <ProgressRing />}
|
|
||||||
</ApiOrMethodRow>
|
</ApiOrMethodRow>
|
||||||
</DataGridCell>
|
</DataGridCell>
|
||||||
{props.modelingInProgress && (
|
|
||||||
<>
|
|
||||||
<DataGridCell>
|
|
||||||
<InProgressDropdown />
|
|
||||||
</DataGridCell>
|
|
||||||
<DataGridCell>
|
|
||||||
<InProgressDropdown />
|
|
||||||
</DataGridCell>
|
|
||||||
<DataGridCell>
|
|
||||||
<InProgressDropdown />
|
|
||||||
</DataGridCell>
|
|
||||||
<DataGridCell>
|
|
||||||
<InProgressDropdown />
|
|
||||||
</DataGridCell>
|
|
||||||
<DataGridCell>
|
|
||||||
<CodiconRow appearance="icon" disabled={true}>
|
|
||||||
<Codicon name="add" label="Add new model" />
|
|
||||||
</CodiconRow>
|
|
||||||
</DataGridCell>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
{!props.modelingInProgress && (
|
|
||||||
<>
|
|
||||||
{shownModeledMethods.map((modeledMethod, index) => {
|
|
||||||
const modelPending = isModelPending(
|
|
||||||
modeledMethod,
|
|
||||||
modelingStatus,
|
|
||||||
processedByAutoModel,
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
{shownModeledMethods.map((modeledMethod, index) => {
|
||||||
<DataGridRow key={index} focused={focusedIndex === index}>
|
return (
|
||||||
<DataGridCell>
|
<DataGridRow key={index} focused={focusedIndex === index}>
|
||||||
<ModelTypeDropdown
|
<DataGridCell>
|
||||||
language={viewState.language}
|
<ModelTypeDropdown
|
||||||
modelConfig={viewState.modelConfig}
|
language={viewState.language}
|
||||||
method={method}
|
modelConfig={viewState.modelConfig}
|
||||||
modeledMethod={modeledMethod}
|
method={method}
|
||||||
modelPending={modelPending}
|
modeledMethod={modeledMethod}
|
||||||
onChange={modeledMethodChangedHandlers[index]}
|
onChange={modeledMethodChangedHandlers[index]}
|
||||||
/>
|
|
||||||
</DataGridCell>
|
|
||||||
<DataGridCell>
|
|
||||||
{inputAccessPathSuggestions === undefined ? (
|
|
||||||
<ModelInputDropdown
|
|
||||||
language={viewState.language}
|
|
||||||
method={method}
|
|
||||||
modeledMethod={modeledMethod}
|
|
||||||
modelPending={modelPending}
|
|
||||||
onChange={modeledMethodChangedHandlers[index]}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<ModelInputSuggestBox
|
|
||||||
modeledMethod={modeledMethod}
|
|
||||||
suggestions={inputAccessPathSuggestions}
|
|
||||||
typePathSuggestions={outputAccessPathSuggestions ?? []}
|
|
||||||
onChange={modeledMethodChangedHandlers[index]}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</DataGridCell>
|
|
||||||
<DataGridCell>
|
|
||||||
{outputAccessPathSuggestions === undefined ? (
|
|
||||||
<ModelOutputDropdown
|
|
||||||
language={viewState.language}
|
|
||||||
method={method}
|
|
||||||
modeledMethod={modeledMethod}
|
|
||||||
modelPending={modelPending}
|
|
||||||
onChange={modeledMethodChangedHandlers[index]}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<ModelOutputSuggestBox
|
|
||||||
modeledMethod={modeledMethod}
|
|
||||||
suggestions={outputAccessPathSuggestions}
|
|
||||||
onChange={modeledMethodChangedHandlers[index]}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</DataGridCell>
|
|
||||||
<DataGridCell>
|
|
||||||
<ModelKindDropdown
|
|
||||||
language={viewState.language}
|
|
||||||
modeledMethod={modeledMethod}
|
|
||||||
modelPending={modelPending}
|
|
||||||
onChange={modeledMethodChangedHandlers[index]}
|
|
||||||
/>
|
|
||||||
</DataGridCell>
|
|
||||||
<DataGridCell>
|
|
||||||
<ModelButtonsContainer>
|
|
||||||
<ModelAlertsIndicator
|
|
||||||
viewState={viewState}
|
|
||||||
modeledMethod={modeledMethod}
|
|
||||||
evaluationRun={evaluationRun}
|
|
||||||
></ModelAlertsIndicator>
|
|
||||||
{index === 0 ? (
|
|
||||||
<CodiconRow
|
|
||||||
appearance="icon"
|
|
||||||
aria-label="Add new model"
|
|
||||||
onClick={(event: React.MouseEvent) => {
|
|
||||||
event.stopPropagation();
|
|
||||||
handleAddModelClick();
|
|
||||||
}}
|
|
||||||
disabled={addModelButtonDisabled}
|
|
||||||
>
|
|
||||||
<Codicon name="add" />
|
|
||||||
</CodiconRow>
|
|
||||||
) : (
|
|
||||||
<CodiconRow
|
|
||||||
appearance="icon"
|
|
||||||
aria-label="Remove model"
|
|
||||||
onClick={(event: React.MouseEvent) => {
|
|
||||||
event.stopPropagation();
|
|
||||||
removeModelClickedHandlers[index]();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Codicon name="trash" />
|
|
||||||
</CodiconRow>
|
|
||||||
)}
|
|
||||||
</ModelButtonsContainer>
|
|
||||||
</DataGridCell>
|
|
||||||
</DataGridRow>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
{validationErrors.map((error, index) => (
|
|
||||||
<DataGridCell gridColumn="span 5" key={index}>
|
|
||||||
<ModeledMethodAlert
|
|
||||||
error={error}
|
|
||||||
setSelectedIndex={setFocusedIndex}
|
|
||||||
/>
|
/>
|
||||||
</DataGridCell>
|
</DataGridCell>
|
||||||
))}
|
<DataGridCell>
|
||||||
</>
|
{inputAccessPathSuggestions === undefined ? (
|
||||||
)}
|
<ModelInputDropdown
|
||||||
|
language={viewState.language}
|
||||||
|
method={method}
|
||||||
|
modeledMethod={modeledMethod}
|
||||||
|
onChange={modeledMethodChangedHandlers[index]}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<ModelInputSuggestBox
|
||||||
|
modeledMethod={modeledMethod}
|
||||||
|
suggestions={inputAccessPathSuggestions}
|
||||||
|
typePathSuggestions={outputAccessPathSuggestions ?? []}
|
||||||
|
onChange={modeledMethodChangedHandlers[index]}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</DataGridCell>
|
||||||
|
<DataGridCell>
|
||||||
|
{outputAccessPathSuggestions === undefined ? (
|
||||||
|
<ModelOutputDropdown
|
||||||
|
language={viewState.language}
|
||||||
|
method={method}
|
||||||
|
modeledMethod={modeledMethod}
|
||||||
|
onChange={modeledMethodChangedHandlers[index]}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<ModelOutputSuggestBox
|
||||||
|
modeledMethod={modeledMethod}
|
||||||
|
suggestions={outputAccessPathSuggestions}
|
||||||
|
onChange={modeledMethodChangedHandlers[index]}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</DataGridCell>
|
||||||
|
<DataGridCell>
|
||||||
|
<ModelKindDropdown
|
||||||
|
language={viewState.language}
|
||||||
|
modeledMethod={modeledMethod}
|
||||||
|
onChange={modeledMethodChangedHandlers[index]}
|
||||||
|
/>
|
||||||
|
</DataGridCell>
|
||||||
|
<DataGridCell>
|
||||||
|
<ModelButtonsContainer>
|
||||||
|
<ModelAlertsIndicator
|
||||||
|
viewState={viewState}
|
||||||
|
modeledMethod={modeledMethod}
|
||||||
|
evaluationRun={evaluationRun}
|
||||||
|
></ModelAlertsIndicator>
|
||||||
|
{index === 0 ? (
|
||||||
|
<CodiconRow
|
||||||
|
appearance="icon"
|
||||||
|
aria-label="Add new model"
|
||||||
|
onClick={(event: React.MouseEvent) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
handleAddModelClick();
|
||||||
|
}}
|
||||||
|
disabled={addModelButtonDisabled}
|
||||||
|
>
|
||||||
|
<Codicon name="add" />
|
||||||
|
</CodiconRow>
|
||||||
|
) : (
|
||||||
|
<CodiconRow
|
||||||
|
appearance="icon"
|
||||||
|
aria-label="Remove model"
|
||||||
|
onClick={(event: React.MouseEvent) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
removeModelClickedHandlers[index]();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Codicon name="trash" />
|
||||||
|
</CodiconRow>
|
||||||
|
)}
|
||||||
|
</ModelButtonsContainer>
|
||||||
|
</DataGridCell>
|
||||||
|
</DataGridRow>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
{validationErrors.map((error, index) => (
|
||||||
|
<DataGridCell gridColumn="span 5" key={index}>
|
||||||
|
<ModeledMethodAlert
|
||||||
|
error={error}
|
||||||
|
setSelectedIndex={setFocusedIndex}
|
||||||
|
/>
|
||||||
|
</DataGridCell>
|
||||||
|
))}
|
||||||
</DataGridRow>
|
</DataGridRow>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -102,12 +102,6 @@ export function ModelEditor({
|
|||||||
new Set(),
|
new Set(),
|
||||||
);
|
);
|
||||||
|
|
||||||
const [inProgressMethods, setInProgressMethods] = useState<Set<string>>(
|
|
||||||
new Set(),
|
|
||||||
);
|
|
||||||
const [processedByAutoModelMethods, setProcessedByAutoModelMethods] =
|
|
||||||
useState<Set<string>>(new Set());
|
|
||||||
|
|
||||||
const [hideModeledMethods, setHideModeledMethods] = useState(
|
const [hideModeledMethods, setHideModeledMethods] = useState(
|
||||||
initialHideModeledMethods,
|
initialHideModeledMethods,
|
||||||
);
|
);
|
||||||
@@ -153,14 +147,6 @@ export function ModelEditor({
|
|||||||
case "setModifiedMethods":
|
case "setModifiedMethods":
|
||||||
setModifiedSignatures(new Set(msg.methodSignatures));
|
setModifiedSignatures(new Set(msg.methodSignatures));
|
||||||
break;
|
break;
|
||||||
case "setInProgressMethods": {
|
|
||||||
setInProgressMethods(new Set(msg.methods));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "setProcessedByAutoModelMethods": {
|
|
||||||
setProcessedByAutoModelMethods(new Set(msg.methods));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "revealMethod":
|
case "revealMethod":
|
||||||
setRevealedMethodSignature(msg.methodSignature);
|
setRevealedMethodSignature(msg.methodSignature);
|
||||||
break;
|
break;
|
||||||
@@ -294,24 +280,6 @@ export function ModelEditor({
|
|||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const onGenerateFromLlmClick = useCallback(
|
|
||||||
(packageName: string, methodSignatures: string[]) => {
|
|
||||||
vscode.postMessage({
|
|
||||||
t: "generateMethodsFromLlm",
|
|
||||||
packageName,
|
|
||||||
methodSignatures,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
const onStopGenerateFromLlmClick = useCallback((packageName: string) => {
|
|
||||||
vscode.postMessage({
|
|
||||||
t: "stopGeneratingMethodsFromLlm",
|
|
||||||
packageName,
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const onOpenDatabaseClick = useCallback(() => {
|
const onOpenDatabaseClick = useCallback(() => {
|
||||||
vscode.postMessage({
|
vscode.postMessage({
|
||||||
t: "openDatabase",
|
t: "openDatabase",
|
||||||
@@ -430,8 +398,6 @@ export function ModelEditor({
|
|||||||
modeledMethodsMap={modeledMethods}
|
modeledMethodsMap={modeledMethods}
|
||||||
modifiedSignatures={modifiedSignatures}
|
modifiedSignatures={modifiedSignatures}
|
||||||
selectedSignatures={selectedSignatures}
|
selectedSignatures={selectedSignatures}
|
||||||
inProgressMethods={inProgressMethods}
|
|
||||||
processedByAutoModelMethods={processedByAutoModelMethods}
|
|
||||||
viewState={viewState}
|
viewState={viewState}
|
||||||
hideModeledMethods={hideModeledMethods}
|
hideModeledMethods={hideModeledMethods}
|
||||||
revealedMethodSignature={revealedMethodSignature}
|
revealedMethodSignature={revealedMethodSignature}
|
||||||
@@ -440,8 +406,6 @@ export function ModelEditor({
|
|||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
onMethodClick={onMethodClick}
|
onMethodClick={onMethodClick}
|
||||||
onSaveModelClick={onSaveModelClick}
|
onSaveModelClick={onSaveModelClick}
|
||||||
onGenerateFromLlmClick={onGenerateFromLlmClick}
|
|
||||||
onStopGenerateFromLlmClick={onStopGenerateFromLlmClick}
|
|
||||||
onGenerateFromSourceClick={onGenerateFromSourceClick}
|
onGenerateFromSourceClick={onGenerateFromSourceClick}
|
||||||
onModelDependencyClick={onModelDependencyClick}
|
onModelDependencyClick={onModelDependencyClick}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ type Props = {
|
|||||||
language: QueryLanguage;
|
language: QueryLanguage;
|
||||||
method: Method;
|
method: Method;
|
||||||
modeledMethod: ModeledMethod | undefined;
|
modeledMethod: ModeledMethod | undefined;
|
||||||
modelPending: boolean;
|
|
||||||
onChange: (modeledMethod: ModeledMethod) => void;
|
onChange: (modeledMethod: ModeledMethod) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -23,7 +22,6 @@ export const ModelInputDropdown = ({
|
|||||||
language,
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethod,
|
modeledMethod,
|
||||||
modelPending,
|
|
||||||
onChange,
|
onChange,
|
||||||
}: Props): React.JSX.Element => {
|
}: Props): React.JSX.Element => {
|
||||||
const options = useMemo(() => {
|
const options = useMemo(() => {
|
||||||
@@ -80,7 +78,6 @@ export const ModelInputDropdown = ({
|
|||||||
value={value}
|
value={value}
|
||||||
options={options}
|
options={options}
|
||||||
disabled={!enabled}
|
disabled={!enabled}
|
||||||
$pending={modelPending}
|
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
aria-label="Input"
|
aria-label="Input"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -15,14 +15,12 @@ import { InputDropdown } from "./InputDropdown";
|
|||||||
type Props = {
|
type Props = {
|
||||||
language: QueryLanguage;
|
language: QueryLanguage;
|
||||||
modeledMethod: ModeledMethod | undefined;
|
modeledMethod: ModeledMethod | undefined;
|
||||||
modelPending: boolean;
|
|
||||||
onChange: (modeledMethod: ModeledMethod) => void;
|
onChange: (modeledMethod: ModeledMethod) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ModelKindDropdown = ({
|
export const ModelKindDropdown = ({
|
||||||
language,
|
language,
|
||||||
modeledMethod,
|
modeledMethod,
|
||||||
modelPending,
|
|
||||||
onChange,
|
onChange,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const predicate = useMemo(() => {
|
const predicate = useMemo(() => {
|
||||||
@@ -92,7 +90,6 @@ export const ModelKindDropdown = ({
|
|||||||
value={value}
|
value={value}
|
||||||
options={options}
|
options={options}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
$pending={modelPending}
|
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
aria-label="Kind"
|
aria-label="Kind"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ type Props = {
|
|||||||
language: QueryLanguage;
|
language: QueryLanguage;
|
||||||
method: Method;
|
method: Method;
|
||||||
modeledMethod: ModeledMethod | undefined;
|
modeledMethod: ModeledMethod | undefined;
|
||||||
modelPending: boolean;
|
|
||||||
onChange: (modeledMethod: ModeledMethod) => void;
|
onChange: (modeledMethod: ModeledMethod) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -23,7 +22,6 @@ export const ModelOutputDropdown = ({
|
|||||||
language,
|
language,
|
||||||
method,
|
method,
|
||||||
modeledMethod,
|
modeledMethod,
|
||||||
modelPending,
|
|
||||||
onChange,
|
onChange,
|
||||||
}: Props): React.JSX.Element => {
|
}: Props): React.JSX.Element => {
|
||||||
const options = useMemo(() => {
|
const options = useMemo(() => {
|
||||||
@@ -81,7 +79,6 @@ export const ModelOutputDropdown = ({
|
|||||||
value={value}
|
value={value}
|
||||||
options={options}
|
options={options}
|
||||||
disabled={!enabled}
|
disabled={!enabled}
|
||||||
$pending={modelPending}
|
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
aria-label="Output"
|
aria-label="Output"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ type Props = {
|
|||||||
modelConfig: ModelConfig;
|
modelConfig: ModelConfig;
|
||||||
method: Method;
|
method: Method;
|
||||||
modeledMethod: ModeledMethod | undefined;
|
modeledMethod: ModeledMethod | undefined;
|
||||||
modelPending: boolean;
|
|
||||||
onChange: (modeledMethod: ModeledMethod) => void;
|
onChange: (modeledMethod: ModeledMethod) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -41,7 +40,6 @@ export const ModelTypeDropdown = ({
|
|||||||
modelConfig,
|
modelConfig,
|
||||||
method,
|
method,
|
||||||
modeledMethod,
|
modeledMethod,
|
||||||
modelPending,
|
|
||||||
onChange,
|
onChange,
|
||||||
}: Props): React.JSX.Element => {
|
}: Props): React.JSX.Element => {
|
||||||
const options = useMemo(() => {
|
const options = useMemo(() => {
|
||||||
@@ -126,7 +124,6 @@ export const ModelTypeDropdown = ({
|
|||||||
<InputDropdown
|
<InputDropdown
|
||||||
value={modeledMethod?.type ?? "none"}
|
value={modeledMethod?.type ?? "none"}
|
||||||
options={options}
|
options={options}
|
||||||
$pending={modelPending}
|
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
aria-label="Model type"
|
aria-label="Model type"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ export type ModeledMethodDataGridProps = {
|
|||||||
modeledMethodsMap: Record<string, ModeledMethod[]>;
|
modeledMethodsMap: Record<string, ModeledMethod[]>;
|
||||||
modifiedSignatures: Set<string>;
|
modifiedSignatures: Set<string>;
|
||||||
selectedSignatures: Set<string>;
|
selectedSignatures: Set<string>;
|
||||||
inProgressMethods: Set<string>;
|
|
||||||
processedByAutoModelMethods: Set<string>;
|
|
||||||
viewState: ModelEditorViewState;
|
viewState: ModelEditorViewState;
|
||||||
hideModeledMethods: boolean;
|
hideModeledMethods: boolean;
|
||||||
revealedMethodSignature: string | null;
|
revealedMethodSignature: string | null;
|
||||||
@@ -34,8 +32,6 @@ export const ModeledMethodDataGrid = ({
|
|||||||
modeledMethodsMap,
|
modeledMethodsMap,
|
||||||
modifiedSignatures,
|
modifiedSignatures,
|
||||||
selectedSignatures,
|
selectedSignatures,
|
||||||
inProgressMethods,
|
|
||||||
processedByAutoModelMethods,
|
|
||||||
viewState,
|
viewState,
|
||||||
hideModeledMethods,
|
hideModeledMethods,
|
||||||
revealedMethodSignature,
|
revealedMethodSignature,
|
||||||
@@ -96,10 +92,6 @@ export const ModeledMethodDataGrid = ({
|
|||||||
modeledMethods={modeledMethods}
|
modeledMethods={modeledMethods}
|
||||||
methodIsUnsaved={modifiedSignatures.has(method.signature)}
|
methodIsUnsaved={modifiedSignatures.has(method.signature)}
|
||||||
methodIsSelected={selectedSignatures.has(method.signature)}
|
methodIsSelected={selectedSignatures.has(method.signature)}
|
||||||
modelingInProgress={inProgressMethods.has(method.signature)}
|
|
||||||
processedByAutoModel={processedByAutoModelMethods.has(
|
|
||||||
method.signature,
|
|
||||||
)}
|
|
||||||
viewState={viewState}
|
viewState={viewState}
|
||||||
revealedMethodSignature={revealedMethodSignature}
|
revealedMethodSignature={revealedMethodSignature}
|
||||||
inputAccessPathSuggestions={inputAccessPathSuggestions}
|
inputAccessPathSuggestions={inputAccessPathSuggestions}
|
||||||
|
|||||||
@@ -16,8 +16,6 @@ export type ModeledMethodsListProps = {
|
|||||||
modeledMethodsMap: Record<string, ModeledMethod[]>;
|
modeledMethodsMap: Record<string, ModeledMethod[]>;
|
||||||
modifiedSignatures: Set<string>;
|
modifiedSignatures: Set<string>;
|
||||||
selectedSignatures: Set<string>;
|
selectedSignatures: Set<string>;
|
||||||
inProgressMethods: Set<string>;
|
|
||||||
processedByAutoModelMethods: Set<string>;
|
|
||||||
revealedMethodSignature: string | null;
|
revealedMethodSignature: string | null;
|
||||||
accessPathSuggestions?: AccessPathSuggestionOptions;
|
accessPathSuggestions?: AccessPathSuggestionOptions;
|
||||||
evaluationRun: ModelEvaluationRunState | undefined;
|
evaluationRun: ModelEvaluationRunState | undefined;
|
||||||
@@ -26,11 +24,6 @@ export type ModeledMethodsListProps = {
|
|||||||
onChange: (methodSignature: string, modeledMethods: ModeledMethod[]) => void;
|
onChange: (methodSignature: string, modeledMethods: ModeledMethod[]) => void;
|
||||||
onMethodClick: (methodSignature: string) => void;
|
onMethodClick: (methodSignature: string) => void;
|
||||||
onSaveModelClick: (methodSignatures: string[]) => void;
|
onSaveModelClick: (methodSignatures: string[]) => void;
|
||||||
onGenerateFromLlmClick: (
|
|
||||||
packageName: string,
|
|
||||||
methodSignatures: string[],
|
|
||||||
) => void;
|
|
||||||
onStopGenerateFromLlmClick: (packageName: string) => void;
|
|
||||||
onGenerateFromSourceClick: () => void;
|
onGenerateFromSourceClick: () => void;
|
||||||
onModelDependencyClick: () => void;
|
onModelDependencyClick: () => void;
|
||||||
};
|
};
|
||||||
@@ -44,8 +37,6 @@ export const ModeledMethodsList = ({
|
|||||||
modeledMethodsMap,
|
modeledMethodsMap,
|
||||||
modifiedSignatures,
|
modifiedSignatures,
|
||||||
selectedSignatures,
|
selectedSignatures,
|
||||||
inProgressMethods,
|
|
||||||
processedByAutoModelMethods,
|
|
||||||
viewState,
|
viewState,
|
||||||
hideModeledMethods,
|
hideModeledMethods,
|
||||||
revealedMethodSignature,
|
revealedMethodSignature,
|
||||||
@@ -54,8 +45,6 @@ export const ModeledMethodsList = ({
|
|||||||
onChange,
|
onChange,
|
||||||
onMethodClick,
|
onMethodClick,
|
||||||
onSaveModelClick,
|
onSaveModelClick,
|
||||||
onGenerateFromLlmClick,
|
|
||||||
onStopGenerateFromLlmClick,
|
|
||||||
onGenerateFromSourceClick,
|
onGenerateFromSourceClick,
|
||||||
onModelDependencyClick,
|
onModelDependencyClick,
|
||||||
}: ModeledMethodsListProps) => {
|
}: ModeledMethodsListProps) => {
|
||||||
@@ -95,8 +84,6 @@ export const ModeledMethodsList = ({
|
|||||||
modeledMethodsMap={modeledMethodsMap}
|
modeledMethodsMap={modeledMethodsMap}
|
||||||
modifiedSignatures={modifiedSignatures}
|
modifiedSignatures={modifiedSignatures}
|
||||||
selectedSignatures={selectedSignatures}
|
selectedSignatures={selectedSignatures}
|
||||||
inProgressMethods={inProgressMethods}
|
|
||||||
processedByAutoModelMethods={processedByAutoModelMethods}
|
|
||||||
viewState={viewState}
|
viewState={viewState}
|
||||||
hideModeledMethods={hideModeledMethods}
|
hideModeledMethods={hideModeledMethods}
|
||||||
revealedMethodSignature={revealedMethodSignature}
|
revealedMethodSignature={revealedMethodSignature}
|
||||||
@@ -105,8 +92,6 @@ export const ModeledMethodsList = ({
|
|||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
onMethodClick={onMethodClick}
|
onMethodClick={onMethodClick}
|
||||||
onSaveModelClick={onSaveModelClick}
|
onSaveModelClick={onSaveModelClick}
|
||||||
onGenerateFromLlmClick={onGenerateFromLlmClick}
|
|
||||||
onStopGenerateFromLlmClick={onStopGenerateFromLlmClick}
|
|
||||||
onGenerateFromSourceClick={onGenerateFromSourceClick}
|
onGenerateFromSourceClick={onGenerateFromSourceClick}
|
||||||
onModelDependencyClick={onModelDependencyClick}
|
onModelDependencyClick={onModelDependencyClick}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -10,8 +10,6 @@ describe(LibraryRow.name, () => {
|
|||||||
const onChange = jest.fn();
|
const onChange = jest.fn();
|
||||||
const onMethodClick = jest.fn();
|
const onMethodClick = jest.fn();
|
||||||
const onSaveModelClick = jest.fn();
|
const onSaveModelClick = jest.fn();
|
||||||
const onGenerateFromLlmClick = jest.fn();
|
|
||||||
const onStopGenerateFromLlmClick = jest.fn();
|
|
||||||
const onModelDependencyClick = jest.fn();
|
const onModelDependencyClick = jest.fn();
|
||||||
|
|
||||||
const viewState = createMockModelEditorViewState();
|
const viewState = createMockModelEditorViewState();
|
||||||
@@ -35,8 +33,6 @@ describe(LibraryRow.name, () => {
|
|||||||
}}
|
}}
|
||||||
modifiedSignatures={new Set([method.signature])}
|
modifiedSignatures={new Set([method.signature])}
|
||||||
selectedSignatures={new Set()}
|
selectedSignatures={new Set()}
|
||||||
inProgressMethods={new Set()}
|
|
||||||
processedByAutoModelMethods={new Set()}
|
|
||||||
evaluationRun={undefined}
|
evaluationRun={undefined}
|
||||||
viewState={viewState}
|
viewState={viewState}
|
||||||
hideModeledMethods={false}
|
hideModeledMethods={false}
|
||||||
@@ -44,8 +40,6 @@ describe(LibraryRow.name, () => {
|
|||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
onMethodClick={onMethodClick}
|
onMethodClick={onMethodClick}
|
||||||
onSaveModelClick={onSaveModelClick}
|
onSaveModelClick={onSaveModelClick}
|
||||||
onGenerateFromLlmClick={onGenerateFromLlmClick}
|
|
||||||
onStopGenerateFromLlmClick={onStopGenerateFromLlmClick}
|
|
||||||
onGenerateFromSourceClick={jest.fn()}
|
onGenerateFromSourceClick={jest.fn()}
|
||||||
onModelDependencyClick={onModelDependencyClick}
|
onModelDependencyClick={onModelDependencyClick}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -74,33 +68,6 @@ describe(LibraryRow.name, () => {
|
|||||||
expect(screen.queryByText("Model dependency")).toBeInTheDocument();
|
expect(screen.queryByText("Model dependency")).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("renders the row when LLM is enabled", () => {
|
|
||||||
render({
|
|
||||||
viewState: {
|
|
||||||
...viewState,
|
|
||||||
showLlmButton: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(screen.queryByText("Model from source")).not.toBeInTheDocument();
|
|
||||||
expect(screen.queryByText("Model with AI")).toBeInTheDocument();
|
|
||||||
expect(screen.queryByText("Model dependency")).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("renders the row when generate button and LLM are enabled", () => {
|
|
||||||
render({
|
|
||||||
viewState: {
|
|
||||||
...viewState,
|
|
||||||
showGenerateButton: true,
|
|
||||||
showLlmButton: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(screen.queryByText("Model from source")).toBeInTheDocument();
|
|
||||||
expect(screen.queryByText("Model with AI")).toBeInTheDocument();
|
|
||||||
expect(screen.queryByText("Model dependency")).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("can expand the row", async () => {
|
it("can expand the row", async () => {
|
||||||
render();
|
render();
|
||||||
|
|
||||||
|
|||||||
@@ -42,8 +42,6 @@ describe(MethodRow.name, () => {
|
|||||||
modeledMethods={[modeledMethod]}
|
modeledMethods={[modeledMethod]}
|
||||||
methodIsUnsaved={false}
|
methodIsUnsaved={false}
|
||||||
methodIsSelected={false}
|
methodIsSelected={false}
|
||||||
modelingInProgress={false}
|
|
||||||
processedByAutoModel={false}
|
|
||||||
revealedMethodSignature={null}
|
revealedMethodSignature={null}
|
||||||
evaluationRun={undefined}
|
evaluationRun={undefined}
|
||||||
viewState={viewState}
|
viewState={viewState}
|
||||||
@@ -186,14 +184,6 @@ describe(MethodRow.name, () => {
|
|||||||
expect(screen.getByLabelText("Method not modeled")).toBeInTheDocument();
|
expect(screen.getByLabelText("Method not modeled")).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("shows the in progress indicator when in progress", () => {
|
|
||||||
render({
|
|
||||||
modelingInProgress: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(screen.getByLabelText("Loading")).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("can render multiple models", () => {
|
it("can render multiple models", () => {
|
||||||
render({
|
render({
|
||||||
modeledMethods: [
|
modeledMethods: [
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ describe(ModelKindDropdown.name, () => {
|
|||||||
<ModelKindDropdown
|
<ModelKindDropdown
|
||||||
language={QueryLanguage.Java}
|
language={QueryLanguage.Java}
|
||||||
modeledMethod={modeledMethod}
|
modeledMethod={modeledMethod}
|
||||||
modelPending={false}
|
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
@@ -47,7 +46,6 @@ describe(ModelKindDropdown.name, () => {
|
|||||||
<ModelKindDropdown
|
<ModelKindDropdown
|
||||||
language={QueryLanguage.Java}
|
language={QueryLanguage.Java}
|
||||||
modeledMethod={modeledMethod}
|
modeledMethod={modeledMethod}
|
||||||
modelPending={false}
|
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
@@ -64,7 +62,6 @@ describe(ModelKindDropdown.name, () => {
|
|||||||
<ModelKindDropdown
|
<ModelKindDropdown
|
||||||
language={QueryLanguage.Java}
|
language={QueryLanguage.Java}
|
||||||
modeledMethod={updatedModeledMethod}
|
modeledMethod={updatedModeledMethod}
|
||||||
modelPending={false}
|
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
@@ -82,7 +79,6 @@ describe(ModelKindDropdown.name, () => {
|
|||||||
<ModelKindDropdown
|
<ModelKindDropdown
|
||||||
language={QueryLanguage.Java}
|
language={QueryLanguage.Java}
|
||||||
modeledMethod={modeledMethod}
|
modeledMethod={modeledMethod}
|
||||||
modelPending={false}
|
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
@@ -102,7 +98,6 @@ describe(ModelKindDropdown.name, () => {
|
|||||||
<ModelKindDropdown
|
<ModelKindDropdown
|
||||||
language={QueryLanguage.Java}
|
language={QueryLanguage.Java}
|
||||||
modeledMethod={modeledMethod}
|
modeledMethod={modeledMethod}
|
||||||
modelPending={false}
|
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ describe(ModelTypeDropdown.name, () => {
|
|||||||
<ModelTypeDropdown
|
<ModelTypeDropdown
|
||||||
language={QueryLanguage.Java}
|
language={QueryLanguage.Java}
|
||||||
modeledMethod={modeledMethod}
|
modeledMethod={modeledMethod}
|
||||||
modelPending={false}
|
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
method={method}
|
method={method}
|
||||||
modelConfig={defaultModelConfig}
|
modelConfig={defaultModelConfig}
|
||||||
@@ -44,7 +43,6 @@ describe(ModelTypeDropdown.name, () => {
|
|||||||
<ModelTypeDropdown
|
<ModelTypeDropdown
|
||||||
language={QueryLanguage.Ruby}
|
language={QueryLanguage.Ruby}
|
||||||
modeledMethod={modeledMethod}
|
modeledMethod={modeledMethod}
|
||||||
modelPending={false}
|
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
method={method}
|
method={method}
|
||||||
modelConfig={defaultModelConfig}
|
modelConfig={defaultModelConfig}
|
||||||
@@ -67,7 +65,6 @@ describe(ModelTypeDropdown.name, () => {
|
|||||||
<ModelTypeDropdown
|
<ModelTypeDropdown
|
||||||
language={QueryLanguage.Java}
|
language={QueryLanguage.Java}
|
||||||
modeledMethod={modeledMethod}
|
modeledMethod={modeledMethod}
|
||||||
modelPending={false}
|
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
method={method}
|
method={method}
|
||||||
modelConfig={defaultModelConfig}
|
modelConfig={defaultModelConfig}
|
||||||
|
|||||||
@@ -57,8 +57,6 @@ describe(ModeledMethodDataGrid.name, () => {
|
|||||||
}}
|
}}
|
||||||
modifiedSignatures={new Set([method1.signature])}
|
modifiedSignatures={new Set([method1.signature])}
|
||||||
selectedSignatures={new Set()}
|
selectedSignatures={new Set()}
|
||||||
inProgressMethods={new Set()}
|
|
||||||
processedByAutoModelMethods={new Set()}
|
|
||||||
evaluationRun={undefined}
|
evaluationRun={undefined}
|
||||||
viewState={viewState}
|
viewState={viewState}
|
||||||
hideModeledMethods={false}
|
hideModeledMethods={false}
|
||||||
|
|||||||
@@ -35,8 +35,6 @@ describe(ModeledMethodsList.name, () => {
|
|||||||
const onChange = jest.fn();
|
const onChange = jest.fn();
|
||||||
const onMethodClick = jest.fn();
|
const onMethodClick = jest.fn();
|
||||||
const onSaveModelClick = jest.fn();
|
const onSaveModelClick = jest.fn();
|
||||||
const onGenerateFromLlmClick = jest.fn();
|
|
||||||
const onStopGenerateFromLlmClick = jest.fn();
|
|
||||||
const onModelDependencyClick = jest.fn();
|
const onModelDependencyClick = jest.fn();
|
||||||
|
|
||||||
const viewState = createMockModelEditorViewState();
|
const viewState = createMockModelEditorViewState();
|
||||||
@@ -58,8 +56,6 @@ describe(ModeledMethodsList.name, () => {
|
|||||||
}}
|
}}
|
||||||
modifiedSignatures={new Set([method1.signature])}
|
modifiedSignatures={new Set([method1.signature])}
|
||||||
selectedSignatures={new Set()}
|
selectedSignatures={new Set()}
|
||||||
inProgressMethods={new Set()}
|
|
||||||
processedByAutoModelMethods={new Set()}
|
|
||||||
evaluationRun={undefined}
|
evaluationRun={undefined}
|
||||||
viewState={viewState}
|
viewState={viewState}
|
||||||
hideModeledMethods={false}
|
hideModeledMethods={false}
|
||||||
@@ -67,8 +63,6 @@ describe(ModeledMethodsList.name, () => {
|
|||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
onMethodClick={onMethodClick}
|
onMethodClick={onMethodClick}
|
||||||
onSaveModelClick={onSaveModelClick}
|
onSaveModelClick={onSaveModelClick}
|
||||||
onGenerateFromLlmClick={onGenerateFromLlmClick}
|
|
||||||
onStopGenerateFromLlmClick={onStopGenerateFromLlmClick}
|
|
||||||
onGenerateFromSourceClick={jest.fn()}
|
onGenerateFromSourceClick={jest.fn()}
|
||||||
onModelDependencyClick={onModelDependencyClick}
|
onModelDependencyClick={onModelDependencyClick}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ export function createMockModelEditorViewState(
|
|||||||
language: QueryLanguage.Java,
|
language: QueryLanguage.Java,
|
||||||
mode: Mode.Application,
|
mode: Mode.Application,
|
||||||
showGenerateButton: false,
|
showGenerateButton: false,
|
||||||
showLlmButton: false,
|
|
||||||
showEvaluationUi: false,
|
showEvaluationUi: false,
|
||||||
showModeSwitchButton: true,
|
showModeSwitchButton: true,
|
||||||
extensionPack: createMockExtensionPack(),
|
extensionPack: createMockExtensionPack(),
|
||||||
|
|||||||
@@ -1,82 +0,0 @@
|
|||||||
import {
|
|
||||||
createAutoModelRequest,
|
|
||||||
encodeSarif,
|
|
||||||
} from "../../../src/model-editor/auto-model";
|
|
||||||
import { Mode } from "../../../src/model-editor/shared/mode";
|
|
||||||
import { AutomodelMode } from "../../../src/model-editor/auto-model-api";
|
|
||||||
import type { AutoModelQueriesResult } from "../../../src/model-editor/auto-model-codeml-queries";
|
|
||||||
import type { Log } from "sarif";
|
|
||||||
import { gzipDecode } from "../../../src/common/zlib";
|
|
||||||
|
|
||||||
describe("createAutoModelRequest", () => {
|
|
||||||
const createSarifLog = (queryId: string): Log => {
|
|
||||||
return {
|
|
||||||
version: "2.1.0",
|
|
||||||
$schema: "http://json.schemastore.org/sarif-2.1.0-rtm.4",
|
|
||||||
runs: [
|
|
||||||
{
|
|
||||||
tool: {
|
|
||||||
driver: {
|
|
||||||
name: "CodeQL",
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
id: queryId,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
results: [
|
|
||||||
{
|
|
||||||
message: {
|
|
||||||
text: "msg",
|
|
||||||
},
|
|
||||||
locations: [
|
|
||||||
{
|
|
||||||
physicalLocation: {
|
|
||||||
contextRegion: {
|
|
||||||
startLine: 10,
|
|
||||||
endLine: 12,
|
|
||||||
snippet: {
|
|
||||||
text: "Foo",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
region: {
|
|
||||||
startLine: 10,
|
|
||||||
startColumn: 1,
|
|
||||||
endColumn: 3,
|
|
||||||
},
|
|
||||||
artifactLocation: {
|
|
||||||
uri: "foo.js",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const result: AutoModelQueriesResult = {
|
|
||||||
candidates: createSarifLog(
|
|
||||||
"java/ml/extract-automodel-application-candidates",
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
it("creates a matching request", async () => {
|
|
||||||
expect(await createAutoModelRequest(Mode.Application, result)).toEqual({
|
|
||||||
mode: AutomodelMode.Application,
|
|
||||||
candidates: await encodeSarif(result.candidates),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("can decode the SARIF", async () => {
|
|
||||||
const request = await createAutoModelRequest(Mode.Application, result);
|
|
||||||
const decoded = Buffer.from(request.candidates, "base64");
|
|
||||||
const decompressed = await gzipDecode(decoded);
|
|
||||||
const json = decompressed.toString("utf-8");
|
|
||||||
const parsed = JSON.parse(json);
|
|
||||||
expect(parsed).toEqual(result.candidates);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
import type { Method } from "../../../../src/model-editor/method";
|
|
||||||
import { EndpointType } from "../../../../src/model-editor/method";
|
|
||||||
import type { ModeledMethod } from "../../../../src/model-editor/modeled-method";
|
|
||||||
import { getCandidates } from "../../../../src/model-editor/shared/auto-model-candidates";
|
|
||||||
import { Mode } from "../../../../src/model-editor/shared/mode";
|
|
||||||
|
|
||||||
describe("getCandidates", () => {
|
|
||||||
it("doesn't return methods that are already modelled", () => {
|
|
||||||
const methods: Method[] = [
|
|
||||||
{
|
|
||||||
library: "my.jar",
|
|
||||||
signature: "org.my.A#x()",
|
|
||||||
endpointType: EndpointType.Method,
|
|
||||||
packageName: "org.my",
|
|
||||||
typeName: "A",
|
|
||||||
methodName: "x",
|
|
||||||
methodParameters: "()",
|
|
||||||
supported: false,
|
|
||||||
supportedType: "none",
|
|
||||||
usages: [],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
const modeledMethods: Record<string, ModeledMethod[]> = {
|
|
||||||
"org.my.A#x()": [
|
|
||||||
{
|
|
||||||
type: "neutral",
|
|
||||||
kind: "sink",
|
|
||||||
provenance: "manual",
|
|
||||||
signature: "org.my.A#x()",
|
|
||||||
endpointType: EndpointType.Method,
|
|
||||||
packageName: "org.my",
|
|
||||||
typeName: "A",
|
|
||||||
methodName: "x",
|
|
||||||
methodParameters: "()",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
const candidates = getCandidates(
|
|
||||||
Mode.Application,
|
|
||||||
methods,
|
|
||||||
modeledMethods,
|
|
||||||
new Set(),
|
|
||||||
);
|
|
||||||
expect(candidates.length).toEqual(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("doesn't return methods that are supported from other sources", () => {
|
|
||||||
const methods: Method[] = [
|
|
||||||
{
|
|
||||||
library: "my.jar",
|
|
||||||
signature: "org.my.A#x()",
|
|
||||||
endpointType: EndpointType.Method,
|
|
||||||
packageName: "org.my",
|
|
||||||
typeName: "A",
|
|
||||||
methodName: "x",
|
|
||||||
methodParameters: "()",
|
|
||||||
supported: true,
|
|
||||||
supportedType: "none",
|
|
||||||
usages: [],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
const modeledMethods = {};
|
|
||||||
const candidates = getCandidates(
|
|
||||||
Mode.Application,
|
|
||||||
methods,
|
|
||||||
modeledMethods,
|
|
||||||
new Set(),
|
|
||||||
);
|
|
||||||
expect(candidates.length).toEqual(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("doesn't return methods that are already processed by auto model", () => {
|
|
||||||
const methods: Method[] = [
|
|
||||||
{
|
|
||||||
library: "my.jar",
|
|
||||||
signature: "org.my.A#x()",
|
|
||||||
endpointType: EndpointType.Method,
|
|
||||||
packageName: "org.my",
|
|
||||||
typeName: "A",
|
|
||||||
methodName: "x",
|
|
||||||
methodParameters: "()",
|
|
||||||
supported: false,
|
|
||||||
supportedType: "none",
|
|
||||||
usages: [],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
const modeledMethods = {};
|
|
||||||
const candidates = getCandidates(
|
|
||||||
Mode.Application,
|
|
||||||
methods,
|
|
||||||
modeledMethods,
|
|
||||||
new Set(["org.my.A#x()"]),
|
|
||||||
);
|
|
||||||
expect(candidates.length).toEqual(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("returns methods that are neither modeled nor supported from other sources", () => {
|
|
||||||
const methods: Method[] = [];
|
|
||||||
methods.push({
|
|
||||||
library: "my.jar",
|
|
||||||
signature: "org.my.A#x()",
|
|
||||||
endpointType: EndpointType.Method,
|
|
||||||
packageName: "org.my",
|
|
||||||
typeName: "A",
|
|
||||||
methodName: "x",
|
|
||||||
methodParameters: "()",
|
|
||||||
supported: false,
|
|
||||||
supportedType: "none",
|
|
||||||
usages: [],
|
|
||||||
});
|
|
||||||
const modeledMethods = {};
|
|
||||||
const candidates = getCandidates(
|
|
||||||
Mode.Application,
|
|
||||||
methods,
|
|
||||||
modeledMethods,
|
|
||||||
new Set(),
|
|
||||||
);
|
|
||||||
expect(candidates.length).toEqual(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -10,16 +10,8 @@ import { shuffle } from "../../../vscode-tests/utils/list-helpers";
|
|||||||
|
|
||||||
describe("sortMethods", () => {
|
describe("sortMethods", () => {
|
||||||
it("uses primary sort order", () => {
|
it("uses primary sort order", () => {
|
||||||
const unsavedPositiveAutoModelPrediction = createMethod({
|
const unsavedModel = createMethod({
|
||||||
signature: "org.sql2o.Sql2o#unsavedPositiveAutoModelPrediction()",
|
signature: "org.sql2o.Sql2o#unsavedModel()",
|
||||||
supported: false,
|
|
||||||
});
|
|
||||||
const negativeAutoModelPrediction = createMethod({
|
|
||||||
signature: "org.sql2o.Sql2o#negativeAutoModelPrediction()",
|
|
||||||
supported: false,
|
|
||||||
});
|
|
||||||
const unsavedManualModel = createMethod({
|
|
||||||
signature: "org.sql2o.Sql2o#unsavedManualModel()",
|
|
||||||
supported: false,
|
supported: false,
|
||||||
});
|
});
|
||||||
const unmodeledMethodWithEarlierSignature = createMethod({
|
const unmodeledMethodWithEarlierSignature = createMethod({
|
||||||
@@ -30,12 +22,8 @@ describe("sortMethods", () => {
|
|||||||
signature: "org.sql2o.Sql2o#zzz_unmodeledMethodWithLaterSignature()",
|
signature: "org.sql2o.Sql2o#zzz_unmodeledMethodWithLaterSignature()",
|
||||||
supported: false,
|
supported: false,
|
||||||
});
|
});
|
||||||
const savedAutoModelPrediction = createMethod({
|
const savedModel = createMethod({
|
||||||
signature: "org.sql2o.Sql2o#savedAutoModelPrediction()",
|
signature: "org.sql2o.Sql2o#savedModel()",
|
||||||
supported: false,
|
|
||||||
});
|
|
||||||
const savedManualModel = createMethod({
|
|
||||||
signature: "org.sql2o.Sql2o#savedManualModel()",
|
|
||||||
supported: false,
|
supported: false,
|
||||||
});
|
});
|
||||||
const supportedMethod = createMethod({
|
const supportedMethod = createMethod({
|
||||||
@@ -44,65 +32,31 @@ describe("sortMethods", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const methods: Method[] = shuffle([
|
const methods: Method[] = shuffle([
|
||||||
unsavedPositiveAutoModelPrediction,
|
unsavedModel,
|
||||||
negativeAutoModelPrediction,
|
|
||||||
unsavedManualModel,
|
|
||||||
unmodeledMethodWithEarlierSignature,
|
unmodeledMethodWithEarlierSignature,
|
||||||
unmodeledMethodWithLaterSignature,
|
unmodeledMethodWithLaterSignature,
|
||||||
savedAutoModelPrediction,
|
savedModel,
|
||||||
savedManualModel,
|
|
||||||
supportedMethod,
|
supportedMethod,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const modeledMethodsMap: Record<string, readonly ModeledMethod[]> = {};
|
const modeledMethodsMap: Record<string, readonly ModeledMethod[]> = {};
|
||||||
modeledMethodsMap[unsavedPositiveAutoModelPrediction.signature] = [
|
modeledMethodsMap[unsavedModel.signature] = [createSinkModeledMethod()];
|
||||||
createSinkModeledMethod(),
|
modeledMethodsMap[savedModel.signature] = [createSinkModeledMethod()];
|
||||||
];
|
|
||||||
modeledMethodsMap[unsavedManualModel.signature] = [
|
|
||||||
createSinkModeledMethod(),
|
|
||||||
];
|
|
||||||
modeledMethodsMap[savedAutoModelPrediction.signature] = [
|
|
||||||
createSinkModeledMethod(),
|
|
||||||
];
|
|
||||||
modeledMethodsMap[savedManualModel.signature] = [createSinkModeledMethod()];
|
|
||||||
|
|
||||||
const modifiedSignatures: Set<string> = new Set([
|
const modifiedSignatures: Set<string> = new Set([unsavedModel.signature]);
|
||||||
unsavedPositiveAutoModelPrediction.signature,
|
|
||||||
unsavedManualModel.signature,
|
|
||||||
]);
|
|
||||||
|
|
||||||
const processedByAutoModelMethods: Set<string> = new Set([
|
expect(sortMethods(methods, modeledMethodsMap, modifiedSignatures)).toEqual(
|
||||||
unsavedPositiveAutoModelPrediction.signature,
|
[
|
||||||
negativeAutoModelPrediction.signature,
|
unmodeledMethodWithEarlierSignature,
|
||||||
savedAutoModelPrediction.signature,
|
unsavedModel,
|
||||||
]);
|
unmodeledMethodWithLaterSignature,
|
||||||
|
savedModel,
|
||||||
expect(
|
supportedMethod,
|
||||||
sortMethods(
|
],
|
||||||
methods,
|
);
|
||||||
modeledMethodsMap,
|
|
||||||
modifiedSignatures,
|
|
||||||
processedByAutoModelMethods,
|
|
||||||
),
|
|
||||||
).toEqual([
|
|
||||||
unsavedPositiveAutoModelPrediction,
|
|
||||||
negativeAutoModelPrediction,
|
|
||||||
unmodeledMethodWithEarlierSignature,
|
|
||||||
unsavedManualModel,
|
|
||||||
unmodeledMethodWithLaterSignature,
|
|
||||||
savedAutoModelPrediction,
|
|
||||||
savedManualModel,
|
|
||||||
supportedMethod,
|
|
||||||
]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("uses secondary sort order based on usages and signature", () => {
|
it("uses secondary sort order based on usages and signature", () => {
|
||||||
const negativeAutoModelPrediction = createMethod({
|
|
||||||
signature: "org.sql2o.Sql2o#negativeAutoModelPrediction()",
|
|
||||||
supported: false,
|
|
||||||
usages: [],
|
|
||||||
});
|
|
||||||
|
|
||||||
const unmodeledMethodWithTwoUsages = createMethod({
|
const unmodeledMethodWithTwoUsages = createMethod({
|
||||||
signature: "org.sql2o.Sql2o#unmodeledMethodWithTwoUsages()",
|
signature: "org.sql2o.Sql2o#unmodeledMethodWithTwoUsages()",
|
||||||
supported: false,
|
supported: false,
|
||||||
@@ -126,7 +80,6 @@ describe("sortMethods", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const methods: Method[] = shuffle([
|
const methods: Method[] = shuffle([
|
||||||
negativeAutoModelPrediction,
|
|
||||||
unmodeledMethodWithTwoUsages,
|
unmodeledMethodWithTwoUsages,
|
||||||
unmodeledMethodWithOneUsage,
|
unmodeledMethodWithOneUsage,
|
||||||
unmodeledMethodWithEarlierSignature,
|
unmodeledMethodWithEarlierSignature,
|
||||||
@@ -137,23 +90,13 @@ describe("sortMethods", () => {
|
|||||||
|
|
||||||
const modifiedSignatures: Set<string> = new Set([]);
|
const modifiedSignatures: Set<string> = new Set([]);
|
||||||
|
|
||||||
const processedByAutoModelMethods: Set<string> = new Set([
|
expect(sortMethods(methods, modeledMethodsMap, modifiedSignatures)).toEqual(
|
||||||
negativeAutoModelPrediction.signature,
|
[
|
||||||
]);
|
unmodeledMethodWithTwoUsages,
|
||||||
|
unmodeledMethodWithOneUsage,
|
||||||
expect(
|
unmodeledMethodWithEarlierSignature,
|
||||||
sortMethods(
|
unmodeledMethodWithLaterSignature,
|
||||||
methods,
|
],
|
||||||
modeledMethodsMap,
|
);
|
||||||
modifiedSignatures,
|
|
||||||
processedByAutoModelMethods,
|
|
||||||
),
|
|
||||||
).toEqual([
|
|
||||||
negativeAutoModelPrediction,
|
|
||||||
unmodeledMethodWithTwoUsages,
|
|
||||||
unmodeledMethodWithOneUsage,
|
|
||||||
unmodeledMethodWithEarlierSignature,
|
|
||||||
unmodeledMethodWithLaterSignature,
|
|
||||||
]);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,207 +0,0 @@
|
|||||||
import { createMockLogger } from "../../../__mocks__/loggerMock";
|
|
||||||
import type { DatabaseItem } from "../../../../src/databases/local-databases";
|
|
||||||
import { DatabaseKind } from "../../../../src/databases/local-databases";
|
|
||||||
import { file } from "tmp-promise";
|
|
||||||
import { QueryResultType } from "../../../../src/query-server/messages";
|
|
||||||
import {
|
|
||||||
generateCandidateFilterPack,
|
|
||||||
runAutoModelQueries,
|
|
||||||
} from "../../../../src/model-editor/auto-model-codeml-queries";
|
|
||||||
import { Mode } from "../../../../src/model-editor/shared/mode";
|
|
||||||
import { mockedObject, mockedUri } from "../../utils/mocking.helpers";
|
|
||||||
import type { CodeQLCliServer } from "../../../../src/codeql-cli/cli";
|
|
||||||
import type { QueryRunner } from "../../../../src/query-server";
|
|
||||||
import * as queryResolver from "../../../../src/local-queries/query-resolver";
|
|
||||||
import type { MethodSignature } from "../../../../src/model-editor/method";
|
|
||||||
import { EndpointType } from "../../../../src/model-editor/method";
|
|
||||||
import { join } from "path";
|
|
||||||
import { pathExists, readFile } from "fs-extra";
|
|
||||||
import { load as loadYaml } from "js-yaml";
|
|
||||||
import { CancellationTokenSource } from "vscode-jsonrpc";
|
|
||||||
import { QueryOutputDir } from "../../../../src/local-queries/query-output-dir";
|
|
||||||
import type { ModelExtensionFile } from "../../../../src/model-editor/model-extension-file";
|
|
||||||
|
|
||||||
describe("runAutoModelQueries", () => {
|
|
||||||
let resolveQueriesSpy: jest.SpiedFunction<
|
|
||||||
typeof queryResolver.resolveQueries
|
|
||||||
>;
|
|
||||||
beforeEach(() => {
|
|
||||||
resolveQueriesSpy = jest
|
|
||||||
.spyOn(queryResolver, "resolveQueries")
|
|
||||||
.mockImplementation(
|
|
||||||
async (_cliServer, _packsToSearch, _name, constraints) => {
|
|
||||||
if (constraints["tags contain all"]?.includes("candidates")) {
|
|
||||||
return ["/a/b/c/ql/candidates.ql"];
|
|
||||||
}
|
|
||||||
if (constraints["tags contain all"]?.includes("positive")) {
|
|
||||||
return ["/a/b/c/ql/positive-examples.ql"];
|
|
||||||
}
|
|
||||||
if (constraints["tags contain all"]?.includes("negative")) {
|
|
||||||
return ["/a/b/c/ql/negative-examples.ql"];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [];
|
|
||||||
},
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should run the query and return the results", async () => {
|
|
||||||
const queryStorageDir = (await file()).path;
|
|
||||||
const outputDir = new QueryOutputDir(join(queryStorageDir, "1"));
|
|
||||||
|
|
||||||
const options = {
|
|
||||||
mode: Mode.Application,
|
|
||||||
candidateMethods: [],
|
|
||||||
cliServer: mockedObject<CodeQLCliServer>({
|
|
||||||
resolveQlpacks: jest.fn().mockResolvedValue({
|
|
||||||
"/a/b/c/my-extension-pack": {},
|
|
||||||
}),
|
|
||||||
resolveMetadata: jest.fn().mockResolvedValue({
|
|
||||||
kind: "problem",
|
|
||||||
}),
|
|
||||||
interpretBqrsSarif: jest.fn().mockResolvedValue({
|
|
||||||
version: "2.1.0",
|
|
||||||
$schema: "http://json.schemastore.org/sarif-2.1.0-rtm.4",
|
|
||||||
runs: [
|
|
||||||
{
|
|
||||||
tool: {
|
|
||||||
driver: {
|
|
||||||
name: "CodeQL",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
results: [
|
|
||||||
{
|
|
||||||
message: {
|
|
||||||
text: "msg",
|
|
||||||
},
|
|
||||||
locations: [
|
|
||||||
{
|
|
||||||
physicalLocation: {
|
|
||||||
contextRegion: {
|
|
||||||
startLine: 10,
|
|
||||||
endLine: 12,
|
|
||||||
snippet: {
|
|
||||||
text: "Foo",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
region: {
|
|
||||||
startLine: 10,
|
|
||||||
startColumn: 1,
|
|
||||||
endColumn: 3,
|
|
||||||
},
|
|
||||||
artifactLocation: {
|
|
||||||
uri: "foo.js",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
queryRunner: mockedObject<QueryRunner>({
|
|
||||||
createQueryRun: jest.fn().mockReturnValue({
|
|
||||||
evaluate: jest.fn().mockResolvedValue({
|
|
||||||
resultType: QueryResultType.SUCCESS,
|
|
||||||
outputDir,
|
|
||||||
}),
|
|
||||||
outputDir,
|
|
||||||
}),
|
|
||||||
logger: createMockLogger(),
|
|
||||||
}),
|
|
||||||
databaseItem: mockedObject<DatabaseItem>({
|
|
||||||
databaseUri: mockedUri("/a/b/c/src.zip"),
|
|
||||||
contents: {
|
|
||||||
kind: DatabaseKind.Database,
|
|
||||||
name: "foo",
|
|
||||||
datasetUri: mockedUri(),
|
|
||||||
},
|
|
||||||
language: "java",
|
|
||||||
getSourceLocationPrefix: jest
|
|
||||||
.fn()
|
|
||||||
.mockResolvedValue("/home/runner/work/my-repo/my-repo"),
|
|
||||||
sourceArchive: mockedUri("/a/b/c/src.zip"),
|
|
||||||
}),
|
|
||||||
queryStorageDir: "/tmp/queries",
|
|
||||||
progress: jest.fn(),
|
|
||||||
cancellationTokenSource: new CancellationTokenSource(),
|
|
||||||
};
|
|
||||||
|
|
||||||
const result = await runAutoModelQueries(options);
|
|
||||||
expect(result).not.toBeUndefined();
|
|
||||||
|
|
||||||
expect(options.cliServer.resolveQlpacks).toHaveBeenCalledTimes(1);
|
|
||||||
expect(options.cliServer.resolveQlpacks).toHaveBeenCalledWith(
|
|
||||||
expect.arrayContaining([expect.stringContaining("tmp")]),
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
expect(resolveQueriesSpy).toHaveBeenCalledTimes(1);
|
|
||||||
expect(resolveQueriesSpy).toHaveBeenCalledWith(
|
|
||||||
options.cliServer,
|
|
||||||
["codeql/java-automodel-queries"],
|
|
||||||
"Extract automodel candidates",
|
|
||||||
{
|
|
||||||
kind: "problem",
|
|
||||||
"tags contain all": ["automodel", "application-mode", "candidates"],
|
|
||||||
},
|
|
||||||
);
|
|
||||||
expect(options.queryRunner.createQueryRun).toHaveBeenCalledTimes(1);
|
|
||||||
expect(options.queryRunner.createQueryRun).toHaveBeenCalledWith(
|
|
||||||
"/a/b/c/src.zip",
|
|
||||||
{
|
|
||||||
queryPath: "/a/b/c/ql/candidates.ql",
|
|
||||||
quickEvalPosition: undefined,
|
|
||||||
quickEvalCountOnly: false,
|
|
||||||
},
|
|
||||||
false,
|
|
||||||
expect.arrayContaining([expect.stringContaining("tmp")]),
|
|
||||||
["/a/b/c/my-extension-pack"],
|
|
||||||
{},
|
|
||||||
"/tmp/queries",
|
|
||||||
undefined,
|
|
||||||
undefined,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("generateCandidateFilterPack", () => {
|
|
||||||
it("should create a temp pack containing the candidate filters", async () => {
|
|
||||||
const candidateMethods: MethodSignature[] = [
|
|
||||||
{
|
|
||||||
signature: "org.my.A#x()",
|
|
||||||
endpointType: EndpointType.Method,
|
|
||||||
packageName: "org.my",
|
|
||||||
typeName: "A",
|
|
||||||
methodName: "x",
|
|
||||||
methodParameters: "()",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
const { packDir, cleanup } = await generateCandidateFilterPack(
|
|
||||||
"java",
|
|
||||||
candidateMethods,
|
|
||||||
);
|
|
||||||
expect(packDir).not.toBeUndefined();
|
|
||||||
const qlpackFile = join(packDir, "codeql-pack.yml");
|
|
||||||
expect(await pathExists(qlpackFile)).toBe(true);
|
|
||||||
const filterFile = join(packDir, "filter.yml");
|
|
||||||
expect(await pathExists(filterFile)).toBe(true);
|
|
||||||
// Read the contents of filterFile and parse as yaml
|
|
||||||
const yaml = (await loadYaml(
|
|
||||||
await readFile(filterFile, "utf8"),
|
|
||||||
)) as ModelExtensionFile;
|
|
||||||
const extensions = yaml.extensions;
|
|
||||||
expect(extensions).toBeInstanceOf(Array);
|
|
||||||
expect(extensions).toHaveLength(1);
|
|
||||||
const extension = extensions[0];
|
|
||||||
expect(extension.addsTo.pack).toEqual("codeql/java-automodel-queries");
|
|
||||||
expect(extension.addsTo.extensible).toEqual("automodelCandidateFilter");
|
|
||||||
expect(extension.data).toBeInstanceOf(Array);
|
|
||||||
expect(extension.data).toHaveLength(1);
|
|
||||||
expect(extension.data[0]).toEqual(["org.my", "A", "x", "()"]);
|
|
||||||
|
|
||||||
await cleanup();
|
|
||||||
expect(await pathExists(packDir)).toBe(false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -153,8 +153,6 @@ describe("method modeling view provider", () => {
|
|||||||
usage: createUsage(),
|
usage: createUsage(),
|
||||||
modeledMethods: [],
|
modeledMethods: [],
|
||||||
isModified: false,
|
isModified: false,
|
||||||
isInProgress: false,
|
|
||||||
processedByAutoModel: false,
|
|
||||||
};
|
};
|
||||||
getSelectedMethodDetails.mockReturnValue(selectedMethodDetails);
|
getSelectedMethodDetails.mockReturnValue(selectedMethodDetails);
|
||||||
|
|
||||||
@@ -191,8 +189,6 @@ describe("method modeling view provider", () => {
|
|||||||
method: selectedMethodDetails.method,
|
method: selectedMethodDetails.method,
|
||||||
modeledMethods: selectedMethodDetails.modeledMethods,
|
modeledMethods: selectedMethodDetails.modeledMethods,
|
||||||
isModified: selectedMethodDetails.isModified,
|
isModified: selectedMethodDetails.isModified,
|
||||||
isInProgress: selectedMethodDetails.isInProgress,
|
|
||||||
processedByAutoModel: selectedMethodDetails.processedByAutoModel,
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -104,8 +104,6 @@ describe("MethodsUsagePanel", () => {
|
|||||||
usage,
|
usage,
|
||||||
modeledMethods[method.signature],
|
modeledMethods[method.signature],
|
||||||
modifiedMethodSignatures.has(method.signature),
|
modifiedMethodSignatures.has(method.signature),
|
||||||
false,
|
|
||||||
false,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(mockTreeView.reveal).toHaveBeenCalledWith(
|
expect(mockTreeView.reveal).toHaveBeenCalledWith(
|
||||||
@@ -139,8 +137,6 @@ describe("MethodsUsagePanel", () => {
|
|||||||
usage,
|
usage,
|
||||||
modeledMethods[method.signature],
|
modeledMethods[method.signature],
|
||||||
modifiedMethodSignatures.has(method.signature),
|
modifiedMethodSignatures.has(method.signature),
|
||||||
false,
|
|
||||||
false,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(mockTreeView.reveal).not.toHaveBeenCalled();
|
expect(mockTreeView.reveal).not.toHaveBeenCalled();
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import type { QueryLanguage } from "../../../../src/common/query-language";
|
|||||||
import { Mode } from "../../../../src/model-editor/shared/mode";
|
import { Mode } from "../../../../src/model-editor/shared/mode";
|
||||||
import { mockedObject } from "../../utils/mocking.helpers";
|
import { mockedObject } from "../../utils/mocking.helpers";
|
||||||
import type { CodeQLCliServer } from "../../../../src/codeql-cli/cli";
|
import type { CodeQLCliServer } from "../../../../src/codeql-cli/cli";
|
||||||
import type { ModelConfig } from "../../../../src/config";
|
|
||||||
import { createMockLogger } from "../../../__mocks__/loggerMock";
|
import { createMockLogger } from "../../../__mocks__/loggerMock";
|
||||||
|
|
||||||
describe("setUpPack", () => {
|
describe("setUpPack", () => {
|
||||||
@@ -44,18 +43,8 @@ describe("setUpPack", () => {
|
|||||||
resolveQueriesInSuite: jest.fn().mockResolvedValue([]),
|
resolveQueriesInSuite: jest.fn().mockResolvedValue([]),
|
||||||
});
|
});
|
||||||
const logger = createMockLogger();
|
const logger = createMockLogger();
|
||||||
const modelConfig = mockedObject<ModelConfig>({
|
|
||||||
llmGeneration: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
await setUpPack(
|
await setUpPack(cliServer, logger, queryDir, language, Mode.Application);
|
||||||
cliServer,
|
|
||||||
logger,
|
|
||||||
queryDir,
|
|
||||||
language,
|
|
||||||
modelConfig,
|
|
||||||
Mode.Application,
|
|
||||||
);
|
|
||||||
|
|
||||||
const queryFiles = await readdir(queryDir);
|
const queryFiles = await readdir(queryDir);
|
||||||
expect(queryFiles).toEqual(
|
expect(queryFiles).toEqual(
|
||||||
@@ -109,18 +98,8 @@ describe("setUpPack", () => {
|
|||||||
.mockResolvedValue(["/a/b/c/ApplicationModeEndpoints.ql"]),
|
.mockResolvedValue(["/a/b/c/ApplicationModeEndpoints.ql"]),
|
||||||
});
|
});
|
||||||
const logger = createMockLogger();
|
const logger = createMockLogger();
|
||||||
const modelConfig = mockedObject<ModelConfig>({
|
|
||||||
llmGeneration: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
await setUpPack(
|
await setUpPack(cliServer, logger, queryDir, language, Mode.Application);
|
||||||
cliServer,
|
|
||||||
logger,
|
|
||||||
queryDir,
|
|
||||||
language,
|
|
||||||
modelConfig,
|
|
||||||
Mode.Application,
|
|
||||||
);
|
|
||||||
|
|
||||||
const queryFiles = await readdir(queryDir);
|
const queryFiles = await readdir(queryDir);
|
||||||
expect(queryFiles.sort()).toEqual(["codeql-pack.yml"].sort());
|
expect(queryFiles.sort()).toEqual(["codeql-pack.yml"].sort());
|
||||||
|
|||||||
Reference in New Issue
Block a user