From 07f3fadd6b97706c82d362ca3453b068c508342c Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Tue, 23 Sep 2025 15:33:37 +0200 Subject: [PATCH 01/61] Initial create vcshell --- package.json | 14 ++++++++++++++ src/extension.ts | 20 ++++++++++++++++++++ src/vcastTestInterface.ts | 27 ++++++++++++++++++++++++++- 3 files changed, 60 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 9a1232dc..e1775f24 100644 --- a/package.json +++ b/package.json @@ -164,6 +164,11 @@ "category": "VectorCAST Test Explorer", "title": "Create VectorCAST Environment" }, + { + "command": "vectorcastTestExplorer.newVCShell", + "category": "VectorCAST Test Explorer", + "title": "Create New VC Shell" + }, { "command": "vectorcastTestExplorer.newEnviroInProjectVCAST", "category": "VectorCAST Test Explorer", @@ -491,6 +496,10 @@ { "command": "vectorcastTestExplorer.newEnviroVCAST", "when": "never" + }, + { + "command": "vectorcastTestExplorer.newVCShell", + "when": "never" }, { "command": "vectorcastTestExplorer.newEnviroInProjectVCAST", @@ -615,6 +624,11 @@ "when": "resourceLangId == cpp || resourceLangId == c", "group": "2_workspace" }, + { + "command": "vectorcastTestExplorer.newVCShell", + "when": "resourceLangId == cpp || resourceLangId == c", + "group": "2_workspace" + }, { "command": "vectorcastTestExplorer.newEnviroInProjectVCAST", "when": "(resourceLangId == cpp || resourceLangId == c) && vectorcastTestExplorer.globalProjectIsOpenedChecker", diff --git a/src/extension.ts b/src/extension.ts index 292a2b27..6682c2f2 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -126,6 +126,7 @@ import { newTestScript, openCodedTest, ProjectEnvParameters, + newVCShell, } from "./vcastTestInterface"; import { @@ -1224,6 +1225,25 @@ async function installPreActivationEventHandlers( ); context.subscriptions.push(newEnviroVCASTCommand); + // Command: vectorcastTestExplorer.newEnviroVCAST //////////////////////////////////////////////////////// + let newVCShellCommand = vscode.commands.registerCommand( + "vectorcastTestExplorer.newVCShell", + async (arg: Uri) => { + // contains a check for already configured, so no work will be done in that case + await checkPrerequisites(context); + if (alreadyConfigured) { + // arg is the actual item that the right click happened on, argList is the list + // of all items if this is a multi-select. Since argList is always valid, even for a single + // selection, we just use this here. + if (arg) { + const filePath = arg.fsPath; + await newVCShell(filePath); + } + } + } + ); + context.subscriptions.push(newVCShellCommand); + const importEnviroToProject = vscode.commands.registerCommand( "vectorcastTestExplorer.importEnviroToProject", async (_args: vscode.Uri, argList: vscode.Uri[]) => { diff --git a/src/vcastTestInterface.ts b/src/vcastTestInterface.ts index bf107ad5..c9ba6180 100644 --- a/src/vcastTestInterface.ts +++ b/src/vcastTestInterface.ts @@ -58,9 +58,13 @@ import { commandStatusType, executeCommandSync, executeVPythonScript, + executeWithRealTimeEchoWithProgress, } from "./vcastCommandRunner"; -import { checksumCommandToUse } from "./vcastInstallation"; +import { + checksumCommandToUse, + getVectorCastInstallationLocation, +} from "./vcastInstallation"; import { closeAnyOpenErrorFiles, @@ -1197,3 +1201,24 @@ export async function getMCDCResultFile( return resultFile; } + +export async function newVCShell(filePath: string) { + const normalizeFilePath = normalizePath(filePath); + const dirName = path.dirname(normalizeFilePath); + const fileName = path.basename(normalizeFilePath); + const unitTestLocation = getUnitTestLocationForPath(dirName); + const normalizedUnitPath = normalizePath(unitTestLocation); + const vcDir = getVectorCastInstallationLocation(); + + if (vcDir) { + const vcShellCommand = path.join(normalizePath(vcDir), `vcshell`); + const commandToRun = `${vcShellCommand}`; + const infoMessage = `Creating vcshell for ${fileName} in ${normalizedUnitPath}`; + await executeWithRealTimeEchoWithProgress( + commandToRun, + ["gcc", "-c", normalizeFilePath], + normalizedUnitPath, + infoMessage + ); + } +} From 145775b1d12f376f0f4d0eecd84922a7839a993d Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Wed, 24 Sep 2025 13:46:31 +0200 Subject: [PATCH 02/61] Initial webview for creating cfg --- package.json | 10 +- src/extension.ts | 126 ++++++++ src/manage/webviews/css/newCFG.css | 306 +++++++++++++++++++ src/manage/webviews/html/newCFG.html | 43 +++ src/manage/webviews/webviewScripts/newCFG.js | 80 +++++ src/vcastTestInterface.ts | 6 + 6 files changed, 570 insertions(+), 1 deletion(-) create mode 100644 src/manage/webviews/css/newCFG.css create mode 100644 src/manage/webviews/html/newCFG.html create mode 100644 src/manage/webviews/webviewScripts/newCFG.js diff --git a/package.json b/package.json index 9a1232dc..f87032c6 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,10 @@ "command": "vectorcastTestExplorer.createNewProject", "title": "VectorCAST: Create New Project" }, + { + "command": "vectorcastTestExplorer.createNewCFG", + "title": "VectorCAST: Create New CFG" + }, { "command": "vectorcastTestExplorer.configure", "category": "VectorCAST Test Explorer", @@ -401,7 +405,11 @@ "file/newFile": [ { "command": "vectorcastTestExplorer.createNewProject", - "group": "1_createnew" + "group": "VectorCAST: New Ressources" + }, + { + "command": "vectorcastTestExplorer.createNewCFG", + "group": "VectorCAST: New Ressources" } ], "commandPalette": [ diff --git a/src/extension.ts b/src/extension.ts index 292a2b27..c9a59c36 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -126,6 +126,7 @@ import { newTestScript, openCodedTest, ProjectEnvParameters, + createNewCFGFile, } from "./vcastTestInterface"; import { @@ -1858,6 +1859,131 @@ async function installPreActivationEventHandlers( return html; } + + const createNewCFGCmd = vscode.commands.registerCommand( + "vectorcastTestExplorer.createNewCFG", + async () => { + const workspaceFolders = vscode.workspace.workspaceFolders; + if (!workspaceFolders?.length) { + vscode.window.showErrorMessage("Open a folder first."); + return; + } + const workspaceRoot = workspaceFolders[0].uri.fsPath; + + const baseDir = resolveWebviewBase(context); + const panel = vscode.window.createWebviewPanel( + "newCFG", + "Create New CFG File", + vscode.ViewColumn.Active, + { + enableScripts: true, + retainContextWhenHidden: true, + localResourceRoots: [vscode.Uri.file(baseDir)], + } + ); + + panel.webview.html = await getNewCFGWebviewContent( + context, + panel, + compilerTagList + ); + + panel.webview.onDidReceiveMessage( + async (msg) => { + switch (msg.command) { + case "submit": { + const compilerName: string | undefined = msg.compilerName?.trim(); + const enableCodedTests: boolean = !!msg.enableCodedTests; + + if (!compilerName) { + vscode.window.showErrorMessage( + "Compiler selection is required." + ); + return; + } + const compilerTag = compilerTagList[compilerName]; + if (!compilerTag) { + vscode.window.showErrorMessage( + `No compiler tag found for "${compilerName}".` + ); + return; + } + + vscode.window.showInformationMessage( + `Creating new CFG file using compiler: ${compilerName} (EnableCodedTests=${enableCodedTests})` + ); + + // pass flag to implementation + await createNewCFGFile( + workspaceRoot, + compilerTag, + enableCodedTests + ); + + panel.dispose(); + break; + } + case "cancel": + panel.dispose(); + break; + } + }, + undefined, + context.subscriptions + ); + } + ); + + context.subscriptions.push(createNewCFGCmd); + + async function getNewCFGWebviewContent( + context: vscode.ExtensionContext, + panel: vscode.WebviewPanel, + compilerTagList: Record, + defaultEnableCodedTests: boolean = false + ): Promise { + // Build paths for webview files + const base = resolveWebviewBase(context); + const cssOnDisk = vscode.Uri.file(path.join(base, "css", "newCFG.css")); + const scriptOnDisk = vscode.Uri.file( + path.join(base, "webviewScripts", "newCFG.js") + ); + const htmlPath = path.join(base, "html", "newCFG.html"); + + // convert to URI + const cssUri = panel.webview.asWebviewUri(cssOnDisk); + const scriptUri = panel.webview.asWebviewUri(scriptOnDisk); + + // JSON list of compilers for autocomplete + const compilerList = JSON.stringify(Object.keys(compilerTagList ?? {})); + let html = fs.readFileSync(htmlPath, "utf8"); + const nonce = getNonce(); + + // build CSP meta (need to allow our scripts with our generated nonce) + const csp = ` + + `; + + // Insert CSP immediately after the opening + html = html.replace(//i, `${csp}`); + html = html.replace(/{{\s*cssUri\s*}}/g, cssUri.toString()); + html = html.replace( + /<\/script>/i, + `` + ); + + // Inline script to expose compilerData and enableCodedTests to the webview client + const injectedScript = ``; + html = html.replace(/\{\{\s*compilerDataScript\s*\}\}/g, injectedScript); + + return html; + } } // this method is called when your extension is deactivated diff --git a/src/manage/webviews/css/newCFG.css b/src/manage/webviews/css/newCFG.css new file mode 100644 index 00000000..d53c6615 --- /dev/null +++ b/src/manage/webviews/css/newCFG.css @@ -0,0 +1,306 @@ +/* Reset and base */ +* { + box-sizing: border-box; + margin: 0; + padding: 0; + } + + body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; + background-color: #1e1e1e; + color: #d4d4d4; + display: flex; + align-items: center; + justify-content: center; + height: 100vh; + } + + /* Modal container */ + .modal { + width: 700px; + background-color: #252526; + padding: 25px; + border-radius: 8px; + box-shadow: 0 0 10px rgba(0,0,0,0.3); + } + + /* Center only the title, not all modal text */ + .modal h2 { + text-align: center; + } + + h2 { + color: #ffffff; + margin-bottom: 15px; + font-size: 22px; + } + + /* Labels and inputs */ + label { + font-size: 16px; + display: block; + text-align: left; + margin-top: 12px; + margin-bottom: 6px; + } + + input[type="text"], select { + padding: 10px; + font-size: 14px; + background-color: #3c3c3c; + color: #d4d4d4; + border: 1px solid #555; + border-radius: 4px; + width: 100%; + } + + /* Folder-picker row */ + .single-input-container { + display: grid; + grid-template-columns: 1fr auto; + gap: 10px; + align-items: center; + margin-bottom: 15px; + } + + /* “Select” button beside the input */ + .select-button { + background-color: #007acc; + color: white; + border: none; + border-radius: 4px; + padding: 10px 16px; + font-size: 14px; + cursor: pointer; + transition: background-color 0.3s; + } + + .select-button:hover { + background-color: #005f99; + } + + /* Autocomplete */ + .autocomplete { + position: relative; + width: 100%; + } + + .suggestions { + position: absolute; + top: 100%; + left: 0; + right: 0; + background: #2a2a2a; + border: 1px solid #555; + max-height: 180px; + overflow-y: auto; + list-style: none; + padding: 0; + margin-top: 4px; + display: none; + z-index: 10; + text-align: left; /* ensure left alignment */ + } + + .suggestions.visible { + display: block; + } + + .suggestions li { + padding: 8px 12px; + cursor: pointer; + font-size: 14px; + } + + .suggestions li:hover, + .suggestions li.active { + background: #007acc; + color: white; + } + + /* =========================== + VS Code–style toggle control + =========================== */ + + .checkbox-row { + display: block; + margin-top: 12px; + } + + .vscode-toggle { + display: inline-block; + position: relative; + width: 44px; + height: 24px; + cursor: pointer; + flex: 0 0 auto; /* ensure switch doesn’t stretch */ + } + + .vscode-toggle input { + opacity: 0; + width: 0; + height: 0; + } + + .vscode-toggle .slider { + position: absolute; + inset: 0; + background: #3c3c3c; + border: 1px solid #555; + border-radius: 12px; + transition: 0.12s; + } + + .vscode-toggle .slider::before { + content: ""; + position: absolute; + top: 1px; + left: 1px; + width: 22px; + height: 22px; + border-radius: 50%; + background: #d4d4d4; + transition: 0.12s; + } + + /* Label text */ + .toggle-label { + font-size: 16px; + color: #d4d4d4; + } + + /* Switch */ + .toggle-switch { + display: inline-block; + position: relative; + width: 44px; + height: 24px; + flex: 0 0 auto; + } + + .toggle-switch input[type="checkbox"] { + position: absolute; + opacity: 0; + width: 0; + height: 0; + margin: 0; + z-index: 2; + left: 0; + top: 0; + } + + .toggle-switch .slider { + position: absolute; + inset: 0; + background: #3c3c3c; + border: 1px solid #555; + border-radius: 12px; + transition: background 0.12s ease, border-color 0.12s ease; + box-sizing: border-box; + } + + .toggle-switch .slider::before { + content: ""; + position: absolute; + top: 1px; + left: 1px; + width: 22px; + height: 22px; + border-radius: 50%; + background: #d4d4d4; + box-shadow: 0 1px 0 rgba(0,0,0,0.25); + transition: left 0.12s ease, background 0.12s ease; + } + + .toggle-switch input[type="checkbox"]:checked + .slider { + background: #007acc; + border-color: #007acc; + } + + .toggle-switch input[type="checkbox"]:checked + .slider::before { + left: 21px; + background: #ffffff; + } + + .toggle-switch input[type="checkbox"]:focus + .slider { + box-shadow: 0 0 0 3px rgba(0,122,204,0.14); + } + + .vscode-toggle:hover .slider { + filter: brightness(1.06); + } + + /* Button container */ + .button-container { + display: flex; + justify-content: flex-end; + gap: 10px; + margin-top: 20px; + } + + /* Primary & cancel buttons */ + .primary-button, + .cancel-button { + padding: 10px 20px; + font-size: 16px; + border: none; + border-radius: 4px; + cursor: pointer; + transition: background-color 0.3s; + } + + .primary-button { + background-color: #007acc; + color: white; + } + + .primary-button:hover { + background-color: #005f99; + } + + .cancel-button { + background-color: #cc4444; + color: white; + } + + .cancel-button:hover { + background-color: #992222; + } + +/* =========================== + Options section + =========================== */ + + .options-section { + margin-top: 20px; + padding-top: 10px; + border-top: 1px solid #444; /* subtle divider */ + width: 80%; /* take 80% of modal width */ + margin-left: auto; /* center horizontally */ + margin-right: auto; + } + + /* Center the section title */ + .options-section h3 { + font-size: 16px; + font-weight: 600; + margin-bottom: 10px; + color: #ffffff; + text-align: center; + } + + /* Each option row: label left, switch right */ + .option-row { + display: flex; + align-items: center; + justify-content: space-between; + padding: 6px 0; + width: 100%; +} + + /* Align option labels like other labels */ + .option-row .toggle-label { + font-size: 16px; + color: #d4d4d4; + } + \ No newline at end of file diff --git a/src/manage/webviews/html/newCFG.html b/src/manage/webviews/html/newCFG.html new file mode 100644 index 00000000..c8c6eb2b --- /dev/null +++ b/src/manage/webviews/html/newCFG.html @@ -0,0 +1,43 @@ + + + + + + Create New CFG File + + + + + + + {{ compilerDataScript }} + + + + diff --git a/src/manage/webviews/webviewScripts/newCFG.js b/src/manage/webviews/webviewScripts/newCFG.js new file mode 100644 index 00000000..e7fe00fc --- /dev/null +++ b/src/manage/webviews/webviewScripts/newCFG.js @@ -0,0 +1,80 @@ +const vscode = acquireVsCodeApi(); + +window.addEventListener("DOMContentLoaded", () => { + const compilers = window.compilerData || []; + const compInput = document.getElementById("compilerInput"); + const suggestions = document.getElementById("suggestions"); + const codedCheckbox = document.getElementById("enableCodedTestsCheckbox"); + + // If extension injected a default, apply it + if (typeof window.enableCodedTests !== "undefined" && codedCheckbox) { + codedCheckbox.checked = !!window.enableCodedTests; + } + + // autocomplete setup + let filtered = [], activeIndex = -1; + + function renderSuggestions() { + suggestions.innerHTML = ""; + if (!filtered.length) return suggestions.classList.remove("visible"); + filtered.forEach((item, i) => { + const li = document.createElement("li"); + li.textContent = item; + if (i === activeIndex) li.classList.add("active"); + li.addEventListener("mousedown", () => { + compInput.value = item; + suggestions.classList.remove("visible"); + }); + suggestions.appendChild(li); + }); + suggestions.classList.add("visible"); + } + + function updateSuggestions(showAll = false) { + const q = (compInput.value || "").toLowerCase().trim(); + filtered = showAll || !q ? [...compilers] : compilers.filter(c => c.toLowerCase().includes(q)); + activeIndex = -1; + renderSuggestions(); + } + + compInput.addEventListener("input", () => updateSuggestions()); + compInput.addEventListener("focus", () => updateSuggestions(true)); + compInput.addEventListener("keydown", e => { + if (!filtered.length) return; + if (e.key === "ArrowDown") { + e.preventDefault(); + activeIndex = (activeIndex + 1) % filtered.length; + renderSuggestions(); + } else if (e.key === "ArrowUp") { + e.preventDefault(); + activeIndex = (activeIndex - 1 + filtered.length) % filtered.length; + renderSuggestions(); + } else if (e.key === "Enter") { + e.preventDefault(); + if (filtered[activeIndex]) { + compInput.value = filtered[activeIndex]; + suggestions.classList.remove("visible"); + } + } else if (e.key === "Escape") { + suggestions.classList.remove("visible"); + } + }); + + document.addEventListener("click", e => { + if (!e.target.closest(".autocomplete")) suggestions.classList.remove("visible"); + }); + + // submit: include enableCodedTests boolean + document.getElementById("btnSubmit").addEventListener("click", () => { + vscode.postMessage({ + command: "submit", + compilerName: (compInput.value || "").trim(), + enableCodedTests: !!(codedCheckbox && codedCheckbox.checked) + }); + }); + + // cancel + document.getElementById("btnCancel").addEventListener("click", () => { + vscode.postMessage({ command: "cancel" }); + }); +}); diff --git a/src/vcastTestInterface.ts b/src/vcastTestInterface.ts index bf107ad5..ce681caf 100644 --- a/src/vcastTestInterface.ts +++ b/src/vcastTestInterface.ts @@ -1197,3 +1197,9 @@ export async function getMCDCResultFile( return resultFile; } + +export async function createNewCFGFile( + workspaceRoot: string, + compilerTag: string, + enableCodedTest: boolean +) {} From 2286fc0775d91e94691762c137c4ec09a5597f45 Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Wed, 24 Sep 2025 14:17:30 +0200 Subject: [PATCH 03/61] Initial webview --- src/extension.ts | 19 +- src/manage/webviews/css/newCFG.css | 546 +++++++++---------- src/manage/webviews/html/newCFG.html | 28 +- src/manage/webviews/webviewScripts/newCFG.js | 29 +- src/vcastTestInterface.ts | 3 +- 5 files changed, 299 insertions(+), 326 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index c9a59c36..26e101ce 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1894,6 +1894,7 @@ async function installPreActivationEventHandlers( case "submit": { const compilerName: string | undefined = msg.compilerName?.trim(); const enableCodedTests: boolean = !!msg.enableCodedTests; + const defaultCFG: boolean = !!msg.defaultCFG; if (!compilerName) { vscode.window.showErrorMessage( @@ -1901,6 +1902,7 @@ async function installPreActivationEventHandlers( ); return; } + const compilerTag = compilerTagList[compilerName]; if (!compilerTag) { vscode.window.showErrorMessage( @@ -1910,22 +1912,21 @@ async function installPreActivationEventHandlers( } vscode.window.showInformationMessage( - `Creating new CFG file using compiler: ${compilerName} (EnableCodedTests=${enableCodedTests})` + `Creating new CFG file using compiler: ${compilerName} ` + + `(EnableCodedTests=${enableCodedTests}, DefaultCFG=${defaultCFG})` ); - // pass flag to implementation + // Pass flags to implementation await createNewCFGFile( workspaceRoot, compilerTag, - enableCodedTests + enableCodedTests, + defaultCFG ); panel.dispose(); break; } - case "cancel": - panel.dispose(); - break; } }, undefined, @@ -1939,8 +1940,7 @@ async function installPreActivationEventHandlers( async function getNewCFGWebviewContent( context: vscode.ExtensionContext, panel: vscode.WebviewPanel, - compilerTagList: Record, - defaultEnableCodedTests: boolean = false + compilerTagList: Record ): Promise { // Build paths for webview files const base = resolveWebviewBase(context); @@ -1978,7 +1978,8 @@ async function installPreActivationEventHandlers( // Inline script to expose compilerData and enableCodedTests to the webview client const injectedScript = ``; html = html.replace(/\{\{\s*compilerDataScript\s*\}\}/g, injectedScript); diff --git a/src/manage/webviews/css/newCFG.css b/src/manage/webviews/css/newCFG.css index d53c6615..0fe1ebb1 100644 --- a/src/manage/webviews/css/newCFG.css +++ b/src/manage/webviews/css/newCFG.css @@ -1,306 +1,254 @@ /* Reset and base */ * { - box-sizing: border-box; - margin: 0; - padding: 0; - } - - body { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; - background-color: #1e1e1e; - color: #d4d4d4; - display: flex; - align-items: center; - justify-content: center; - height: 100vh; - } - - /* Modal container */ - .modal { - width: 700px; - background-color: #252526; - padding: 25px; - border-radius: 8px; - box-shadow: 0 0 10px rgba(0,0,0,0.3); - } - - /* Center only the title, not all modal text */ - .modal h2 { - text-align: center; - } - - h2 { - color: #ffffff; - margin-bottom: 15px; - font-size: 22px; - } - - /* Labels and inputs */ - label { - font-size: 16px; - display: block; - text-align: left; - margin-top: 12px; - margin-bottom: 6px; - } - - input[type="text"], select { - padding: 10px; - font-size: 14px; - background-color: #3c3c3c; - color: #d4d4d4; - border: 1px solid #555; - border-radius: 4px; - width: 100%; - } - - /* Folder-picker row */ - .single-input-container { - display: grid; - grid-template-columns: 1fr auto; - gap: 10px; - align-items: center; - margin-bottom: 15px; - } - - /* “Select” button beside the input */ - .select-button { - background-color: #007acc; - color: white; - border: none; - border-radius: 4px; - padding: 10px 16px; - font-size: 14px; - cursor: pointer; - transition: background-color 0.3s; - } - - .select-button:hover { - background-color: #005f99; - } - - /* Autocomplete */ - .autocomplete { - position: relative; - width: 100%; - } - - .suggestions { - position: absolute; - top: 100%; - left: 0; - right: 0; - background: #2a2a2a; - border: 1px solid #555; - max-height: 180px; - overflow-y: auto; - list-style: none; - padding: 0; - margin-top: 4px; - display: none; - z-index: 10; - text-align: left; /* ensure left alignment */ - } - - .suggestions.visible { - display: block; - } - - .suggestions li { - padding: 8px 12px; - cursor: pointer; - font-size: 14px; - } - - .suggestions li:hover, - .suggestions li.active { - background: #007acc; - color: white; - } - - /* =========================== - VS Code–style toggle control - =========================== */ - - .checkbox-row { - display: block; - margin-top: 12px; - } - - .vscode-toggle { - display: inline-block; - position: relative; - width: 44px; - height: 24px; - cursor: pointer; - flex: 0 0 auto; /* ensure switch doesn’t stretch */ - } - - .vscode-toggle input { - opacity: 0; - width: 0; - height: 0; - } - - .vscode-toggle .slider { - position: absolute; - inset: 0; - background: #3c3c3c; - border: 1px solid #555; - border-radius: 12px; - transition: 0.12s; - } - - .vscode-toggle .slider::before { - content: ""; - position: absolute; - top: 1px; - left: 1px; - width: 22px; - height: 22px; - border-radius: 50%; - background: #d4d4d4; - transition: 0.12s; - } - - /* Label text */ - .toggle-label { - font-size: 16px; - color: #d4d4d4; - } - - /* Switch */ - .toggle-switch { - display: inline-block; - position: relative; - width: 44px; - height: 24px; - flex: 0 0 auto; - } - - .toggle-switch input[type="checkbox"] { - position: absolute; - opacity: 0; - width: 0; - height: 0; - margin: 0; - z-index: 2; - left: 0; - top: 0; - } - - .toggle-switch .slider { - position: absolute; - inset: 0; - background: #3c3c3c; - border: 1px solid #555; - border-radius: 12px; - transition: background 0.12s ease, border-color 0.12s ease; - box-sizing: border-box; - } - - .toggle-switch .slider::before { - content: ""; - position: absolute; - top: 1px; - left: 1px; - width: 22px; - height: 22px; - border-radius: 50%; - background: #d4d4d4; - box-shadow: 0 1px 0 rgba(0,0,0,0.25); - transition: left 0.12s ease, background 0.12s ease; - } - - .toggle-switch input[type="checkbox"]:checked + .slider { - background: #007acc; - border-color: #007acc; - } - - .toggle-switch input[type="checkbox"]:checked + .slider::before { - left: 21px; - background: #ffffff; - } - - .toggle-switch input[type="checkbox"]:focus + .slider { - box-shadow: 0 0 0 3px rgba(0,122,204,0.14); - } - - .vscode-toggle:hover .slider { - filter: brightness(1.06); - } - - /* Button container */ - .button-container { - display: flex; - justify-content: flex-end; - gap: 10px; - margin-top: 20px; - } - - /* Primary & cancel buttons */ - .primary-button, - .cancel-button { - padding: 10px 20px; - font-size: 16px; - border: none; - border-radius: 4px; - cursor: pointer; - transition: background-color 0.3s; - } - - .primary-button { - background-color: #007acc; - color: white; - } - - .primary-button:hover { - background-color: #005f99; - } - - .cancel-button { - background-color: #cc4444; - color: white; - } - - .cancel-button:hover { - background-color: #992222; - } + box-sizing: border-box; + margin: 0; + padding: 0; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; + background-color: #1e1e1e; + color: #d4d4d4; + display: flex; + align-items: center; + justify-content: center; + height: 100vh; +} + +/* Modal container */ +.modal { + width: 700px; + background-color: #252526; + padding: 25px; + border-radius: 8px; + box-shadow: 0 0 10px rgba(0,0,0,0.3); + display: flex; + flex-direction: column; +} + +/* Modal title */ +.modal h2 { + text-align: center; + color: #ffffff; + margin-bottom: 15px; + font-size: 22px; +} + +/* Labels and inputs */ +label, .toggle-label { + font-size: 16px; + color: #d4d4d4; +} + +input[type="text"], select { + padding: 10px; + font-size: 14px; + background-color: #3c3c3c; + color: #d4d4d4; + border: 1px solid #555; + border-radius: 4px; + width: 100%; +} + +/* Folder-picker row */ +.single-input-container { + display: grid; + grid-template-columns: 1fr auto; + gap: 10px; + align-items: center; + margin-bottom: 15px; +} + +/* “Select” button beside the input */ +.select-button { + background-color: #007acc; + color: white; + border: none; + border-radius: 4px; + padding: 10px 16px; + font-size: 14px; + cursor: pointer; + transition: background-color 0.3s; +} + +.select-button:hover { + background-color: #005f99; +} + +/* Add spacing between label and autocomplete */ +label[for="compilerInput"] { + margin-bottom: 10px; /* extra space for clarity */ +} + +/* Autocomplete */ +.autocomplete { + position: relative; + width: 100%; +} + +.suggestions { + position: absolute; + top: 100%; + left: 0; + right: 0; + background: #2a2a2a; + border: 1px solid #555; + max-height: 180px; + overflow-y: auto; + list-style: none; + padding: 0; + margin-top: 4px; + display: none; + z-index: 10; + text-align: left; +} + +.suggestions.visible { + display: block; +} + +.suggestions li { + padding: 8px 12px; + cursor: pointer; + font-size: 14px; +} + +.suggestions li:hover, +.suggestions li.active { + background: #007acc; + color: white; +} /* =========================== Options section =========================== */ +.options-section { + margin-top: 20px; + padding-top: 10px; + border-top: 1px solid #444; + width: 80%; + margin-left: auto; + margin-right: auto; +} + +.options-section h3 { + font-size: 16px; + font-weight: 600; + margin-bottom: 10px; + color: #ffffff; + text-align: center; +} + +.option-row { + display: flex; + align-items: center; + justify-content: space-between; + padding: 6px 0; + width: 100%; +} - .options-section { - margin-top: 20px; - padding-top: 10px; - border-top: 1px solid #444; /* subtle divider */ - width: 80%; /* take 80% of modal width */ - margin-left: auto; /* center horizontally */ - margin-right: auto; - } - - /* Center the section title */ - .options-section h3 { - font-size: 16px; - font-weight: 600; - margin-bottom: 10px; - color: #ffffff; - text-align: center; - } - - /* Each option row: label left, switch right */ - .option-row { - display: flex; - align-items: center; - justify-content: space-between; - padding: 6px 0; - width: 100%; -} - - /* Align option labels like other labels */ - .option-row .toggle-label { - font-size: 16px; - color: #d4d4d4; - } - \ No newline at end of file +.option-row .toggle-label { + font-size: 16px; + color: #d4d4d4; +} + +/* =========================== + VS Code–style toggle + =========================== */ +.vscode-toggle { + display: inline-block; + cursor: pointer; +} + +.toggle-switch { + display: inline-block; + position: relative; + width: 44px; + height: 24px; +} + +.toggle-switch input { + opacity: 0; + width: 0; + height: 0; + margin: 0; +} + +.toggle-switch .slider { + position: absolute; + inset: 0; + background: #3c3c3c; + border: 1px solid #555; + border-radius: 12px; + transition: background 0.12s ease, border-color 0.12s ease; + box-sizing: border-box; +} + +.toggle-switch .slider::before { + content: ""; + position: absolute; + top: 50%; + left: 1px; + width: 22px; + height: 22px; + border-radius: 50%; + background: #d4d4d4; + box-shadow: 0 1px 0 rgba(0,0,0,0.25); + transform: translateY(-50%); + transition: left 0.12s ease, background 0.12s ease; +} + +.toggle-switch input:checked + .slider { + background: #007acc; + border-color: #007acc; +} + +.toggle-switch input:checked + .slider::before { + left: 21px; + background: #ffffff; +} + +.toggle-switch input:focus + .slider { + box-shadow: 0 0 0 3px rgba(0,122,204,0.14); +} + +.vscode-toggle:hover .slider { + filter: brightness(1.06); +} + +/* =========================== + Buttons + =========================== */ +.button-container { + display: flex; + justify-content: space-between; /* cancel left, create right */ + margin-top: 25px; /* space between options and buttons */ +} + +.primary-button, +.cancel-button { + padding: 10px 20px; + font-size: 16px; + border: none; + border-radius: 4px; + cursor: pointer; + transition: background-color 0.3s; +} + +.primary-button { + background-color: #007acc; + color: white; +} + +.primary-button:hover { + background-color: #005f99; +} + +.cancel-button { + background-color: #cc4444; + color: white; +} + +.cancel-button:hover { + background-color: #992222; +} diff --git a/src/manage/webviews/html/newCFG.html b/src/manage/webviews/html/newCFG.html index c8c6eb2b..bca2a1e8 100644 --- a/src/manage/webviews/html/newCFG.html +++ b/src/manage/webviews/html/newCFG.html @@ -19,15 +19,25 @@

Create New CFG File

Additional Options:

- - -
-
+ Enable Coded Tests + + + +
+ Set as Default Configuration File + +
+
diff --git a/src/manage/webviews/webviewScripts/newCFG.js b/src/manage/webviews/webviewScripts/newCFG.js index e7fe00fc..c9e17748 100644 --- a/src/manage/webviews/webviewScripts/newCFG.js +++ b/src/manage/webviews/webviewScripts/newCFG.js @@ -2,21 +2,28 @@ const vscode = acquireVsCodeApi(); window.addEventListener("DOMContentLoaded", () => { const compilers = window.compilerData || []; - const compInput = document.getElementById("compilerInput"); + const compInput = document.getElementById("compilerInput"); const suggestions = document.getElementById("suggestions"); - const codedCheckbox = document.getElementById("enableCodedTestsCheckbox"); - // If extension injected a default, apply it + // Toggle checkboxes + const codedCheckbox = document.getElementById("enableCodedTests"); + const defaultCheckbox = document.getElementById("defaultCFG"); + + // If extension injected defaults, apply them if (typeof window.enableCodedTests !== "undefined" && codedCheckbox) { codedCheckbox.checked = !!window.enableCodedTests; } + if (typeof window.defaultCFG !== "undefined" && defaultCheckbox) { + defaultCheckbox.checked = !!window.defaultCFG; + } - // autocomplete setup + // Autocomplete setup let filtered = [], activeIndex = -1; function renderSuggestions() { suggestions.innerHTML = ""; if (!filtered.length) return suggestions.classList.remove("visible"); + filtered.forEach((item, i) => { const li = document.createElement("li"); li.textContent = item; @@ -27,20 +34,25 @@ window.addEventListener("DOMContentLoaded", () => { }); suggestions.appendChild(li); }); + suggestions.classList.add("visible"); } function updateSuggestions(showAll = false) { const q = (compInput.value || "").toLowerCase().trim(); - filtered = showAll || !q ? [...compilers] : compilers.filter(c => c.toLowerCase().includes(q)); + filtered = showAll || !q + ? [...compilers] + : compilers.filter(c => c.toLowerCase().includes(q)); activeIndex = -1; renderSuggestions(); } compInput.addEventListener("input", () => updateSuggestions()); compInput.addEventListener("focus", () => updateSuggestions(true)); + compInput.addEventListener("keydown", e => { if (!filtered.length) return; + if (e.key === "ArrowDown") { e.preventDefault(); activeIndex = (activeIndex + 1) % filtered.length; @@ -64,16 +76,17 @@ window.addEventListener("DOMContentLoaded", () => { if (!e.target.closest(".autocomplete")) suggestions.classList.remove("visible"); }); - // submit: include enableCodedTests boolean + // Submit button: send both toggle values document.getElementById("btnSubmit").addEventListener("click", () => { vscode.postMessage({ command: "submit", compilerName: (compInput.value || "").trim(), - enableCodedTests: !!(codedCheckbox && codedCheckbox.checked) + enableCodedTests: !!(codedCheckbox && codedCheckbox.checked), + defaultCFG: !!(defaultCheckbox && defaultCheckbox.checked) }); }); - // cancel + // Cancel button document.getElementById("btnCancel").addEventListener("click", () => { vscode.postMessage({ command: "cancel" }); }); diff --git a/src/vcastTestInterface.ts b/src/vcastTestInterface.ts index ce681caf..2c9d7cc7 100644 --- a/src/vcastTestInterface.ts +++ b/src/vcastTestInterface.ts @@ -1201,5 +1201,6 @@ export async function getMCDCResultFile( export async function createNewCFGFile( workspaceRoot: string, compilerTag: string, - enableCodedTest: boolean + enableCodedTest: boolean, + defaultCFG: boolean ) {} From 547cfa00cb1d97501d2b8fc75d6faf9873ef70ad Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Wed, 24 Sep 2025 15:49:05 +0200 Subject: [PATCH 04/61] CFG creation logic --- src/extension.ts | 13 +++--- src/vcastTestInterface.ts | 85 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 87 insertions(+), 11 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index 26e101ce..4a6ed751 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -127,6 +127,7 @@ import { openCodedTest, ProjectEnvParameters, createNewCFGFile, + ConfigurationOptions, } from "./vcastTestInterface"; import { @@ -1895,6 +1896,10 @@ async function installPreActivationEventHandlers( const compilerName: string | undefined = msg.compilerName?.trim(); const enableCodedTests: boolean = !!msg.enableCodedTests; const defaultCFG: boolean = !!msg.defaultCFG; + const configurationOptions: ConfigurationOptions = { + enableCodedTests: enableCodedTests, + defaultCFG: defaultCFG, + }; if (!compilerName) { vscode.window.showErrorMessage( @@ -1911,17 +1916,11 @@ async function installPreActivationEventHandlers( return; } - vscode.window.showInformationMessage( - `Creating new CFG file using compiler: ${compilerName} ` + - `(EnableCodedTests=${enableCodedTests}, DefaultCFG=${defaultCFG})` - ); - // Pass flags to implementation await createNewCFGFile( workspaceRoot, compilerTag, - enableCodedTests, - defaultCFG + configurationOptions ); panel.dispose(); diff --git a/src/vcastTestInterface.ts b/src/vcastTestInterface.ts index 2c9d7cc7..56d035df 100644 --- a/src/vcastTestInterface.ts +++ b/src/vcastTestInterface.ts @@ -58,9 +58,13 @@ import { commandStatusType, executeCommandSync, executeVPythonScript, + executeWithRealTimeEchoWithProgress, } from "./vcastCommandRunner"; -import { checksumCommandToUse } from "./vcastInstallation"; +import { + checksumCommandToUse, + getVectorCastInstallationLocation, +} from "./vcastInstallation"; import { closeAnyOpenErrorFiles, @@ -71,6 +75,7 @@ import { closeConnection, globalEnviroDataServerActive, } from "../src-common/vcastServer"; +import { createNewCFGFromCompiler } from "./manage/manageSrc/manageUtils"; const fs = require("fs"); const path = require("path"); @@ -1198,9 +1203,81 @@ export async function getMCDCResultFile( return resultFile; } +export interface ConfigurationOptions { + enableCodedTests: boolean; + defaultCFG: boolean; +} + export async function createNewCFGFile( workspaceRoot: string, compilerTag: string, - enableCodedTest: boolean, - defaultCFG: boolean -) {} + configurationOptions: ConfigurationOptions +) { + const unitTestLocation = getUnitTestLocationForPath(workspaceRoot); + const vcDir = getVectorCastInstallationLocation(); + const commandToRun = path.join(vcDir, "clicast"); + + // Should not happen as we would get that message when initializing the extension, but to be sure + if (!vcDir) { + vectorMessage( + `Could not find VectorCAST Installation Location. Aborting creating a new CFG.` + ); + return; + } + + // Check if a CFG already exists + const cfgFile = path.join(unitTestLocation, "CCAST_.CFG"); + if (fs.existsSync(cfgFile)) { + const choice = await vscode.window.showInformationMessage( + "A CFG file already exists at this location. Do you want to overwrite it?", + "Yes", + "Cancel" + ); + + if (choice !== "Yes") { + vscode.window.showInformationMessage( + `Operation cancelled. Existing CFG ( ${cfgFile} ) was not overwritten.` + ); + return; + } + } + + // First create new CFG and return path + const compilerPath = await createNewCFGFromCompiler( + compilerTag, + unitTestLocation + ); + + // Set Coded Tests option + let codedFlag = "FALSE"; + if (configurationOptions.enableCodedTests) { + codedFlag = "TRUE"; + } + + const codedOptionArgs = [ + "-lc", + "option", + "VCAST_CODED_TESTS_SUPPORT", + codedFlag, + ]; + const codedOptionInfoMessage = + "Setting VCAST_CODED_TESTS_SUPPORT in CFG File"; + await executeWithRealTimeEchoWithProgress( + commandToRun, + codedOptionArgs, + unitTestLocation, + codedOptionInfoMessage + ); + + // Set as Default CFG if required + if (configurationOptions.defaultCFG) { + const settings = vscode.workspace.getConfiguration( + "vectorcastTestExplorer" + ); + settings.update( + "configurationLocation", + compilerPath, + vscode.ConfigurationTarget.Workspace + ); + } +} From 5eaa093d2b25f2a109e89dbf39fbfc365a8a1973 Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Mon, 17 Nov 2025 09:01:59 +0100 Subject: [PATCH 05/61] vcshell update --- package.json | 22 +++++++++++++++++++++- src/extension.ts | 39 +++++++++++++++++++++++++++++++++++++++ src/vcastTestInterface.ts | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index e1775f24..0ff0a351 100644 --- a/package.json +++ b/package.json @@ -169,6 +169,11 @@ "category": "VectorCAST Test Explorer", "title": "Create New VC Shell" }, + { + "command": "vectorcastTestExplorer.defaultVCShell", + "category": "VectorCAST Test Explorer", + "title": "Set as default Database" + }, { "command": "vectorcastTestExplorer.newEnviroInProjectVCAST", "category": "VectorCAST Test Explorer", @@ -346,6 +351,12 @@ "default": "", "description": "The file path to an existing VectorCAST configuration that should be used when creating new environments. If a value is not specified, the configuration editor will be launched" }, + "vectorcastTestExplorer.databaseLocation": { + "type": "string", + "order": 4, + "default": "", + "description": "The file path to an existing VectorCAST database file that should be used when creating new environments." + }, "vectorcastTestExplorer.showReportOnExecute": { "type": "boolean", "order": 5, @@ -497,10 +508,14 @@ "command": "vectorcastTestExplorer.newEnviroVCAST", "when": "never" }, - { + { "command": "vectorcastTestExplorer.newVCShell", "when": "never" }, + { + "command": "vectorcastTestExplorer.defaultVCShell", + "when": "never" + }, { "command": "vectorcastTestExplorer.newEnviroInProjectVCAST", "when": "never" @@ -629,6 +644,11 @@ "when": "resourceLangId == cpp || resourceLangId == c", "group": "2_workspace" }, + { + "command": "vectorcastTestExplorer.defaultVCShell", + "when": "vectorcastTestExplorer.configured && resourceExtname==.db", + "group": "2_workspace" + }, { "command": "vectorcastTestExplorer.newEnviroInProjectVCAST", "when": "(resourceLangId == cpp || resourceLangId == c) && vectorcastTestExplorer.globalProjectIsOpenedChecker", diff --git a/src/extension.ts b/src/extension.ts index 6682c2f2..4fb6fe43 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -127,6 +127,7 @@ import { openCodedTest, ProjectEnvParameters, newVCShell, + updateVCShellDatabase, } from "./vcastTestInterface"; import { @@ -1244,6 +1245,44 @@ async function installPreActivationEventHandlers( ); context.subscriptions.push(newVCShellCommand); + let defaultVCShellCommand = vscode.commands.registerCommand( + "vectorcastTestExplorer.defaultVCShell", + async (fileURI: Uri) => { + // contains a check for already configured, so no work will be done in that case + await checkPrerequisites(context); + if (alreadyConfigured) { + if (fileURI) { + const filePath = fileURI.fsPath; + const settings = vscode.workspace.getConfiguration( + "vectorcastTestExplorer" + ); + const defaultConfigurationPath = settings.get( + "configurationLocation", + undefined + ); + if (!defaultConfigurationPath) { + vscode.window.showWarningMessage( + `Cannot set ${filePath} as default db. You first need to set a default Configuration file.` + ); + return; + } + const configDirName = path.dirname(defaultConfigurationPath); + const fileDirName = path.dirname(filePath); + + if (configDirName !== fileDirName) { + vscode.window.showWarningMessage( + `Cannot set ${filePath} as default db. The .db file (located in ${fileDirName}) has to be in the same directory as your default Configuraion file (${configDirName}).` + ); + return; + } + + await updateVCShellDatabase(filePath); + } + } + } + ); + context.subscriptions.push(defaultVCShellCommand); + const importEnviroToProject = vscode.commands.registerCommand( "vectorcastTestExplorer.importEnviroToProject", async (_args: vscode.Uri, argList: vscode.Uri[]) => { diff --git a/src/vcastTestInterface.ts b/src/vcastTestInterface.ts index c9ba6180..f9383f0d 100644 --- a/src/vcastTestInterface.ts +++ b/src/vcastTestInterface.ts @@ -1222,3 +1222,40 @@ export async function newVCShell(filePath: string) { ); } } + +export async function updateVCShellDatabase(vcShellPath: string) { + // Retrieve VectorCAST Dir + const vcDir = getVectorCastInstallationLocation(); + if (!vcDir) { + vectorMessage("VectorCAST Installation Location not found. Aborting."); + vscode.window.showWarningMessage( + `VectorCAST Installation Location not found. Aborting.` + ); + return; + } + + // Build paths + const vcShellCommand = path.join(normalizePath(vcDir), `clicast`); + const commandToRun = `${vcShellCommand}`; + const dirName = path.dirname(vcShellPath); + const fileName = path.basename(vcShellPath); + const unitTestLocation = getUnitTestLocationForPath(dirName); + const normalizedUnitPath = normalizePath(unitTestLocation); + + // Execute + const infoMessage = `Loading VectorCAST database from ${fileName} and setting it as the active VCDB.`; + await executeWithRealTimeEchoWithProgress( + commandToRun, + ["-lc", "option", "VCDB_FILENAME", `$(readlink -f ${fileName})`], + normalizedUnitPath, + infoMessage + ); + + // Update Settings + const settings = vscode.workspace.getConfiguration("vectorcastTestExplorer"); + settings.update("databaseLocation", vcShellPath); + + vscode.window.showInformationMessage( + `Default Database location has been set to: ${vcShellPath}` + ); +} From 22536e23bb2853113dc3b1f3689f655391e7ffab Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Mon, 17 Nov 2025 15:06:30 +0100 Subject: [PATCH 06/61] Fixed issue where vcshell is not created when the dir does not exist --- src/extension.ts | 79 +++++++++++++++++++++++++++++---------- src/vcastTestInterface.ts | 12 ++++++ 2 files changed, 71 insertions(+), 20 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index 0d854b80..02cf68d9 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1570,39 +1570,78 @@ async function installPreActivationEventHandlers( let defaultVCShellCommand = vscode.commands.registerCommand( "vectorcastTestExplorer.defaultVCShell", async (fileURI: Uri) => { - // contains a check for already configured, so no work will be done in that case await checkPrerequisites(context); - if (alreadyConfigured) { - if (fileURI) { - const filePath = fileURI.fsPath; - const settings = vscode.workspace.getConfiguration( - "vectorcastTestExplorer" + + if (!alreadyConfigured) { + return; + } + + if (fileURI) { + const filePath = fileURI.fsPath; + const settings = vscode.workspace.getConfiguration( + "vectorcastTestExplorer" + ); + + const defaultConfigurationPath = settings.get( + "configurationLocation", + undefined + ); + + if (!defaultConfigurationPath) { + vscode.window.showWarningMessage( + `Cannot set ${filePath} as default db. You first need to set a default Configuration file.` ); - const defaultConfigurationPath = settings.get( - "configurationLocation", - undefined + return; + } + + const configDirName = path.dirname(defaultConfigurationPath); + const fileDirName = path.dirname(filePath); + + // If not in same directory → ask user if they want to move it + if (configDirName !== fileDirName) { + const choice = await vscode.window.showWarningMessage( + `The VC shell database is not in the same directory as the default configuration.\n\n` + + `Current location:\n${filePath}\n\n` + + `Target directory:\n${configDirName}\n\n` + + `Do you want to move the database to the configuration directory?`, + { modal: false }, + "Yes", + "Cancel" ); - if (!defaultConfigurationPath) { - vscode.window.showWarningMessage( - `Cannot set ${filePath} as default db. You first need to set a default Configuration file.` - ); + + if (choice !== "Yes") { return; } - const configDirName = path.dirname(defaultConfigurationPath); - const fileDirName = path.dirname(filePath); - if (configDirName !== fileDirName) { - vscode.window.showWarningMessage( - `Cannot set ${filePath} as default db. The .db file (located in ${fileDirName}) has to be in the same directory as your default Configuraion file (${configDirName}).` + try { + // Try to move the file + const targetPath = path.join( + configDirName, + path.basename(filePath) + ); + await fs.promises.rename(filePath, targetPath); + + vscode.window.showInformationMessage( + `Moved database:\n${filePath}\n→\n${targetPath}` + ); + + // Continue using the new file path + await updateVCShellDatabase(targetPath); + return; + } catch (err: any) { + vscode.window.showErrorMessage( + `Failed to move database: ${err.message}` ); return; } - - await updateVCShellDatabase(filePath); } + + // Normal flow (already in correct directory) + await updateVCShellDatabase(filePath); } } ); + context.subscriptions.push(defaultVCShellCommand); const importEnviroToProject = vscode.commands.registerCommand( diff --git a/src/vcastTestInterface.ts b/src/vcastTestInterface.ts index f9383f0d..350993bd 100644 --- a/src/vcastTestInterface.ts +++ b/src/vcastTestInterface.ts @@ -1211,9 +1211,21 @@ export async function newVCShell(filePath: string) { const vcDir = getVectorCastInstallationLocation(); if (vcDir) { + // Ensure the target directory exists before running vcshell + try { + await fs.promises.mkdir(normalizedUnitPath, { recursive: true }); + } catch (err: any) { + vscode.window.showErrorMessage( + `Failed to create directory ${normalizedUnitPath}: ${err.message}` + ); + return; + } + const vcShellCommand = path.join(normalizePath(vcDir), `vcshell`); const commandToRun = `${vcShellCommand}`; + const infoMessage = `Creating vcshell for ${fileName} in ${normalizedUnitPath}`; + await executeWithRealTimeEchoWithProgress( commandToRun, ["gcc", "-c", normalizeFilePath], From ec2e71756e426281d3f9cb7d5a8d0af32c18246f Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Mon, 17 Nov 2025 15:22:25 +0100 Subject: [PATCH 07/61] Adapted new project webview --- src/extension.ts | 53 ++++-- src/manage/manageSrc/manageCommands.ts | 16 +- src/manage/webviews/css/newProject.css | 153 ++++++++++++++---- src/manage/webviews/html/newProject.html | 42 ++++- .../webviews/webviewScripts/newProject.js | 63 ++++++-- 5 files changed, 258 insertions(+), 69 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index 4a6ed751..6aef2d75 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1662,32 +1662,47 @@ async function installPreActivationEventHandlers( projectName?: string; compilerName?: string; targetDir?: string; + useDefaultCFG?: boolean; }) { - const { projectName, compilerName, targetDir } = message; - // Make sure that Inputs have to be filled and the compiler tag is found + const { projectName, compilerName, targetDir, useDefaultCFG } = message; if (!projectName) { vscode.window.showErrorMessage("Project Name is required."); return; } - if (!compilerName) { - vscode.window.showErrorMessage("Compiler selection is required."); - return; - } - const compilerTag = compilerTagList[compilerName]; - if (!compilerTag) { - vscode.window.showErrorMessage( - `No compiler tag found for "${compilerName}".` + + let compiler: string | undefined; + let usingDefaultCFG = false; + + if (useDefaultCFG) { + const settings = vscode.workspace.getConfiguration( + "vectorcastTestExplorer" ); - return; + const defaultCFG = settings.get("configurationLocation"); + usingDefaultCFG = true; + if (!defaultCFG) { + vscode.window.showErrorMessage("No default CFG is defined."); + return; + } + // Derive compilerTag from default CFG if possible + compiler = defaultCFG; // TODO: adjust to however your system maps CFG → compilerTag + } else { + if (!compilerName) { + vscode.window.showErrorMessage("Compiler selection is required."); + return; + } + compiler = compilerTagList[compilerName]; + if (!compiler) { + vscode.window.showErrorMessage( + `No compiler tag found for "${compilerName}".` + ); + return; + } } const base = targetDir ?? workspaceRoot; const projectPath = path.join(base, projectName); - vscode.window.showInformationMessage( - `Creating project "${projectName}" at ${projectPath} using ${compilerName}.` - ); - await createNewProject(projectPath, compilerTag); + await createNewProject(projectPath, compiler, usingDefaultCFG); panel.dispose(); } } @@ -1711,9 +1726,14 @@ async function installPreActivationEventHandlers( const scriptUri = panel.webview.asWebviewUri(scriptOnDisk); const compilersJson = JSON.stringify(Object.keys(compilerTagList)); - // pass default targetDir as workspace root const workspaceJson = JSON.stringify(workspaceRoot); + // read defaultCFG setting + const settings = vscode.workspace.getConfiguration( + "vectorcastTestExplorer" + ); + const defaultCFG = settings.get("configurationLocation") ?? ""; + let html = fs.readFileSync(htmlPath, "utf8"); const nonce = getNonce(); html = html.replace( @@ -1725,6 +1745,7 @@ async function installPreActivationEventHandlers( ` ); html = html.replace("{{ cssUri }}", cssUri.toString()); diff --git a/src/manage/manageSrc/manageCommands.ts b/src/manage/manageSrc/manageCommands.ts index ae7d82d9..f948cba6 100644 --- a/src/manage/manageSrc/manageCommands.ts +++ b/src/manage/manageSrc/manageCommands.ts @@ -121,9 +121,14 @@ export async function createNewCompilerInProject( /** * Creates a new Project including a new Compiler * @param projectPath Path to the new project file - * @param compiler Compiler Name + * @param compiler Compiler Tag OR compiler path in case we are using the default CFG from the settings + * @param usingDefaultCFG Boolean, if the user selected to use the default cfg in the settings */ -export async function createNewProject(projectPath: string, compiler: string) { +export async function createNewProject( + projectPath: string, + compiler: string, + usingDefaultCFG: boolean = false +) { const projectName = path.basename(projectPath); const projectLocation = path.dirname(projectPath); const progressMessage = `Creating new Project ${projectName} ...`; @@ -136,7 +141,12 @@ export async function createNewProject(projectPath: string, compiler: string) { progressMessage ); - await createNewCompilerInProject(projectPath, compiler); + // If we're using default cfg, the cfg already exists and we only need to import it to the project + if (usingDefaultCFG) { + await addCompilerToProject(projectPath, compiler); + } else { + await createNewCompilerInProject(projectPath, compiler); + } } export async function cleanProjectEnvironment( diff --git a/src/manage/webviews/css/newProject.css b/src/manage/webviews/css/newProject.css index 5be0367a..541e4ee2 100644 --- a/src/manage/webviews/css/newProject.css +++ b/src/manage/webviews/css/newProject.css @@ -22,26 +22,24 @@ body { padding: 25px; border-radius: 8px; box-shadow: 0 0 10px rgba(0,0,0,0.3); + display: flex; + flex-direction: column; } -/* Center only the title, not all modal text */ +/* Modal title */ .modal h2 { text-align: center; -} - -h2 { color: #ffffff; margin-bottom: 15px; font-size: 22px; } /* Labels and inputs */ -label { +label, .toggle-label { font-size: 16px; + color: #d4d4d4; display: block; - text-align: left; - margin-top: 12px; - margin-bottom: 6px; + margin-bottom: 8px; /* spacing between label and field */ } input[type="text"], select { @@ -52,6 +50,7 @@ input[type="text"], select { border: 1px solid #555; border-radius: 4px; width: 100%; + margin-bottom: 0; /* remove extra spacing because we handle spacing via container */ } /* Folder-picker row */ @@ -74,10 +73,7 @@ input[type="text"], select { cursor: pointer; transition: background-color 0.3s; } - -.select-button:hover { - background-color: #005f99; -} +.select-button:hover { background-color: #005f99; } /* Autocomplete */ .autocomplete { @@ -99,34 +95,137 @@ input[type="text"], select { margin-top: 4px; display: none; z-index: 10; - text-align: left; /* ensure left alignment */ -} - -.suggestions.visible { - display: block; + text-align: left; } - +.suggestions.visible { display: block; } .suggestions li { padding: 8px 12px; cursor: pointer; font-size: 14px; } - .suggestions li:hover, .suggestions li.active { background: #007acc; color: white; } -/* Button container */ -.button-container { - display: flex; - justify-content: flex-end; - gap: 10px; +/* Options section */ +.options-section { margin-top: 20px; + padding-top: 10px; + border-top: 1px solid #444; + width: 80%; + margin-left: auto; + margin-right: auto; +} + +.options-section h3 { + font-size: 16px; + font-weight: 600; + margin: 0 0 8px 0; /* remove extra space above */ + color: #ffffff; + text-align: center; } -/* Primary & cancel buttons */ +/* Boxes for default CFG and new compiler */ +#defaultCompilerRow, +#newCompilerSection { + border: 1px solid #555; + border-radius: 6px; + padding: 8px 12px; + margin-bottom: 10px; + display: flex; + align-items: center; + justify-content: space-between; +} + +/* Ensure label wraps in its space */ +#defaultCompilerRow .toggle-label, +#newCompilerSection label { + margin: 0; + line-height: 1.4; + flex: 1; +} + +#defaultCFGPath { + display: block; + margin-top: 4px; + font-size: 12px; + color: #aaa; + word-break: break-all; /* force wrap if path is too long */ + max-width: 420px; /* prevent stretching modal */ +} + +/* OR separator */ +#orSeparator h3 { + margin: 12px 0; + color: #fff; + font-weight: 600; + font-size: 16px; + text-align: center; +} + +/* VS Code–style toggle */ +.vscode-toggle { + display: inline-block; + cursor: pointer; +} +.toggle-switch { + display: inline-block; + position: relative; + width: 44px; + height: 24px; + vertical-align: middle; +} +.toggle-switch input { + opacity: 0; + width: 0; + height: 0; + margin: 0; +} +.toggle-switch .slider { + position: absolute; + inset: 0; + background: #3c3c3c; + border: 1px solid #555; + border-radius: 12px; + transition: background 0.12s ease, border-color 0.12s ease; + box-sizing: border-box; +} +.toggle-switch .slider::before { + content: ""; + position: absolute; + top: 50%; + left: 1px; + width: 22px; + height: 22px; + border-radius: 50%; + background: #d4d4d4; + box-shadow: 0 1px 0 rgba(0,0,0,0.25); + transform: translateY(-50%); + transition: left 0.12s ease, background 0.12s ease; +} +.toggle-switch input:checked + .slider { + background: #007acc; + border-color: #007acc; +} +.toggle-switch input:checked + .slider::before { + left: 21px; + background: #ffffff; +} +.toggle-switch input:focus + .slider { + box-shadow: 0 0 0 3px rgba(0,122,204,0.14); +} +.vscode-toggle:hover .slider { + filter: brightness(1.06); +} + +/* Buttons */ +.button-container { + display: flex; + justify-content: space-between; + margin-top: 25px; +} .primary-button, .cancel-button { padding: 10px 20px; @@ -136,21 +235,17 @@ input[type="text"], select { cursor: pointer; transition: background-color 0.3s; } - .primary-button { background-color: #007acc; color: white; } - .primary-button:hover { background-color: #005f99; } - .cancel-button { background-color: #cc4444; color: white; } - .cancel-button:hover { background-color: #992222; } diff --git a/src/manage/webviews/html/newProject.html b/src/manage/webviews/html/newProject.html index d5937b84..82b756dc 100644 --- a/src/manage/webviews/html/newProject.html +++ b/src/manage/webviews/html/newProject.html @@ -25,10 +25,42 @@

Create New Project

- -
- -
    +
    +

    Compiler Selection

    + + + + + + + + +
    + +
    + +
      +
      +
      @@ -39,4 +71,4 @@

      Create New Project

      {{ scriptUri }} - \ No newline at end of file + diff --git a/src/manage/webviews/webviewScripts/newProject.js b/src/manage/webviews/webviewScripts/newProject.js index ce7abfeb..3d5864c4 100644 --- a/src/manage/webviews/webviewScripts/newProject.js +++ b/src/manage/webviews/webviewScripts/newProject.js @@ -2,24 +2,48 @@ const vscode = acquireVsCodeApi(); window.addEventListener("DOMContentLoaded", () => { const compilers = window.compilerData || []; - const defaultDir = window.defaultDir || ""; + const defaultCFG = window.defaultCFG || ""; + const defaultRow = document.getElementById("defaultCompilerRow"); + const defaultPath = document.getElementById("defaultCFGPath"); + const orSeparator = document.getElementById("orSeparator"); + const useDefaultCheckbox = document.getElementById("useDefaultCompiler"); + const newCompilerSection = document.getElementById("newCompilerSection"); const targetInput = document.getElementById("targetDirInput"); - const browseBtn = document.getElementById("btnBrowse"); - const nameInput = document.getElementById("projectNameInput"); - const compInput = document.getElementById("compilerInput"); + const browseBtn = document.getElementById("btnBrowse"); + const nameInput = document.getElementById("projectNameInput"); + const compInput = document.getElementById("compilerInput"); const suggestions = document.getElementById("suggestions"); - // initialize target folder - let targetDir = defaultDir; - targetInput.value = targetDir; + // Show default CFG row + OR only if defaultCFG exists + if (defaultCFG) { + defaultRow.style.display = "flex"; + orSeparator.style.display = "block"; + defaultPath.textContent = defaultCFG; + } else { + defaultRow.style.display = "none"; + orSeparator.style.display = "none"; + } + + function updateCompilerVisibility() { + if (useDefaultCheckbox && useDefaultCheckbox.checked) { + newCompilerSection.style.display = "none"; + orSeparator.style.display = "none"; // hide OR when default is selected + } else { + newCompilerSection.style.display = "block"; + if (defaultCFG) orSeparator.style.display = "block"; + } + } + + if (useDefaultCheckbox) useDefaultCheckbox.addEventListener("change", updateCompilerVisibility); + updateCompilerVisibility(); - // browse for folder + // Folder browse + let targetDir = window.defaultDir || ""; + targetInput.value = targetDir; browseBtn.addEventListener("click", () => { vscode.postMessage({ command: "browseForDir" }); }); - - // receive chosen folder window.addEventListener("message", (e) => { const msg = e.data; if (msg.command === "setTargetDir") { @@ -28,8 +52,9 @@ window.addEventListener("DOMContentLoaded", () => { } }); - // autocomplete setup (unchanged)... + // Autocomplete let filtered = [], activeIndex = -1; + function renderSuggestions() { suggestions.innerHTML = ""; if (!filtered.length) return suggestions.classList.remove("visible"); @@ -45,6 +70,7 @@ window.addEventListener("DOMContentLoaded", () => { }); suggestions.classList.add("visible"); } + function updateSuggestions(showAll = false) { const q = compInput.value.toLowerCase().trim(); filtered = showAll || !q @@ -53,8 +79,10 @@ window.addEventListener("DOMContentLoaded", () => { activeIndex = -1; renderSuggestions(); } + compInput.addEventListener("input", () => updateSuggestions()); compInput.addEventListener("focus", () => updateSuggestions(true)); + compInput.addEventListener("click", () => updateSuggestions(true)); compInput.addEventListener("keydown", e => { if (!filtered.length) return; if (e.key === "ArrowDown") { @@ -79,18 +107,21 @@ window.addEventListener("DOMContentLoaded", () => { if (!e.target.closest(".autocomplete")) suggestions.classList.remove("visible"); }); - // submit + // Submit document.getElementById("btnSubmit").addEventListener("click", () => { vscode.postMessage({ command: "submit", projectName: nameInput.value.trim(), - compilerName: compInput.value.trim(), - targetDir + compilerName: useDefaultCheckbox && useDefaultCheckbox.checked + ? undefined + : compInput.value.trim(), + useDefaultCFG: useDefaultCheckbox && useDefaultCheckbox.checked, + targetDir, }); }); - // cancel + // Cancel document.getElementById("btnCancel").addEventListener("click", () => { vscode.postMessage({ command: "cancel" }); }); -}); \ No newline at end of file +}); From 7c6ab845728ba91873ba706828c4319741a70ade Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Fri, 21 Nov 2025 10:08:33 +0100 Subject: [PATCH 08/61] Removed ability to create new vcshell --- package.json | 14 -------------- src/vcastTestInterface.ts | 33 --------------------------------- 2 files changed, 47 deletions(-) diff --git a/package.json b/package.json index e7be2bc5..15fd5795 100644 --- a/package.json +++ b/package.json @@ -169,11 +169,6 @@ "category": "VectorCAST Test Explorer", "title": "Create VectorCAST Environment" }, - { - "command": "vectorcastTestExplorer.newVCShell", - "category": "VectorCAST Test Explorer", - "title": "Create New VC Shell" - }, { "command": "vectorcastTestExplorer.defaultVCShell", "category": "VectorCAST Test Explorer", @@ -711,10 +706,6 @@ "command": "vectorcastTestExplorer.newEnviroVCAST", "when": "never" }, - { - "command": "vectorcastTestExplorer.newVCShell", - "when": "never" - }, { "command": "vectorcastTestExplorer.defaultVCShell", "when": "never" @@ -870,11 +861,6 @@ "when": "resourceLangId == cpp || resourceLangId == c", "group": "2_workspace" }, - { - "command": "vectorcastTestExplorer.newVCShell", - "when": "resourceLangId == cpp || resourceLangId == c", - "group": "2_workspace" - }, { "command": "vectorcastTestExplorer.defaultVCShell", "when": "vectorcastTestExplorer.configured && resourceExtname==.db", diff --git a/src/vcastTestInterface.ts b/src/vcastTestInterface.ts index 350993bd..b4095444 100644 --- a/src/vcastTestInterface.ts +++ b/src/vcastTestInterface.ts @@ -1202,39 +1202,6 @@ export async function getMCDCResultFile( return resultFile; } -export async function newVCShell(filePath: string) { - const normalizeFilePath = normalizePath(filePath); - const dirName = path.dirname(normalizeFilePath); - const fileName = path.basename(normalizeFilePath); - const unitTestLocation = getUnitTestLocationForPath(dirName); - const normalizedUnitPath = normalizePath(unitTestLocation); - const vcDir = getVectorCastInstallationLocation(); - - if (vcDir) { - // Ensure the target directory exists before running vcshell - try { - await fs.promises.mkdir(normalizedUnitPath, { recursive: true }); - } catch (err: any) { - vscode.window.showErrorMessage( - `Failed to create directory ${normalizedUnitPath}: ${err.message}` - ); - return; - } - - const vcShellCommand = path.join(normalizePath(vcDir), `vcshell`); - const commandToRun = `${vcShellCommand}`; - - const infoMessage = `Creating vcshell for ${fileName} in ${normalizedUnitPath}`; - - await executeWithRealTimeEchoWithProgress( - commandToRun, - ["gcc", "-c", normalizeFilePath], - normalizedUnitPath, - infoMessage - ); - } -} - export async function updateVCShellDatabase(vcShellPath: string) { // Retrieve VectorCAST Dir const vcDir = getVectorCastInstallationLocation(); From f98f61132dd2ce72bfa3ed4691fdcd9100393861 Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Fri, 21 Nov 2025 10:10:23 +0100 Subject: [PATCH 09/61] Removed ability to create new vcshell 2 --- src/extension.ts | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index 02cf68d9..141658ab 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -149,7 +149,6 @@ import { newTestScript, openCodedTest, ProjectEnvParameters, - newVCShell, updateVCShellDatabase, } from "./vcastTestInterface"; @@ -1548,25 +1547,6 @@ async function installPreActivationEventHandlers( ); context.subscriptions.push(newEnviroVCASTCommand); - // Command: vectorcastTestExplorer.newEnviroVCAST //////////////////////////////////////////////////////// - let newVCShellCommand = vscode.commands.registerCommand( - "vectorcastTestExplorer.newVCShell", - async (arg: Uri) => { - // contains a check for already configured, so no work will be done in that case - await checkPrerequisites(context); - if (alreadyConfigured) { - // arg is the actual item that the right click happened on, argList is the list - // of all items if this is a multi-select. Since argList is always valid, even for a single - // selection, we just use this here. - if (arg) { - const filePath = arg.fsPath; - await newVCShell(filePath); - } - } - } - ); - context.subscriptions.push(newVCShellCommand); - let defaultVCShellCommand = vscode.commands.registerCommand( "vectorcastTestExplorer.defaultVCShell", async (fileURI: Uri) => { From 4888fa459ff0fd9be36ca2a8db61cff46298d127 Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Thu, 27 Nov 2025 16:46:41 +0100 Subject: [PATCH 10/61] Updated new project ui --- src/extension.ts | 59 +++-- src/manage/manageSrc/manageCommands.ts | 77 +++++- src/manage/webviews/css/newProject.css | 223 +++++++++++------- src/manage/webviews/html/newProject.html | 59 +++-- .../webviews/webviewScripts/newProject.js | 45 +++- 5 files changed, 333 insertions(+), 130 deletions(-) diff --git a/src/extension.ts b/src/extension.ts index 6aef2d75..1f1fd868 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1663,33 +1663,45 @@ async function installPreActivationEventHandlers( compilerName?: string; targetDir?: string; useDefaultCFG?: boolean; + enableCodedTests?: boolean; + defaultCFG?: boolean; }) { - const { projectName, compilerName, targetDir, useDefaultCFG } = message; + const { + projectName, + compilerName, + targetDir, + useDefaultCFG, + enableCodedTests, + defaultCFG, + } = message; + if (!projectName) { vscode.window.showErrorMessage("Project Name is required."); return; } let compiler: string | undefined; - let usingDefaultCFG = false; + let configurationOptions: ConfigurationOptions | undefined; if (useDefaultCFG) { const settings = vscode.workspace.getConfiguration( "vectorcastTestExplorer" ); - const defaultCFG = settings.get("configurationLocation"); - usingDefaultCFG = true; - if (!defaultCFG) { + const defaultCFGPath = settings.get("configurationLocation"); + + if (!defaultCFGPath) { vscode.window.showErrorMessage("No default CFG is defined."); return; } - // Derive compilerTag from default CFG if possible - compiler = defaultCFG; // TODO: adjust to however your system maps CFG → compilerTag + // When using default CFG, the 'compiler' string is the path to the CFG + compiler = defaultCFGPath; } else { + // Manual Compiler Selection if (!compilerName) { vscode.window.showErrorMessage("Compiler selection is required."); return; } + compiler = compilerTagList[compilerName]; if (!compiler) { vscode.window.showErrorMessage( @@ -1697,12 +1709,24 @@ async function installPreActivationEventHandlers( ); return; } + + // Pack the boolean options + configurationOptions = { + enableCodedTests: !!enableCodedTests, + defaultCFG: !!defaultCFG, + }; } const base = targetDir ?? workspaceRoot; const projectPath = path.join(base, projectName); - await createNewProject(projectPath, compiler, usingDefaultCFG); + await createNewProject( + projectPath, + compiler, + !!useDefaultCFG, + configurationOptions + ); + panel.dispose(); } } @@ -1710,6 +1734,7 @@ async function installPreActivationEventHandlers( context.subscriptions.push(createNewProjectCmd); + // Helper function for Webview Content async function getNewProjectWebviewContent( context: vscode.ExtensionContext, panel: vscode.WebviewPanel, @@ -1728,7 +1753,6 @@ async function installPreActivationEventHandlers( const compilersJson = JSON.stringify(Object.keys(compilerTagList)); const workspaceJson = JSON.stringify(workspaceRoot); - // read defaultCFG setting const settings = vscode.workspace.getConfiguration( "vectorcastTestExplorer" ); @@ -1736,17 +1760,18 @@ async function installPreActivationEventHandlers( let html = fs.readFileSync(htmlPath, "utf8"); const nonce = getNonce(); + html = html.replace( //, ` - - ` + + ` ); html = html.replace("{{ cssUri }}", cssUri.toString()); html = html.replace( diff --git a/src/manage/manageSrc/manageCommands.ts b/src/manage/manageSrc/manageCommands.ts index f948cba6..e725abb1 100644 --- a/src/manage/manageSrc/manageCommands.ts +++ b/src/manage/manageSrc/manageCommands.ts @@ -23,7 +23,10 @@ import { getEnviroNodeData } from "../../testData"; import { executeWithRealTimeEchoWithProgress } from "../../vcastCommandRunner"; -import { manageCommandToUse } from "../../vcastInstallation"; +import { + getVectorCastInstallationLocation, + manageCommandToUse, +} from "../../vcastInstallation"; import { checkIfEnvironmentIsBuildMultipleTimes, @@ -44,6 +47,7 @@ import { } from "../../testPane"; import { normalizePath } from "../../utilities"; import { viewResultsReportVC } from "../../reporting"; +import { ConfigurationOptions } from "../../vcastTestInterface"; const path = require("path"); @@ -127,11 +131,15 @@ export async function createNewCompilerInProject( export async function createNewProject( projectPath: string, compiler: string, - usingDefaultCFG: boolean = false + usingDefaultCFG: boolean = false, + configurationOptions?: ConfigurationOptions ) { const projectName = path.basename(projectPath); const projectLocation = path.dirname(projectPath); - const progressMessage = `Creating new Project ${projectName} ...`; + + // 1. Create the Project Directory Structure + const progressMessage = `Creating new Project ${projectName} ...`; + // Assuming 'manageCommandToUse' is defined globally or imported const manageArgs = [`-p${projectName}`, `--create`, "--force"]; await executeWithRealTimeEchoWithProgress( @@ -141,11 +149,70 @@ export async function createNewProject( progressMessage ); - // If we're using default cfg, the cfg already exists and we only need to import it to the project + // 2. Configure the Compiler / CFG if (usingDefaultCFG) { + // Scenario A: Use an existing CFG file + // 'compiler' variable here is the PATH to the CFG await addCompilerToProject(projectPath, compiler); } else { - await createNewCompilerInProject(projectPath, compiler); + // Scenario B: Create a NEW CFG based on a Compiler Tag + // 'compiler' variable here is the Compiler Tag (e.g., "GNU_Native") + + // Create the CFG file inside the new project directory + // We reuse the helper used in createNewCFGFile + const createdCfgPath = await createNewCFGFromCompiler( + compiler, + projectPath + ); + + // Handle Additional Configuration Options (if provided) + if (configurationOptions) { + const vcDir = getVectorCastInstallationLocation(); + if (vcDir) { + const clicastCmd = path.join(vcDir, "clicast"); + + // Apply Coded Tests Option + const codedFlag = configurationOptions.enableCodedTests + ? "TRUE" + : "FALSE"; + const codedOptionArgs = [ + "-lc", + "option", + "VCAST_CODED_TESTS_SUPPORT", + codedFlag, + ]; + + // We run this command INSIDE the new project path so it affects the local CFG + await executeWithRealTimeEchoWithProgress( + clicastCmd, + codedOptionArgs, + projectPath, + "Setting VCAST_CODED_TESTS_SUPPORT in Project CFG" + ); + + // Set as Default CFG in VS Code Settings + if (configurationOptions.defaultCFG) { + const settings = vscode.workspace.getConfiguration( + "vectorcastTestExplorer" + ); + await settings.update( + "configurationLocation", + createdCfgPath, + vscode.ConfigurationTarget.Workspace + ); + } + } else { + vscode.window.showErrorMessage( + "Could not determine VectorCAST location. configuration options could not be applied." + ); + } + } + + // If CFG options are done, add the compiler to the project + // If the path would be undefined, we will get a message from createNewCFGFromCompiler, so no handling here + if (createdCfgPath) { + await addCompilerToProject(projectPath, createdCfgPath); + } } } diff --git a/src/manage/webviews/css/newProject.css b/src/manage/webviews/css/newProject.css index 541e4ee2..e386e4a8 100644 --- a/src/manage/webviews/css/newProject.css +++ b/src/manage/webviews/css/newProject.css @@ -24,33 +24,44 @@ body { box-shadow: 0 0 10px rgba(0,0,0,0.3); display: flex; flex-direction: column; + max-height: 95vh; + overflow-y: auto; } -/* Modal title */ +/* Modal Main Title */ .modal h2 { text-align: center; color: #ffffff; - margin-bottom: 15px; + margin-bottom: 20px; font-size: 22px; + font-weight: 600; } -/* Labels and inputs */ +/* Generic Labels */ label, .toggle-label { - font-size: 16px; - color: #d4d4d4; + font-size: 14px; + color: #cccccc; display: block; - margin-bottom: 8px; /* spacing between label and field */ + margin-bottom: 6px; + font-weight: 400; } +/* Inputs */ input[type="text"], select { - padding: 10px; + padding: 8px 10px; font-size: 14px; background-color: #3c3c3c; color: #d4d4d4; - border: 1px solid #555; + border: 1px solid #3c3c3c; border-radius: 4px; width: 100%; - margin-bottom: 0; /* remove extra spacing because we handle spacing via container */ + margin-bottom: 15px; + transition: border-color 0.2s; +} + +input[type="text"]:focus, select:focus { + border-color: #007acc; + outline: none; } /* Folder-picker row */ @@ -58,20 +69,26 @@ input[type="text"], select { display: grid; grid-template-columns: 1fr auto; gap: 10px; - align-items: center; + align-items: start; margin-bottom: 15px; } +.single-input-container input[type="text"] { + margin-bottom: 0; +} -/* “Select” button beside the input */ +/* Select Button */ .select-button { background-color: #007acc; color: white; border: none; border-radius: 4px; - padding: 10px 16px; + padding: 0 16px; font-size: 14px; cursor: pointer; + height: 35px; /* Match input height */ transition: background-color 0.3s; + display: flex; + align-items: center; } .select-button:hover { background-color: #005f99; } @@ -80,92 +97,141 @@ input[type="text"], select { position: relative; width: 100%; } - .suggestions { position: absolute; top: 100%; left: 0; right: 0; - background: #2a2a2a; - border: 1px solid #555; + background: #252526; + border: 1px solid #454545; max-height: 180px; overflow-y: auto; list-style: none; padding: 0; - margin-top: 4px; + margin-top: 2px; display: none; - z-index: 10; - text-align: left; + z-index: 100; + box-shadow: 0 4px 6px rgba(0,0,0,0.3); } .suggestions.visible { display: block; } .suggestions li { padding: 8px 12px; cursor: pointer; font-size: 14px; + border-bottom: 1px solid #333; } +.suggestions li:last-child { border-bottom: none; } .suggestions li:hover, .suggestions li.active { background: #007acc; color: white; } -/* Options section */ +/* ========================================= + Options Section & Headers + ========================================= */ + .options-section { - margin-top: 20px; - padding-top: 10px; - border-top: 1px solid #444; - width: 80%; + margin-top: 15px; + padding-top: 15px; + border-top: 1px solid #3e3e3e; + width: 98%; margin-left: auto; margin-right: auto; } +/* MAIN SECTION TITLE (Compiler Selection) */ .options-section h3 { font-size: 16px; - font-weight: 600; - margin: 0 0 8px 0; /* remove extra space above */ - color: #ffffff; + font-weight: 700; + color: #ffffff; + margin: 0 0 15px 0; text-align: center; + text-transform: uppercase; + letter-spacing: 0.5px; } -/* Boxes for default CFG and new compiler */ -#defaultCompilerRow, -#newCompilerSection { - border: 1px solid #555; +/* Selection Boxes */ +.selection-box { + border: 1px solid #444; border-radius: 6px; - padding: 8px 12px; - margin-bottom: 10px; + padding: 15px; + margin-bottom: 15px; + background-color: #2d2d2d; +} + +/* Default Compiler Row */ +#defaultCompilerRow { display: flex; align-items: center; justify-content: space-between; } - -/* Ensure label wraps in its space */ -#defaultCompilerRow .toggle-label, -#newCompilerSection label { - margin: 0; - line-height: 1.4; - flex: 1; +#defaultCompilerRow .toggle-label { + margin: 0; + color: #fff; + font-weight: 600; } - #defaultCFGPath { display: block; margin-top: 4px; font-size: 12px; - color: #aaa; - word-break: break-all; /* force wrap if path is too long */ - max-width: 420px; /* prevent stretching modal */ + color: #888; + font-weight: 400; + word-break: break-all; } -/* OR separator */ -#orSeparator h3 { - margin: 12px 0; - color: #fff; - font-weight: 600; - font-size: 16px; +/* OR Separator */ +#orSeparator { text-align: center; + margin: 10px 0; +} +#orSeparator h3 { + font-size: 14px; + color: #ffffff; + font-weight: 700; + margin: 0; + text-transform: none; +} + +/* New Compiler Section */ +#newCompilerSection { + display: block; +} + +/* SUB-SECTION TITLE (Configuration Options) */ +.config-options-wrapper { + margin-top: 20px; + padding-top: 15px; + border-top: 1px dashed #444; +} + +.config-options-wrapper h4 { + font-size: 14px; + color: #ffffff; + font-weight: 700; + margin-bottom: 12px; + display: block; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +/* Option Rows */ +.option-row { + display: flex; + align-items: center; + justify-content: space-between; + padding: 8px 0; + width: 100%; +} + +.option-row .toggle-label { + font-size: 14px; + color: #d4d4d4; + font-weight: 400; + margin-bottom: 0; } -/* VS Code–style toggle */ +/* Toggle Switch */ .vscode-toggle { display: inline-block; cursor: pointer; @@ -173,79 +239,76 @@ input[type="text"], select { .toggle-switch { display: inline-block; position: relative; - width: 44px; - height: 24px; + width: 40px; + height: 20px; vertical-align: middle; } .toggle-switch input { opacity: 0; width: 0; height: 0; - margin: 0; } .toggle-switch .slider { position: absolute; inset: 0; background: #3c3c3c; border: 1px solid #555; - border-radius: 12px; - transition: background 0.12s ease, border-color 0.12s ease; - box-sizing: border-box; + border-radius: 10px; + transition: .2s; } .toggle-switch .slider::before { content: ""; position: absolute; - top: 50%; - left: 1px; - width: 22px; - height: 22px; + height: 16px; + width: 16px; + left: 2px; + bottom: 1px; + background-color: #ccc; border-radius: 50%; - background: #d4d4d4; - box-shadow: 0 1px 0 rgba(0,0,0,0.25); - transform: translateY(-50%); - transition: left 0.12s ease, background 0.12s ease; + transition: .2s; } .toggle-switch input:checked + .slider { - background: #007acc; + background-color: #007acc; border-color: #007acc; } .toggle-switch input:checked + .slider::before { - left: 21px; - background: #ffffff; -} -.toggle-switch input:focus + .slider { - box-shadow: 0 0 0 3px rgba(0,122,204,0.14); + transform: translateX(20px); + background-color: white; } .vscode-toggle:hover .slider { - filter: brightness(1.06); + border-color: #666; } /* Buttons */ .button-container { display: flex; - justify-content: space-between; - margin-top: 25px; + justify-content: flex-end; + gap: 10px; + margin-top: 20px; + padding-top: 10px; } + .primary-button, .cancel-button { - padding: 10px 20px; - font-size: 16px; + padding: 8px 24px; + font-size: 14px; + font-weight: 600; border: none; border-radius: 4px; cursor: pointer; - transition: background-color 0.3s; + transition: background-color 0.2s; } + .primary-button { background-color: #007acc; color: white; } -.primary-button:hover { - background-color: #005f99; -} +.primary-button:hover { background-color: #005f99; } + .cancel-button { background-color: #cc4444; color: white; } .cancel-button:hover { background-color: #992222; -} +} \ No newline at end of file diff --git a/src/manage/webviews/html/newProject.html b/src/manage/webviews/html/newProject.html index 82b756dc..a49b2036 100644 --- a/src/manage/webviews/html/newProject.html +++ b/src/manage/webviews/html/newProject.html @@ -29,10 +29,10 @@

      Create New Project

      Compiler Selection

      -
      diff --git a/src/manage/webviews/webviewScripts/newCFG.js b/src/manage/webviews/webviewScripts/newCFG.js index c9e17748..0159460f 100644 --- a/src/manage/webviews/webviewScripts/newCFG.js +++ b/src/manage/webviews/webviewScripts/newCFG.js @@ -2,6 +2,8 @@ const vscode = acquireVsCodeApi(); window.addEventListener("DOMContentLoaded", () => { const compilers = window.compilerData || []; + const defaultDB = window.defaultDB || ""; + const compInput = document.getElementById("compilerInput"); const suggestions = document.getElementById("suggestions"); @@ -9,6 +11,11 @@ window.addEventListener("DOMContentLoaded", () => { const codedCheckbox = document.getElementById("enableCodedTests"); const defaultCheckbox = document.getElementById("defaultCFG"); + // DB Elements + const dbOptionRow = document.getElementById("dbOptionRow"); + const dbPathLabel = document.getElementById("dbPathLabel"); + const dbCheckbox = document.getElementById("useDefaultDB"); + // If extension injected defaults, apply them if (typeof window.enableCodedTests !== "undefined" && codedCheckbox) { codedCheckbox.checked = !!window.enableCodedTests; @@ -17,6 +24,16 @@ window.addEventListener("DOMContentLoaded", () => { defaultCheckbox.checked = !!window.defaultCFG; } + // --- DB Toggle Visibility Logic --- + if (defaultDB) { + // Setting exists and file exists -> Show the toggle + dbOptionRow.style.display = "flex"; + dbPathLabel.textContent = defaultDB; + } else { + // Setting empty OR file not found -> Keep hidden + dbOptionRow.style.display = "none"; + } + // Autocomplete setup let filtered = [], activeIndex = -1; @@ -82,7 +99,9 @@ window.addEventListener("DOMContentLoaded", () => { command: "submit", compilerName: (compInput.value || "").trim(), enableCodedTests: !!(codedCheckbox && codedCheckbox.checked), - defaultCFG: !!(defaultCheckbox && defaultCheckbox.checked) + defaultCFG: !!(defaultCheckbox && defaultCheckbox.checked), + // NEW: Send the DB toggle state + useDefaultDB: !!(dbCheckbox && dbCheckbox.checked) }); }); @@ -90,4 +109,4 @@ window.addEventListener("DOMContentLoaded", () => { document.getElementById("btnCancel").addEventListener("click", () => { vscode.postMessage({ command: "cancel" }); }); -}); +}); \ No newline at end of file diff --git a/src/manage/webviews/webviewScripts/newProject.js b/src/manage/webviews/webviewScripts/newProject.js index 8af25fdc..99f06266 100644 --- a/src/manage/webviews/webviewScripts/newProject.js +++ b/src/manage/webviews/webviewScripts/newProject.js @@ -3,6 +3,7 @@ const vscode = acquireVsCodeApi(); window.addEventListener("DOMContentLoaded", () => { const compilers = window.compilerData || []; const defaultCFG = window.defaultCFG || ""; + const defaultDB = window.defaultDB || ""; // DOM Elements const defaultRow = document.getElementById("defaultCompilerRow"); @@ -21,6 +22,11 @@ window.addEventListener("DOMContentLoaded", () => { const codedCheckbox = document.getElementById("enableCodedTests"); const defaultCFGCheckbox = document.getElementById("defaultCFG"); + // DB Option Elements + const dbOptionRow = document.getElementById("dbOptionRow"); + const dbPathLabel = document.getElementById("dbPathLabel"); + const dbCheckbox = document.getElementById("useDefaultDB"); + // --- Initialization Logic --- // Show default CFG row + OR only if defaultCFG exists @@ -33,6 +39,14 @@ window.addEventListener("DOMContentLoaded", () => { orSeparator.style.display = "none"; } + // Show Default DB row if a valid path exists + if (defaultDB) { + dbOptionRow.style.display = "flex"; + dbPathLabel.textContent = defaultDB; + } else { + dbOptionRow.style.display = "none"; + } + function updateCompilerVisibility() { if (useDefaultCheckbox && useDefaultCheckbox.checked) { newCompilerSection.style.display = "none"; @@ -135,7 +149,8 @@ window.addEventListener("DOMContentLoaded", () => { compilerName: isUsingDefault ? undefined : compInput.value.trim(), // Send compiler options enableCodedTests: !!(codedCheckbox && codedCheckbox.checked), - defaultCFG: !!(defaultCFGCheckbox && defaultCFGCheckbox.checked) + defaultCFG: !!(defaultCFGCheckbox && defaultCFGCheckbox.checked), + useDefaultDB: !!(dbCheckbox && dbCheckbox.checked) }); }); diff --git a/src/vcastTestInterface.ts b/src/vcastTestInterface.ts index 33a3761e..90e00377 100644 --- a/src/vcastTestInterface.ts +++ b/src/vcastTestInterface.ts @@ -1232,6 +1232,7 @@ export async function updateCFGWithVCShellDatabase( const commandToRun = `${vcShellCommand}`; const fileName = path.basename(vcShellPath); const normalizedVCShellPath = normalizePath(vcShellPath); + const normalizedCFGDir = normalizePath(path.dirname(normalizedCFGPath)); // Execute const infoMessage = `Loading VectorCAST database from ${fileName} and setting it as the active VCDB.`; @@ -1243,7 +1244,7 @@ export async function updateCFGWithVCShellDatabase( "VCDB_FILENAME", `$(readlink -f ${normalizedVCShellPath})`, ], - normalizedCFGPath, + normalizedCFGDir, infoMessage ); } @@ -1251,6 +1252,7 @@ export async function updateCFGWithVCShellDatabase( export interface ConfigurationOptions { enableCodedTests: boolean; defaultCFG: boolean; + useDefaultDB: boolean; } export async function createNewCFGFile( @@ -1325,4 +1327,20 @@ export async function createNewCFGFile( vscode.ConfigurationTarget.Workspace ); } + + // Apply Default Database if requested and path exists (NEW LOGIC) + if (configurationOptions.useDefaultDB && compilerPath) { + const settings = vscode.workspace.getConfiguration( + "vectorcastTestExplorer" + ); + const dbPath = settings.get("databaseLocation"); + + if (dbPath && fs.existsSync(dbPath)) { + await updateCFGWithVCShellDatabase(dbPath, compilerPath); + } else { + vscode.window.showWarningMessage( + "Could not set Default Database: The database file defined in settings could not be found." + ); + } + } } From b35e494d6717285d09dca0a33062e54f638d914f Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Tue, 2 Dec 2025 09:28:49 +0100 Subject: [PATCH 13/61] Comments --- src/manage/manageSrc/manageCommands.ts | 8 +++----- src/manage/webviews/css/newCFG.css | 4 ++-- src/manage/webviews/html/newProject.html | 2 +- src/manage/webviews/webviewScripts/newCFG.js | 4 ++-- src/vcastTestInterface.ts | 17 ++++++++++++++++- 5 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/manage/manageSrc/manageCommands.ts b/src/manage/manageSrc/manageCommands.ts index 325a1ef9..9e046812 100644 --- a/src/manage/manageSrc/manageCommands.ts +++ b/src/manage/manageSrc/manageCommands.ts @@ -140,9 +140,8 @@ export async function createNewProject( const projectName = path.basename(projectPath); const projectLocation = path.dirname(projectPath); - // 1. Create the Project Directory Structure + // Create the Project Directory Structure const progressMessage = `Creating new Project ${projectName} ...`; - // Assuming 'manageCommandToUse' is defined globally or imported const manageArgs = [`-p${projectName}`, `--create`, "--force"]; await executeWithRealTimeEchoWithProgress( @@ -154,7 +153,7 @@ export async function createNewProject( let activeCFGPath: string | undefined; - // 2. Configure the Compiler / CFG + // Configure the Compiler / CFG if (usingDefaultCFG) { // Scenario A: Use an existing CFG file // 'compiler' variable here is the PATH to the CFG @@ -165,7 +164,6 @@ export async function createNewProject( // 'compiler' variable here is the Compiler Tag (e.g., "GNU_Native") // Create the CFG file inside the new project directory - // We reuse the helper used in createNewCFGFile const createdCfgPath = await createNewCFGFromCompiler( compiler, projectPath @@ -223,7 +221,7 @@ export async function createNewProject( } } - // 3. Apply Default Database if requested and path exists + // Apply Default Database if requested and path exists if (configurationOptions?.useDefaultDB && activeCFGPath) { const settings = vscode.workspace.getConfiguration( "vectorcastTestExplorer" diff --git a/src/manage/webviews/css/newCFG.css b/src/manage/webviews/css/newCFG.css index 0fe1ebb1..452d744c 100644 --- a/src/manage/webviews/css/newCFG.css +++ b/src/manage/webviews/css/newCFG.css @@ -77,7 +77,7 @@ input[type="text"], select { /* Add spacing between label and autocomplete */ label[for="compilerInput"] { - margin-bottom: 10px; /* extra space for clarity */ + margin-bottom: 10px; } /* Autocomplete */ @@ -222,7 +222,7 @@ label[for="compilerInput"] { .button-container { display: flex; justify-content: space-between; /* cancel left, create right */ - margin-top: 25px; /* space between options and buttons */ + margin-top: 25px } .primary-button, diff --git a/src/manage/webviews/html/newProject.html b/src/manage/webviews/html/newProject.html index 6c3fd989..13305a81 100644 --- a/src/manage/webviews/html/newProject.html +++ b/src/manage/webviews/html/newProject.html @@ -65,7 +65,7 @@

      OR

      - +

      Configuration Options:

      diff --git a/src/manage/webviews/webviewScripts/newCFG.js b/src/manage/webviews/webviewScripts/newCFG.js index 0159460f..dacaccb2 100644 --- a/src/manage/webviews/webviewScripts/newCFG.js +++ b/src/manage/webviews/webviewScripts/newCFG.js @@ -93,14 +93,14 @@ window.addEventListener("DOMContentLoaded", () => { if (!e.target.closest(".autocomplete")) suggestions.classList.remove("visible"); }); - // Submit button: send both toggle values + // Submit button document.getElementById("btnSubmit").addEventListener("click", () => { vscode.postMessage({ command: "submit", compilerName: (compInput.value || "").trim(), + // Toggle Values enableCodedTests: !!(codedCheckbox && codedCheckbox.checked), defaultCFG: !!(defaultCheckbox && defaultCheckbox.checked), - // NEW: Send the DB toggle state useDefaultDB: !!(dbCheckbox && dbCheckbox.checked) }); }); diff --git a/src/vcastTestInterface.ts b/src/vcastTestInterface.ts index 90e00377..7bc4df9a 100644 --- a/src/vcastTestInterface.ts +++ b/src/vcastTestInterface.ts @@ -1203,6 +1203,10 @@ export async function getMCDCResultFile( return resultFile; } +/** + * Updates databaseLocation setting + * @param vcShellPath Path to the defaultV VCDB + */ export async function updateVCShellDatabase(vcShellPath: string) { // Update Settings const settings = vscode.workspace.getConfiguration("vectorcastTestExplorer"); @@ -1213,6 +1217,11 @@ export async function updateVCShellDatabase(vcShellPath: string) { ); } +/** + * Updates CFG VCDB_FILENAME option + * @param vcShellPath Path of the vcshell db + * @param normalizedCFGPath Path to CFG + */ export async function updateCFGWithVCShellDatabase( vcShellPath: string, normalizedCFGPath: string @@ -1255,6 +1264,12 @@ export interface ConfigurationOptions { useDefaultDB: boolean; } +/** + * Creates new CFG including selected options like: Default CFG, Enable Coded Tests + * @param workspaceRoot Root of Workspace + * @param compilerTag Compiler name + * @param configurationOptions Additional CFG options + */ export async function createNewCFGFile( workspaceRoot: string, compilerTag: string, @@ -1328,7 +1343,7 @@ export async function createNewCFGFile( ); } - // Apply Default Database if requested and path exists (NEW LOGIC) + // Apply Default Database if requested and path exists if (configurationOptions.useDefaultDB && compilerPath) { const settings = vscode.workspace.getConfiguration( "vectorcastTestExplorer" From 9b6241d5fb22c2432d03fbc09ff0684fc87b2856 Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Tue, 2 Dec 2025 10:33:23 +0100 Subject: [PATCH 14/61] Adapting tests 1 --- tests/internal/e2e/test/specs/vcast_manage.test.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/internal/e2e/test/specs/vcast_manage.test.ts b/tests/internal/e2e/test/specs/vcast_manage.test.ts index 0b462eec..45945d1f 100644 --- a/tests/internal/e2e/test/specs/vcast_manage.test.ts +++ b/tests/internal/e2e/test/specs/vcast_manage.test.ts @@ -151,6 +151,8 @@ describe("vTypeCheck VS Code Extension", () => { await browser.keys("GNU Native_Automatic_C++17"); await browser.keys(["Tab"]); await browser.keys(["Tab"]); + await browser.keys(["Tab"]); + await browser.keys(["Tab"]); await browser.keys(["Enter"]); await browser.waitUntil( From 86dace9133d4e35b3494a91e560482fc170cc99b Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Tue, 2 Dec 2025 13:44:22 +0100 Subject: [PATCH 15/61] Adapting tests 2 --- tests/internal/e2e/test/specs/vcast_manage.test.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/internal/e2e/test/specs/vcast_manage.test.ts b/tests/internal/e2e/test/specs/vcast_manage.test.ts index 45945d1f..448e8d30 100644 --- a/tests/internal/e2e/test/specs/vcast_manage.test.ts +++ b/tests/internal/e2e/test/specs/vcast_manage.test.ts @@ -159,7 +159,15 @@ describe("vTypeCheck VS Code Extension", () => { async () => (await outputView.getText()) .toString() - .includes(`Added Compiler CCAST_.CFG to Project ANewProject`), + .includes(`-lc option VCAST_CODED_TESTS_SUPPORT FALSE`), + { timeout: TIMEOUT } + ); + + await browser.waitUntil( + async () => + (await outputView.getText()) + .toString() + .includes(`Processing project: ANewProject`), { timeout: TIMEOUT } ); From 7e22a92b34e3dcaffff0074d19614dc88089449b Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Tue, 2 Dec 2025 14:18:35 +0100 Subject: [PATCH 16/61] Adapting tests 3 --- .../e2e/test/specs/vcast_manage.test.ts | 124 +++++++++--------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/tests/internal/e2e/test/specs/vcast_manage.test.ts b/tests/internal/e2e/test/specs/vcast_manage.test.ts index 448e8d30..c7803c51 100644 --- a/tests/internal/e2e/test/specs/vcast_manage.test.ts +++ b/tests/internal/e2e/test/specs/vcast_manage.test.ts @@ -505,6 +505,67 @@ describe("vTypeCheck VS Code Extension", () => { await editorView.closeEditor("VectorCAST Report", 1); }); + it("testing deleting an environment from project", async () => { + await updateTestID(); + await bottomBar.toggle(true); + const outputView = await bottomBar.openOutputView(); + await outputView.clearText(); + + const notificationsCenter = await workbench.openNotificationsCenter(); + await notificationsCenter.clearAllNotifications(); + + console.log("Deleting Environment QUACK from Project"); + await executeContextMenuAction( + 3, + "QUACK", + true, + "Delete Environment from Project" + ); + + console.log("Confirming Notifications to delete the Environment"); + const notifications = await $("aria/Notifications"); + await notifications.click(); + const vcastNotificationSourceElement = await $( + "aria/VectorCAST Test Explorer (Extension)" + ); + const vcastNotification = await vcastNotificationSourceElement.$(".."); + await (await vcastNotification.$("aria/Delete")).click(); + + console.log("Checking for Output logs if Environment deletion is finished"); + await browser.waitUntil( + async () => + (await outputView.getText()) + .toString() + .includes( + `manage: '-pTest.vcm -eQUACK --delete --force' returned exit code: 0` + ), + { timeout: TIMEOUT } + ); + await browser.waitUntil( + async () => + (await outputView.getText()) + .toString() + .includes(`Processing environment data for:`), + { timeout: TIMEOUT } + ); + + console.log("Checking if Env node QUACK is not in Tree"); + await browser.waitUntil( + async () => { + const testsuiteNode = await findTreeNodeAtLevel(3, "QUACK"); + return testsuiteNode === undefined; + }, + { + timeout: TIMEOUT, + interval: 500, + timeoutMsg: + 'Expected Env node "QUACK" to be not in the tree within timeout', + } + ); + const testsuiteNode = await findTreeNodeAtLevel(3, "QUACK"); + expect(testsuiteNode).toBeUndefined(); + }); + it("testing creating a Testsuite", async () => { await updateTestID(); await bottomBar.toggle(true); @@ -588,7 +649,7 @@ describe("vTypeCheck VS Code Extension", () => { expect(testsuiteNode).toBeUndefined(); }); - it("testing deleting a project Environment", async () => { + it("testing cleaning a project Environment", async () => { await updateTestID(); await bottomBar.toggle(true); const outputView = await bottomBar.openOutputView(); @@ -726,67 +787,6 @@ describe("vTypeCheck VS Code Extension", () => { expect(testsuiteNode).toBeUndefined(); }); - it("testing deleting an environment from project", async () => { - await updateTestID(); - await bottomBar.toggle(true); - const outputView = await bottomBar.openOutputView(); - await outputView.clearText(); - - const notificationsCenter = await workbench.openNotificationsCenter(); - await notificationsCenter.clearAllNotifications(); - - console.log("Deleting Environment QUACK from Project"); - await executeContextMenuAction( - 3, - "QUACK", - true, - "Delete Environment from Project" - ); - - console.log("Confirming Notifications to delete the Environment"); - const notifications = await $("aria/Notifications"); - await notifications.click(); - const vcastNotificationSourceElement = await $( - "aria/VectorCAST Test Explorer (Extension)" - ); - const vcastNotification = await vcastNotificationSourceElement.$(".."); - await (await vcastNotification.$("aria/Delete")).click(); - - console.log("Checking for Output logs if Environment deletion is finished"); - await browser.waitUntil( - async () => - (await outputView.getText()) - .toString() - .includes( - `manage: '-pTest.vcm -eQUACK --delete --force' returned exit code: 0` - ), - { timeout: TIMEOUT } - ); - await browser.waitUntil( - async () => - (await outputView.getText()) - .toString() - .includes(`Processing environment data for:`), - { timeout: TIMEOUT } - ); - - console.log("Checking if Env node QUACK is not in Tree"); - await browser.waitUntil( - async () => { - const testsuiteNode = await findTreeNodeAtLevel(3, "QUACK"); - return testsuiteNode === undefined; - }, - { - timeout: TIMEOUT, - interval: 500, - timeoutMsg: - 'Expected Env node "QUACK" to be not in the tree within timeout', - } - ); - const testsuiteNode = await findTreeNodeAtLevel(3, "QUACK"); - expect(testsuiteNode).toBeUndefined(); - }); - it("testing creating an Env from Source Files", async () => { await updateTestID(); await bottomBar.toggle(true); From a7d1594b307f1a85c7a880e941d6c86a009b5514 Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Tue, 2 Dec 2025 14:41:07 +0100 Subject: [PATCH 17/61] Adapting tests 4 --- .../e2e/test/specs/vcast_manage.test.ts | 123 +++++++++--------- 1 file changed, 62 insertions(+), 61 deletions(-) diff --git a/tests/internal/e2e/test/specs/vcast_manage.test.ts b/tests/internal/e2e/test/specs/vcast_manage.test.ts index c7803c51..999b8dc0 100644 --- a/tests/internal/e2e/test/specs/vcast_manage.test.ts +++ b/tests/internal/e2e/test/specs/vcast_manage.test.ts @@ -505,67 +505,6 @@ describe("vTypeCheck VS Code Extension", () => { await editorView.closeEditor("VectorCAST Report", 1); }); - it("testing deleting an environment from project", async () => { - await updateTestID(); - await bottomBar.toggle(true); - const outputView = await bottomBar.openOutputView(); - await outputView.clearText(); - - const notificationsCenter = await workbench.openNotificationsCenter(); - await notificationsCenter.clearAllNotifications(); - - console.log("Deleting Environment QUACK from Project"); - await executeContextMenuAction( - 3, - "QUACK", - true, - "Delete Environment from Project" - ); - - console.log("Confirming Notifications to delete the Environment"); - const notifications = await $("aria/Notifications"); - await notifications.click(); - const vcastNotificationSourceElement = await $( - "aria/VectorCAST Test Explorer (Extension)" - ); - const vcastNotification = await vcastNotificationSourceElement.$(".."); - await (await vcastNotification.$("aria/Delete")).click(); - - console.log("Checking for Output logs if Environment deletion is finished"); - await browser.waitUntil( - async () => - (await outputView.getText()) - .toString() - .includes( - `manage: '-pTest.vcm -eQUACK --delete --force' returned exit code: 0` - ), - { timeout: TIMEOUT } - ); - await browser.waitUntil( - async () => - (await outputView.getText()) - .toString() - .includes(`Processing environment data for:`), - { timeout: TIMEOUT } - ); - - console.log("Checking if Env node QUACK is not in Tree"); - await browser.waitUntil( - async () => { - const testsuiteNode = await findTreeNodeAtLevel(3, "QUACK"); - return testsuiteNode === undefined; - }, - { - timeout: TIMEOUT, - interval: 500, - timeoutMsg: - 'Expected Env node "QUACK" to be not in the tree within timeout', - } - ); - const testsuiteNode = await findTreeNodeAtLevel(3, "QUACK"); - expect(testsuiteNode).toBeUndefined(); - }); - it("testing creating a Testsuite", async () => { await updateTestID(); await bottomBar.toggle(true); @@ -787,6 +726,68 @@ describe("vTypeCheck VS Code Extension", () => { expect(testsuiteNode).toBeUndefined(); }); + it("testing deleting an environment from project", async () => { + await updateTestID(); + await bottomBar.toggle(true); + const outputView = await bottomBar.openOutputView(); + await outputView.clearText(); + + const notificationsCenter = await workbench.openNotificationsCenter(); + await notificationsCenter.clearAllNotifications(); + + const node: TreeItem | undefined = await findTreeNodeAtLevel(3, "QUACK"); + expect(node).toBeDefined(); + await executeContextMenuAction( + 3, + "QUACK", + true, + "Delete Environment from Project" + ); + + console.log("Confirming Notifications to delete the Environment"); + const notifications = await $("aria/Notifications"); + await notifications.click(); + const vcastNotificationSourceElement = await $( + "aria/VectorCAST Test Explorer (Extension)" + ); + const vcastNotification = await vcastNotificationSourceElement.$(".."); + await (await vcastNotification.$("aria/Delete")).click(); + + console.log("Checking for Output logs if Environment deletion is finished"); + await browser.waitUntil( + async () => + (await outputView.getText()) + .toString() + .includes( + `manage: '-pTest.vcm -eQUACK --delete --force' returned exit code: 0` + ), + { timeout: TIMEOUT } + ); + await browser.waitUntil( + async () => + (await outputView.getText()) + .toString() + .includes(`Processing environment data for:`), + { timeout: TIMEOUT } + ); + + console.log("Checking if Env node QUACK is not in Tree"); + await browser.waitUntil( + async () => { + const testsuiteNode = await findTreeNodeAtLevel(3, "QUACK"); + return testsuiteNode === undefined; + }, + { + timeout: TIMEOUT, + interval: 500, + timeoutMsg: + 'Expected Env node "QUACK" to be not in the tree within timeout', + } + ); + const testsuiteNode = await findTreeNodeAtLevel(3, "QUACK"); + expect(testsuiteNode).toBeUndefined(); + }); + it("testing creating an Env from Source Files", async () => { await updateTestID(); await bottomBar.toggle(true); From 6bb63106aea090cdac2e2d88081ba7bfc72bac56 Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Tue, 2 Dec 2025 15:06:59 +0100 Subject: [PATCH 18/61] Adapting tests 5 --- tests/internal/e2e/test/specs/vcast_manage.test.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/internal/e2e/test/specs/vcast_manage.test.ts b/tests/internal/e2e/test/specs/vcast_manage.test.ts index 999b8dc0..2e02340b 100644 --- a/tests/internal/e2e/test/specs/vcast_manage.test.ts +++ b/tests/internal/e2e/test/specs/vcast_manage.test.ts @@ -735,14 +735,16 @@ describe("vTypeCheck VS Code Extension", () => { const notificationsCenter = await workbench.openNotificationsCenter(); await notificationsCenter.clearAllNotifications(); - const node: TreeItem | undefined = await findTreeNodeAtLevel(3, "QUACK"); - expect(node).toBeDefined(); await executeContextMenuAction( 3, "QUACK", true, "Delete Environment from Project" ); + await browser.takeScreenshot(); + await browser.saveScreenshot( + "info_clicked_on_delete.png" + ); console.log("Confirming Notifications to delete the Environment"); const notifications = await $("aria/Notifications"); From 47b79b8fcf73dbfa9047b96db1ca80086129cf34 Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Tue, 2 Dec 2025 15:33:39 +0100 Subject: [PATCH 19/61] Adapting tests 6 --- .../e2e/test/specs/vcast_manage.test.ts | 34 ++++++++++++++----- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/tests/internal/e2e/test/specs/vcast_manage.test.ts b/tests/internal/e2e/test/specs/vcast_manage.test.ts index 2e02340b..3b76aa3d 100644 --- a/tests/internal/e2e/test/specs/vcast_manage.test.ts +++ b/tests/internal/e2e/test/specs/vcast_manage.test.ts @@ -4,6 +4,7 @@ import { TreeItem, type BottomBarPanel, type Workbench, + NotificationType, } from "wdio-vscode-service"; import { Key } from "webdriverio"; import { @@ -742,18 +743,33 @@ describe("vTypeCheck VS Code Extension", () => { "Delete Environment from Project" ); await browser.takeScreenshot(); - await browser.saveScreenshot( - "info_clicked_on_delete.png" - ); + await browser.saveScreenshot("info_clicked_on_delete.png"); console.log("Confirming Notifications to delete the Environment"); - const notifications = await $("aria/Notifications"); - await notifications.click(); - const vcastNotificationSourceElement = await $( - "aria/VectorCAST Test Explorer (Extension)" + const deleteNotif = await browser.waitUntil( + async () => { + const nc = await workbench.openNotificationsCenter(); + const notifs = await nc.getNotifications(NotificationType.Any); + + for (const n of notifs) { + const msg = await n.getMessage(); + const src = await n.getSource(); + if (msg.includes("Delete") || src.includes("VectorCAST")) { + return n; + } + } + return false; // keep waiting + }, + { + timeout: TIMEOUT, + interval: 300, + timeoutMsg: "Timed out waiting for delete notification", + } ); - const vcastNotification = await vcastNotificationSourceElement.$(".."); - await (await vcastNotification.$("aria/Delete")).click(); + + console.log("Found delete notification, clicking Delete..."); + await deleteNotif.expand(); + await deleteNotif.takeAction("Delete"); console.log("Checking for Output logs if Environment deletion is finished"); await browser.waitUntil( From 78f20cce1b7a6ac63a842a035614233cb4264b38 Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Tue, 2 Dec 2025 15:53:41 +0100 Subject: [PATCH 20/61] Adapting tests 7 --- .../e2e/test/specs/vcast_manage.test.ts | 40 +++++++++++-------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/tests/internal/e2e/test/specs/vcast_manage.test.ts b/tests/internal/e2e/test/specs/vcast_manage.test.ts index 3b76aa3d..7bf510aa 100644 --- a/tests/internal/e2e/test/specs/vcast_manage.test.ts +++ b/tests/internal/e2e/test/specs/vcast_manage.test.ts @@ -4,7 +4,6 @@ import { TreeItem, type BottomBarPanel, type Workbench, - NotificationType, } from "wdio-vscode-service"; import { Key } from "webdriverio"; import { @@ -746,30 +745,37 @@ describe("vTypeCheck VS Code Extension", () => { await browser.saveScreenshot("info_clicked_on_delete.png"); console.log("Confirming Notifications to delete the Environment"); - const deleteNotif = await browser.waitUntil( + const notifications = await $("aria/Notifications"); + await notifications.click(); + // Wait until the specific VectorCAST notification appears + const vcastNotificationSourceElement = await browser.waitUntil( async () => { - const nc = await workbench.openNotificationsCenter(); - const notifs = await nc.getNotifications(NotificationType.Any); - - for (const n of notifs) { - const msg = await n.getMessage(); - const src = await n.getSource(); - if (msg.includes("Delete") || src.includes("VectorCAST")) { - return n; - } - } - return false; // keep waiting + const elem = await $("aria/VectorCAST Test Explorer (Extension)"); + return (await elem.isExisting()) ? elem : false; }, { timeout: TIMEOUT, interval: 300, - timeoutMsg: "Timed out waiting for delete notification", + timeoutMsg: "Timed out waiting for VectorCAST notification to appear", + } + ); + + const vcastNotification = await vcastNotificationSourceElement.$(".."); + + // Wait until the Delete action exists, then click it + const deleteAction = await browser.waitUntil( + async () => { + const action = await vcastNotification.$("aria/Delete"); + return (await action.isExisting()) ? action : false; + }, + { + timeout: TIMEOUT, + interval: 200, + timeoutMsg: "Timed out waiting for Delete action in notification", } ); - console.log("Found delete notification, clicking Delete..."); - await deleteNotif.expand(); - await deleteNotif.takeAction("Delete"); + await deleteAction.click(); console.log("Checking for Output logs if Environment deletion is finished"); await browser.waitUntil( From 013eaad8c647ea5553548d851d59f8db2469ee7f Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Tue, 2 Dec 2025 16:15:56 +0100 Subject: [PATCH 21/61] Adapting tests 8 --- .../e2e/test/specs/vcast_manage.test.ts | 44 +++++++++---------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/tests/internal/e2e/test/specs/vcast_manage.test.ts b/tests/internal/e2e/test/specs/vcast_manage.test.ts index 7bf510aa..a621a5f7 100644 --- a/tests/internal/e2e/test/specs/vcast_manage.test.ts +++ b/tests/internal/e2e/test/specs/vcast_manage.test.ts @@ -746,34 +746,31 @@ describe("vTypeCheck VS Code Extension", () => { console.log("Confirming Notifications to delete the Environment"); const notifications = await $("aria/Notifications"); + + // Ensure the bell itself is clickable before interacting + await notifications.waitForClickable({ timeout: TIMEOUT }); await notifications.click(); - // Wait until the specific VectorCAST notification appears - const vcastNotificationSourceElement = await browser.waitUntil( - async () => { - const elem = await $("aria/VectorCAST Test Explorer (Extension)"); - return (await elem.isExisting()) ? elem : false; - }, - { - timeout: TIMEOUT, - interval: 300, - timeoutMsg: "Timed out waiting for VectorCAST notification to appear", - } + + // Wait specifically for the VectorCAST notification source to be DISPLAYED (visible), + // not just existing in the DOM. + const vcastNotificationSourceElement = await $( + "aria/VectorCAST Test Explorer (Extension)" ); + await vcastNotificationSourceElement.waitForDisplayed({ + timeout: TIMEOUT, + timeoutMsg: + "VectorCAST notification entry did not appear or become visible", + }); const vcastNotification = await vcastNotificationSourceElement.$(".."); - // Wait until the Delete action exists, then click it - const deleteAction = await browser.waitUntil( - async () => { - const action = await vcastNotification.$("aria/Delete"); - return (await action.isExisting()) ? action : false; - }, - { - timeout: TIMEOUT, - interval: 200, - timeoutMsg: "Timed out waiting for Delete action in notification", - } - ); + // Find the Delete button + const deleteAction = await vcastNotification.$("aria/Delete"); + + await deleteAction.waitForClickable({ + timeout: TIMEOUT, + timeoutMsg: "Delete button in notification was not interactable", + }); await deleteAction.click(); @@ -811,7 +808,6 @@ describe("vTypeCheck VS Code Extension", () => { const testsuiteNode = await findTreeNodeAtLevel(3, "QUACK"); expect(testsuiteNode).toBeUndefined(); }); - it("testing creating an Env from Source Files", async () => { await updateTestID(); await bottomBar.toggle(true); From 8e0e0b0868dc6f62f5a3fa315c091c244a91e3cf Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Tue, 2 Dec 2025 16:40:08 +0100 Subject: [PATCH 22/61] Adapting tests 9 --- .../e2e/test/specs/vcast_manage.test.ts | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/tests/internal/e2e/test/specs/vcast_manage.test.ts b/tests/internal/e2e/test/specs/vcast_manage.test.ts index a621a5f7..43419e21 100644 --- a/tests/internal/e2e/test/specs/vcast_manage.test.ts +++ b/tests/internal/e2e/test/specs/vcast_manage.test.ts @@ -735,6 +735,7 @@ describe("vTypeCheck VS Code Extension", () => { const notificationsCenter = await workbench.openNotificationsCenter(); await notificationsCenter.clearAllNotifications(); + // Trigger the Delete action await executeContextMenuAction( 3, "QUACK", @@ -745,28 +746,36 @@ describe("vTypeCheck VS Code Extension", () => { await browser.saveScreenshot("info_clicked_on_delete.png"); console.log("Confirming Notifications to delete the Environment"); - const notifications = await $("aria/Notifications"); - // Ensure the bell itself is clickable before interacting + // Wait for the notification to be generated (exist in DOM) + const vcastNotificationSelector = + "aria/VectorCAST Test Explorer (Extension)"; + const pendingNotification = await $(vcastNotificationSelector); + await pendingNotification.waitForExist({ + timeout: TIMEOUT, + timeoutMsg: "Timeout waiting for VectorCAST notification to be generated", + }); + + // Open the Notification Center + const notifications = await $("aria/Notifications"); await notifications.waitForClickable({ timeout: TIMEOUT }); await notifications.click(); - // Wait specifically for the VectorCAST notification source to be DISPLAYED (visible), - // not just existing in the DOM. - const vcastNotificationSourceElement = await $( - "aria/VectorCAST Test Explorer (Extension)" - ); + // Re-select the element now that the Center is open + const vcastNotificationSourceElement = await $(vcastNotificationSelector); + + // Wait for it to be VISIBLE (handles the sliding animation of the panel) await vcastNotificationSourceElement.waitForDisplayed({ timeout: TIMEOUT, timeoutMsg: - "VectorCAST notification entry did not appear or become visible", + "VectorCAST notification entry did not become visible in the center", }); + // Navigate to the Delete button const vcastNotification = await vcastNotificationSourceElement.$(".."); - - // Find the Delete button const deleteAction = await vcastNotification.$("aria/Delete"); + // Wait for the button to be Clickable (handles animation/obscuring) await deleteAction.waitForClickable({ timeout: TIMEOUT, timeoutMsg: "Delete button in notification was not interactable", @@ -808,6 +817,7 @@ describe("vTypeCheck VS Code Extension", () => { const testsuiteNode = await findTreeNodeAtLevel(3, "QUACK"); expect(testsuiteNode).toBeUndefined(); }); + it("testing creating an Env from Source Files", async () => { await updateTestID(); await bottomBar.toggle(true); From 345eea607b92a52b904bd5b69c6a41703234f8f5 Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Tue, 2 Dec 2025 16:59:53 +0100 Subject: [PATCH 23/61] Adapting tests 10 --- .../e2e/test/specs/vcast_manage.test.ts | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/tests/internal/e2e/test/specs/vcast_manage.test.ts b/tests/internal/e2e/test/specs/vcast_manage.test.ts index 43419e21..330feb02 100644 --- a/tests/internal/e2e/test/specs/vcast_manage.test.ts +++ b/tests/internal/e2e/test/specs/vcast_manage.test.ts @@ -756,23 +756,8 @@ describe("vTypeCheck VS Code Extension", () => { timeoutMsg: "Timeout waiting for VectorCAST notification to be generated", }); - // Open the Notification Center - const notifications = await $("aria/Notifications"); - await notifications.waitForClickable({ timeout: TIMEOUT }); - await notifications.click(); - - // Re-select the element now that the Center is open - const vcastNotificationSourceElement = await $(vcastNotificationSelector); - - // Wait for it to be VISIBLE (handles the sliding animation of the panel) - await vcastNotificationSourceElement.waitForDisplayed({ - timeout: TIMEOUT, - timeoutMsg: - "VectorCAST notification entry did not become visible in the center", - }); - // Navigate to the Delete button - const vcastNotification = await vcastNotificationSourceElement.$(".."); + const vcastNotification = await $(vcastNotificationSelector).$(".."); const deleteAction = await vcastNotification.$("aria/Delete"); // Wait for the button to be Clickable (handles animation/obscuring) From bd592613c9797b17e272467258861eb9a076604c Mon Sep 17 00:00:00 2001 From: Denis Moslavac Date: Thu, 11 Dec 2025 16:21:55 +0100 Subject: [PATCH 24/61] Sonar --- src/manage/webviews/html/newCFG.html | 27 ++++++++++--------- src/manage/webviews/html/newProject.html | 20 +++++++------- src/manage/webviews/webviewScripts/newCFG.js | 14 +++++----- .../webviews/webviewScripts/newProject.js | 12 ++++----- 4 files changed, 37 insertions(+), 36 deletions(-) diff --git a/src/manage/webviews/html/newCFG.html b/src/manage/webviews/html/newCFG.html index 2ee6f6db..67d63cf7 100644 --- a/src/manage/webviews/html/newCFG.html +++ b/src/manage/webviews/html/newCFG.html @@ -18,39 +18,40 @@

      Create New CFG File

      Additional Options:

      +
      - Enable Coded Tests -
      +
      -
      - Set as Default Configuration File -
      - -
      diff --git a/src/manage/webviews/html/newProject.html b/src/manage/webviews/html/newProject.html index 13305a81..60097c1b 100644 --- a/src/manage/webviews/html/newProject.html +++ b/src/manage/webviews/html/newProject.html @@ -30,11 +30,11 @@

      Compiler Selection