diff --git a/src/cmakeProject.ts b/src/cmakeProject.ts index 6e66b9b35..2b9cb9d5d 100644 --- a/src/cmakeProject.ts +++ b/src/cmakeProject.ts @@ -119,6 +119,10 @@ export interface DiagnosticsSettings { configureOnOpen: boolean | null; } +export interface ConfigureCancelInformation { + canceled: boolean; +} + /** * Class implementing the extension. It's all here! * @@ -1585,7 +1589,12 @@ export class CMakeProject { }, async (progress, cancel) => { progress.report({ message: localize('preparing.to.configure', 'Preparing to configure') }); + const cancelInformation: ConfigureCancelInformation = { + canceled: false + }; cancel.onCancellationRequested(() => { + // We need to update the canceled information by reference before starting the cancel to ensure it's updated before the process is cancelled. + cancelInformation.canceled = true; rollbar.invokeAsync(localize('stop.on.cancellation', 'Stop on cancellation'), () => this.cancelConfiguration()); }); @@ -1594,6 +1603,8 @@ export class CMakeProject { // if there is a debugger information, we are debugging. Set up a listener for stopping a cmake debug session. if (debuggerInformation) { const trackerFactoryDisposable = vscode.debug.registerDebugAdapterTrackerFactory("cmake", new DebugTrackerFactory(async () => { + // We need to update the canceled information by reference before starting the cancel to ensure it's updated before the process is cancelled. + cancelInformation.canceled = true; forciblyCanceled = true; await this.cancelConfiguration(); trackerFactoryDisposable.dispose(); @@ -1622,23 +1633,23 @@ export class CMakeProject { let result: ConfigureResult; await setContextAndStore(isConfiguringKey, true); if (type === ConfigureType.Cache) { - result = await drv.configure(trigger, [], consumer, debuggerInformation); + result = await drv.configure(trigger, [], consumer, cancelInformation, debuggerInformation); } else { switch (type) { case ConfigureType.Normal: - result = await drv.configure(trigger, extraArgs, consumer); + result = await drv.configure(trigger, extraArgs, consumer, cancelInformation); break; case ConfigureType.NormalWithDebugger: - result = await drv.configure(trigger, extraArgs, consumer, debuggerInformation); + result = await drv.configure(trigger, extraArgs, consumer, cancelInformation, debuggerInformation); break; case ConfigureType.Clean: - result = await drv.cleanConfigure(trigger, extraArgs, consumer); + result = await drv.cleanConfigure(trigger, extraArgs, consumer, cancelInformation); break; case ConfigureType.CleanWithDebugger: - result = await drv.cleanConfigure(trigger, extraArgs, consumer, debuggerInformation); + result = await drv.cleanConfigure(trigger, extraArgs, consumer, cancelInformation, debuggerInformation); break; case ConfigureType.ShowCommandOnly: - result = await drv.configure(trigger, extraArgs, consumer, undefined, false, true); + result = await drv.configure(trigger, extraArgs, consumer, cancelInformation, undefined, false, true); break; default: rollbar.error(localize('unexpected.configure.type', 'Unexpected configure type'), { type }); @@ -1654,7 +1665,7 @@ export class CMakeProject { if (result.result === 0) { await enableFullFeatureSet(true); await this.refreshCompileDatabase(drv.expansionOptions); - } else if (result.result !== 0 && (await this.getCMakeExecutable()).isDebuggerSupported && cmakeConfiguration.get(showDebuggerConfigurationString) && !forciblyCanceled && result.resultType === ConfigureResultType.NormalOperation) { + } else if (result.result !== 0 && (await this.getCMakeExecutable()).isDebuggerSupported && cmakeConfiguration.get(showDebuggerConfigurationString) && !forciblyCanceled && !cancelInformation.canceled && result.resultType === ConfigureResultType.NormalOperation) { log.showChannel(true); const yesButtonTitle: string = localize( "yes.configureWithDebugger.button", diff --git a/src/cmakeTaskProvider.ts b/src/cmakeTaskProvider.ts index 8148940c3..2a26b77b0 100644 --- a/src/cmakeTaskProvider.ts +++ b/src/cmakeTaskProvider.ts @@ -441,7 +441,7 @@ export class CustomBuildTaskTerminal implements vscode.Pseudoterminal, proc.Outp this.preset = await this.resolvePresetName(this.preset, project.useCMakePresets, CommandType.config); const configPreset: preset.ConfigurePreset | undefined = await project?.expandConfigPresetbyName(this.preset); - const result = await cmakeDriver.configure(ConfigureTrigger.taskProvider, [], this, undefined, false, false, configPreset, this.options); + const result = await cmakeDriver.configure(ConfigureTrigger.taskProvider, [], this, undefined, undefined, false, false, configPreset, this.options); if (result === undefined || result === null) { this.writeEmitter.fire(localize('configure.terminated', 'Configure was terminated') + endOfLine); this.closeEmitter.fire(-1); diff --git a/src/drivers/cmakeDriver.ts b/src/drivers/cmakeDriver.ts index 094ecbddb..ffe52cbf6 100644 --- a/src/drivers/cmakeDriver.ts +++ b/src/drivers/cmakeDriver.ts @@ -8,7 +8,7 @@ import * as lodash from "lodash"; import { CMakeExecutable } from '@cmt/cmake/cmakeExecutable'; import * as codepages from '@cmt/codePageTable'; -import { ConfigureTrigger, DiagnosticsConfiguration } from "@cmt/cmakeProject"; +import { ConfigureCancelInformation, ConfigureTrigger, DiagnosticsConfiguration } from "@cmt/cmakeProject"; import { CompileCommand } from '@cmt/compilationDatabase'; import { ConfigurationReader, checkBuildOverridesPresent, checkConfigureOverridesPresent, checkTestOverridesPresent, checkPackageOverridesPresent, defaultNumJobs } from '@cmt/config'; import { CMakeBuildConsumer, CompileOutputConsumer } from '@cmt/diagnostics/build'; @@ -1039,7 +1039,7 @@ export abstract class CMakeDriver implements vscode.Disposable { * Perform a clean configure. Deletes cached files before running the config * @param consumer The output consumer */ - public async cleanConfigure(trigger: ConfigureTrigger, extra_args: string[], consumer?: proc.OutputConsumer, debuggerInformation?: DebuggerInformation): Promise { + public async cleanConfigure(trigger: ConfigureTrigger, extra_args: string[], consumer?: proc.OutputConsumer, cancelInformation?: ConfigureCancelInformation, debuggerInformation?: DebuggerInformation): Promise { if (this.isConfigInProgress) { await this.preconditionHandler(CMakePreconditionProblems.ConfigureIsAlreadyRunning); return { result: -1, resultType: ConfigureResultType.ForcedCancel }; @@ -1052,7 +1052,7 @@ export abstract class CMakeDriver implements vscode.Disposable { await this.doPreCleanConfigure(); this.isConfigInProgress = false; - return this.configure(trigger, extra_args, consumer, debuggerInformation); + return this.configure(trigger, extra_args, consumer, cancelInformation, debuggerInformation); } async testCompilerVersion(program: string, cwd: string, arg: string | undefined, regexp: RegExp, captureGroup: number): Promise { @@ -1426,7 +1426,9 @@ export abstract class CMakeDriver implements vscode.Disposable { return Promise.all(expanded_flags_promises); } - async configure(trigger: ConfigureTrigger, extra_args: string[], consumer?: proc.OutputConsumer, debuggerInformation?: DebuggerInformation, withoutCmakeSettings: boolean = false, showCommandOnly?: boolean, presetOverride?: preset.ConfigurePreset, options?: proc.ExecutionOptions): Promise { + // The `cancelInformation` parameter is an object that allows for passing the `cancelled` field to be modified by reference. This allows us to better understand if a user + // manually cancelled the configure process. + async configure(trigger: ConfigureTrigger, extra_args: string[], consumer?: proc.OutputConsumer, cancelInformation?: ConfigureCancelInformation, debuggerInformation?: DebuggerInformation, withoutCmakeSettings: boolean = false, showCommandOnly?: boolean, presetOverride?: preset.ConfigurePreset, options?: proc.ExecutionOptions): Promise { // Check if the configuration is using cache in the first configuration and adjust the logging messages based on that. const shouldUseCachedConfiguration: boolean = this.shouldUseCachedConfiguration(trigger); @@ -1619,6 +1621,7 @@ export abstract class CMakeDriver implements vscode.Disposable { } } + telemetryProperties.Canceled = cancelInformation?.canceled ? "true" : "false"; telemetry.logEvent('configure', telemetryProperties, telemetryMeasures); return { result: retc, resultType: ConfigureResultType.NormalOperation };