Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ Improvements:
- Make it easier for a new developer of CMake Tools to run tests. [#4620](https://github.com/microsoft/vscode-cmake-tools/pull/4620) [@cwalther](https://github.com/cwalther)

Bug Fixes:
- Fix cache edits from "Edit Cache (UI)" being overwritten in presets mode when the edited variable is defined by the active configure preset. The extension now writes an override into CMakeUserPresets.json and reconfigures with that user preset so the change persists.
- Fix stale C/C++ custom-configuration entries persisting after reconfigure/preset switches, which could cause Go to Definition/IntelliSense to surface symbols from inactive sources in the same folder. [#4472](https://github.com/microsoft/vscode-cmake-tools/issues/4472)
- Fix IntelliSense not updating when switching the active project in multi-project workspaces with multiple `cmake.sourceDirectory` entries. [#4390](https://github.com/microsoft/vscode-cmake-tools/issues/4390)
- Fix `tasks.json` schema validation rejecting valid CMake task commands `package` and `workflow`. [#4167](https://github.com/microsoft/vscode-cmake-tools/issues/4167)
Expand Down
6 changes: 5 additions & 1 deletion src/presets/presetsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1723,7 +1723,7 @@ export class PresetsController implements vscode.Disposable {
return { insertSpaces, tabSize };
}

async updatePresetsFile(presetsFile: preset.PresetsFile, isUserPresets = false): Promise<vscode.TextEditor | undefined> {
async updatePresetsFile(presetsFile: preset.PresetsFile, isUserPresets = false, showInEditor = true): Promise<vscode.TextEditor | undefined> {
const presetsFilePath = isUserPresets ? this.userPresetsPath : this.presetsPath;
const indent = this.getIndentationSettings();
try {
Expand All @@ -1733,6 +1733,10 @@ export class PresetsController implements vscode.Disposable {
return;
}

if (!showInEditor) {
return undefined;
}

return vscode.window.showTextDocument(vscode.Uri.file(presetsFilePath));
}

Expand Down
60 changes: 50 additions & 10 deletions src/ui/cacheView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFo
const localize: nls.LocalizeFunc = nls.loadMessageBundle();

export interface IOption {
key: string; // same as CMake cache variable key names
type: string; // "Bool" for boolean and "String" for anything else for now
key: string; // same as CMake cache variable key names
type: string; // "Bool" for boolean and "String" for anything else for now
helpString: string;
choices: string[];
value: string; // value from the cache file or changed in the UI
value: string | boolean; // value from the cache file or changed in the UI
dirty: boolean; // if the variable was edited in the UI
presetSource?: string; // where this variable is defined in presets
differsFromPresetValue?: boolean; // true if cache value differs from preset value
}

/**
Expand Down Expand Up @@ -50,7 +52,11 @@ export class ConfigurationWebview {

private options: IOption[] = [];

constructor(protected cachePath: string, protected save: () => void) {
constructor(
protected cachePath: string,
protected save: (dirtyOptions: IOption[]) => Promise<void>,
protected getPresetOptionMetadata?: (options: IOption[]) => Promise<Map<string, { presetSource: string; differsFromPresetValue?: boolean }>>
) {
this.panel = vscode.window.createWebviewPanel(
'cmakeConfiguration', // Identifies the type of the webview. Used internally
this.cmakeCacheEditorText, // Title of the panel displayed to the user
Expand All @@ -66,11 +72,17 @@ export class ConfigurationWebview {
async persistCacheEntries() {
if (this.isDirty) {
telemetry.logEvent("editCMakeCache", { command: "saveCMakeCacheUI" });
await this.saveCmakeCache(this.options);
const dirtyOptions = this.options.filter(option => option.dirty);
await this.saveCmakeCache(dirtyOptions);
void vscode.window.showInformationMessage(localize('cmake.cache.saved', 'CMake options have been saved.'));
// start configure
this.save();
// Start configure after persisting the edited values.
await this.save(dirtyOptions);
this.isDirty = false;
// Force a post-configure refresh so the editor reflects cache changes immediately.
this.options = await this.getConfigurationOptions();
if (this.panel.visible) {
await this.renderWebview(this.panel, false);
}
}
}

Expand Down Expand Up @@ -207,7 +219,11 @@ export class ConfigurationWebview {

async saveCmakeCache(options: IOption[]) {
const cmakeCache = await CMakeCache.fromPath(this.cachePath);
await cmakeCache.saveAll(options);
const serializedOptions = options.map(option => ({
key: option.key,
value: util.isBoolean(option.value) ? (option.value ? 'TRUE' : 'FALSE') : option.value
}));
await cmakeCache.saveAll(serializedOptions);
}

/**
Expand All @@ -225,6 +241,18 @@ export class ConfigurationWebview {
options.push({ key: entry.key, helpString: entry.helpString, choices: entry.choices, type: (entry.type === CacheEntryType.Bool) ? "Bool" : "String", value: entry.value, dirty: false });
}
}

if (this.getPresetOptionMetadata) {
const metadataByKey = await this.getPresetOptionMetadata(options);
for (const option of options) {
const metadata = metadataByKey.get(option.key);
if (metadata) {
option.presetSource = metadata.presetSource;
option.differsFromPresetValue = metadata.differsFromPresetValue;
}
}
}

return options;
}

Expand Down Expand Up @@ -254,6 +282,10 @@ export class ConfigurationWebview {
const saveButtonText = localize("save", "Save");
const keyColumnText = localize("key", "Key");
const valueColumnText = localize("value", "Value");
const sourceColumnText = localize("source", "Source");
const notSetInPresetsText = localize("not.set.in.presets", "Cmake Cache");
const differsFromPresetText = localize("differs.from.preset", "Changed in cache");
const matchesPresetText = localize("matches.preset", "Matches preset");

let html = `
<!DOCTYPE html>
Expand Down Expand Up @@ -484,6 +516,7 @@ export class ConfigurationWebview {
<th style="width: 30px"></th>
<th style="width: 1px; white-space: nowrap;">${keyColumnText}</th>
<th>${valueColumnText}</th>
<th style="width: 1px; white-space: nowrap;">${sourceColumnText}</th>
</tr>
${key}
</table>
Expand All @@ -506,9 +539,10 @@ export class ConfigurationWebview {

const id = escapeAttribute(option.key);
let editControls = '';
const stringValue = util.isBoolean(option.value) ? (option.value ? 'TRUE' : 'FALSE') : String(option.value);

if (option.type === "Bool") {
editControls = `<input class="cmake-input-bool" id="${id}" type="checkbox" ${util.isTruthy(option.value) ? 'checked' : ''}>
editControls = `<input class="cmake-input-bool" id="${id}" type="checkbox" ${util.isTruthy(stringValue) ? 'checked' : ''}>
<label id="LABEL_${id}" for="${id}"/>`;
} else {
const hasChoices = option.choices.length > 0;
Expand All @@ -517,14 +551,20 @@ export class ConfigurationWebview {
${option.choices.map(ch => `<option value="${escapeAttribute(ch)}">`).join()}
</datalist>`;
}
editControls += `<input class="cmake-input-text" id="${id}" value="${escapeAttribute(option.value)}" style="width: 90%;"
editControls += `<input class="cmake-input-text" id="${id}" value="${escapeAttribute(stringValue)}" style="width: 90%;"
type="text" ${hasChoices ? `list="CHOICES_${id}"` : ''}>`;
}

let sourceText = option.presetSource || notSetInPresetsText;
if (option.presetSource && option.differsFromPresetValue !== undefined) {
sourceText = `${sourceText} | ${option.differsFromPresetValue ? differsFromPresetText : matchesPresetText}`;
}

return `<tr class="content-tr">
<td></td>
<td title="${escapeAttribute(option.helpString)}">${escapeHtml(option.key)}</td>
<td>${editControls}</td>
<td>${escapeHtml(sourceText)}</td>
</tr>`;
});

Expand Down