diff --git a/extensions/ql-vscode/src/common/interface-types.ts b/extensions/ql-vscode/src/common/interface-types.ts index cc7c60f16..e27b8bb3b 100644 --- a/extensions/ql-vscode/src/common/interface-types.ts +++ b/extensions/ql-vscode/src/common/interface-types.ts @@ -590,6 +590,14 @@ interface StopGeneratingMethodsFromLlmMessage { packageName: string; } +interface StartModelEvaluationMessage { + t: "startModelEvaluation"; +} + +interface StopModelEvaluationMessage { + t: "stopModelEvaluation"; +} + interface ModelDependencyMessage { t: "modelDependency"; } @@ -648,7 +656,9 @@ export type FromModelEditorMessage = | StopGeneratingMethodsFromLlmMessage | ModelDependencyMessage | HideModeledMethodsMessage - | SetMultipleModeledMethodsMessage; + | SetMultipleModeledMethodsMessage + | StartModelEvaluationMessage + | StopModelEvaluationMessage; interface RevealInEditorMessage { t: "revealInModelEditor"; diff --git a/extensions/ql-vscode/src/config.ts b/extensions/ql-vscode/src/config.ts index 50937cf15..9aa54ad33 100644 --- a/extensions/ql-vscode/src/config.ts +++ b/extensions/ql-vscode/src/config.ts @@ -715,6 +715,7 @@ const LLM_GENERATION_DEV_ENDPOINT = new Setting( "llmGenerationDevEndpoint", MODEL_SETTING, ); +const MODEL_EVALUATION = new Setting("evaluation", MODEL_SETTING); const EXTENSIONS_DIRECTORY = new Setting("extensionsDirectory", MODEL_SETTING); const ENABLE_PYTHON = new Setting("enablePython", MODEL_SETTING); const ENABLE_ACCESS_PATH_SUGGESTIONS = new Setting( @@ -759,6 +760,10 @@ export class ModelConfigListener extends ConfigListener implements ModelConfig { return LLM_GENERATION_DEV_ENDPOINT.getValue(); } + public get modelEvaluation(): boolean { + return !!MODEL_EVALUATION.getValue(); + } + public getExtensionsDirectory(languageId: string): string | undefined { return EXTENSIONS_DIRECTORY.getValue({ languageId, diff --git a/extensions/ql-vscode/src/model-editor/model-editor-view.ts b/extensions/ql-vscode/src/model-editor/model-editor-view.ts index 2c1e886ee..393e09673 100644 --- a/extensions/ql-vscode/src/model-editor/model-editor-view.ts +++ b/extensions/ql-vscode/src/model-editor/model-editor-view.ts @@ -337,6 +337,12 @@ export class ModelEditorView extends AbstractWebview< this.setModeledMethods(msg.methodSignature, msg.modeledMethods); break; } + case "startModelEvaluation": + this.startModelEvaluation(); + break; + case "stopModelEvaluation": + this.stopModelEvaluation(); + break; case "telemetry": telemetryListener?.sendUIInteraction(msg.action); break; @@ -402,6 +408,8 @@ export class ModelEditorView extends AbstractWebview< const showLlmButton = this.databaseItem.language === "java" && this.modelConfig.llmGeneration; + const showEvaluationUi = this.modelConfig.modelEvaluation; + const sourceArchiveAvailable = this.databaseItem.hasSourceArchiveInExplorer(); @@ -416,6 +424,7 @@ export class ModelEditorView extends AbstractWebview< language: this.language, showGenerateButton, showLlmButton, + showEvaluationUi, mode: this.modelingStore.getMode(this.databaseItem), showModeSwitchButton, sourceArchiveAvailable, @@ -910,4 +919,12 @@ export class ModelEditorView extends AbstractWebview< ); this.modelingStore.addModifiedMethod(this.databaseItem, signature); } + + private startModelEvaluation() { + // Do nothing for now. This will be fleshed out in the near future. + } + + private stopModelEvaluation() { + // Do nothing for now. This will be fleshed out in the near future. + } } diff --git a/extensions/ql-vscode/src/model-editor/shared/view-state.ts b/extensions/ql-vscode/src/model-editor/shared/view-state.ts index 3e962b599..111019e30 100644 --- a/extensions/ql-vscode/src/model-editor/shared/view-state.ts +++ b/extensions/ql-vscode/src/model-editor/shared/view-state.ts @@ -7,6 +7,7 @@ export interface ModelEditorViewState { language: QueryLanguage; showGenerateButton: boolean; showLlmButton: boolean; + showEvaluationUi: boolean; mode: Mode; showModeSwitchButton: boolean; sourceArchiveAvailable: boolean; diff --git a/extensions/ql-vscode/src/view/model-editor/ModelEditor.tsx b/extensions/ql-vscode/src/view/model-editor/ModelEditor.tsx index d7c9a70cb..fd775551f 100644 --- a/extensions/ql-vscode/src/view/model-editor/ModelEditor.tsx +++ b/extensions/ql-vscode/src/view/model-editor/ModelEditor.tsx @@ -74,6 +74,50 @@ const ButtonsContainer = styled.div` margin-top: 1rem; `; +const ModelEvaluation = ({ + viewState, + modeledMethods, + modifiedSignatures, + onStartEvaluation, + onStopEvaluation, + evaluationInProgress, +}: { + viewState: ModelEditorViewState; + modeledMethods: Record; + modifiedSignatures: Set; + onStartEvaluation: () => void; + onStopEvaluation: () => void; + evaluationInProgress: boolean; +}) => { + if (!viewState.showEvaluationUi) { + return null; + } + + if (!evaluationInProgress) { + const customModelsExist = Object.values(modeledMethods).some( + (methods) => methods.filter((m) => m.type !== "none").length > 0, + ); + + const unsavedChanges = modifiedSignatures.size > 0; + + return ( + + Evaluate + + ); + } else { + return ( + + Stop evaluation + + ); + } +}; + type Props = { initialViewState?: ModelEditorViewState; initialMethods?: Method[]; @@ -114,6 +158,8 @@ export function ModelEditor({ string | null >(null); + const [evaluationInProgress, setEvaluationInProgress] = useState(false); + useEffect(() => { vscode.postMessage({ t: "hideModeledMethods", @@ -254,6 +300,20 @@ export function ModelEditor({ [selectedSignatures], ); + const onStartEvaluation = useCallback(() => { + setEvaluationInProgress(true); + vscode.postMessage({ + t: "startModelEvaluation", + }); + }, []); + + const onStopEvaluation = useCallback(() => { + setEvaluationInProgress(false); + vscode.postMessage({ + t: "stopModelEvaluation", + }); + }, []); + const onGenerateFromSourceClick = useCallback(() => { vscode.postMessage({ t: "generateMethod", @@ -373,6 +433,14 @@ export function ModelEditor({ Generate )} + diff --git a/extensions/ql-vscode/test/factories/model-editor/view-state.ts b/extensions/ql-vscode/test/factories/model-editor/view-state.ts index 8cb933ad9..06a40da5a 100644 --- a/extensions/ql-vscode/test/factories/model-editor/view-state.ts +++ b/extensions/ql-vscode/test/factories/model-editor/view-state.ts @@ -11,6 +11,7 @@ export function createMockModelEditorViewState( mode: Mode.Application, showGenerateButton: false, showLlmButton: false, + showEvaluationUi: false, showModeSwitchButton: true, extensionPack: createMockExtensionPack(), sourceArchiveAvailable: true,