Skip to content

Commit

Permalink
Set usepresets context after manually creating presets file (#3935)
Browse files Browse the repository at this point in the history
Fixes #3854. Support for watching multiple paths (cmakepresets.json/cmakeuserpresets.json/include files) was broken due to a Chokidar bug. Created a wrapper class to handle this scenario.
  • Loading branch information
qarni authored Aug 1, 2024
1 parent ca04165 commit e7cf93e
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 16 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Bug Fixes:
- Fix our keybindings for debug and run without debugging to better match VS Code. [#3507](https://github.com/microsoft/vscode-cmake-tools/issues/3507)
- Allow success recovery in the configure precondition handler. [#3554](https://github.com/microsoft/vscode-cmake-tools/issues/3554)
- Prevent second configure after `QuickStart` if the `automaticReconfigure` setting is enabled. [#3910](https://github.com/microsoft/vscode-cmake-tools/issues/3910)
- Set usepresets context after manually creating a CMakePresets.json/CMakeUserPresets.json or using QuickStart to create it. [#3854](https://github.com/microsoft/vscode-cmake-tools/issues/3854)

## 1.18.43

Expand Down
4 changes: 1 addition & 3 deletions src/cmakeProject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ export class CMakeProject {
private onDidOpenTextDocumentListener: vscode.Disposable | undefined;
private disposables: vscode.Disposable[] = [];
private readonly onUseCMakePresetsChangedEmitter = new vscode.EventEmitter<boolean>();
private projectController: ProjectController | undefined;
public projectController: ProjectController | undefined;
public readonly cTestController: CTestDriver;
public readonly cPackageController: CPackDriver;
public readonly workflowController: WorkflowDriver;
Expand Down Expand Up @@ -2921,8 +2921,6 @@ export class CMakeProject {
}
}

await this.projectController?.updateActiveProject(this.workspaceFolder);

// Regardless of the following configure return code,
// we want full feature set view for the whole workspace.
await enableFullFeatureSet(true);
Expand Down
68 changes: 55 additions & 13 deletions src/presetsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ const log = logging.createLogger('presetController');

type SetPresetsFileFunc = (folder: string, presets: preset.PresetsFile | undefined) => void;

export class PresetsController {
private _presetsWatcher: chokidar.FSWatcher | undefined;
export class PresetsController implements vscode.Disposable {
private _presetsWatchers: FileWatcher | undefined;
private _sourceDir: string = '';
private _sourceDirChangedSub: vscode.Disposable | undefined;
private _presetsFileExists = false;
Expand Down Expand Up @@ -1943,26 +1943,68 @@ export class PresetsController {
return vscode.window.showTextDocument(vscode.Uri.file(presetsFilePath));
}

// this is used for the file watcher on adding a new presets file
async onCreatePresetsFile() {
await this.reapplyPresets();
await this.project.projectController?.updateActiveProject(this.workspaceFolder);
}

private async watchPresetsChange() {
if (this._presetsWatcher) {
this._presetsWatcher.close().then(() => {}, () => {});
}

const handler = () => {
const presetChangeHandler = () => {
void this.reapplyPresets();
};
this._presetsWatcher = chokidar.watch(this._referencedFiles, { ignoreInitial: true })
.on('add', handler)
.on('change', handler)
.on('unlink', handler);
const presetCreatedHandler = () => {
void this.onCreatePresetsFile();
};

const events: Map<string, () => void> = new Map<string, () => void>([
["change", presetChangeHandler],
["unlink", presetChangeHandler],
["add", presetCreatedHandler]
]);

this._presetsWatchers?.dispose();
this._presetsWatchers = new FileWatcher(this._referencedFiles, events, { ignoreInitial: true });
};

dispose() {
if (this._presetsWatcher) {
this._presetsWatcher.close().then(() => {}, () => {});
}
this._presetsWatchers?.dispose();

if (this._sourceDirChangedSub) {
this._sourceDirChangedSub.dispose();
}
}
}

/**
* FileWatcher is a wrapper around chokidar's FSWatcher that allows for watching multiple paths.
* Chokidar's support for watching multiple paths is currently broken, if it is fixed in the future, this class can be removed.
*/
class FileWatcher implements vscode.Disposable {
private watchers: Map<string, chokidar.FSWatcher>;

public constructor(paths: string | string[], eventHandlers: Map<string, () => void>, options?: chokidar.WatchOptions) {
this.watchers = new Map<string, chokidar.FSWatcher>();

for (const path of Array.isArray(paths) ? paths : [paths]) {
try {
const watcher = chokidar.watch(path, { ...options });
const eventHandlerEntries = Array.from(eventHandlers);
for (let i = 0; i < eventHandlerEntries.length; i++) {
const [event, handler] = eventHandlerEntries[i];
watcher.on(event, handler);
}
this.watchers.set(path, watcher);
} catch (error) {
log.error(localize('failed.to.watch', 'Watcher could not be created for {0}: {1}', path, util.errorToString(error)));
}
}
}

public dispose() {
for (const watcher of this.watchers.values()) {
watcher.close().then(() => {}, () => {});
}
}
}

0 comments on commit e7cf93e

Please sign in to comment.