From 8005f82b67b96eaa7676558dc144534bbbb3ba9f Mon Sep 17 00:00:00 2001 From: tamarleviCm <110327792+tamarleviCm@users.noreply.github.com> Date: Thu, 15 Aug 2024 10:55:03 +0300 Subject: [PATCH] AST-38524 Vorpal extension (#881) * first working code * WIP: 10ba35b docs(changelog): update release notes * settings * tests * Merge branch 'vorpal-engine-extention' of https://github.com/Checkmarx/ast-vscode-extension into vorpal-engine-extention * delete problems when disabled vorpal * test * tests * tests * test * test * ignore log files * ignore settings.json windows * tests * fix tests * tests * onDidChangeActiveTextEditor * tests * log settings * fix tests * tests * fixes * fix * Update launch.json * Update package.json * ignore system files * tests * test name * try * revert * Update launch.json * try * fix * remove test * order * fix mock * vorpal tests * try import again * clear tests * fix test mock * setting name without space * timeout * fix the test * beezrat hashem * vorpal test * settings test * add test * test * test cases * code review * await * latest wrapper and settings descreption * formmater * change log.err to log.warn in scan vorpal * support Critical severities * Update extension.ts * Delete src/test/9.vorpal.test.ts * code review --------- Co-authored-by: AlvoBen <144705560+AlvoBen@users.noreply.github.com> --- package-lock.json | 27 ++++--- package.json | 20 ++++- src/commands/vorpalCommand.ts | 80 +++++++++++++++++++ src/cx/cx.ts | 42 +++++++++- src/cx/cxMock.ts | 13 ++- src/cx/cxPlatform.ts | 12 +++ src/extension.ts | 5 +- src/test/0.welcome.test.ts | 2 +- src/test/1.settings.test.ts | 31 +++++++- src/test/utils/utils.ts | 1 + src/utils/common/constants.ts | 10 ++- src/utils/listener/listeners.ts | 13 ++- src/vorpal/vorpalService.ts | 136 ++++++++++++++++++++++++++++++++ 13 files changed, 366 insertions(+), 26 deletions(-) create mode 100644 src/commands/vorpalCommand.ts create mode 100644 src/vorpal/vorpalService.ts diff --git a/package-lock.json b/package-lock.json index b84d8a2b..355f5565 100644 --- a/package-lock.json +++ b/package-lock.json @@ -565,20 +565,22 @@ } }, "node_modules/@redhat-developer/locators": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@redhat-developer/locators/-/locators-1.1.2.tgz", - "integrity": "sha512-3QbR55JT9ZokixXsO/U2FuPsfAJ3EUbsyROuTKrg9JVbe+1auOlebyK5LD/7pe8WcG1AtUSiheRUDXMQ7OooEQ==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@redhat-developer/locators/-/locators-1.1.3.tgz", + "integrity": "sha512-wO+qoL7daG40vJkzX400YcvxFLOInxmfgbViCiUtj42ihwEr/k2aBKNDOxsJqq2kzQ5HWkxFJqmxQx80aYnaQg==", "dev": true, + "license": "Apache-2.0", "peerDependencies": { "@redhat-developer/page-objects": ">=1.0.0", "selenium-webdriver": ">=4.6.1" } }, "node_modules/@redhat-developer/page-objects": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@redhat-developer/page-objects/-/page-objects-1.1.2.tgz", - "integrity": "sha512-buwlHi5MOutdOoWAvaaOFPHjSbJMcnWZ6Lsmp1+VLD88sLPMk4Mek6LVwtNQeczDTD5KpOHPlwgONhPX2TB0Rw==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@redhat-developer/page-objects/-/page-objects-1.1.3.tgz", + "integrity": "sha512-oqntfrz02Gv4PbBBYPqkW00OHYCAM3AbHx67sFPeO2DaQO5SzaRwiS1CJ97jUGNiALjsaw0SgFpjRpHoOYwyRA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "clipboardy": "^4.0.0", "clone-deep": "^4.0.1", @@ -6163,6 +6165,7 @@ "resolved": "https://registry.npmjs.org/vscode-extension-tester/-/vscode-extension-tester-8.3.0.tgz", "integrity": "sha512-x9/OiwUWDqlxyrf/ALHX25ChVHm38on1VHtmmS8NpDSGmbYsaeXaJg3Kw9c4mRUoV8eugNlowRwTG98fuT2rWA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "@redhat-developer/locators": "^1.1.2", "@redhat-developer/page-objects": "^1.1.2", @@ -7059,16 +7062,16 @@ "optional": true }, "@redhat-developer/locators": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@redhat-developer/locators/-/locators-1.1.2.tgz", - "integrity": "sha512-3QbR55JT9ZokixXsO/U2FuPsfAJ3EUbsyROuTKrg9JVbe+1auOlebyK5LD/7pe8WcG1AtUSiheRUDXMQ7OooEQ==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@redhat-developer/locators/-/locators-1.1.3.tgz", + "integrity": "sha512-wO+qoL7daG40vJkzX400YcvxFLOInxmfgbViCiUtj42ihwEr/k2aBKNDOxsJqq2kzQ5HWkxFJqmxQx80aYnaQg==", "dev": true, "requires": {} }, "@redhat-developer/page-objects": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@redhat-developer/page-objects/-/page-objects-1.1.2.tgz", - "integrity": "sha512-buwlHi5MOutdOoWAvaaOFPHjSbJMcnWZ6Lsmp1+VLD88sLPMk4Mek6LVwtNQeczDTD5KpOHPlwgONhPX2TB0Rw==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@redhat-developer/page-objects/-/page-objects-1.1.3.tgz", + "integrity": "sha512-oqntfrz02Gv4PbBBYPqkW00OHYCAM3AbHx67sFPeO2DaQO5SzaRwiS1CJ97jUGNiALjsaw0SgFpjRpHoOYwyRA==", "dev": true, "requires": { "clipboardy": "^4.0.0", diff --git a/package.json b/package.json index 05c5d878..5339d104 100644 --- a/package.json +++ b/package.json @@ -780,7 +780,7 @@ { "title": "Checkmarx One", "id": "ast-results", - "order": 3, + "order": 4, "properties": { "checkmarxOne.apiKey": { "type": "string", @@ -825,7 +825,7 @@ { "title": "Checkmarx AI Security Champion", "id": "ask-kics", - "order": 2, + "order": 3, "properties": { "CheckmarxSecurityChampion.key": { "type": "string", @@ -849,6 +849,19 @@ ] } } + }, + { + "title": "Activate Vorpal Auto Scanning", + "id": "vorpal", + "order": 2, + "properties": { + "CheckmarxVorpal.ActivateVorpalAutoScanning": { + "type": "boolean", + "order": 3, + "default": false, + "markdownDescription": "Scans your file as you code" + } + } } ] }, @@ -861,7 +874,7 @@ "copytestproject": "copyfiles -u 2 \"src/resources/**/*\" out/test/ -E", "copymedia": "copyfiles \"media/icons/*\" out/ -E", "configure-husky": "npx husky install && npx husky add .husky/pre-commit \"npx --no-install lint-staged\"", - "test": "export TEST=true && npm run compile && extest setup-and-run './out/test/**/*test.js' -c 1.71.0 -i -r .", + "test": "export TEST=true && npm run compile && extest setup-and-run './out/test/**/*test.js' -c 1.87.2 -i -r .", "win-test": "set TEST=true&& npm run compile && extest setup-and-run './out/test/**/*test.js' -c 1.87.2 -i -r ." }, "devDependencies": { @@ -883,6 +896,7 @@ "webpack-cli": "^5.1.4" }, "dependencies": { + "@checkmarxdev/ast-cli-javascript-wrapper": "0.0.111", "copyfiles": "2.4.1", "eslint-config-prettier": "^9.1.0", diff --git a/src/commands/vorpalCommand.ts b/src/commands/vorpalCommand.ts new file mode 100644 index 00000000..22a8a719 --- /dev/null +++ b/src/commands/vorpalCommand.ts @@ -0,0 +1,80 @@ +import * as vscode from "vscode"; +import { Logs } from "../models/logs"; +import { + clearVorpalProblems, + installVorpal, + scanVorpal, +} from "../vorpal/vorpalService"; +import { constants } from "../utils/common/constants"; + +let timeout = null; +export class VorpalCommand { + context: vscode.ExtensionContext; + logs: Logs; + onDidChangeTextDocument: vscode.Disposable; + constructor(context: vscode.ExtensionContext, logs: Logs) { + this.context = context; + this.logs = logs; + } + public async registerVorpal() { + try { + const vorpalActive = vscode.workspace + .getConfiguration(constants.CheckmarxVorpal) + .get(constants.ActivateVorpalAutoScanning) as boolean; + if (vorpalActive) { + await this.installVorpal(); + await this.registerVorpalScanOnChangeText(); + this.logs.info(constants.vorpalStart); + } else { + await this.disposeVorpalScanOnChangeText(); + await clearVorpalProblems(); + this.logs.info(constants.vorpalDisabled); + } + } catch (error) { + console.error(error); + } + } + public installVorpal() { + installVorpal(this.logs); + this.onDidChangeTextDocument = vscode.workspace.onDidChangeTextDocument( + // Must be no less than 2000ms. Otherwise, the temporary file can be deleted before the vorpal scan is finished. + this.debounce(this.onTextChange, 2000) + ); + } + + public onTextChange(event) { + try { + scanVorpal(event.document, this.logs); + } catch (error) { + console.error(error); + this.logs.warn("fail to scan vorpal"); + } + } + // Debounce function + public debounce(func, wait) { + const context = this; + console.log("onDidChangeTextDocument"); + return function (...args) { + try { + const later = () => { + clearTimeout(timeout); + func.apply(context, args); + }; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + } catch (error) { + console.error(error); + } + }; + } + + public registerVorpalScanOnChangeText() { + this.context.subscriptions.push(this.onDidChangeTextDocument); + } + public disposeVorpalScanOnChangeText() { + if (this.onDidChangeTextDocument) { + this.onDidChangeTextDocument.dispose(); + this.context.subscriptions.push(this.onDidChangeTextDocument); + } + } +} diff --git a/src/cx/cx.ts b/src/cx/cx.ts index 1a86bb8b..5438ab72 100644 --- a/src/cx/cx.ts +++ b/src/cx/cx.ts @@ -5,9 +5,7 @@ import CxScan from "@checkmarxdev/ast-cli-javascript-wrapper/dist/main/scan/CxSc import CxProject from "@checkmarxdev/ast-cli-javascript-wrapper/dist/main/project/CxProject"; import CxCodeBashing from "@checkmarxdev/ast-cli-javascript-wrapper/dist/main/codebashing/CxCodeBashing"; import { CxConfig } from "@checkmarxdev/ast-cli-javascript-wrapper/dist/main/wrapper/CxConfig"; -import { - constants -} from "../utils/common/constants"; +import { constants } from "../utils/common/constants"; import { getFilePath, getResultsFilePath } from "../utils/utils"; import { SastNode } from "../models/sastNode"; import AstError from "../exceptions/AstError"; @@ -17,6 +15,7 @@ import { CxPlatform } from "./cxPlatform"; import { CxCommandOutput } from "@checkmarxdev/ast-cli-javascript-wrapper/dist/main/wrapper/CxCommandOutput"; import { ChildProcessWithoutNullStreams } from "child_process"; import CxLearnMoreDescriptions from "@checkmarxdev/ast-cli-javascript-wrapper/dist/main/learnmore/CxLearnMoreDescriptions"; +import CxVorpal from "@checkmarxdev/ast-cli-javascript-wrapper/dist/main/vorpal/CxVorpal"; import { messages } from "../utils/common/messages"; export class Cx implements CxPlatform { async scaScanCreate(sourcePath: string): Promise { @@ -425,4 +424,39 @@ export class Cx implements CxPlatform { statusBarItem.text = text; show ? statusBarItem.show() : statusBarItem.hide(); } -} + async installVorpal(): Promise { + let config = this.getAstConfiguration(); + if (!config) { + config = new CxConfig(); + } + const cx = new CxWrapper(config); + const scans = await cx.scanVorpal(null, true, constants.vsCodeAgent); + if (scans.payload && scans.exitCode === 0) { + return scans.payload[0]; + } else { + return this.getVorpalError(scans.status, "Failed to run vorpal engine"); + } + } + + private getVorpalError(scanStatus: string, errorMessage: string) { + console.error(errorMessage); + const errorRes = new CxVorpal(); + errorRes.error = scanStatus; + return errorRes; + } + + async scanVorpal(sourcePath: string): Promise { + let config = this.getAstConfiguration(); + if (!config) { + config = new CxConfig(); + } + const cx = new CxWrapper(config); + const scans = await cx.scanVorpal(sourcePath, false, constants.vsCodeAgent); + if (scans.payload && scans.exitCode === 0) { + return scans.payload[0]; + } else { + return this.getVorpalError(scans.status, "Fail to call vorpal scan"); + } + } + } + \ No newline at end of file diff --git a/src/cx/cxMock.ts b/src/cx/cxMock.ts index 86d53a27..f480a2e7 100644 --- a/src/cx/cxMock.ts +++ b/src/cx/cxMock.ts @@ -7,9 +7,12 @@ import { CxConfig } from "@checkmarxdev/ast-cli-javascript-wrapper/dist/main/wra import { getFilePath } from "../utils/utils"; import { writeFileSync } from "fs"; import { CxPlatform } from "./cxPlatform"; +import CxVorpal from "@checkmarxdev/ast-cli-javascript-wrapper/dist/main/vorpal/CxVorpal"; import { EMPTY_RESULTS_SCAN_ID } from "../test/utils/envs"; export class CxMock implements CxPlatform { + + // eslint-disable-next-line @typescript-eslint/no-explicit-any async scaScanCreate(): Promise { return [ @@ -552,7 +555,7 @@ export class CxMock implements CxPlatform { await this.sleep(1000); return [{ conversationId: '0', response: ["Mock message response from gpt"] }]; } - + sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } @@ -561,5 +564,13 @@ export class CxMock implements CxPlatform { statusBarItem.text = text; show ? statusBarItem.show() : statusBarItem.hide(); } + + installVorpal(): Promise { + return null; + } + + async scanVorpal(sourcePath: string): Promise { + return new CxVorpal(); + } } diff --git a/src/cx/cxPlatform.ts b/src/cx/cxPlatform.ts index c1eb40ce..8d531580 100644 --- a/src/cx/cxPlatform.ts +++ b/src/cx/cxPlatform.ts @@ -8,6 +8,7 @@ import { Logs } from "../models/logs"; import { ChildProcessWithoutNullStreams } from "child_process"; import { CxCommandOutput } from "@checkmarxdev/ast-cli-javascript-wrapper/dist/main/wrapper/CxCommandOutput"; import CxLearnMoreDescriptions from "@checkmarxdev/ast-cli-javascript-wrapper/dist/main/learnmore/CxLearnMoreDescriptions"; +import CxVorpal from "@checkmarxdev/ast-cli-javascript-wrapper/dist/main/vorpal/CxVorpal"; export interface CxPlatform { /** @@ -176,5 +177,16 @@ export interface CxPlatform { * @param statusBarItem The {@link vscode.StatusBarItem} associated with the results. */ updateStatusBarItem(text: string, show: boolean, statusBarItem: vscode.StatusBarItem); + + /** + * install the Vorpal engine + */ + installVorpal(): Promise; + + /** + * Scan the edited file in the vorpal engine and show the results in the problem section + * @param sourcePath the edited file sent to the vorpal engine + */ + scanVorpal(sourcePath: string): Promise; } diff --git a/src/extension.ts b/src/extension.ts index 88edd0ef..85ae1f6f 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -23,6 +23,7 @@ import { WorkspaceListener } from "./utils/listener/workspaceListener"; import { DocAndFeedbackView } from "./views/docsAndFeedbackView/docAndFeedbackView"; import { messages } from "./utils/common/messages"; import { commands } from "./utils/common/commands"; +import { VorpalCommand } from "./commands/vorpalCommand"; export async function activate(context: vscode.ExtensionContext) { // Create logs channel and make it visible @@ -175,6 +176,8 @@ export async function activate(context: vscode.ExtensionContext) { } } }); + const vorpalCommand = new VorpalCommand(context, logs); + vorpalCommand.registerVorpal(); // Register Settings const commonCommand = new CommonCommand(context, logs); commonCommand.registerSettings(); @@ -186,7 +189,7 @@ export async function activate(context: vscode.ExtensionContext) { // SCA auto scanning enablement await commonCommand.executeCheckScaScanEnabled(); // execute command to listen to settings change - await executeCheckSettingsChange(kicsStatusBarItem, logs); + await executeCheckSettingsChange(kicsStatusBarItem, logs, vorpalCommand); const treeCommand = new TreeCommand( context, diff --git a/src/test/0.welcome.test.ts b/src/test/0.welcome.test.ts index 921fd05b..3e26acce 100644 --- a/src/test/0.welcome.test.ts +++ b/src/test/0.welcome.test.ts @@ -7,7 +7,7 @@ describe("Welcome view test", () => { let bench: Workbench; before(async function () { - this.timeout(8000); + this.timeout(100000); bench = new Workbench(); }); diff --git a/src/test/1.settings.test.ts b/src/test/1.settings.test.ts index 9a960985..85cf433b 100644 --- a/src/test/1.settings.test.ts +++ b/src/test/1.settings.test.ts @@ -8,9 +8,15 @@ import { BottomBarPanel, } from "vscode-extension-tester"; import { expect } from "chai"; -import { CX_API_KEY_SETTINGS, CX_CATETORY, CX_KICS, CX_KICS_NAME } from "./utils/constants"; +import { + CX_API_KEY_SETTINGS, + CX_CATETORY, + CX_KICS, + CX_KICS_NAME, +} from "./utils/constants"; import { waitStatusBar } from "./utils/waiters"; import { API_KEY } from "./utils/envs"; +import { constants } from "../utils/common/constants"; describe("Extension settings tests", () => { let settingsEditor: SettingsEditor; @@ -33,7 +39,7 @@ describe("Extension settings tests", () => { await waitStatusBar(); settingsEditor = await bench.openSettings(); const settings = (await settingsEditor.findSetting( - "fake setting", + "fake setting" )) as LinkSetting; expect(settings).to.be.undefined; }); @@ -60,4 +66,25 @@ describe("Extension settings tests", () => { const enablement = await setting.getValue(); expect(enablement).to.equal(true); }); + + it("verify vorpal checkbox exists in the settings", async function () { + settingsEditor = await bench.openSettings(); + const vorpalCheckbox = await settingsEditor.findSetting( + constants.ActivateVorpalAutoScanning, + constants.CheckmarxVorpal + ); + let vorpalCheckboxValue = await vorpalCheckbox.getValue(); + expect(vorpalCheckboxValue).to.not.be.undefined; + }); + + it("vorpal starts when the Vorpal checkbox is True in settings", async function () { + settingsEditor = await bench.openSettings(); + const vorpalCheckbox = await settingsEditor.findSetting( + constants.ActivateVorpalAutoScanning, + constants.CheckmarxVorpal + ); + await vorpalCheckbox.setValue(true); + let vorpalCheckboxValue = await vorpalCheckbox.getValue(); + expect(vorpalCheckboxValue).to.be.true; + }); }); diff --git a/src/test/utils/utils.ts b/src/test/utils/utils.ts index 535fdcd3..81e8e17d 100644 --- a/src/test/utils/utils.ts +++ b/src/test/utils/utils.ts @@ -95,3 +95,4 @@ export async function validateRootNode(scan: any): Promise<[number, any]> { export const delay = (ms: number | undefined) => new Promise(res => setTimeout(res, ms)); + diff --git a/src/utils/common/constants.ts b/src/utils/common/constants.ts index 1d2dbce5..b0928b4d 100644 --- a/src/utils/common/constants.ts +++ b/src/utils/common/constants.ts @@ -138,7 +138,15 @@ export const constants = { gptEngineKey: "model", // Documentation & Feedback feedback: "Send us enhancement request or report a bug", - documentation: "Documentation" + documentation: "Documentation", + // Vorpal engine + errorInstallation: "Failed to run vorpal engine", + errorScanVorpal: "failed to handle vorpal scan", + vorpalStart: "Vorpal engine started", + vorpalDisabled: "Vorpal Auto Scanning is disabled now.", + vorpalEngineName: "Vorpal", + ActivateVorpalAutoScanning:"ActivateVorpalAutoScanning", + CheckmarxVorpal:"CheckmarxVorpal", }; export enum GroupBy { diff --git a/src/utils/listener/listeners.ts b/src/utils/listener/listeners.ts index 85530f99..36129e05 100644 --- a/src/utils/listener/listeners.ts +++ b/src/utils/listener/listeners.ts @@ -9,6 +9,7 @@ import { getFromState, updateState } from "../common/globalState"; import { cx } from "../../cx"; import { getGitAPIRepository, isKicsFile, isSystemFile } from "../utils"; import { messages } from "../common/messages"; +import { VorpalCommand } from "../../commands/vorpalCommand"; export async function getBranchListener( context: vscode.ExtensionContext, @@ -168,8 +169,9 @@ export async function gitExtensionListener( export async function executeCheckSettingsChange( kicsStatusBarItem: vscode.StatusBarItem, logs: Logs, + vorpalCommand: VorpalCommand ) { - vscode.workspace.onDidChangeConfiguration(async () => { + vscode.workspace.onDidChangeConfiguration(async (event) => { vscode.commands.executeCommand( commands.setContext, commands.isValidCredentials, @@ -188,5 +190,14 @@ export async function executeCheckSettingsChange( ? messages.kicsStatusBarConnect : messages.kicsStatusBarDisconnect; await vscode.commands.executeCommand(commands.refreshTree); + const vorpalEffected = event.affectsConfiguration( + `${constants.CheckmarxVorpal}.${constants.ActivateVorpalAutoScanning}` + ); + const apikeyEffected = event.affectsConfiguration( + "checkmarxOne.apiKey" + ); + if (vorpalEffected || apikeyEffected) { + await vorpalCommand.registerVorpal(); + } }); } diff --git a/src/vorpal/vorpalService.ts b/src/vorpal/vorpalService.ts new file mode 100644 index 00000000..c6b9dcd6 --- /dev/null +++ b/src/vorpal/vorpalService.ts @@ -0,0 +1,136 @@ +import * as vscode from "vscode"; +import { cx } from "../cx"; +import fs from "fs"; +import path from "path"; +import * as os from "os"; +import { error } from "console"; +import { Logs } from "../models/logs"; +import CxVorpal from "@checkmarxdev/ast-cli-javascript-wrapper/dist/main/vorpal/CxVorpal"; +import { constants } from "../utils/common/constants"; + +const vorpalDir = "CxVorpal"; + +export const diagnosticCollection = vscode.languages.createDiagnosticCollection( + constants.extensionFullName +); + +export async function scanVorpal(document: vscode.TextDocument, logs: Logs) { + + if (ignoreFiles(document)) + {return;} + try { + // SAVE TEMP FILE + const filePath = saveTempFile( + path.basename(document.uri.fsPath), + document.getText() + ); + // RUN VORPAL SCAN + logs.info("Start Vorpal Scan On File: " + document.uri.fsPath); + const scanVorpalResult = await cx.scanVorpal(filePath); + // DELETE TEMP FILE + deleteFile(filePath); + console.info("file %s deleted", filePath); + // HANDLE ERROR + if (scanVorpalResult.error) { + logs.warn( + "Vorpal Warning: " + + (scanVorpalResult.error.description ?? scanVorpalResult.error) + ); + return; + } + // VIEW PROBLEMS + logs.info( + scanVorpalResult.scanDetails.length + + " vulnerabilities were found in " + + document.uri.fsPath + ); + updateProblems(scanVorpalResult, document.uri); + } catch (error) { + console.error(error); + logs.error(constants.errorScanVorpal); + } +} + +function ignoreFiles(document: vscode.TextDocument): boolean { + // ignore vscode system files + return document.uri.scheme !== 'file'; +} + +export async function clearVorpalProblems() { + diagnosticCollection.clear(); +} + +function updateProblems(scanVorpalResult: CxVorpal, uri: vscode.Uri) { + diagnosticCollection.delete(uri); + const diagnostics: vscode.Diagnostic[] = []; + + for (let i = 0; i < scanVorpalResult.scanDetails.length; i++) { + const res = scanVorpalResult.scanDetails[i]; + const range = new vscode.Range( + new vscode.Position(res.line - 1, 0), + new vscode.Position(res.line - 1, 100) + ); + const diagnostic: vscode.Diagnostic = new vscode.Diagnostic( + range, + `${res.ruleName} - ${res.remediationAdvise}`, + parseSeverity(res.severity) + ); + diagnostic.source = constants.vorpalEngineName; + diagnostics.push(diagnostic); + } + diagnosticCollection.set(uri, diagnostics); +} + +function parseSeverity(vorpalSeverity: string): vscode.DiagnosticSeverity { + const severityMap: Record = { + CRITICAL: vscode.DiagnosticSeverity.Error, + HIGH: vscode.DiagnosticSeverity.Error, + MEDIUM: vscode.DiagnosticSeverity.Warning, + LOW: vscode.DiagnosticSeverity.Information + }; + + const severity = severityMap[vorpalSeverity.toUpperCase()]; + + if (severity === undefined) { + console.log(`Invalid vorpalSeverity value: ${vorpalSeverity}`); + return vscode.DiagnosticSeverity.Information; + } + + return severity; +} + +function saveTempFile(fileName: string, content: string): string | null { + try { + const tempDir = os.tmpdir(); + const tempFilePath = path.join(tempDir, vorpalDir, fileName); + fs.writeFileSync(tempFilePath, content); + console.info("Temp file was saved in: " + tempFilePath); + return tempFilePath; + } catch (error) { + console.error("Failed to save temporary file:", error); + return null; + } +} + +export async function installVorpal(logs: Logs) { + try { + const res = await cx.installVorpal(); + if (res.error) { + const errorMessage = constants.errorInstallation + " : " + res.error; + vscode.window.showErrorMessage(errorMessage); + logs.error(errorMessage); + return; + } + } catch (error) { + console.log(error); + logs.warn(constants.errorInstallation); + } +} + +function deleteFile(filePath: string) { + try { + fs.unlinkSync(filePath); + } catch (error) { + // when the file sent again before it come back... + } +}