in src/cmake-tools.ts [572:701]
public async cmakePreConditionProblemHandler(e: CMakePreconditionProblems, isConfiguring: boolean, config?: ConfigurationReader): Promise<void> {
let telemetryEvent: string | undefined;
const telemetryProperties: telemetry.Properties = {};
switch (e) {
case CMakePreconditionProblems.ConfigureIsAlreadyRunning:
void vscode.window.showErrorMessage(localize('configuration.already.in.progress', 'Configuration is already in progress.'));
break;
case CMakePreconditionProblems.BuildIsAlreadyRunning:
void vscode.window.showErrorMessage(localize('task.already.running', 'A CMake task is already running. Stop it before trying to run a new CMake task.'));
break;
case CMakePreconditionProblems.NoSourceDirectoryFound:
void vscode.window.showErrorMessage(localize('no.source.directory.found', 'You do not have a source directory open'));
break;
case CMakePreconditionProblems.MissingCMakeListsFile:
telemetryEvent = "partialActivation";
telemetryProperties["ignoreCMakeListsMissing"] = this.workspaceContext.state.ignoreCMakeListsMissing.toString();
if (!this.workspaceContext.state.ignoreCMakeListsMissing) {
const quickStart = localize('quickstart.cmake.project', "Create");
const changeSourceDirectory = localize('edit.setting', "Locate");
const ignoreCMakeListsMissing = localize('ignore.activation', "Don't show again");
let showCMakeLists: boolean = await expShowCMakeLists();
const existingCmakeListsFiles: string[] | undefined = await util.getAllCMakeListsPaths(this.folder.uri);
if (showCMakeLists) {
showCMakeLists = existingCmakeListsFiles !== undefined && existingCmakeListsFiles.length > 0;
telemetryProperties["ignoreExperiment"] = (!showCMakeLists).toString();
}
telemetryProperties["missingCMakeListsPopupType"] = showCMakeLists ? "selectFromAllCMakeLists" : "toastCreateLocateIgnore";
const result = showCMakeLists ? changeSourceDirectory : await vscode.window.showErrorMessage(
localize('missing.cmakelists', 'CMakeLists.txt was not found in the root of the folder {0}. How would you like to proceed?', `"${this.folderName}"`),
quickStart, changeSourceDirectory, ignoreCMakeListsMissing);
if (result === quickStart) {
// Return here, since the updateFolderFullFeature set below (after the "switch")
// will set unnecessarily a partial feature set view for this folder
// if quickStart doesn't finish early enough.
// quickStart will update correctly the full/partial view state at the end.
telemetryProperties["missingCMakeListsUserAction"] = "quickStart";
telemetry.logEvent(telemetryEvent, telemetryProperties);
return vscode.commands.executeCommand('cmake.quickStart');
} else if (result === changeSourceDirectory) {
// Open the search file dialog from the path set by cmake.sourceDirectory or from the current workspace folder
// if the setting is not defined.
interface FileItem extends vscode.QuickPickItem {
fullPath: string;
}
const items: FileItem[] = existingCmakeListsFiles ? existingCmakeListsFiles.map<FileItem>(file => ({
label: util.getRelativePath(file, this.folder.uri.fsPath) + "/CMakeLists.txt",
fullPath: file
})) : [];
const browse: string = localize("browse.for.cmakelists", "[Browse for CMakeLists.txt]");
items.push({ label: browse, fullPath: "", description: "Search for CMakeLists.txt on this computer" });
const selection: FileItem | undefined = await vscode.window.showQuickPick(items, {
placeHolder: (items.length === 1 ? localize("cmakelists.not.found", "No CMakeLists.txt was found.") : localize("select.cmakelists", "Select CMakeLists.txt"))
});
if (showCMakeLists) {
telemetryProperties["missingCMakeListsUserAction"] = (selection === undefined) ? "dismissed" : (selection.label === browse) ? "browse" : "pick";
} else {
telemetryProperties["missingCMakeListsUserAction"] = "changeSourceDirectory";
}
let selectedFile: string | undefined;
if (!selection) {
break; // User canceled it.
} else if (selection.label === browse) {
const openOpts: vscode.OpenDialogOptions = {
canSelectMany: false,
defaultUri: vscode.Uri.file(this.folder.uri.fsPath),
filters: { "CMake files": ["txt"], "All files": ["*"] },
openLabel: "Load"
};
const cmakeListsFile = await vscode.window.showOpenDialog(openOpts);
if (cmakeListsFile) {
selectedFile = cmakeListsFile[0].fsPath;
}
} else {
selectedFile = selection.fullPath;
}
if (selectedFile) {
const relPath = util.getRelativePath(selectedFile, this.folder.uri.fsPath);
void vscode.workspace.getConfiguration('cmake', this.folder.uri).update("sourceDirectory", relPath);
if (config) {
// Updating sourceDirectory here, at the beginning of the configure process,
// doesn't need to fire the settings change event (which would trigger unnecessarily
// another immediate configure, which will be blocked anyway).
config.updatePartial({ sourceDirectory: relPath }, false);
// Since the source directory is set via a file open dialog tuned to CMakeLists.txt,
// we know that it exists and we don't need any other additional checks on its value,
// so simply enable full feature set.
await enableFullFeatureSet(true);
if (!isConfiguring) {
telemetry.logEvent(telemetryEvent, telemetryProperties);
return vscode.commands.executeCommand('cmake.configure');
}
}
}
} else if (result === ignoreCMakeListsMissing) {
// The user ignores the missing CMakeLists.txt file --> limit the CMake Tools extension functionality
// (hide commands and status bar) and record this choice so that this popup doesn't trigger next time.
// The switch back to full functionality can be done later by changes to the cmake.sourceDirectory setting
// or to the CMakeLists.txt file, a successful configure or a configure failing with anything but CMakePreconditionProblems.MissingCMakeListsFile.
// After that switch (back to a full activation), another occurrence of missing CMakeLists.txt
// would trigger this popup again.
telemetryProperties["missingCMakeListsUserAction"] = "ignore";
await this.workspaceContext.state.setIgnoreCMakeListsMissing(true);
} else {
// "invalid" normally shouldn't happen since the popup can be closed by either dismissing it or clicking any of the three buttons.
telemetryProperties["missingCMakeListsUserAction"] = (result === undefined) ? "dismissed" : "invalid";
}
}
break;
}
if (telemetryEvent) {
telemetry.logEvent(telemetryEvent, telemetryProperties);
}
// This CMT folder can go through various changes while executing this function
// that could be relevant to the partial/full feature set view.
// This is a good place for an update.
return updateFullFeatureSetForFolder(this.folder);
}