From dda1122df218aaf97e7b569af183f3853a31faf0 Mon Sep 17 00:00:00 2001 From: Andreea Isac Date: Fri, 17 Jul 2020 05:29:34 -0700 Subject: [PATCH] Configure support and edits. --- package.json | 23 ++++++++++ src/configuration.ts | 102 ++++++++++++++++++++++++++++++++++++------- src/extension.ts | 14 +++++- src/make.ts | 4 ++ 4 files changed, 125 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index e221af1..d507cea 100644 --- a/package.json +++ b/package.json @@ -46,6 +46,7 @@ "onCommand:makefile.setLaunchConfiguration", "onCommand:makefile.launchDebug", "onCommand:makefile.launchRun", + "onCommand:makefile.configure", "workspaceContains:makefile", "workspaceContains:Makefile" ], @@ -75,6 +76,10 @@ { "command": "makefile.setLaunchConfiguration", "title": "Makefile: Set the make launch configuration" + }, + { + "command": "makefile.configure", + "title": "Makefile: Configure" } ], "configuration": { @@ -257,6 +262,24 @@ "type": "string" }, "scope": "resource" + }, + "makefile.configureOnOpen": { + "type": "boolean", + "default": true, + "description": "Automatically configure Makefile project directories when they are opened", + "scope": "resource" + }, + "makefile.configureOnEdit": { + "type": "boolean", + "default": true, + "description": "Automatically configure Makefile project directories when any relevant makefiles and/or settings are changed", + "scope": "resource" + }, + "makefile.configureAfterCommand": { + "type": "boolean", + "default": true, + "description": "Automatically configure Makefile project directories after relevant operations, like change build configuration or makefile target", + "scope": "resource" } } } diff --git a/src/configuration.ts b/src/configuration.ts index 73ef856..d2c9f23 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -478,11 +478,38 @@ export function stopListeningToSettingsChanged(): void { ignoreSettingsChanged = true; } +let configureOnOpen: boolean; +export function getConfigureOnOpen(): boolean { return configureOnOpen; } +export function setConfigureOnOpen(configure: boolean): void { configureOnOpen = configure; } +export function readConfigureOnOpen(): void { + let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); + // how to get default from package.json to avoid problem with 'undefined' type? + configureOnOpen = workspaceConfiguration.get("configureOnOpen", true); +} + +let configureOnEdit: boolean; +export function getConfigureOnEdit(): boolean { return configureOnEdit; } +export function setConfigureOnEdit(configure: boolean): void { configureOnEdit = configure; } +export function readConfigureOnEdit(): void { + let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); + // how to get default from package.json to avoid problem with 'undefined' type? + configureOnEdit = workspaceConfiguration.get("configureOnEdit", true); +} + +let configureAfterCommand: boolean; +export function getConfigureAfterCommand(): boolean { return configureAfterCommand; } +export function setConfigureAfterCommand(configure: boolean): void { configureAfterCommand = configure; } +export function readConfigureAfterCommand(): void { + let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); + // how to get default from package.json to avoid problem with 'undefined' type? + configureAfterCommand = workspaceConfiguration.get("configureAfterCommand", true); +} + // Triggers IntelliSense config provider updates after relevant changes // are made in settings or in the makefiles. // To avoid unnecessary dry-runs, these updates are not performed with every document save // but after leaving the focus of the document. -let configProviderDirty: boolean = false; +let updateConfigProviderAfterEdit: boolean = false; // Initialization from settings (or backup default rules), done at activation time export function initFromStateAndSettings(): void { @@ -497,17 +524,30 @@ export function initFromStateAndSettings(): void { readCurrentTarget(); readCurrentLaunchConfiguration(); readDebugConfig(); + readConfigureOnOpen(); + readConfigureOnEdit(); + readConfigureAfterCommand(); // Verify the dirty state of the IntelliSense config provider and update accordingly. // The makefile.configureOnEdit setting can be set to false when this behavior is inconvenient. vscode.window.onDidChangeActiveTextEditor(e => { - if (configProviderDirty) { - logger.message("Updating the Intellisense config provider..."); - getCommandForConfiguration(currentMakefileConfiguration); - getBuildLogForConfiguration(currentMakefileConfiguration); - make.parseBuildOrDryRun(); + if (updateConfigProviderAfterEdit) { + if (configureOnEdit) { + logger.message("Updating the Intellisense config provider..."); + getCommandForConfiguration(currentMakefileConfiguration); + getBuildLogForConfiguration(currentMakefileConfiguration); + make.parseBuildOrDryRun(); + } else { + logger.message("makefile.configureOnEdit is set to false. " + + "The project will not configure automatically after edits on any of the makefiles or after settings changes."); + logger.message("In order to have an up to date IntelliSense after these edits, it is recommended that you run the command makefile.configure at your earliest convenience."); + } - configProviderDirty = false; + // updateConfigProviderAfterEdit needs to be set to false regardless of whether an update to the config provider + // has been triggered (when makefile.configureOnEdit would be true) because it causes the message to be displayed + // on each text editor focus change (until an eventual configure would set it to true). + // For now, this variable is not the usual 'dirty' state boolean. + updateConfigProviderAfterEdit = false; } }); @@ -519,7 +559,7 @@ export function initFromStateAndSettings(): void { // TODO: don't trigger an update for any dummy save, verify how the content changed. vscode.workspace.onDidSaveTextDocument(e => { if (e.uri.fsPath.toLowerCase().endsWith("makefile")) { - configProviderDirty = true; + updateConfigProviderAfterEdit = true; } }); @@ -550,7 +590,7 @@ export function initFromStateAndSettings(): void { let updatedBuildLog : string | undefined = workspaceConfiguration.get("buildLog", "./build.log"); if (util.resolvePathToRoot(updatedBuildLog) !== buildLog) { - configProviderDirty = true; + updateConfigProviderAfterEdit = true; logger.message("makefile.buildLog setting changed."); readBuildLog(); } @@ -564,7 +604,7 @@ export function initFromStateAndSettings(): void { let updatedDryrunCache : string | undefined = workspaceConfiguration.get("dryrunCache", "./dryrunCache.log"); if (util.resolvePathToRoot(updatedDryrunCache) !== dryrunCache) { - configProviderDirty = true; + updateConfigProviderAfterEdit = true; logger.message("makefile.dryrunCache setting changed."); readDryrunCache(); } @@ -575,14 +615,14 @@ export function initFromStateAndSettings(): void { // may produce a different dry-run output with potential impact on IntelliSense, // so trigger an update. logger.message("makefile.makePath setting changed."); - configProviderDirty = true; + updateConfigProviderAfterEdit = true; readMakePath(); } let updatedMakefilePath : string | undefined = workspaceConfiguration.get("makefilePath"); if (updatedMakefilePath !== makefilePath) { logger.message("makefile.makefilePath setting changed."); - configProviderDirty = true; + updateConfigProviderAfterEdit = true; readMakefilePath(); } @@ -591,7 +631,7 @@ export function initFromStateAndSettings(): void { // todo: skip over updating the IntelliSense configuration provider if the current makefile configuration // is not among the subobjects that suffered modifications. logger.message("makefile.configurations setting changed."); - configProviderDirty = true; + updateConfigProviderAfterEdit = true; readMakefileConfigurations(); } @@ -599,10 +639,28 @@ export function initFromStateAndSettings(): void { if (!util.areEqual(updatedDryRunSwitches, dryRunSwitches)) { // A change in makefile.dryRunSwitches should trigger an IntelliSense update // only if the extension is not currently reading from a build log. - configProviderDirty = !buildLog || !util.checkFileExistsSync(buildLog); + updateConfigProviderAfterEdit = !buildLog || !util.checkFileExistsSync(buildLog); logger.message("makefile.dryRunSwitches setting changed."); readDryRunSwitches(); } + + let updatedConfigureOnOpen : boolean | undefined = workspaceConfiguration.get("configureOnOpen"); + if (updatedConfigureOnOpen !== configureOnOpen) { + logger.message("makefile.configureOnOpen setting changed."); + readConfigureOnOpen(); + } + + let updatedConfigureOnEdit : boolean | undefined = workspaceConfiguration.get("configureOnEdit"); + if (updatedConfigureOnEdit !== configureOnEdit) { + logger.message("makefile.configureOnEdit setting changed."); + readConfigureOnEdit(); + } + + let updatedConfigureAfterCommand : boolean | undefined = workspaceConfiguration.get("configureAfterCommand"); + if (updatedConfigureAfterCommand !== configureAfterCommand) { + logger.message("makefile.configureAfterCommand setting changed."); + readConfigureAfterCommand(); + } } }); } @@ -610,7 +668,13 @@ export function initFromStateAndSettings(): void { export function setConfigurationByName(configurationName: string): void { extension.extensionContext.workspaceState.update("buildConfiguration", configurationName); setCurrentMakefileConfiguration(configurationName); - make.parseBuildOrDryRun(); + if (configureAfterCommand) { + make.parseBuildOrDryRun(); + } else { + logger.message("makefile.configureAfterCommand is set to false. " + + "The project will not configure automatically after this build configuration change."); + logger.message("In order to have an up to date IntelliSense, it is recommended that you run the command makefile.configure at your earliest convenience."); + } } export function prepareConfigurationsQuickPick(): string[] { @@ -821,7 +885,13 @@ export function setTargetByName(targetName: string) : void { statusBar.setTarget(currentTarget); logger.message("Setting target " + currentTarget); extension.extensionContext.workspaceState.update("buildTarget", currentTarget); - make.parseBuildOrDryRun(); + if (configureAfterCommand) { + make.parseBuildOrDryRun(); + } else { + logger.message("makefile.configureAfterCommand is set to false. " + + "The project will not configure automatically after this target change."); + logger.message("In order to have an up to date IntelliSense, it is recommended that you run the command makefile.configure at your earliest convenience."); + } } // Fill a drop-down with all the target names run by building the makefile for the current configuration diff --git a/src/extension.ts b/src/extension.ts index 74ed670..78837cb 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -157,6 +157,10 @@ export async function activate(context: vscode.ExtensionContext): Promise return launcher.launchTargetArgsConcat(); })); + context.subscriptions.push(vscode.commands.registerCommand('makefile.configure', () => { + make.parseBuildOrDryRun(); + })); + configuration.readLoggingLevel(); configuration.readExtensionLog(); @@ -169,8 +173,14 @@ export async function activate(context: vscode.ExtensionContext): Promise // Read configuration info from settings configuration.initFromStateAndSettings(); - // Generate the dry-run output used for parsing the info to be sent to CppTools - make.parseBuildOrDryRun(); + // Generate the dry-run output used for parsing the info to be sent to CppTools, + // unless the user disabled automatic configure after opening. + if (configuration.getConfigureOnOpen()) { + make.parseBuildOrDryRun(); + } else { + logger.message("makefile.configureOnOpen is set to false. The project will not configure automatically after opening."); + logger.message("For the extension to work properly, it is recommended that you run the command makefile.configure at your earliest convenience."); + } } export async function deactivate(): Promise { diff --git a/src/make.ts b/src/make.ts index af969ce..ea3a5b9 100644 --- a/src/make.ts +++ b/src/make.ts @@ -63,6 +63,10 @@ export function parseBuild(): boolean { export async function parseBuildOrDryRun(): Promise { // If a build log is specified in makefile.configurations or makefile.buildLog // (and if it exists on disk) it must be parsed instead of invoking a dry-run make command. + // If a dry-run cache is present, we don't parse from it here. This operation is performed + // when a project is loaded (we don't know how any setting or makefile have been changed + // since the last open) and when the user executes the makefile.configure command + // (which doesn't make sense to be run without some edits since the last configure). if (parseBuild()) { return; }