From 7b3cc9f1d002615bac9fa4429e46c24cff3debe5 Mon Sep 17 00:00:00 2001 From: Andreea Isac <48239328+andreeis@users.noreply.github.com> Date: Fri, 14 Apr 2023 14:06:38 -0700 Subject: [PATCH] Variable expansion - initial support (#457) * Variable expansion - initial support * Update baselines and more bug fixes. * One more baseline update, forgot full path to personal machine enlistment * More baseline updates for windows * Fix persistance issue with launch configurations and also make sure we don't override settings in workspace with expanded values * Fix more object/arrays persistance bugs. Implement possibility to escape varexp syntax. --- package.json | 2 + src/configuration.ts | 414 +++++++++--------- src/extension.ts | 28 +- src/make.ts | 2 +- src/telemetry.ts | 16 +- .../fakeSuite/Repros/.vscode/settings.json | 9 + .../fakeSuite/Repros/8cc_linux_baseline.out | 87 ++++ .../fakeSuite/Repros/Fido_linux_baseline.out | 87 ++++ ...erestingSmallMakefile_windows_baseline.out | 199 +++++++++ .../complex_escaped_quotes_baseline.out | 29 ++ ...complex_escaped_quotes_nonWin_baseline.out | 29 ++ ...omplex_escaped_quotes_winOnly_baseline.out | 29 ++ .../Repros/test_real_make_nonWin_baseline.out | 62 +++ .../test_real_make_windows_baseline.out | 62 +++ .../Repros/tinyvm_linux_baseline.out | 87 ++++ src/test/fakeSuite/Repros/varexp_baseline.out | 11 + .../Repros/varexp_win32_baseline.out | 11 + src/test/fakeSuite/extension.test.ts | 238 +++++----- src/util.ts | 293 ++++++++++++- 19 files changed, 1374 insertions(+), 321 deletions(-) create mode 100644 src/test/fakeSuite/Repros/varexp_baseline.out create mode 100644 src/test/fakeSuite/Repros/varexp_win32_baseline.out diff --git a/package.json b/package.json index f5a5a63..cdb75d9 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,9 @@ ], "activationEvents": [ "onCommand:makefile.setBuildConfiguration", + "onCommand:makefile.getConfiguration", "onCommand:makefile.setBuildTarget", + "onCommand:makefile.getBuildTarget", "onCommand:makefile.buildTarget", "onCommand:makefile.buildCleanTarget", "onCommand:makefile.buildAll", diff --git a/src/configuration.ts b/src/configuration.ts index 78f9f51..8d0b32a 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -71,12 +71,11 @@ export function getCurrentMakefileConfiguration(): string { return currentMakefi export async function setCurrentMakefileConfiguration(configuration: string): Promise { currentMakefileConfiguration = configuration; statusBar.setConfiguration(currentMakefileConfiguration); - logger.message(`Setting configuration - ${currentMakefileConfiguration}`); await analyzeConfigureParams(); } // Read the current configuration from workspace state, update status bar item -function readCurrentMakefileConfiguration(): void { +export function readCurrentMakefileConfiguration(): void { let buildConfiguration : string | undefined = extension.getState().buildConfiguration; if (!buildConfiguration) { logger.message("No current configuration is defined in the workspace state. Assuming 'Default'."); @@ -135,11 +134,10 @@ export function isOptionalFeatureEnabled(propertyName: string): boolean { } // Override default settings for each feature based on workspace current information -function updateOptionalFeaturesWithWorkspace(): void { - let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); +async function updateOptionalFeaturesWithWorkspace(): Promise { // optionalFeatures will be set with default values. // override with values from the workspace - let features: MakefilePanelVisibility | undefined = workspaceConfiguration.get("panel.visibility") || undefined; + let features: MakefilePanelVisibility | undefined = await util.getExpandedSetting("panel.visibility") || undefined; if (features) { if (Object.entries(features).length < panelVisibility.features.length) { // At least one feature is missing from the settings, which means we need to use defaults. @@ -178,8 +176,8 @@ function enableOptionallyVisibleCommands(): void { } } } -function readFeaturesVisibility(): void { - updateOptionalFeaturesWithWorkspace(); +async function readFeaturesVisibility(): Promise { + await updateOptionalFeaturesWithWorkspace(); } let makePath: string | undefined; @@ -189,16 +187,10 @@ export function setMakePath(path: string): void { makePath = path; } // Read the path (full or directory only) of the make tool if defined in settings. // It represents a default to look for if no other path is already included // in "makefile.configurations.makePath". -function readMakePath(): void { - let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); - makePath = workspaceConfiguration.get("makePath"); +async function readMakePath(): Promise { + makePath = await util.getExpandedSetting("makePath"); if (!makePath) { logger.message("No path to the make tool is defined in the settings file."); - } else { - // Don't resolve makePath to root, because make needs to be searched in the path too. - // Instead, offer ability to substitute ${workspaceRoot}/${workspacePath} to the current - // workspace directory. - makePath = util.resolveSubstitutedPath(makePath); } } @@ -209,9 +201,8 @@ export function setMakefilePath(path: string): void { makefilePath = path; } // It represents a default to look for if no other makefile is already provided // in makefile.configurations.makefilePath. // TODO: validate and integrate with "-f [Makefile]" passed in makefile.configurations.makeArgs. -function readMakefilePath(): void { - let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); - makefilePath = workspaceConfiguration.get("makefilePath"); +async function readMakefilePath(): Promise { + makefilePath = await util.getExpandedSetting("makefilePath"); if (!makefilePath) { logger.message("No path to the makefile is defined in the settings file."); } else { @@ -226,9 +217,8 @@ export function setMakeDirectory(dir: string): void { makeDirectory = dir; } // It represents a default to look for if no other makeDirectory is already provided // in makefile.configurations.makeDirectory. // TODO: validate and integrate with "-C [DIR_PATH]" passed in makefile.configurations.makeArgs. -function readMakeDirectory(): void { - let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); - makeDirectory = workspaceConfiguration.get("makeDirectory"); +async function readMakeDirectory(): Promise { + makeDirectory = await util.getExpandedSetting("makeDirectory"); if (!makeDirectory) { logger.message("No folder path to the makefile is defined in the settings file."); } else { @@ -286,9 +276,8 @@ export function setBuildLog(path: string): void { buildLog = path; } // If any of the above switches is missing, the extension may have less log to parse from, // therefore offering less intellisense information for source files, // identifying less possible binaries to debug or not providing any makefile targets (other than the 'all' default). -function readBuildLog(): void { - let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); - buildLog = workspaceConfiguration.get("buildLog"); +export async function readBuildLog(): Promise { + buildLog = await util.getExpandedSetting("buildLog"); if (buildLog) { buildLog = util.resolvePathToRoot(buildLog); logger.message(`Build log defined at "${buildLog}"`); @@ -303,14 +292,8 @@ export function getLoggingLevel(): string | undefined { return loggingLevel; } export function setLoggingLevel(logLevel: string): void { loggingLevel = logLevel; } // Read from settings the desired logging level for the Makefile Tools extension. -export function readLoggingLevel(): void { - let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); - loggingLevel = workspaceConfiguration.get("loggingLevel"); - - if (!loggingLevel) { - loggingLevel = "Normal"; - } - +export async function readLoggingLevel(): Promise { + loggingLevel = await util.getExpandedSetting("loggingLevel") || "Normal"; logger.message(`Logging level: ${loggingLevel}`); } @@ -321,10 +304,8 @@ export function setExtensionOutputFolder(folder: string): void { extensionOutput // Read from settings the path to a folder where the extension is dropping various output files // (like extension.log, dry-run.log, targets.log). // Useful to control where such potentially large files should reside. -export function readExtensionOutputFolder(): void { - let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); - const propKey: string = "extensionOutputFolder"; - extensionOutputFolder = workspaceConfiguration.get(propKey); +export async function readExtensionOutputFolder(): Promise { + extensionOutputFolder = await util.getExpandedSetting("extensionOutputFolder"); if (extensionOutputFolder) { extensionOutputFolder = util.resolvePathToRoot(extensionOutputFolder); } else { @@ -335,8 +316,9 @@ export function readExtensionOutputFolder(): void { if (extensionOutputFolder) { if (!util.checkDirectoryExistsSync(extensionOutputFolder)) { if (!util.createDirectorySync(extensionOutputFolder)) { + extensionOutputFolder = extension.extensionContext.storagePath; logger.message(`Extension output folder does not exist and could not be created: ${extensionOutputFolder}.`); - extensionOutputFolder = undefined; + logger.message(`Reverting to '${extensionOutputFolder}' default for extension output folder.`); return; } } @@ -356,9 +338,8 @@ export function setExtensionLog(path: string): void { extensionLog = path; } // If an extension log is specified, its content is cleared during activation. // Any messages that are being logged throughout the lifetime of the extension // are going to be appended to this file. -export function readExtensionLog(): void { - let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); - extensionLog = workspaceConfiguration.get("extensionLog"); +export async function readExtensionLog(): Promise { + extensionLog = await util.getExpandedSetting("extensionLog"); if (extensionLog) { // If there is a directory defined within the extension log path, // honor it and don't append to extensionOutputFolder. @@ -379,9 +360,8 @@ export function setPreConfigureScript(path: string): void { preConfigureScript = // Read from settings the path to a script file that needs to have been run at least once // before a sucessful configure of this project. -export function readPreConfigureScript(): void { - let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); - preConfigureScript = workspaceConfiguration.get("preConfigureScript"); +export async function readPreConfigureScript(): Promise { + preConfigureScript = await util.getExpandedSetting("preConfigureScript"); if (preConfigureScript) { preConfigureScript = util.resolvePathToRoot(preConfigureScript); logger.message(`Found pre-configure script defined as ${preConfigureScript}`); @@ -397,9 +377,8 @@ export function setAlwaysPreConfigure(path: boolean): void { alwaysPreConfigure // Read from settings whether the pre-configure step is supposed to be executed // always before the configure operation. -export function readAlwaysPreConfigure(): void { - let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); - alwaysPreConfigure = workspaceConfiguration.get("alwaysPreConfigure"); +export async function readAlwaysPreConfigure(): Promise { + alwaysPreConfigure = await util.getExpandedSetting("alwaysPreConfigure"); logger.message(`Always pre-configure: ${alwaysPreConfigure}`); } @@ -410,13 +389,13 @@ export function setConfigurationCachePath(path: string): void { configurationCac // Read from settings the path to a cache file containing the output of the last dry-run make command. // This file is recreated when opening a project, when changing the build configuration or the build target // and when the settings watcher detects a change of any properties that may impact the dryrun output. -export function readConfigurationCachePath(): void { - let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); +export async function readConfigurationCachePath(): Promise { // how to get default from package.json to avoid problem with 'undefined' type? - configurationCachePath = workspaceConfiguration.get("configurationCachePath"); + configurationCachePath = await util.getExpandedSetting("configurationCachePath"); if (!configurationCachePath && extensionOutputFolder) { configurationCachePath = path.join(extensionOutputFolder, 'configurationCache.log'); } + if (configurationCachePath) { // If there is a directory defined within the configuration cache path, // honor it and don't append to extensionOutputFolder. @@ -426,18 +405,16 @@ export function readConfigurationCachePath(): void { } else { configurationCachePath = util.resolvePathToRoot(configurationCachePath); } - } - logger.message(`Configurations cached at ${configurationCachePath}`); + logger.message(`Configurations cached at ${configurationCachePath}`); + } } let compileCommandsPath: string | undefined; export function getCompileCommandsPath(): string | undefined { return compileCommandsPath; } export function setCompileCommandsPath(path: string): void { compileCommandsPath = path; } -export function readCompileCommandsPath(): void { - let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); - - compileCommandsPath = workspaceConfiguration.get("compileCommandsPath"); +export async function readCompileCommandsPath(): Promise { + compileCommandsPath = await util.getExpandedSetting("compileCommandsPath"); if (compileCommandsPath) { compileCommandsPath = util.resolvePathToRoot(compileCommandsPath); } @@ -448,19 +425,21 @@ export function readCompileCommandsPath(): void { let additionalCompilerNames: string[] | undefined; export function getAdditionalCompilerNames(): string[] | undefined { return additionalCompilerNames; } export function setAdditionalCompilerNames(compilerNames: string[]): void { additionalCompilerNames = compilerNames; } -export function readAdditionalCompilerNames(): void { - let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); - additionalCompilerNames = workspaceConfiguration.get("additionalCompilerNames"); - logger.message(`Additional compiler names: ${additionalCompilerNames}`); +export async function readAdditionalCompilerNames(): Promise { + additionalCompilerNames = await util.getExpandedSetting("additionalCompilerNames"); + if (additionalCompilerNames && additionalCompilerNames.length > 0) { + logger.message(`Additional compiler names: '${additionalCompilerNames?.join("', '")}'`); + } } let excludeCompilerNames: string[] | undefined; export function getExcludeCompilerNames(): string[] | undefined { return excludeCompilerNames; } export function setExcludeCompilerNames(compilerNames: string[]): void { excludeCompilerNames = compilerNames; } -export function readExcludeCompilerNames(): void { - let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); - excludeCompilerNames = workspaceConfiguration.get("excludeCompilerNames"); - logger.message(`Exclude compiler names: ${excludeCompilerNames}`); +export async function readExcludeCompilerNames(): Promise { + excludeCompilerNames = await util.getExpandedSetting("excludeCompilerNames"); + if (excludeCompilerNames && excludeCompilerNames.length > 0) { + logger.message(`Exclude compiler names: '${excludeCompilerNames?.join("', '")}'`); + } } let dryrunSwitches: string[] | undefined; @@ -475,10 +454,11 @@ export function setDryrunSwitches(switches: string[]): void { dryrunSwitches = s // infinite reconfiguration loops, resulting in the extension being unusable. // To work around this, the setting makefile.dryrunSwitches is providing a way to skip over the problematic make arguments, // even if this results in not ideal behavior: less information available to be parsed, which leads to incomplete IntelliSense or missing targets. -export function readDryrunSwitches(): void { - let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); - dryrunSwitches = workspaceConfiguration.get("dryrunSwitches"); - logger.message(`Dry-run switches: ${dryrunSwitches}`); +export async function readDryrunSwitches(): Promise { + dryrunSwitches = await util.getExpandedSetting("dryrunSwitches"); + if (dryrunSwitches && dryrunSwitches.length > 0) { + logger.message(`Dry-run switches: '${dryrunSwitches?.join("', '")}'`); + } } // Currently, the makefile extension supports debugging only an executable. @@ -505,10 +485,9 @@ let launchConfigurations: LaunchConfiguration[] = []; export function getLaunchConfigurations(): LaunchConfiguration[] { return launchConfigurations; } export function setLaunchConfigurations(configurations: LaunchConfiguration[]): void { launchConfigurations = configurations; } -// Read make configurations optionally defined by the user in settings: makefile.configurations. -function readLaunchConfigurations(): void { - let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); - launchConfigurations = workspaceConfiguration.get("launchConfigurations") || []; +// Read launch configurations defined by the user in settings: makefile.launchConfigurations[] +async function readLaunchConfigurations(): Promise { + launchConfigurations = await util.getExpandedSetting("launchConfigurations") || []; } // Helper used to fill the launch configurations quick pick. @@ -550,9 +529,9 @@ export async function stringToLaunchConfiguration(str: string): Promise { +export async function setCurrentLaunchConfiguration(configuration: LaunchConfiguration | undefined): Promise { currentLaunchConfiguration = configuration; - let launchConfigStr: string = launchConfigurationToString(currentLaunchConfiguration); + let launchConfigStr: string = currentLaunchConfiguration ? launchConfigurationToString(currentLaunchConfiguration) : ""; statusBar.setLaunchConfiguration(launchConfigStr); await extension._projectOutlineProvider.updateLaunchTarget(launchConfigStr); } @@ -570,7 +549,7 @@ function getLaunchConfiguration(name: string): LaunchConfiguration | undefined { // in the launch configurations array from settings. // Also update the status bar item. async function readCurrentLaunchConfiguration(): Promise { - readLaunchConfigurations(); + await readLaunchConfigurations(); let currentLaunchConfigurationName: string | undefined = extension.getState().launchConfiguration; if (currentLaunchConfigurationName) { currentLaunchConfiguration = getLaunchConfiguration(currentLaunchConfigurationName); @@ -609,9 +588,8 @@ let defaultLaunchConfiguration: DefaultLaunchConfiguration | undefined; export function getDefaultLaunchConfiguration(): DefaultLaunchConfiguration | undefined { return defaultLaunchConfiguration; } // No setter needed. Currently only the user can define makefile.defaultLaunchConfiguration -export function readDefaultLaunchConfiguration(): void { - let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); - defaultLaunchConfiguration = workspaceConfiguration.get("defaultLaunchConfiguration"); +export async function readDefaultLaunchConfiguration(): Promise { + defaultLaunchConfiguration = await util.getExpandedSetting("defaultLaunchConfiguration"); logger.message(`Default launch configuration: MIMode = ${defaultLaunchConfiguration?.MIMode}, miDebuggerPath = ${defaultLaunchConfiguration?.miDebuggerPath}, stopAtEntry = ${defaultLaunchConfiguration?.stopAtEntry}, @@ -695,9 +673,9 @@ export async function getCommandForConfiguration(configuration: string | undefin // makefile.configurations.makefilePath overwrites makefile.makefilePath. configurationMakefile = makefileConfiguration?.makefilePath ? util.resolvePathToRoot(makefileConfiguration?.makefilePath) : makefilePath; if (configurationMakefile) { - // check if the makefile path is a directory. If so, try adding `Makefile` or `makefile` + // check if the makefile path is a directory. If so, try adding `Makefile` or `makefile` if (util.checkDirectoryExistsSync(configurationMakefile)) { - let makeFileTest = path.join(configurationMakefile, "Makefile"); + let makeFileTest: string = path.join(configurationMakefile, "Makefile"); if (!util.checkFileExistsSync(makeFileTest)) { makeFileTest = path.join(configurationMakefile, "makefile"); } @@ -705,7 +683,7 @@ export async function getCommandForConfiguration(configuration: string | undefin // if we found the makefile in the directory, set the `configurationMakefile` to the found file path. if (util.checkFileExistsSync(makeFileTest)) { configurationMakefile = makeFileTest; - } + } } configurationMakeArgs.push("-f"); @@ -865,7 +843,9 @@ export function getMakefileConfigurations(): MakefileConfiguration[] { return ma export function setMakefileConfigurations(configurations: MakefileConfiguration[]): void { makefileConfigurations = configurations; } // Read make configurations optionally defined by the user in settings: makefile.configurations. -async function readMakefileConfigurations(): Promise { +export async function readMakefileConfigurations(): Promise { + // We need to read "makefile.configurations" unexpanded first, because we may write back into these settings + // in case we indentify "name" missing. We'll expand later, see end of function. let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); makefileConfigurations = workspaceConfiguration.get("configurations") || []; let detectedUnnamedConfigurations: boolean = false; @@ -899,20 +879,22 @@ async function readMakefileConfigurations(): Promise { if (detectedUnnamedConfigurations) { logger.message("Updating makefile configurations in settings."); - workspaceConfiguration.update("configurations", makefileConfigurations); + await workspaceConfiguration.update("configurations", makefileConfigurations); } + // Now read "makefile.configurations" again and expand as needed. + makefileConfigurations = await util.getExpandedSetting("configurations") || []; + // Log the updated list of configuration names const makefileConfigurationNames: string[] = makefileConfigurations.map((k => { return k.name; })); - if (makefileConfigurationNames.length > 0) { - logger.message("Found the following configurations defined in makefile.configurations setting: " + - makefileConfigurationNames.join(";")); + logger.message("Found the following configurations defined in makefile.configurations setting: " + makefileConfigurationNames.join(";")); } - // Verify if the current makefile configuration is still part of the list and unset otherwise. + // Verify if the current makefile configuration (check against the expanded values) + // is still part of the list and unset otherwise. // Exception: "Default" which means the user didn't set it and relies on whatever default // the current set of makefiles support. "Default" is not going to be part of the list // but we shouldn't log about it. @@ -949,67 +931,60 @@ function readCurrentTarget(): void { let configureOnOpen: boolean | undefined; export function getConfigureOnOpen(): boolean | undefined { return configureOnOpen; } export function setConfigureOnOpen(configure: boolean): void { configureOnOpen = configure; } -export function readConfigureOnOpen(): void { - let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); +export async function readConfigureOnOpen(): Promise { // how to get default from package.json to avoid problem with 'undefined' type? - configureOnOpen = workspaceConfiguration.get("configureOnOpen"); + configureOnOpen = await util.getExpandedSetting("configureOnOpen"); logger.message(`Configure on open: ${configureOnOpen}`); } let configureOnEdit: boolean | undefined; export function getConfigureOnEdit(): boolean | undefined { return configureOnEdit; } export function setConfigureOnEdit(configure: boolean): void { configureOnEdit = configure; } -export function readConfigureOnEdit(): void { - let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); +export async function readConfigureOnEdit(): Promise { // how to get default from package.json to avoid problem with 'undefined' type? - configureOnEdit = workspaceConfiguration.get("configureOnEdit"); + configureOnEdit = await util.getExpandedSetting("configureOnEdit"); logger.message(`Configure on edit: ${configureOnEdit}`); } let configureAfterCommand: boolean | undefined; export function getConfigureAfterCommand(): boolean | undefined { return configureAfterCommand; } export function setConfigureAfterCommand(configure: boolean): void { configureAfterCommand = configure; } -export function readConfigureAfterCommand(): void { - let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); +export async function readConfigureAfterCommand(): Promise { // how to get default from package.json to avoid problem with 'undefined' type? - configureAfterCommand = workspaceConfiguration.get("configureAfterCommand"); + configureAfterCommand = await util.getExpandedSetting("configureAfterCommand"); logger.message(`Configure after command: ${configureAfterCommand}`); } let phonyOnlyTargets: boolean | undefined; export function getPhonyOnlyTargets(): boolean | undefined { return phonyOnlyTargets; } export function setPhonyOnlyTargets(phony: boolean): void { phonyOnlyTargets = phony; } -export function readPhonyOnlyTargets(): void { - let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); +export async function readPhonyOnlyTargets(): Promise { // how to get default from package.json to avoid problem with 'undefined' type? - phonyOnlyTargets = workspaceConfiguration.get("phonyOnlyTargets"); + phonyOnlyTargets = await util.getExpandedSetting("phonyOnlyTargets"); logger.message(`Only .PHONY targets: ${phonyOnlyTargets}`); } let saveBeforeBuildOrConfigure: boolean | undefined; export function getSaveBeforeBuildOrConfigure(): boolean | undefined { return saveBeforeBuildOrConfigure; } export function setSaveBeforeBuildOrConfigure(save: boolean): void { saveBeforeBuildOrConfigure = save; } -export function readSaveBeforeBuildOrConfigure(): void { - let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); - saveBeforeBuildOrConfigure = workspaceConfiguration.get("saveBeforeBuildOrConfigure"); +export async function readSaveBeforeBuildOrConfigure(): Promise { + saveBeforeBuildOrConfigure = await util.getExpandedSetting("saveBeforeBuildOrConfigure"); logger.message(`Save before build or configure: ${saveBeforeBuildOrConfigure}`); } let buildBeforeLaunch: boolean | undefined; export function getBuildBeforeLaunch(): boolean | undefined { return buildBeforeLaunch; } export function setBuildBeforeLaunch(build: boolean): void { buildBeforeLaunch = build; } -export function readBuildBeforeLaunch(): void { - let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); - buildBeforeLaunch = workspaceConfiguration.get("buildBeforeLaunch"); +export async function readBuildBeforeLaunch(): Promise { + buildBeforeLaunch = await util.getExpandedSetting("buildBeforeLaunch"); logger.message(`Build before launch: ${buildBeforeLaunch}`); } let clearOutputBeforeBuild: boolean | undefined; export function getClearOutputBeforeBuild(): boolean | undefined { return clearOutputBeforeBuild; } export function setClearOutputBeforeBuild(clear: boolean): void { clearOutputBeforeBuild = clear; } -export function readClearOutputBeforeBuild(): void { - let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); - clearOutputBeforeBuild = workspaceConfiguration.get("clearOutputBeforeBuild"); +export async function readClearOutputBeforeBuild(): Promise { + clearOutputBeforeBuild = await util.getExpandedSetting("clearOutputBeforeBuild"); logger.message(`Clear output before build: ${clearOutputBeforeBuild}`); } @@ -1022,41 +997,70 @@ export function readClearOutputBeforeBuild(): void { let ignoreDirectoryCommands: boolean | undefined; export function getIgnoreDirectoryCommands(): boolean | undefined { return ignoreDirectoryCommands; } export function setIgnoreDirectoryCommands(ignore: boolean): void { ignoreDirectoryCommands = ignore; } -export function readIgnoreDirectoryCommands(): void { - let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); +export async function readIgnoreDirectoryCommands(): Promise { // how to get default from package.json to avoid problem with 'undefined' type? - ignoreDirectoryCommands = workspaceConfiguration.get("ignoreDirectoryCommands"); + ignoreDirectoryCommands = await util.getExpandedSetting("ignoreDirectoryCommands"); logger.message(`Ignore directory commands: ${ignoreDirectoryCommands}`); } -// Initialization from settings (or backup default rules), done at activation time -export async function initFromStateAndSettings(): Promise { - readConfigurationCachePath(); - readMakePath(); - readMakefilePath(); - readMakeDirectory(); - readBuildLog(); - readPreConfigureScript(); - readAlwaysPreConfigure(); - readDryrunSwitches(); - readAdditionalCompilerNames(); - readExcludeCompilerNames(); - readCurrentMakefileConfiguration(); +// Initialization from the state of the workspace. +// The user does not have direct access to this data. +// The extension sets state variables via user actions like: +// set configuration, set build target, set launch target. +// At activation time we read from state, update UI accordingly +// and commands become available to be run in settings via expansion. +// These can also be resetted via the makefile.resetState command. +export function initFromState(): void { + readCurrentMakefileConfiguration(); + readCurrentTarget(); +} + +// Initialization from settings (or backup default rules). +// This is called at activation time (with activation boolean being passed as true explicitly) +// or after any change in the configuration/build-target workspace state variables, in which case +// we need a refresh of all settings expanding ${configuration} or ${buildTarget}. +export async function initFromSettings(activation: boolean = false): Promise { + // Read first anything related to the output folder and the extension log, + // to be able to document any upcoming reads. + await readExtensionOutputFolder(); + await readExtensionLog(); + + // Delete the extension log file, if exists, even if we lose what we logged earlier + // about reading the output folder and extension log. + // The deletion should happen only at activation time (to not allow the log file to grow indefinitely), + // while reading the settings is done at activation time and also anytime later, + // after changing a makefile configuration, a build or a launch target. + let extensionLog : string | undefined = getExtensionLog(); + if (extensionLog && activation && util.checkFileExistsSync(extensionLog)) { + util.deleteFileSync(extensionLog); + } + + await readLoggingLevel(); + await readConfigurationCachePath(); + await readMakePath(); + await readMakefilePath(); + await readMakeDirectory(); + await readBuildLog(); + await readPreConfigureScript(); + await readAlwaysPreConfigure(); + await readDryrunSwitches(); + await readAdditionalCompilerNames(); + await readExcludeCompilerNames(); await readMakefileConfigurations(); - readCurrentTarget(); await readCurrentLaunchConfiguration(); - readDefaultLaunchConfiguration(); - readConfigureOnOpen(); - readConfigureOnEdit(); - readConfigureAfterCommand(); - readPhonyOnlyTargets(); - readSaveBeforeBuildOrConfigure(); - readBuildBeforeLaunch(); - readClearOutputBeforeBuild(); - readIgnoreDirectoryCommands(); - readCompileCommandsPath(); + await readDefaultLaunchConfiguration(); + await readConfigureOnOpen(); + await readConfigureOnEdit(); + await readConfigureAfterCommand(); + await readPhonyOnlyTargets(); + await readSaveBeforeBuildOrConfigure(); + await readBuildBeforeLaunch(); + await readClearOutputBeforeBuild(); + await readIgnoreDirectoryCommands(); + await readCompileCommandsPath(); + initOptionalFeatures(); - readFeaturesVisibility(); + await readFeaturesVisibility(); await analyzeConfigureParams(); @@ -1133,11 +1137,10 @@ export async function initFromStateAndSettings(): Promise { // Avoid unnecessary updates (for example, when settings are modified via the extension quickPick). let telemetryProperties: telemetry.Properties | null = {}; let updatedSettingsSubkeys: string[] = []; - let keyRoot: string = "makefile"; - let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration(keyRoot); - + const keyRoot: string = "makefile"; let subKey: string = "launchConfigurations"; - let updatedLaunchConfigurations : LaunchConfiguration[] | undefined = workspaceConfiguration.get(subKey); + + let updatedLaunchConfigurations : LaunchConfiguration[] | undefined = await util.getExpandedSetting(subKey); if (!util.areEqual(updatedLaunchConfigurations, launchConfigurations)) { // Changing a launch configuration does not impact the make or compiler tools invocations, // so no IntelliSense update is needed. @@ -1147,23 +1150,23 @@ export async function initFromStateAndSettings(): Promise { } subKey = "defaultLaunchConfiguration"; - let updatedDefaultLaunchConfiguration : DefaultLaunchConfiguration | undefined = workspaceConfiguration.get(subKey); + let updatedDefaultLaunchConfiguration : DefaultLaunchConfiguration | undefined = await util.getExpandedSetting(subKey); if (!util.areEqual(updatedDefaultLaunchConfiguration, defaultLaunchConfiguration)) { // Changing a global debug configuration does not impact the make or compiler tools invocations, // so no IntelliSense update is needed. - readDefaultLaunchConfiguration(); + await readDefaultLaunchConfiguration(); updatedSettingsSubkeys.push(subKey); } subKey = "loggingLevel"; - let updatedLoggingLevel : string | undefined = workspaceConfiguration.get(subKey); + let updatedLoggingLevel : string | undefined = await util.getExpandedSetting(subKey); if (updatedLoggingLevel !== loggingLevel) { - readLoggingLevel(); + await readLoggingLevel(); updatedSettingsSubkeys.push(subKey); } subKey = "buildLog"; - let updatedBuildLog : string | undefined = workspaceConfiguration.get(subKey); + let updatedBuildLog : string | undefined = await util.getExpandedSetting(subKey); if (updatedBuildLog) { updatedBuildLog = util.resolvePathToRoot(updatedBuildLog); } @@ -1179,12 +1182,12 @@ export async function initFromStateAndSettings(): Promise { extension.getState().configureDirty = extension.getState().configureDirty || !currentMakefileConfiguration || !currentMakefileConfiguration.buildLog; - readBuildLog(); + await readBuildLog(); updatedSettingsSubkeys.push(subKey); } subKey = "extensionOutputFolder"; - let updatedExtensionOutputFolder : string | undefined = workspaceConfiguration.get(subKey); + let updatedExtensionOutputFolder : string | undefined = await util.getExpandedSetting(subKey); if (updatedExtensionOutputFolder) { updatedExtensionOutputFolder = util.resolvePathToRoot(updatedExtensionOutputFolder); if (!util.checkDirectoryExistsSync(updatedExtensionOutputFolder) && @@ -1196,12 +1199,12 @@ export async function initFromStateAndSettings(): Promise { } if (updatedExtensionOutputFolder !== extensionOutputFolder) { // No IntelliSense update needed. - readExtensionOutputFolder(); + await readExtensionOutputFolder(); updatedSettingsSubkeys.push(subKey); } subKey = "extensionLog"; - let updatedExtensionLog : string | undefined = workspaceConfiguration.get(subKey); + let updatedExtensionLog : string | undefined = await util.getExpandedSetting(subKey); if (updatedExtensionLog) { // If there is a directory defined within the extension log path, // honor it and don't append to extensionOutputFolder. @@ -1214,31 +1217,31 @@ export async function initFromStateAndSettings(): Promise { } if (updatedExtensionLog !== extensionLog) { // No IntelliSense update needed. - readExtensionLog(); + await readExtensionLog(); updatedSettingsSubkeys.push(subKey); } subKey = "preConfigureScript"; - let updatedPreConfigureScript : string | undefined = workspaceConfiguration.get(subKey); + let updatedPreConfigureScript : string | undefined = await util.getExpandedSetting(subKey); if (updatedPreConfigureScript) { updatedPreConfigureScript = util.resolvePathToRoot(updatedPreConfigureScript); } if (updatedPreConfigureScript !== preConfigureScript) { // No IntelliSense update needed. - readPreConfigureScript(); + await readPreConfigureScript(); updatedSettingsSubkeys.push(subKey); } subKey = "alwaysPreConfigure"; - let updatedAlwaysPreConfigure : boolean | undefined = workspaceConfiguration.get(subKey); + let updatedAlwaysPreConfigure : boolean | undefined = await util.getExpandedSetting(subKey); if (updatedAlwaysPreConfigure !== alwaysPreConfigure) { // No IntelliSense update needed. - readAlwaysPreConfigure(); + await readAlwaysPreConfigure(); updatedSettingsSubkeys.push(subKey); } subKey = "configurationCachePath"; - let updatedConfigurationCachePath : string | undefined = workspaceConfiguration.get(subKey); + let updatedConfigurationCachePath : string | undefined = await util.getExpandedSetting(subKey); if (updatedConfigurationCachePath) { // If there is a directory defined within the configuration cache path, // honor it and don't append to extensionOutputFolder. @@ -1254,24 +1257,24 @@ export async function initFromStateAndSettings(): Promise { // only if the extension is not currently reading from a build log. extension.getState().configureDirty = extension.getState().configureDirty || !buildLog || !util.checkFileExistsSync(buildLog); - readConfigurationCachePath(); + await readConfigurationCachePath(); updatedSettingsSubkeys.push(subKey); } subKey = "makePath"; - let updatedMakePath : string | undefined = workspaceConfiguration.get(subKey); + let updatedMakePath : string | undefined = await util.getExpandedSetting(subKey); if (updatedMakePath !== makePath) { // Not very likely, but it is safe to consider that a different make tool // may produce a different dry-run output with potential impact on IntelliSense, // so trigger an update (unless we read from a build log). extension.getState().configureDirty = extension.getState().configureDirty || !buildLog || !util.checkFileExistsSync(buildLog); - readMakePath(); + await readMakePath(); updatedSettingsSubkeys.push(subKey); } subKey = "makefilePath"; - let updatedMakefilePath : string | undefined = workspaceConfiguration.get(subKey); + let updatedMakefilePath : string | undefined = await util.getExpandedSetting(subKey); if (updatedMakefilePath) { updatedMakefilePath = util.resolvePathToRoot(updatedMakefilePath); } @@ -1280,12 +1283,12 @@ export async function initFromStateAndSettings(): Promise { // only if the extension is not currently reading from a build log. extension.getState().configureDirty = extension.getState().configureDirty || !buildLog || !util.checkFileExistsSync(buildLog); - readMakefilePath(); + await readMakefilePath(); updatedSettingsSubkeys.push(subKey); } subKey = "makeDirectory"; - let updatedMakeDirectory : string | undefined = workspaceConfiguration.get(subKey); + let updatedMakeDirectory : string | undefined = await util.getExpandedSetting(subKey); if (updatedMakeDirectory) { updatedMakeDirectory = util.resolvePathToRoot(updatedMakeDirectory); } @@ -1294,12 +1297,12 @@ export async function initFromStateAndSettings(): Promise { // only if the extension is not currently reading from a build log. extension.getState().configureDirty = extension.getState().configureDirty || !buildLog || !util.checkFileExistsSync(buildLog); - readMakeDirectory(); + await readMakeDirectory(); updatedSettingsSubkeys.push(subKey); } subKey = "configurations"; - let updatedMakefileConfigurations : MakefileConfiguration[] | undefined = workspaceConfiguration.get(subKey); + let updatedMakefileConfigurations : MakefileConfiguration[] | undefined = await util.getExpandedSetting(subKey); if (!util.areEqual(updatedMakefileConfigurations, makefileConfigurations)) { // todo: skip over updating the IntelliSense configuration provider if the current makefile configuration // is not among the subobjects that suffered modifications. @@ -1309,105 +1312,104 @@ export async function initFromStateAndSettings(): Promise { } subKey = "dryrunSwitches"; - let updatedDryrunSwitches : string[] | undefined = workspaceConfiguration.get(subKey); + let updatedDryrunSwitches : string[] | undefined = await util.getExpandedSetting(subKey); 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. extension.getState().configureDirty = extension.getState().configureDirty || !buildLog || !util.checkFileExistsSync(buildLog); - readDryrunSwitches(); + await readDryrunSwitches(); updatedSettingsSubkeys.push(subKey); } subKey = "additionalCompilerNames"; - let updatedAdditionalCompilerNames : string[] | undefined = workspaceConfiguration.get(subKey); + let updatedAdditionalCompilerNames : string[] | undefined = await util.getExpandedSetting(subKey); if (!util.areEqual(updatedAdditionalCompilerNames, additionalCompilerNames)) { - readAdditionalCompilerNames(); + await readAdditionalCompilerNames(); updatedSettingsSubkeys.push(subKey); } subKey = "excludeCompilerNames"; - let updatedExcludeCompilerNames : string[] | undefined = workspaceConfiguration.get(subKey); + let updatedExcludeCompilerNames : string[] | undefined = await util.getExpandedSetting(subKey); if (!util.areEqual(updatedExcludeCompilerNames, excludeCompilerNames)) { - readExcludeCompilerNames(); + await readExcludeCompilerNames(); updatedSettingsSubkeys.push(subKey); } subKey = "configureOnOpen"; - let updatedConfigureOnOpen : boolean | undefined = workspaceConfiguration.get(subKey); + let updatedConfigureOnOpen : boolean | undefined = await util.getExpandedSetting(subKey); if (updatedConfigureOnOpen !== configureOnOpen) { - readConfigureOnOpen(); + await readConfigureOnOpen(); updatedSettingsSubkeys.push(subKey); } subKey = "configureOnEdit"; - let updatedConfigureOnEdit : boolean | undefined = workspaceConfiguration.get(subKey); + let updatedConfigureOnEdit : boolean | undefined = await util.getExpandedSetting(subKey); if (updatedConfigureOnEdit !== configureOnEdit) { - readConfigureOnEdit(); + await readConfigureOnEdit(); updatedSettingsSubkeys.push(subKey); } subKey = "configureAfterCommand"; - let updatedConfigureAfterCommand : boolean | undefined = workspaceConfiguration.get(subKey); + let updatedConfigureAfterCommand : boolean | undefined = await util.getExpandedSetting(subKey); if (updatedConfigureAfterCommand !== configureAfterCommand) { - readConfigureAfterCommand(); + await readConfigureAfterCommand(); updatedSettingsSubkeys.push(subKey); } subKey = "phonyOnlyTargets"; - let updatedPhonyOnlyTargets : boolean | undefined = workspaceConfiguration.get(subKey); + let updatedPhonyOnlyTargets : boolean | undefined = await util.getExpandedSetting(subKey); if (updatedPhonyOnlyTargets !== phonyOnlyTargets) { - readPhonyOnlyTargets(); + await readPhonyOnlyTargets(); updatedSettingsSubkeys.push(subKey); } subKey = "saveBeforeBuildOrConfigure"; - let updatedSaveBeforeBuildOrConfigure : boolean | undefined = workspaceConfiguration.get(subKey); + let updatedSaveBeforeBuildOrConfigure : boolean | undefined = await util.getExpandedSetting(subKey); if (updatedSaveBeforeBuildOrConfigure !== saveBeforeBuildOrConfigure) { - readSaveBeforeBuildOrConfigure(); + await readSaveBeforeBuildOrConfigure(); updatedSettingsSubkeys.push(subKey); } subKey = "buildBeforeLaunch"; - let updatedBuildBeforeLaunch : boolean | undefined = workspaceConfiguration.get(subKey); + let updatedBuildBeforeLaunch : boolean | undefined = await util.getExpandedSetting(subKey); if (updatedBuildBeforeLaunch !== buildBeforeLaunch) { - readBuildBeforeLaunch(); + await readBuildBeforeLaunch(); updatedSettingsSubkeys.push(subKey); } subKey = "clearOutputBeforeBuild"; - let updatedClearOutputBeforeBuild : boolean | undefined = workspaceConfiguration.get(subKey); + let updatedClearOutputBeforeBuild : boolean | undefined = await util.getExpandedSetting(subKey); if (updatedClearOutputBeforeBuild !== clearOutputBeforeBuild) { - readClearOutputBeforeBuild(); + await readClearOutputBeforeBuild(); updatedSettingsSubkeys.push(subKey); } subKey = "ignoreDirectoryCommands"; - let updatedIgnoreDirectoryCommands : boolean | undefined = workspaceConfiguration.get(subKey); + let updatedIgnoreDirectoryCommands : boolean | undefined = await util.getExpandedSetting(subKey); if (updatedIgnoreDirectoryCommands !== ignoreDirectoryCommands) { - readIgnoreDirectoryCommands(); + await readIgnoreDirectoryCommands(); updatedSettingsSubkeys.push(subKey); } subKey = "compileCommandsPath"; - let updatedCompileCommandsPath: string | undefined = workspaceConfiguration.get(subKey); + let updatedCompileCommandsPath: string | undefined = await util.getExpandedSetting(subKey); if (updatedCompileCommandsPath) { updatedCompileCommandsPath = util.resolvePathToRoot(updatedCompileCommandsPath); } if (updatedCompileCommandsPath !== compileCommandsPath) { - readCompileCommandsPath(); + await readCompileCommandsPath(); updatedSettingsSubkeys.push(subKey); } subKey = "panel.visibility"; let wasLocalDebugEnabled: boolean = isOptionalFeatureEnabled("debug"); let wasLocalRunningEnabled: boolean = isOptionalFeatureEnabled("run"); - readFeaturesVisibility(); + await readFeaturesVisibility(); enableOptionallyVisibleCommands(); let isLocalDebugEnabled: boolean = isOptionalFeatureEnabled("debug"); let isLocalRunningEnabled: boolean = isOptionalFeatureEnabled("run"); - if ((wasLocalDebugEnabled && !isLocalDebugEnabled) || (!wasLocalDebugEnabled && isLocalDebugEnabled) || - (wasLocalRunningEnabled && !isLocalRunningEnabled) || (!wasLocalRunningEnabled && isLocalRunningEnabled)) { + if ((wasLocalDebugEnabled !== isLocalDebugEnabled) || (wasLocalRunningEnabled !== isLocalRunningEnabled)) { extension._projectOutlineProvider.updateTree(); updatedSettingsSubkeys.push(subKey); } @@ -1423,7 +1425,7 @@ export async function initFromStateAndSettings(): Promise { // in the object makefile.launchConfigurations and makefile.configurations // apply exactly to the current launch configuration, since we don't collect and aggregate // information from all the array yet. - updatedSettingsSubkeys.forEach(subKey => { + updatedSettingsSubkeys.forEach(async (subKey) => { let key: string = keyRoot + "." + subKey; logger.message(`${key} setting changed.`, "Verbose"); try { @@ -1431,6 +1433,7 @@ export async function initFromStateAndSettings(): Promise { // to the telemetry function. Currently, the schema for such a setting // is represented differently than the workspace setting value. let settingObj: any; + let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration(keyRoot); if (subKey.includes(".")) { const subKeys: string[] = subKey.split("."); settingObj = workspaceConfiguration; @@ -1441,7 +1444,7 @@ export async function initFromStateAndSettings(): Promise { settingObj = workspaceConfiguration[subKey]; } - telemetryProperties = telemetry.analyzeSettings(settingObj, key, + telemetryProperties = await telemetry.analyzeSettings(settingObj, key, util.thisExtensionPackage().contributes.configuration.properties[key], false, telemetryProperties); } catch (e) { @@ -1453,12 +1456,16 @@ export async function initFromStateAndSettings(): Promise { telemetry.logEvent("settingsChanged", telemetryProperties); } } - }); + }); } export async function setConfigurationByName(configurationName: string): Promise { extension.getState().buildConfiguration = configurationName; + logger.message(`Setting configuration - ${configurationName}`); + logger.message("Re-reading settings after configuration change."); await setCurrentMakefileConfiguration(configurationName); + // Refresh settings, they may reference variables or commands reading state configuration var (${configuration}). + await initFromSettings(); extension._projectOutlineProvider.updateConfiguration(configurationName); } @@ -1518,7 +1525,7 @@ export async function setNewConfiguration(): Promise { let makefileonfigurationSetting: any = workspaceConfiguration[subKey]; if (makefileonfigurationSetting) { try { - telemetryProperties = telemetry.analyzeSettings(makefileonfigurationSetting, key, + telemetryProperties = await telemetry.analyzeSettings(makefileonfigurationSetting, key, util.thisExtensionPackage().contributes.configuration.properties[key], true, telemetryProperties); } catch (e) { @@ -1532,12 +1539,15 @@ export async function setNewConfiguration(): Promise { } } -export function setTargetByName(targetName: string) : void { +export async function setTargetByName(targetName: string) : Promise { currentTarget = targetName; let displayTarget: string = targetName ? currentTarget : "Default"; statusBar.setTarget(displayTarget); logger.message(`Setting target ${displayTarget}`); + logger.message("Re-reading settings after target change."); + // Refresh settings, they may reference variables or commands reading state target var (${buildTarget}). extension.getState().buildTarget = currentTarget; + await initFromSettings(); extension._projectOutlineProvider.updateBuildTarget(targetName); } @@ -1591,7 +1601,7 @@ export async function selectTarget(): Promise { }; telemetry.logEvent("stateChanged", telemetryProperties); - setTargetByName(chosen); + await setTargetByName(chosen); if (configureAfterCommand) { // The set of build targets remains the same even if the current target has changed @@ -1616,11 +1626,16 @@ export async function setLaunchConfigurationByName(launchConfigurationName: stri if (!currentLaunchConfiguration) { currentLaunchConfiguration = await stringToLaunchConfiguration(launchConfigurationName); if (currentLaunchConfiguration) { + // Read again all launch configurations from settings, so that we push this incoming into that array as well + // because we want to persist the original unexpanded content of launch configurations. + let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); + let launchConfigAsInSettings: LaunchConfiguration[] = workspaceConfiguration.get("launchConfigurations") || []; + launchConfigAsInSettings.push(currentLaunchConfiguration); + // Push into the processed 'in-memory' launch configurations array as well. launchConfigurations.push(currentLaunchConfiguration); // Avoid updating the launchConfigurations array in settings.json for regression tests. if (process.env['MAKEFILE_TOOLS_TESTING'] !== '1') { - let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); - workspaceConfiguration.update("launchConfigurations", launchConfigurations); + await workspaceConfiguration.update("launchConfigurations", launchConfigAsInSettings); } logger.message(`Inserting a new entry for ${launchConfigurationName} in the array of makefile.launchConfigurations. ` + "You may define any additional debug properties for it in settings."); @@ -1641,6 +1656,9 @@ export async function setLaunchConfigurationByName(launchConfigurationName: stri statusBar.setLaunchConfiguration("No launch configuration set"); } + // Refresh settings, they may reference variables or commands reading launch targets commands: ${command:makefile.getLaunchTargetPath} and others... + logger.message("Re-reading settings after launch target change."); + await initFromSettings(); await extension._projectOutlineProvider.updateLaunchTarget(launchConfigurationName); } @@ -1713,7 +1731,7 @@ export async function selectLaunchConfiguration(): Promise { let launchConfigurationSetting: any = workspaceConfiguration[subKey]; if (launchConfigurationSetting) { try { - telemetryProperties = telemetry.analyzeSettings(launchConfigurationSetting, key, + telemetryProperties = await telemetry.analyzeSettings(launchConfigurationSetting, key, util.thisExtensionPackage().contributes.configuration.properties[key], true, telemetryProperties); } catch (e) { diff --git a/src/extension.ts b/src/extension.ts index d9b8bcc..588dd68 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -209,10 +209,20 @@ export async function activate(context: vscode.ExtensionContext): Promise await configuration.setNewConfiguration(); })); + context.subscriptions.push(vscode.commands.registerCommand('makefile.getConfiguration', async () => { + telemetry.logEvent("getConfiguration"); + return configuration.getCurrentMakefileConfiguration(); + })); + context.subscriptions.push(vscode.commands.registerCommand('makefile.setBuildTarget', async () => { await configuration.selectTarget(); })); + context.subscriptions.push(vscode.commands.registerCommand('makefile.getBuildTarget', async () => { + telemetry.logEvent("getBuildTarget"); + return configuration.getCurrentTarget() || ""; + })); + context.subscriptions.push(vscode.commands.registerCommand('makefile.buildTarget', async () => { await make.buildTarget(make.TriggeredBy.buildTarget, configuration.getCurrentTarget() || "", false); })); @@ -342,15 +352,10 @@ export async function activate(context: vscode.ExtensionContext): Promise return vscode.commands.executeCommand("makefile.setBuildConfiguration"); })); - configuration.readLoggingLevel(); - configuration.readExtensionOutputFolder(); - configuration.readExtensionLog(); - - // Delete the extension log file, if exists - let extensionLog : string | undefined = configuration.getExtensionLog(); - if (extensionLog && util.checkFileExistsSync(extensionLog)) { - util.deleteFileSync(extensionLog); - } + // Read from the workspace state before reading from settings, + // becase the latter may use state info in variable expansion. + configuration.initFromState(); + await configuration.initFromSettings(true); // Delete the script that is created by this extension in the temporary folder // with the purpose of spliting a compilation command fragment into switch arguments @@ -364,9 +369,6 @@ export async function activate(context: vscode.ExtensionContext): Promise util.deleteFileSync(parseCompilerArgsScript); } - // Read configuration info from settings - await configuration.initFromStateAndSettings(); - if (configuration.getConfigureOnOpen() && extension.getFullFeatureSet()) { // Always clean configure on open await make.cleanConfigure(make.TriggeredBy.cleanConfigureOnOpen); @@ -376,7 +378,7 @@ export async function activate(context: vscode.ExtensionContext): Promise let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); let telemetryProperties: telemetry.Properties | null = {}; try { - telemetryProperties = telemetry.analyzeSettings(workspaceConfiguration, "makefile", + telemetryProperties = await telemetry.analyzeSettings(workspaceConfiguration, "makefile", util.thisExtensionPackage().contributes.configuration.properties, true, telemetryProperties); } catch (e) { diff --git a/src/make.ts b/src/make.ts index 0e7d789..ea5d3d6 100644 --- a/src/make.ts +++ b/src/make.ts @@ -1488,7 +1488,7 @@ export async function doConfigure(progress: vscode.Progress<{}>, cancel: vscode. // as the caller and its result will be included into the telemetry information reported by that. // There can be only one level of recursivity because once the target is reset to empty, // it is impossible to get into the state of having a target that is not found in the available list. - configuration.setTargetByName(""); + await configuration.setTargetByName(""); logger.message("Automatically reconfiguring the project after a build target change."); recursiveDoConfigure = true; diff --git a/src/telemetry.ts b/src/telemetry.ts index 5ebbc45..ce0551e 100644 --- a/src/telemetry.ts +++ b/src/telemetry.ts @@ -179,7 +179,7 @@ function filterKey(key: string): string { // If analyzeSettings gets called before a configure (or after an unsuccesful one), it is possible to have // inaccurate or incomplete telemetry information for makefile and launch configurations. // This is not very critical since any of their state changes will update telemetry for them. -export function analyzeSettings(setting: any, key: string, propSchema: any, ignoreDefault: boolean, telemetryProperties: Properties | null): Properties | null { +export async function analyzeSettings(setting: any, key: string, propSchema: any, ignoreDefault: boolean, telemetryProperties: Properties | null): Promise { // type can be undefined if setting is null, // which happens when the user removes that setting. let type : string | undefined = setting ? typeof (setting) : undefined; @@ -207,15 +207,19 @@ export function analyzeSettings(setting: any, key: string, propSchema: any, igno } // Enum values always safe to report. + // Validate the allowed values against the expanded variable. let enumValues: any[] = propSchema.enum; if (enumValues && enumValues.length > 0) { - if (!enumValues.includes(setting)) { - telemetryLogger(`Invalid value "${setting}" for enum "${key}". Only "${enumValues.join(";")}" values are allowed."`); + const regexp: RegExp = /(makefile\.)(.+)/mg; + const res: RegExpExecArray | null = regexp.exec(key); + let expandedSetting: string = res ? await util.getExpandedSetting(res[2]) : setting; + if (!enumValues.includes(expandedSetting)) { + telemetryLogger(`Invalid value "${expandedSetting}" for enum "${key}". Only "${enumValues.join(";")}" values are allowed."`); if (telemetryProperties) { telemetryProperties[filterKey(key)] = "invalid"; } } else if (telemetryProperties) { - telemetryProperties[filterKey(key)] = setting; + telemetryProperties[filterKey(key)] = expandedSetting; } return telemetryProperties; @@ -255,7 +259,7 @@ export function analyzeSettings(setting: any, key: string, propSchema: any, igno active = activeArrayItem(setting, key); } - settingsProps.forEach(prop => { + settingsProps.forEach(async (prop) => { index++; let jsonProps: any; let newPropObj: any = setting[prop]; @@ -302,7 +306,7 @@ export function analyzeSettings(setting: any, key: string, propSchema: any, igno if (type !== "function" /*&& jsonType !== undefined*/ && (jsonType !== "array" || prop !== "length")) { let newTelemetryProperties: Properties | null = {}; - newTelemetryProperties = analyzeSettings(newPropObj, key + "." + prop, jsonProps, ignoreDefault, + newTelemetryProperties = await analyzeSettings(newPropObj, key + "." + prop, jsonProps, ignoreDefault, ((jsonType !== "array" || index === active)) ? newTelemetryProperties : null); // If telemetryProperties is null, it means we're not interested in reporting any telemetry for this subtree diff --git a/src/test/fakeSuite/Repros/.vscode/settings.json b/src/test/fakeSuite/Repros/.vscode/settings.json index 00aa144..f1a000c 100644 --- a/src/test/fakeSuite/Repros/.vscode/settings.json +++ b/src/test/fakeSuite/Repros/.vscode/settings.json @@ -2,11 +2,20 @@ "C_Cpp.default.configurationProvider": "ms-vscode.makefile-tools", "makefile.buildLog": "./dummy_dryrun.log", "makefile.extensionOutputFolder": "./.vscode", + "makefile.extensionLog": "./.vscode/Makefile.out", "makefile.makePath": "c:/some/other/fake/path", + "makefile.buildBeforeLaunch": false, "makefile.loggingLevel": "Debug", "makefile.additionalCompilerNames": ["MyOwnFakeCompiler"], + "makefile.compileCommandsPath": "./.vscode/compile_commands.json", + "makefile.panel.visibility": { + "debug": true + }, "makefile.configureOnOpen": false, "makefile.configurations": [ + { + "name": "varexp", + }, { "name": "test-make-f", "makePath": "./doesnt/exist/make", diff --git a/src/test/fakeSuite/Repros/8cc_linux_baseline.out b/src/test/fakeSuite/Repros/8cc_linux_baseline.out index 3ee7704..6f017dd 100644 --- a/src/test/fakeSuite/Repros/8cc_linux_baseline.out +++ b/src/test/fakeSuite/Repros/8cc_linux_baseline.out @@ -2,6 +2,35 @@ Pre-configuring... Script: "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/preconfigure_nonwin.sh" The pre-configure succeeded. Setting configuration - 8cc_linux +Re-reading settings after configuration change. +Found build log path setting "./8cc_linux_dryrun.log" defined for configuration "8cc_linux" +Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/8cc_linux_dryrun.log" +Deduced command 'c:/some/other/fake/path ' for configuration "8cc_linux" +Dropping various extension output files at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode +Writing extension log at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/Makefile.out +Logging level: Debug +Configurations cached at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/configurationCache.log +No path to the makefile is defined in the settings file. +No folder path to the makefile is defined in the settings file. +Build log defined at "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/dummy_dryrun.log" +Always pre-configure: false +Dry-run switches: '--always-make', '--keep-going', '--print-directory' +Additional compiler names: 'MyOwnFakeCompiler' +Found the following configurations defined in makefile.configurations setting: varexp;test-make-f;test-make-C;complex_escaped_quotes;complex_escaped_quotes_winOnly;InterestingSmallMakefile_windows_configDebug;InterestingSmallMakefile_windows_configRelSize;InterestingSmallMakefile_windows_configRelSpeed;8cc_linux;8cc_mingw;Fido_linux;Fido_mingw;tinyvm_linux_pedantic;tinyvm_mingw_pedantic +No current launch configuration is set in the workspace state. +Default launch configuration: MIMode = undefined, + miDebuggerPath = undefined, + stopAtEntry = undefined, + symbolSearchPath = undefined +Configure on open: false +Configure on edit: true +Configure after command: true +Only .PHONY targets: false +Save before build or configure: true +Build before launch: false +Clear output before build: true +Ignore directory commands: true +compile_commands.json path: {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/compile_commands.json Found build log path setting "./8cc_linux_dryrun.log" defined for configuration "8cc_linux" Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/8cc_linux_dryrun.log" Deduced command 'c:/some/other/fake/path ' for configuration "8cc_linux" @@ -194,6 +223,35 @@ Configure succeeded. Configure elapsed time: 0 Inserting a new entry for {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros>8cc() in the array of makefile.launchConfigurations. You may define any additional debug properties for it in settings. Setting current launch target "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros>8cc()" +Re-reading settings after launch target change. +Dropping various extension output files at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode +Writing extension log at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/Makefile.out +Logging level: Debug +Configurations cached at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/configurationCache.log +No path to the makefile is defined in the settings file. +No folder path to the makefile is defined in the settings file. +Build log defined at "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/dummy_dryrun.log" +Always pre-configure: false +Dry-run switches: '--always-make', '--keep-going', '--print-directory' +Additional compiler names: 'MyOwnFakeCompiler' +Found the following configurations defined in makefile.configurations setting: varexp;test-make-f;test-make-C;complex_escaped_quotes;complex_escaped_quotes_winOnly;InterestingSmallMakefile_windows_configDebug;InterestingSmallMakefile_windows_configRelSize;InterestingSmallMakefile_windows_configRelSpeed;8cc_linux;8cc_mingw;Fido_linux;Fido_mingw;tinyvm_linux_pedantic;tinyvm_mingw_pedantic +Reading current launch configuration "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros>8cc()" from the workspace state. +Default launch configuration: MIMode = undefined, + miDebuggerPath = undefined, + stopAtEntry = undefined, + symbolSearchPath = undefined +Configure on open: false +Configure on edit: true +Configure after command: true +Only .PHONY targets: false +Save before build or configure: true +Build before launch: false +Clear output before build: true +Ignore directory commands: true +compile_commands.json path: {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/compile_commands.json +Found build log path setting "./8cc_linux_dryrun.log" defined for configuration "8cc_linux" +Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/8cc_linux_dryrun.log" +Deduced command 'c:/some/other/fake/path ' for configuration "8cc_linux" Created the following debug config: type = cppdbg cwd = {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros (= {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros) @@ -205,4 +263,33 @@ Created the following debug config: symbolSearchPath = undefined Running command '"{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/8cc" ' in the terminal from location '{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros' Setting target all +Re-reading settings after target change. +Dropping various extension output files at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode +Writing extension log at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/Makefile.out +Logging level: Debug +Configurations cached at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/configurationCache.log +No path to the makefile is defined in the settings file. +No folder path to the makefile is defined in the settings file. +Build log defined at "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/dummy_dryrun.log" +Always pre-configure: false +Dry-run switches: '--always-make', '--keep-going', '--print-directory' +Additional compiler names: 'MyOwnFakeCompiler' +Found the following configurations defined in makefile.configurations setting: varexp;test-make-f;test-make-C;complex_escaped_quotes;complex_escaped_quotes_winOnly;InterestingSmallMakefile_windows_configDebug;InterestingSmallMakefile_windows_configRelSize;InterestingSmallMakefile_windows_configRelSpeed;8cc_linux;8cc_mingw;Fido_linux;Fido_mingw;tinyvm_linux_pedantic;tinyvm_mingw_pedantic +Reading current launch configuration "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros>8cc()" from the workspace state. +Default launch configuration: MIMode = undefined, + miDebuggerPath = undefined, + stopAtEntry = undefined, + symbolSearchPath = undefined +Configure on open: false +Configure on edit: true +Configure after command: true +Only .PHONY targets: false +Save before build or configure: true +Build before launch: false +Clear output before build: true +Ignore directory commands: true +compile_commands.json path: {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/compile_commands.json +Found build log path setting "./8cc_linux_dryrun.log" defined for configuration "8cc_linux" +Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/8cc_linux_dryrun.log" +Deduced command 'c:/some/other/fake/path ' for configuration "8cc_linux" Building target "all" with command: 'c:/some/other/fake/path all' diff --git a/src/test/fakeSuite/Repros/Fido_linux_baseline.out b/src/test/fakeSuite/Repros/Fido_linux_baseline.out index 2bd71f9..540cd0e 100644 --- a/src/test/fakeSuite/Repros/Fido_linux_baseline.out +++ b/src/test/fakeSuite/Repros/Fido_linux_baseline.out @@ -2,6 +2,35 @@ Pre-configuring... Script: "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/preconfigure_nonwin.sh" The pre-configure succeeded. Setting configuration - Fido_linux +Re-reading settings after configuration change. +Found build log path setting "./Fido_linux_dryrun.log" defined for configuration "Fido_linux" +Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/Fido_linux_dryrun.log" +Deduced command 'c:/some/other/fake/path ' for configuration "Fido_linux" +Dropping various extension output files at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode +Writing extension log at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/Makefile.out +Logging level: Debug +Configurations cached at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/configurationCache.log +No path to the makefile is defined in the settings file. +No folder path to the makefile is defined in the settings file. +Build log defined at "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/dummy_dryrun.log" +Always pre-configure: false +Dry-run switches: '--always-make', '--keep-going', '--print-directory' +Additional compiler names: 'MyOwnFakeCompiler' +Found the following configurations defined in makefile.configurations setting: varexp;test-make-f;test-make-C;complex_escaped_quotes;complex_escaped_quotes_winOnly;InterestingSmallMakefile_windows_configDebug;InterestingSmallMakefile_windows_configRelSize;InterestingSmallMakefile_windows_configRelSpeed;8cc_linux;8cc_mingw;Fido_linux;Fido_mingw;tinyvm_linux_pedantic;tinyvm_mingw_pedantic +No current launch configuration is set in the workspace state. +Default launch configuration: MIMode = undefined, + miDebuggerPath = undefined, + stopAtEntry = undefined, + symbolSearchPath = undefined +Configure on open: false +Configure on edit: true +Configure after command: true +Only .PHONY targets: false +Save before build or configure: true +Build before launch: false +Clear output before build: true +Ignore directory commands: true +compile_commands.json path: {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/compile_commands.json Found build log path setting "./Fido_linux_dryrun.log" defined for configuration "Fido_linux" Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/Fido_linux_dryrun.log" Deduced command 'c:/some/other/fake/path ' for configuration "Fido_linux" @@ -214,6 +243,35 @@ Configure succeeded. Configure elapsed time: 0 Inserting a new entry for {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros>bin/foo.o() in the array of makefile.launchConfigurations. You may define any additional debug properties for it in settings. Setting current launch target "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros>bin/foo.o()" +Re-reading settings after launch target change. +Dropping various extension output files at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode +Writing extension log at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/Makefile.out +Logging level: Debug +Configurations cached at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/configurationCache.log +No path to the makefile is defined in the settings file. +No folder path to the makefile is defined in the settings file. +Build log defined at "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/dummy_dryrun.log" +Always pre-configure: false +Dry-run switches: '--always-make', '--keep-going', '--print-directory' +Additional compiler names: 'MyOwnFakeCompiler' +Found the following configurations defined in makefile.configurations setting: varexp;test-make-f;test-make-C;complex_escaped_quotes;complex_escaped_quotes_winOnly;InterestingSmallMakefile_windows_configDebug;InterestingSmallMakefile_windows_configRelSize;InterestingSmallMakefile_windows_configRelSpeed;8cc_linux;8cc_mingw;Fido_linux;Fido_mingw;tinyvm_linux_pedantic;tinyvm_mingw_pedantic +Reading current launch configuration "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros>bin/foo.o()" from the workspace state. +Default launch configuration: MIMode = undefined, + miDebuggerPath = undefined, + stopAtEntry = undefined, + symbolSearchPath = undefined +Configure on open: false +Configure on edit: true +Configure after command: true +Only .PHONY targets: false +Save before build or configure: true +Build before launch: false +Clear output before build: true +Ignore directory commands: true +compile_commands.json path: {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/compile_commands.json +Found build log path setting "./Fido_linux_dryrun.log" defined for configuration "Fido_linux" +Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/Fido_linux_dryrun.log" +Deduced command 'c:/some/other/fake/path ' for configuration "Fido_linux" Created the following debug config: type = cppdbg cwd = {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros (= {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros) @@ -225,4 +283,33 @@ Created the following debug config: symbolSearchPath = undefined Running command '"{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/bin/foo.o" ' in the terminal from location '{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros' Setting target bin/foo.o +Re-reading settings after target change. +Dropping various extension output files at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode +Writing extension log at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/Makefile.out +Logging level: Debug +Configurations cached at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/configurationCache.log +No path to the makefile is defined in the settings file. +No folder path to the makefile is defined in the settings file. +Build log defined at "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/dummy_dryrun.log" +Always pre-configure: false +Dry-run switches: '--always-make', '--keep-going', '--print-directory' +Additional compiler names: 'MyOwnFakeCompiler' +Found the following configurations defined in makefile.configurations setting: varexp;test-make-f;test-make-C;complex_escaped_quotes;complex_escaped_quotes_winOnly;InterestingSmallMakefile_windows_configDebug;InterestingSmallMakefile_windows_configRelSize;InterestingSmallMakefile_windows_configRelSpeed;8cc_linux;8cc_mingw;Fido_linux;Fido_mingw;tinyvm_linux_pedantic;tinyvm_mingw_pedantic +Reading current launch configuration "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros>bin/foo.o()" from the workspace state. +Default launch configuration: MIMode = undefined, + miDebuggerPath = undefined, + stopAtEntry = undefined, + symbolSearchPath = undefined +Configure on open: false +Configure on edit: true +Configure after command: true +Only .PHONY targets: false +Save before build or configure: true +Build before launch: false +Clear output before build: true +Ignore directory commands: true +compile_commands.json path: {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/compile_commands.json +Found build log path setting "./Fido_linux_dryrun.log" defined for configuration "Fido_linux" +Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/Fido_linux_dryrun.log" +Deduced command 'c:/some/other/fake/path ' for configuration "Fido_linux" Building target "bin/foo.o" with command: 'c:/some/other/fake/path bin/foo.o' diff --git a/src/test/fakeSuite/Repros/InterestingSmallMakefile_windows_baseline.out b/src/test/fakeSuite/Repros/InterestingSmallMakefile_windows_baseline.out index 581d909..b171960 100644 --- a/src/test/fakeSuite/Repros/InterestingSmallMakefile_windows_baseline.out +++ b/src/test/fakeSuite/Repros/InterestingSmallMakefile_windows_baseline.out @@ -4,6 +4,35 @@ Script: "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\preconfi {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros>call "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\preconfigure.bat" The pre-configure succeeded. Setting configuration - InterestingSmallMakefile_windows_configDebug +Re-reading settings after configuration change. +Found build log path setting "./InterestingSmallMakefile_windows_dryrunDebug.log" defined for configuration "InterestingSmallMakefile_windows_configDebug" +Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\InterestingSmallMakefile_windows_dryrunDebug.log" +Deduced command 'c:\some\other\fake\path.exe ' for configuration "InterestingSmallMakefile_windows_configDebug" +Dropping various extension output files at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode +Writing extension log at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\Makefile.out +Logging level: Debug +Configurations cached at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\configurationCache.log +No path to the makefile is defined in the settings file. +No folder path to the makefile is defined in the settings file. +Build log defined at "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\dummy_dryrun.log" +Always pre-configure: false +Dry-run switches: '--always-make', '--keep-going', '--print-directory' +Additional compiler names: 'MyOwnFakeCompiler' +Found the following configurations defined in makefile.configurations setting: varexp;test-make-f;test-make-C;complex_escaped_quotes;complex_escaped_quotes_winOnly;InterestingSmallMakefile_windows_configDebug;InterestingSmallMakefile_windows_configRelSize;InterestingSmallMakefile_windows_configRelSpeed;8cc_linux;8cc_mingw;Fido_linux;Fido_mingw;tinyvm_linux_pedantic;tinyvm_mingw_pedantic +No current launch configuration is set in the workspace state. +Default launch configuration: MIMode = undefined, + miDebuggerPath = undefined, + stopAtEntry = undefined, + symbolSearchPath = undefined +Configure on open: false +Configure on edit: true +Configure after command: true +Only .PHONY targets: false +Save before build or configure: true +Build before launch: false +Clear output before build: true +Ignore directory commands: true +compile_commands.json path: {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\compile_commands.json Found build log path setting "./InterestingSmallMakefile_windows_dryrunDebug.log" defined for configuration "InterestingSmallMakefile_windows_configDebug" Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\InterestingSmallMakefile_windows_dryrunDebug.log" Deduced command 'c:\some\other\fake\path.exe ' for configuration "InterestingSmallMakefile_windows_configDebug" @@ -204,6 +233,35 @@ Configure succeeded. Configure elapsed time: 0 Inserting a new entry for {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros>bin\InterestingSmallMakefile\ARC H3\Debug\main.exe(str3a,str3b,str3c) in the array of makefile.launchConfigurations. You may define any additional debug properties for it in settings. Setting current launch target "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros>bin\InterestingSmallMakefile\ARC H3\Debug\main.exe(str3a,str3b,str3c)" +Re-reading settings after launch target change. +Dropping various extension output files at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode +Writing extension log at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\Makefile.out +Logging level: Debug +Configurations cached at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\configurationCache.log +No path to the makefile is defined in the settings file. +No folder path to the makefile is defined in the settings file. +Build log defined at "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\dummy_dryrun.log" +Always pre-configure: false +Dry-run switches: '--always-make', '--keep-going', '--print-directory' +Additional compiler names: 'MyOwnFakeCompiler' +Found the following configurations defined in makefile.configurations setting: varexp;test-make-f;test-make-C;complex_escaped_quotes;complex_escaped_quotes_winOnly;InterestingSmallMakefile_windows_configDebug;InterestingSmallMakefile_windows_configRelSize;InterestingSmallMakefile_windows_configRelSpeed;8cc_linux;8cc_mingw;Fido_linux;Fido_mingw;tinyvm_linux_pedantic;tinyvm_mingw_pedantic +Reading current launch configuration "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros>bin\InterestingSmallMakefile\ARC H3\Debug\main.exe(str3a,str3b,str3c)" from the workspace state. +Default launch configuration: MIMode = undefined, + miDebuggerPath = undefined, + stopAtEntry = undefined, + symbolSearchPath = undefined +Configure on open: false +Configure on edit: true +Configure after command: true +Only .PHONY targets: false +Save before build or configure: true +Build before launch: false +Clear output before build: true +Ignore directory commands: true +compile_commands.json path: {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\compile_commands.json +Found build log path setting "./InterestingSmallMakefile_windows_dryrunDebug.log" defined for configuration "InterestingSmallMakefile_windows_configDebug" +Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\InterestingSmallMakefile_windows_dryrunDebug.log" +Deduced command 'c:\some\other\fake\path.exe ' for configuration "InterestingSmallMakefile_windows_configDebug" Created the following debug config: type = cppvsdbg cwd = {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros (= {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros) @@ -216,6 +274,35 @@ Created the following debug config: Running command '"{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\bin\InterestingSmallMakefile\ARC H3\Debug\main.exe" str3a str3b str3c' in the terminal from location '{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros' Inserting a new entry for {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros>bin\InterestingSmallMakefile\arch1\Debug\main.exe(str3a,str3b,str3c) in the array of makefile.launchConfigurations. You may define any additional debug properties for it in settings. Setting current launch target "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros>bin\InterestingSmallMakefile\arch1\Debug\main.exe(str3a,str3b,str3c)" +Re-reading settings after launch target change. +Dropping various extension output files at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode +Writing extension log at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\Makefile.out +Logging level: Debug +Configurations cached at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\configurationCache.log +No path to the makefile is defined in the settings file. +No folder path to the makefile is defined in the settings file. +Build log defined at "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\dummy_dryrun.log" +Always pre-configure: false +Dry-run switches: '--always-make', '--keep-going', '--print-directory' +Additional compiler names: 'MyOwnFakeCompiler' +Found the following configurations defined in makefile.configurations setting: varexp;test-make-f;test-make-C;complex_escaped_quotes;complex_escaped_quotes_winOnly;InterestingSmallMakefile_windows_configDebug;InterestingSmallMakefile_windows_configRelSize;InterestingSmallMakefile_windows_configRelSpeed;8cc_linux;8cc_mingw;Fido_linux;Fido_mingw;tinyvm_linux_pedantic;tinyvm_mingw_pedantic +Reading current launch configuration "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros>bin\InterestingSmallMakefile\arch1\Debug\main.exe(str3a,str3b,str3c)" from the workspace state. +Default launch configuration: MIMode = undefined, + miDebuggerPath = undefined, + stopAtEntry = undefined, + symbolSearchPath = undefined +Configure on open: false +Configure on edit: true +Configure after command: true +Only .PHONY targets: false +Save before build or configure: true +Build before launch: false +Clear output before build: true +Ignore directory commands: true +compile_commands.json path: {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\compile_commands.json +Found build log path setting "./InterestingSmallMakefile_windows_dryrunDebug.log" defined for configuration "InterestingSmallMakefile_windows_configDebug" +Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\InterestingSmallMakefile_windows_dryrunDebug.log" +Deduced command 'c:\some\other\fake\path.exe ' for configuration "InterestingSmallMakefile_windows_configDebug" Created the following debug config: type = cppvsdbg cwd = {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros (= {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros) @@ -228,6 +315,35 @@ Created the following debug config: Running command '"{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\bin\InterestingSmallMakefile\arch1\Debug\main.exe" str3a str3b str3c' in the terminal from location '{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros' Inserting a new entry for {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros>bin\InterestingSmallMakefile\arch2\Debug\main.exe() in the array of makefile.launchConfigurations. You may define any additional debug properties for it in settings. Setting current launch target "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros>bin\InterestingSmallMakefile\arch2\Debug\main.exe()" +Re-reading settings after launch target change. +Dropping various extension output files at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode +Writing extension log at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\Makefile.out +Logging level: Debug +Configurations cached at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\configurationCache.log +No path to the makefile is defined in the settings file. +No folder path to the makefile is defined in the settings file. +Build log defined at "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\dummy_dryrun.log" +Always pre-configure: false +Dry-run switches: '--always-make', '--keep-going', '--print-directory' +Additional compiler names: 'MyOwnFakeCompiler' +Found the following configurations defined in makefile.configurations setting: varexp;test-make-f;test-make-C;complex_escaped_quotes;complex_escaped_quotes_winOnly;InterestingSmallMakefile_windows_configDebug;InterestingSmallMakefile_windows_configRelSize;InterestingSmallMakefile_windows_configRelSpeed;8cc_linux;8cc_mingw;Fido_linux;Fido_mingw;tinyvm_linux_pedantic;tinyvm_mingw_pedantic +Reading current launch configuration "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros>bin\InterestingSmallMakefile\arch2\Debug\main.exe()" from the workspace state. +Default launch configuration: MIMode = undefined, + miDebuggerPath = undefined, + stopAtEntry = undefined, + symbolSearchPath = undefined +Configure on open: false +Configure on edit: true +Configure after command: true +Only .PHONY targets: false +Save before build or configure: true +Build before launch: false +Clear output before build: true +Ignore directory commands: true +compile_commands.json path: {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\compile_commands.json +Found build log path setting "./InterestingSmallMakefile_windows_dryrunDebug.log" defined for configuration "InterestingSmallMakefile_windows_configDebug" +Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\InterestingSmallMakefile_windows_dryrunDebug.log" +Deduced command 'c:\some\other\fake\path.exe ' for configuration "InterestingSmallMakefile_windows_configDebug" Created the following debug config: type = cppvsdbg cwd = {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros (= {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros) @@ -239,10 +355,93 @@ Created the following debug config: symbolSearchPath = undefined Running command '"{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\bin\InterestingSmallMakefile\arch2\Debug\main.exe" ' in the terminal from location '{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros' Setting configuration - InterestingSmallMakefile_windows_configRelSize +Re-reading settings after configuration change. +Found build log path setting "./InterestingSmallMakefile_windows_dryrunRelSize.log" defined for configuration "InterestingSmallMakefile_windows_configRelSize" +Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\InterestingSmallMakefile_windows_dryrunRelSize.log" +Deduced command 'c:\some\other\fake\make.exe OPT=RelSize' for configuration "InterestingSmallMakefile_windows_configRelSize" +Dropping various extension output files at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode +Writing extension log at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\Makefile.out +Logging level: Debug +Configurations cached at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\configurationCache.log +No path to the makefile is defined in the settings file. +No folder path to the makefile is defined in the settings file. +Build log defined at "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\dummy_dryrun.log" +Always pre-configure: false +Dry-run switches: '--always-make', '--keep-going', '--print-directory' +Additional compiler names: 'MyOwnFakeCompiler' +Found the following configurations defined in makefile.configurations setting: varexp;test-make-f;test-make-C;complex_escaped_quotes;complex_escaped_quotes_winOnly;InterestingSmallMakefile_windows_configDebug;InterestingSmallMakefile_windows_configRelSize;InterestingSmallMakefile_windows_configRelSpeed;8cc_linux;8cc_mingw;Fido_linux;Fido_mingw;tinyvm_linux_pedantic;tinyvm_mingw_pedantic +Reading current launch configuration "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros>bin\InterestingSmallMakefile\arch2\Debug\main.exe()" from the workspace state. +Default launch configuration: MIMode = undefined, + miDebuggerPath = undefined, + stopAtEntry = undefined, + symbolSearchPath = undefined +Configure on open: false +Configure on edit: true +Configure after command: true +Only .PHONY targets: false +Save before build or configure: true +Build before launch: false +Clear output before build: true +Ignore directory commands: true +compile_commands.json path: {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\compile_commands.json Found build log path setting "./InterestingSmallMakefile_windows_dryrunRelSize.log" defined for configuration "InterestingSmallMakefile_windows_configRelSize" Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\InterestingSmallMakefile_windows_dryrunRelSize.log" Deduced command 'c:\some\other\fake\make.exe OPT=RelSize' for configuration "InterestingSmallMakefile_windows_configRelSize" Setting configuration - InterestingSmallMakefile_windows_configRelSpeed +Re-reading settings after configuration change. +Deduced command 'c:\fake\path\make.exe OPT=RelSpeed' for configuration "InterestingSmallMakefile_windows_configRelSpeed" +Dropping various extension output files at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode +Writing extension log at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\Makefile.out +Logging level: Debug +Configurations cached at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\configurationCache.log +No path to the makefile is defined in the settings file. +No folder path to the makefile is defined in the settings file. +Build log defined at "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\dummy_dryrun.log" +Always pre-configure: false +Dry-run switches: '--always-make', '--keep-going', '--print-directory' +Additional compiler names: 'MyOwnFakeCompiler' +Found the following configurations defined in makefile.configurations setting: varexp;test-make-f;test-make-C;complex_escaped_quotes;complex_escaped_quotes_winOnly;InterestingSmallMakefile_windows_configDebug;InterestingSmallMakefile_windows_configRelSize;InterestingSmallMakefile_windows_configRelSpeed;8cc_linux;8cc_mingw;Fido_linux;Fido_mingw;tinyvm_linux_pedantic;tinyvm_mingw_pedantic +Reading current launch configuration "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros>bin\InterestingSmallMakefile\arch2\Debug\main.exe()" from the workspace state. +Default launch configuration: MIMode = undefined, + miDebuggerPath = undefined, + stopAtEntry = undefined, + symbolSearchPath = undefined +Configure on open: false +Configure on edit: true +Configure after command: true +Only .PHONY targets: false +Save before build or configure: true +Build before launch: false +Clear output before build: true +Ignore directory commands: true +compile_commands.json path: {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\compile_commands.json Deduced command 'c:\fake\path\make.exe OPT=RelSpeed' for configuration "InterestingSmallMakefile_windows_configRelSpeed" Setting target Execute_Arch3 +Re-reading settings after target change. +Dropping various extension output files at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode +Writing extension log at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\Makefile.out +Logging level: Debug +Configurations cached at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\configurationCache.log +No path to the makefile is defined in the settings file. +No folder path to the makefile is defined in the settings file. +Build log defined at "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\dummy_dryrun.log" +Always pre-configure: false +Dry-run switches: '--always-make', '--keep-going', '--print-directory' +Additional compiler names: 'MyOwnFakeCompiler' +Found the following configurations defined in makefile.configurations setting: varexp;test-make-f;test-make-C;complex_escaped_quotes;complex_escaped_quotes_winOnly;InterestingSmallMakefile_windows_configDebug;InterestingSmallMakefile_windows_configRelSize;InterestingSmallMakefile_windows_configRelSpeed;8cc_linux;8cc_mingw;Fido_linux;Fido_mingw;tinyvm_linux_pedantic;tinyvm_mingw_pedantic +Reading current launch configuration "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros>bin\InterestingSmallMakefile\arch2\Debug\main.exe()" from the workspace state. +Default launch configuration: MIMode = undefined, + miDebuggerPath = undefined, + stopAtEntry = undefined, + symbolSearchPath = undefined +Configure on open: false +Configure on edit: true +Configure after command: true +Only .PHONY targets: false +Save before build or configure: true +Build before launch: false +Clear output before build: true +Ignore directory commands: true +compile_commands.json path: {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\compile_commands.json +Deduced command 'c:\fake\path\make.exe OPT=RelSpeed' for configuration "InterestingSmallMakefile_windows_configRelSpeed" Building target "Execute_Arch3" with command: 'c:\fake\path\make.exe Execute_Arch3 OPT=RelSpeed' diff --git a/src/test/fakeSuite/Repros/complex_escaped_quotes_baseline.out b/src/test/fakeSuite/Repros/complex_escaped_quotes_baseline.out index 6f73fdc..bae69dc 100644 --- a/src/test/fakeSuite/Repros/complex_escaped_quotes_baseline.out +++ b/src/test/fakeSuite/Repros/complex_escaped_quotes_baseline.out @@ -4,6 +4,35 @@ Script: "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\preconfi {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros>call "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\preconfigure.bat" The pre-configure succeeded. Setting configuration - complex_escaped_quotes +Re-reading settings after configuration change. +Found build log path setting "./complex_escaped_quotes_dryrun.log" defined for configuration "complex_escaped_quotes" +Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\complex_escaped_quotes_dryrun.log" +Deduced command 'c:\some\other\fake\path.exe ' for configuration "complex_escaped_quotes" +Dropping various extension output files at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode +Writing extension log at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\Makefile.out +Logging level: Debug +Configurations cached at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\configurationCache.log +No path to the makefile is defined in the settings file. +No folder path to the makefile is defined in the settings file. +Build log defined at "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\dummy_dryrun.log" +Always pre-configure: false +Dry-run switches: '--always-make', '--keep-going', '--print-directory' +Additional compiler names: 'MyOwnFakeCompiler' +Found the following configurations defined in makefile.configurations setting: varexp;test-make-f;test-make-C;complex_escaped_quotes;complex_escaped_quotes_winOnly;InterestingSmallMakefile_windows_configDebug;InterestingSmallMakefile_windows_configRelSize;InterestingSmallMakefile_windows_configRelSpeed;8cc_linux;8cc_mingw;Fido_linux;Fido_mingw;tinyvm_linux_pedantic;tinyvm_mingw_pedantic +No current launch configuration is set in the workspace state. +Default launch configuration: MIMode = undefined, + miDebuggerPath = undefined, + stopAtEntry = undefined, + symbolSearchPath = undefined +Configure on open: false +Configure on edit: true +Configure after command: true +Only .PHONY targets: false +Save before build or configure: true +Build before launch: false +Clear output before build: true +Ignore directory commands: true +compile_commands.json path: {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\compile_commands.json Found build log path setting "./complex_escaped_quotes_dryrun.log" defined for configuration "complex_escaped_quotes" Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\complex_escaped_quotes_dryrun.log" Deduced command 'c:\some\other\fake\path.exe ' for configuration "complex_escaped_quotes" diff --git a/src/test/fakeSuite/Repros/complex_escaped_quotes_nonWin_baseline.out b/src/test/fakeSuite/Repros/complex_escaped_quotes_nonWin_baseline.out index 15b4feb..03372b3 100644 --- a/src/test/fakeSuite/Repros/complex_escaped_quotes_nonWin_baseline.out +++ b/src/test/fakeSuite/Repros/complex_escaped_quotes_nonWin_baseline.out @@ -2,6 +2,35 @@ Pre-configuring... Script: "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/preconfigure_nonwin.sh" The pre-configure succeeded. Setting configuration - complex_escaped_quotes +Re-reading settings after configuration change. +Found build log path setting "./complex_escaped_quotes_dryrun.log" defined for configuration "complex_escaped_quotes" +Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/complex_escaped_quotes_dryrun.log" +Deduced command 'c:/some/other/fake/path ' for configuration "complex_escaped_quotes" +Dropping various extension output files at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode +Writing extension log at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/Makefile.out +Logging level: Debug +Configurations cached at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/configurationCache.log +No path to the makefile is defined in the settings file. +No folder path to the makefile is defined in the settings file. +Build log defined at "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/dummy_dryrun.log" +Always pre-configure: false +Dry-run switches: '--always-make', '--keep-going', '--print-directory' +Additional compiler names: 'MyOwnFakeCompiler' +Found the following configurations defined in makefile.configurations setting: varexp;test-make-f;test-make-C;complex_escaped_quotes;complex_escaped_quotes_winOnly;InterestingSmallMakefile_windows_configDebug;InterestingSmallMakefile_windows_configRelSize;InterestingSmallMakefile_windows_configRelSpeed;8cc_linux;8cc_mingw;Fido_linux;Fido_mingw;tinyvm_linux_pedantic;tinyvm_mingw_pedantic +No current launch configuration is set in the workspace state. +Default launch configuration: MIMode = undefined, + miDebuggerPath = undefined, + stopAtEntry = undefined, + symbolSearchPath = undefined +Configure on open: false +Configure on edit: true +Configure after command: true +Only .PHONY targets: false +Save before build or configure: true +Build before launch: false +Clear output before build: true +Ignore directory commands: true +compile_commands.json path: {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/compile_commands.json Found build log path setting "./complex_escaped_quotes_dryrun.log" defined for configuration "complex_escaped_quotes" Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/complex_escaped_quotes_dryrun.log" Deduced command 'c:/some/other/fake/path ' for configuration "complex_escaped_quotes" diff --git a/src/test/fakeSuite/Repros/complex_escaped_quotes_winOnly_baseline.out b/src/test/fakeSuite/Repros/complex_escaped_quotes_winOnly_baseline.out index 37b9481..b2c98c8 100644 --- a/src/test/fakeSuite/Repros/complex_escaped_quotes_winOnly_baseline.out +++ b/src/test/fakeSuite/Repros/complex_escaped_quotes_winOnly_baseline.out @@ -4,6 +4,35 @@ Script: "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\preconfi {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros>call "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\preconfigure.bat" The pre-configure succeeded. Setting configuration - complex_escaped_quotes_winOnly +Re-reading settings after configuration change. +Found build log path setting "./complex_escaped_quotes_winOnly_dryrun.log" defined for configuration "complex_escaped_quotes_winOnly" +Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\complex_escaped_quotes_winOnly_dryrun.log" +Deduced command 'c:\some\other\fake\path.exe ' for configuration "complex_escaped_quotes_winOnly" +Dropping various extension output files at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode +Writing extension log at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\Makefile.out +Logging level: Debug +Configurations cached at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\configurationCache.log +No path to the makefile is defined in the settings file. +No folder path to the makefile is defined in the settings file. +Build log defined at "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\dummy_dryrun.log" +Always pre-configure: false +Dry-run switches: '--always-make', '--keep-going', '--print-directory' +Additional compiler names: 'MyOwnFakeCompiler' +Found the following configurations defined in makefile.configurations setting: varexp;test-make-f;test-make-C;complex_escaped_quotes;complex_escaped_quotes_winOnly;InterestingSmallMakefile_windows_configDebug;InterestingSmallMakefile_windows_configRelSize;InterestingSmallMakefile_windows_configRelSpeed;8cc_linux;8cc_mingw;Fido_linux;Fido_mingw;tinyvm_linux_pedantic;tinyvm_mingw_pedantic +No current launch configuration is set in the workspace state. +Default launch configuration: MIMode = undefined, + miDebuggerPath = undefined, + stopAtEntry = undefined, + symbolSearchPath = undefined +Configure on open: false +Configure on edit: true +Configure after command: true +Only .PHONY targets: false +Save before build or configure: true +Build before launch: false +Clear output before build: true +Ignore directory commands: true +compile_commands.json path: {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\compile_commands.json Found build log path setting "./complex_escaped_quotes_winOnly_dryrun.log" defined for configuration "complex_escaped_quotes_winOnly" Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\complex_escaped_quotes_winOnly_dryrun.log" Deduced command 'c:\some\other\fake\path.exe ' for configuration "complex_escaped_quotes_winOnly" diff --git a/src/test/fakeSuite/Repros/test_real_make_nonWin_baseline.out b/src/test/fakeSuite/Repros/test_real_make_nonWin_baseline.out index b4bc952..fccf94f 100644 --- a/src/test/fakeSuite/Repros/test_real_make_nonWin_baseline.out +++ b/src/test/fakeSuite/Repros/test_real_make_nonWin_baseline.out @@ -1,4 +1,35 @@ Setting configuration - test-make-f +Re-reading settings after configuration change. +Found build log path setting "./doesnt_exist.log" defined for configuration "test-make-f" +Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/doesnt_exist.log" +Build log not found. Remove the build log setting or provide a build log file on disk at the given location. +Deduced command 'doesnt/exist/make -f ./SubDir/makefile with space' for configuration "test-make-f" +Make was not found on disk at the location provided via makefile.makePath or makefile.configurations[].makePath. +Dropping various extension output files at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode +Writing extension log at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/Makefile.out +Logging level: Debug +Configurations cached at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/configurationCache.log +No path to the makefile is defined in the settings file. +No folder path to the makefile is defined in the settings file. +Build log defined at "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/dummy_dryrun.log" +Always pre-configure: false +Dry-run switches: '--always-make', '--keep-going', '--print-directory' +Additional compiler names: 'MyOwnFakeCompiler' +Found the following configurations defined in makefile.configurations setting: varexp;test-make-f;test-make-C;complex_escaped_quotes;complex_escaped_quotes_winOnly;InterestingSmallMakefile_windows_configDebug;InterestingSmallMakefile_windows_configRelSize;InterestingSmallMakefile_windows_configRelSpeed;8cc_linux;8cc_mingw;Fido_linux;Fido_mingw;tinyvm_linux_pedantic;tinyvm_mingw_pedantic +No current launch configuration is set in the workspace state. +Default launch configuration: MIMode = undefined, + miDebuggerPath = undefined, + stopAtEntry = undefined, + symbolSearchPath = undefined +Configure on open: false +Configure on edit: true +Configure after command: true +Only .PHONY targets: false +Save before build or configure: true +Build before launch: false +Clear output before build: true +Ignore directory commands: true +compile_commands.json path: {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/compile_commands.json Found build log path setting "./doesnt_exist.log" defined for configuration "test-make-f" Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/doesnt_exist.log" Build log not found. Remove the build log setting or provide a build log file on disk at the given location. @@ -62,6 +93,37 @@ parseTargets: return code = 0, elapsed time = 0 Configure succeeded. Configure elapsed time: 0 Setting configuration - test-make-C +Re-reading settings after configuration change. +Found build log path setting "./doesnt_exist.log" defined for configuration "test-make-C" +Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/doesnt_exist.log" +Build log not found. Remove the build log setting or provide a build log file on disk at the given location. +Deduced command 'doesnt/exist/make -C {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/SubDir with space/' for configuration "test-make-C" +Make was not found on disk at the location provided via makefile.makePath or makefile.configurations[].makePath. +Dropping various extension output files at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode +Writing extension log at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/Makefile.out +Logging level: Debug +Configurations cached at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/configurationCache.log +No path to the makefile is defined in the settings file. +No folder path to the makefile is defined in the settings file. +Build log defined at "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/dummy_dryrun.log" +Always pre-configure: false +Dry-run switches: '--always-make', '--keep-going', '--print-directory' +Additional compiler names: 'MyOwnFakeCompiler' +Found the following configurations defined in makefile.configurations setting: varexp;test-make-f;test-make-C;complex_escaped_quotes;complex_escaped_quotes_winOnly;InterestingSmallMakefile_windows_configDebug;InterestingSmallMakefile_windows_configRelSize;InterestingSmallMakefile_windows_configRelSpeed;8cc_linux;8cc_mingw;Fido_linux;Fido_mingw;tinyvm_linux_pedantic;tinyvm_mingw_pedantic +No current launch configuration is set in the workspace state. +Default launch configuration: MIMode = undefined, + miDebuggerPath = undefined, + stopAtEntry = undefined, + symbolSearchPath = undefined +Configure on open: false +Configure on edit: true +Configure after command: true +Only .PHONY targets: false +Save before build or configure: true +Build before launch: false +Clear output before build: true +Ignore directory commands: true +compile_commands.json path: {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/compile_commands.json Found build log path setting "./doesnt_exist.log" defined for configuration "test-make-C" Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/doesnt_exist.log" Build log not found. Remove the build log setting or provide a build log file on disk at the given location. diff --git a/src/test/fakeSuite/Repros/test_real_make_windows_baseline.out b/src/test/fakeSuite/Repros/test_real_make_windows_baseline.out index f084d2d..f8e639c 100644 --- a/src/test/fakeSuite/Repros/test_real_make_windows_baseline.out +++ b/src/test/fakeSuite/Repros/test_real_make_windows_baseline.out @@ -1,4 +1,35 @@ Setting configuration - test-make-f +Re-reading settings after configuration change. +Found build log path setting "./doesnt_exist.log" defined for configuration "test-make-f" +Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\doesnt_exist.log" +Build log not found. Remove the build log setting or provide a build log file on disk at the given location. +Deduced command 'doesnt\exist\make.exe -f ./SubDir/makefile with space' for configuration "test-make-f" +Make was not found on disk at the location provided via makefile.makePath or makefile.configurations[].makePath. +Dropping various extension output files at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode +Writing extension log at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\Makefile.out +Logging level: Debug +Configurations cached at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\configurationCache.log +No path to the makefile is defined in the settings file. +No folder path to the makefile is defined in the settings file. +Build log defined at "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\dummy_dryrun.log" +Always pre-configure: false +Dry-run switches: '--always-make', '--keep-going', '--print-directory' +Additional compiler names: 'MyOwnFakeCompiler' +Found the following configurations defined in makefile.configurations setting: varexp;test-make-f;test-make-C;complex_escaped_quotes;complex_escaped_quotes_winOnly;InterestingSmallMakefile_windows_configDebug;InterestingSmallMakefile_windows_configRelSize;InterestingSmallMakefile_windows_configRelSpeed;8cc_linux;8cc_mingw;Fido_linux;Fido_mingw;tinyvm_linux_pedantic;tinyvm_mingw_pedantic +No current launch configuration is set in the workspace state. +Default launch configuration: MIMode = undefined, + miDebuggerPath = undefined, + stopAtEntry = undefined, + symbolSearchPath = undefined +Configure on open: false +Configure on edit: true +Configure after command: true +Only .PHONY targets: false +Save before build or configure: true +Build before launch: false +Clear output before build: true +Ignore directory commands: true +compile_commands.json path: {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\compile_commands.json Found build log path setting "./doesnt_exist.log" defined for configuration "test-make-f" Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\doesnt_exist.log" Build log not found. Remove the build log setting or provide a build log file on disk at the given location. @@ -62,6 +93,37 @@ parseTargets: return code = 0, elapsed time = 0 Configure succeeded. Configure elapsed time: 0 Setting configuration - test-make-C +Re-reading settings after configuration change. +Found build log path setting "./doesnt_exist.log" defined for configuration "test-make-C" +Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\doesnt_exist.log" +Build log not found. Remove the build log setting or provide a build log file on disk at the given location. +Deduced command 'doesnt\exist\make.exe -C {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\SubDir with space\' for configuration "test-make-C" +Make was not found on disk at the location provided via makefile.makePath or makefile.configurations[].makePath. +Dropping various extension output files at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode +Writing extension log at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\Makefile.out +Logging level: Debug +Configurations cached at {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\configurationCache.log +No path to the makefile is defined in the settings file. +No folder path to the makefile is defined in the settings file. +Build log defined at "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\dummy_dryrun.log" +Always pre-configure: false +Dry-run switches: '--always-make', '--keep-going', '--print-directory' +Additional compiler names: 'MyOwnFakeCompiler' +Found the following configurations defined in makefile.configurations setting: varexp;test-make-f;test-make-C;complex_escaped_quotes;complex_escaped_quotes_winOnly;InterestingSmallMakefile_windows_configDebug;InterestingSmallMakefile_windows_configRelSize;InterestingSmallMakefile_windows_configRelSpeed;8cc_linux;8cc_mingw;Fido_linux;Fido_mingw;tinyvm_linux_pedantic;tinyvm_mingw_pedantic +No current launch configuration is set in the workspace state. +Default launch configuration: MIMode = undefined, + miDebuggerPath = undefined, + stopAtEntry = undefined, + symbolSearchPath = undefined +Configure on open: false +Configure on edit: true +Configure after command: true +Only .PHONY targets: false +Save before build or configure: true +Build before launch: false +Clear output before build: true +Ignore directory commands: true +compile_commands.json path: {REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\.vscode\compile_commands.json Found build log path setting "./doesnt_exist.log" defined for configuration "test-make-C" Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros\doesnt_exist.log" Build log not found. Remove the build log setting or provide a build log file on disk at the given location. diff --git a/src/test/fakeSuite/Repros/tinyvm_linux_baseline.out b/src/test/fakeSuite/Repros/tinyvm_linux_baseline.out index 78e0ec2..687182f 100644 --- a/src/test/fakeSuite/Repros/tinyvm_linux_baseline.out +++ b/src/test/fakeSuite/Repros/tinyvm_linux_baseline.out @@ -2,6 +2,35 @@ Pre-configuring... Script: "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/preconfigure_nonwin.sh" The pre-configure succeeded. Setting configuration - tinyvm_linux_pedantic +Re-reading settings after configuration change. +Found build log path setting "./tinyvm_linux_dryrunPedantic.log" defined for configuration "tinyvm_linux_pedantic" +Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/tinyvm_linux_dryrunPedantic.log" +Deduced command 'c:/some/other/fake/make PEDANTIC=yes' for configuration "tinyvm_linux_pedantic" +Dropping various extension output files at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode +Writing extension log at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/Makefile.out +Logging level: Debug +Configurations cached at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/configurationCache.log +No path to the makefile is defined in the settings file. +No folder path to the makefile is defined in the settings file. +Build log defined at "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/dummy_dryrun.log" +Always pre-configure: false +Dry-run switches: '--always-make', '--keep-going', '--print-directory' +Additional compiler names: 'MyOwnFakeCompiler' +Found the following configurations defined in makefile.configurations setting: varexp;test-make-f;test-make-C;complex_escaped_quotes;complex_escaped_quotes_winOnly;InterestingSmallMakefile_windows_configDebug;InterestingSmallMakefile_windows_configRelSize;InterestingSmallMakefile_windows_configRelSpeed;8cc_linux;8cc_mingw;Fido_linux;Fido_mingw;tinyvm_linux_pedantic;tinyvm_mingw_pedantic +No current launch configuration is set in the workspace state. +Default launch configuration: MIMode = undefined, + miDebuggerPath = undefined, + stopAtEntry = undefined, + symbolSearchPath = undefined +Configure on open: false +Configure on edit: true +Configure after command: true +Only .PHONY targets: false +Save before build or configure: true +Build before launch: false +Clear output before build: true +Ignore directory commands: true +compile_commands.json path: {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/compile_commands.json Found build log path setting "./tinyvm_linux_dryrunPedantic.log" defined for configuration "tinyvm_linux_pedantic" Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/tinyvm_linux_dryrunPedantic.log" Deduced command 'c:/some/other/fake/make PEDANTIC=yes' for configuration "tinyvm_linux_pedantic" @@ -158,6 +187,35 @@ Configure succeeded. Configure elapsed time: 0 Inserting a new entry for {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros>bin/tvmi() in the array of makefile.launchConfigurations. You may define any additional debug properties for it in settings. Setting current launch target "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros>bin/tvmi()" +Re-reading settings after launch target change. +Dropping various extension output files at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode +Writing extension log at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/Makefile.out +Logging level: Debug +Configurations cached at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/configurationCache.log +No path to the makefile is defined in the settings file. +No folder path to the makefile is defined in the settings file. +Build log defined at "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/dummy_dryrun.log" +Always pre-configure: false +Dry-run switches: '--always-make', '--keep-going', '--print-directory' +Additional compiler names: 'MyOwnFakeCompiler' +Found the following configurations defined in makefile.configurations setting: varexp;test-make-f;test-make-C;complex_escaped_quotes;complex_escaped_quotes_winOnly;InterestingSmallMakefile_windows_configDebug;InterestingSmallMakefile_windows_configRelSize;InterestingSmallMakefile_windows_configRelSpeed;8cc_linux;8cc_mingw;Fido_linux;Fido_mingw;tinyvm_linux_pedantic;tinyvm_mingw_pedantic +Reading current launch configuration "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros>bin/tvmi()" from the workspace state. +Default launch configuration: MIMode = undefined, + miDebuggerPath = undefined, + stopAtEntry = undefined, + symbolSearchPath = undefined +Configure on open: false +Configure on edit: true +Configure after command: true +Only .PHONY targets: false +Save before build or configure: true +Build before launch: false +Clear output before build: true +Ignore directory commands: true +compile_commands.json path: {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/compile_commands.json +Found build log path setting "./tinyvm_linux_dryrunPedantic.log" defined for configuration "tinyvm_linux_pedantic" +Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/tinyvm_linux_dryrunPedantic.log" +Deduced command 'c:/some/other/fake/make PEDANTIC=yes' for configuration "tinyvm_linux_pedantic" Created the following debug config: type = cppdbg cwd = {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros (= {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros) @@ -169,4 +227,33 @@ Created the following debug config: symbolSearchPath = undefined Running command '"{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/bin/tvmi" ' in the terminal from location '{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros' Setting target tvmi +Re-reading settings after target change. +Dropping various extension output files at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode +Writing extension log at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/Makefile.out +Logging level: Debug +Configurations cached at {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/configurationCache.log +No path to the makefile is defined in the settings file. +No folder path to the makefile is defined in the settings file. +Build log defined at "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/dummy_dryrun.log" +Always pre-configure: false +Dry-run switches: '--always-make', '--keep-going', '--print-directory' +Additional compiler names: 'MyOwnFakeCompiler' +Found the following configurations defined in makefile.configurations setting: varexp;test-make-f;test-make-C;complex_escaped_quotes;complex_escaped_quotes_winOnly;InterestingSmallMakefile_windows_configDebug;InterestingSmallMakefile_windows_configRelSize;InterestingSmallMakefile_windows_configRelSpeed;8cc_linux;8cc_mingw;Fido_linux;Fido_mingw;tinyvm_linux_pedantic;tinyvm_mingw_pedantic +Reading current launch configuration "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros>bin/tvmi()" from the workspace state. +Default launch configuration: MIMode = undefined, + miDebuggerPath = undefined, + stopAtEntry = undefined, + symbolSearchPath = undefined +Configure on open: false +Configure on edit: true +Configure after command: true +Only .PHONY targets: false +Save before build or configure: true +Build before launch: false +Clear output before build: true +Ignore directory commands: true +compile_commands.json path: {REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/.vscode/compile_commands.json +Found build log path setting "./tinyvm_linux_dryrunPedantic.log" defined for configuration "tinyvm_linux_pedantic" +Resolving build log path to "{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/tinyvm_linux_dryrunPedantic.log" +Deduced command 'c:/some/other/fake/make PEDANTIC=yes' for configuration "tinyvm_linux_pedantic" Building target "tvmi" with command: 'c:/some/other/fake/make tvmi PEDANTIC=yes' diff --git a/src/test/fakeSuite/Repros/varexp_baseline.out b/src/test/fakeSuite/Repros/varexp_baseline.out new file mode 100644 index 0000000..7551c76 --- /dev/null +++ b/src/test/fakeSuite/Repros/varexp_baseline.out @@ -0,0 +1,11 @@ +Expanding from './${workspaceFolder}/${configuration}/${buildTarget}/something/${configuration}/${buildTarget}/build.log' to './{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/varexp/all/something/varexp/all/build.log' for setting 'buildLog'. +Expanding from '${config:makefile.panel.visibility.debug}' to 'true' for setting 'defaultLaunchConfiguration.stopAtEntry'. +Expanding from './${workspaceRoot}/${command:makefile.getConfiguration}/${command:makefile.getBuildTarget}' to './{REPO:VSCODE-MAKEFILE-TOOLS}/src/test/fakeSuite/Repros/varexp/all' for setting 'defaultLaunchConfiguration.miDebuggerPath'. +Expanding from '${env:ProgramFiles(x86)}/${workspaceFolderBasename}/make' to '/Repros/make' for setting 'configurations.0.makePath'. +Expanding from '${command:makefile.getLaunchTargetPath}' to '' for setting 'configurations.0.makeArgs.0'. +Unrecognized variable format: ${SomeUnsupportedVar} +Expanding from '${SomeUnsupportedVar}' to 'unknown' for setting 'configurations.0.makeArgs.1'. +Detected escaped variable expansion patterns in setting 'configurations.0.makeArgs.2', within value 'try_\${escape_varexp1}_various_\${escape_varexp2}_escapes'. +Exception while executing command "makefile.inexistentCommand": 'command 'makefile.inexistentCommand' not found' +Expanding from '${command:makefile.inexistentCommand}' to 'unknown' for setting 'configurations.0.makeArgs.3'. +Expanding from '${config:makefile.inexistentSetting}' to 'unknown' for setting 'configurations.0.makeArgs.4'. diff --git a/src/test/fakeSuite/Repros/varexp_win32_baseline.out b/src/test/fakeSuite/Repros/varexp_win32_baseline.out new file mode 100644 index 0000000..b00bbb2 --- /dev/null +++ b/src/test/fakeSuite/Repros/varexp_win32_baseline.out @@ -0,0 +1,11 @@ +Expanding from './${workspaceFolder}/${configuration}/${buildTarget}/something/${configuration}/${buildTarget}/build.log' to './{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros/varexp/all/something/varexp/all/build.log' for setting 'buildLog'. +Expanding from '${config:makefile.panel.visibility.debug}' to 'true' for setting 'defaultLaunchConfiguration.stopAtEntry'. +Expanding from './${workspaceRoot}/${command:makefile.getConfiguration}/${command:makefile.getBuildTarget}' to './{REPO:VSCODE-MAKEFILE-TOOLS}\src\test\fakeSuite\Repros/varexp/all' for setting 'defaultLaunchConfiguration.miDebuggerPath'. +Expanding from '${env:ProgramFiles(x86)}/${workspaceFolderBasename}/make' to 'C:\Program Files (x86)/Repros/make' for setting 'configurations.0.makePath'. +Expanding from '${command:makefile.getLaunchTargetPath}' to '' for setting 'configurations.0.makeArgs.0'. +Unrecognized variable format: ${SomeUnsupportedVar} +Expanding from '${SomeUnsupportedVar}' to 'unknown' for setting 'configurations.0.makeArgs.1'. +Detected escaped variable expansion patterns in setting 'configurations.0.makeArgs.2', within value 'try_\${escape_varexp1}_various_\${escape_varexp2}_escapes'. +Exception while executing command "makefile.inexistentCommand": 'command 'makefile.inexistentCommand' not found' +Expanding from '${command:makefile.inexistentCommand}' to 'unknown' for setting 'configurations.0.makeArgs.3'. +Expanding from '${config:makefile.inexistentSetting}' to 'unknown' for setting 'configurations.0.makeArgs.4'. diff --git a/src/test/fakeSuite/extension.test.ts b/src/test/fakeSuite/extension.test.ts index 0e58cd3..a70bf75 100644 --- a/src/test/fakeSuite/extension.test.ts +++ b/src/test/fakeSuite/extension.test.ts @@ -61,7 +61,11 @@ suite('Fake dryrun parsing', /*async*/() => { test(`Complex scenarios with quotes and escaped quotes - ${systemPlatform}`, async () => { // Settings reset from the previous test run. extension.getState().reset(false); - await configuration.initFromStateAndSettings(); + configuration.setCurrentLaunchConfiguration(undefined); + configuration.setCurrentMakefileConfiguration("Default"); + configuration.setCurrentTarget(undefined); + configuration.initFromState(); + await configuration.initFromSettings(); // We define extension log here as opposed to in the fake repro .vscode/settings.json // because the logging produced at the first project load has too few important data to verify and much variations @@ -71,11 +75,10 @@ suite('Fake dryrun parsing', /*async*/() => { // than without debugging/loading the project before. // If we define extension log here instead of .vscode/settings.json, we also have to clean it up // because at project load time, there is no makefile log identified and no file is deleted on activation. - let extensionLogPath: string = path.join(vscode.workspace.rootPath || "./", ".vscode/Makefile.out"); + let extensionLogPath: string = configuration.getExtensionLog() || path.join(vscode.workspace.rootPath || "./", ".vscode/Makefile.out"); if (util.checkFileExistsSync(extensionLogPath)) { util.deleteFileSync(extensionLogPath); } - configuration.setExtensionLog(extensionLogPath); // Run a preconfigure script to include our tests fake compilers path so that we always find gcc/gpp/clang/...etc... // from this extension repository instead of a real installation which may vary from system to system. @@ -83,7 +86,7 @@ suite('Fake dryrun parsing', /*async*/() => { await make.preConfigure(make.TriggeredBy.tests); configuration.prepareConfigurationsQuickPick(); - configuration.setConfigurationByName("complex_escaped_quotes"); + await configuration.setConfigurationByName("complex_escaped_quotes"); // No need to setting and building a target, running a launch target, ...etc... like the other tests // Compare log output only from a configure to see how we parse the quotes and escape characters in compiler command lines. @@ -101,8 +104,8 @@ suite('Fake dryrun parsing', /*async*/() => { let extensionRootPath: string = path.resolve(__dirname, "../../../../"); baselineLogContent = baselineLogContent.replace(/{REPO:VSCODE-MAKEFILE-TOOLS}/mg, extensionRootPath); baselineLogContent = baselineLogContent.replace(/\r\n/mg, "\n"); - // fs.writeFileSync(path.join(parsedPath.dir, "base.out"), baselineLogContent); - // fs.writeFileSync(path.join(parsedPath.dir, "diff.out"), extensionLogContent); + // fs.writeFileSync(path.join(parsedPath.dir, "base6.out"), baselineLogContent); + // fs.writeFileSync(path.join(parsedPath.dir, "diff6.out"), extensionLogContent); expect(extensionLogContent).to.be.equal(baselineLogContent); }); @@ -111,8 +114,12 @@ suite('Fake dryrun parsing', /*async*/() => { test(`Complex scenarios with quotes and escaped quotes - winOnly`, async () => { // Settings reset from the previous test run. extension.getState().reset(false); - await configuration.initFromStateAndSettings(); - + configuration.setCurrentLaunchConfiguration(undefined); + configuration.setCurrentMakefileConfiguration("Default"); + configuration.setCurrentTarget(undefined); + configuration.initFromState(); + await configuration.initFromSettings(); + // We define extension log here as opposed to in the fake repro .vscode/settings.json // because the logging produced at the first project load has too few important data to verify and much variations // that are not worth to be processed when comparing with a baseline. @@ -121,11 +128,10 @@ suite('Fake dryrun parsing', /*async*/() => { // than without debugging/loading the project before. // If we define extension log here instead of .vscode/settings.json, we also have to clean it up // because at project load time, there is no makefile log identified and no file is deleted on activation. - let extensionLogPath: string = path.join(vscode.workspace.rootPath || "./", ".vscode/Makefile.out"); + let extensionLogPath: string = configuration.getExtensionLog() || path.join(vscode.workspace.rootPath || "./", ".vscode/Makefile.out"); if (util.checkFileExistsSync(extensionLogPath)) { util.deleteFileSync(extensionLogPath); } - configuration.setExtensionLog(extensionLogPath); // Run a preconfigure script to include our tests fake compilers path so that we always find gcc/gpp/clang/...etc... // from this extension repository instead of a real installation which may vary from system to system. @@ -133,7 +139,7 @@ suite('Fake dryrun parsing', /*async*/() => { await make.preConfigure(make.TriggeredBy.tests); configuration.prepareConfigurationsQuickPick(); - configuration.setConfigurationByName("complex_escaped_quotes_winOnly"); + await configuration.setConfigurationByName("complex_escaped_quotes_winOnly"); // No need to setting and building a target, running a launch target, ...etc... like the other tests // Compare log output only from a configure to see how we parse the quotes and escape characters in compiler command lines. @@ -162,21 +168,18 @@ suite('Fake dryrun parsing', /*async*/() => { test('Interesting small makefile - windows', async () => { // Settings reset from the previous test run. extension.getState().reset(false); - await configuration.initFromStateAndSettings(); + configuration.setCurrentLaunchConfiguration(undefined); + configuration.setCurrentMakefileConfiguration("Default"); + configuration.setCurrentTarget(undefined); + configuration.initFromState(); + await configuration.initFromSettings(); - // We define extension log here as opposed to in the fake repro .vscode/settings.json - // because the logging produced at the first project load has too few important data to verify and much variations - // that are not worth to be processed when comparing with a baseline. - // Example: when running a test after incomplete debugging or after loading the fake repro project independently of the testing framework, - // which leaves the workspace state not clean, resulting in a different extension output log - // than without debugging/loading the project before. - // If we define extension log here instead of .vscode/settings.json, we also have to clean it up - // because at project load time, there is no makefile log identified and no file is deleted on activation. - let extensionLogPath: string = path.join(vscode.workspace.rootPath || "./", ".vscode/Makefile.out"); - if (util.checkFileExistsSync(extensionLogPath)) { + // Extension log is defined in the test .vscode/settings.json but delete it now + // because we are interested to compare against a baseline from this point further. + let extensionLogPath: string = configuration.getExtensionLog() || path.join(vscode.workspace.rootPath || "./", ".vscode/Makefile.out"); + if (extensionLogPath && util.checkFileExistsSync(extensionLogPath)) { util.deleteFileSync(extensionLogPath); } - configuration.setExtensionLog(extensionLogPath); // Run a preconfigure script to include our tests "Program Files" path so that we always find a cl.exe // from this extension repository instead of a real VS installation that happens to be in the path. @@ -184,10 +187,9 @@ suite('Fake dryrun parsing', /*async*/() => { await make.preConfigure(make.TriggeredBy.tests); configuration.prepareConfigurationsQuickPick(); - configuration.setConfigurationByName("InterestingSmallMakefile_windows_configDebug"); + await configuration.setConfigurationByName("InterestingSmallMakefile_windows_configDebug"); const retc: number = await make.cleanConfigure(make.TriggeredBy.tests, true); - configuration.setBuildBeforeLaunch(false); const launchConfigurations: string[] = ["bin\\InterestingSmallMakefile\\ARC H3\\Debug\\main.exe(str3a,str3b,str3c)", "bin\\InterestingSmallMakefile\\arch1\\Debug\\main.exe(str3a,str3b,str3c)", "bin\\InterestingSmallMakefile\\arch2\\Debug\\main.exe()"]; @@ -209,11 +211,11 @@ suite('Fake dryrun parsing', /*async*/() => { // to exercise different combinations of pre-created build log and/or make tools. // No configure is necessary to be run here, it is enough to look at what happens // when changing a configuration. - configuration.setConfigurationByName("InterestingSmallMakefile_windows_configRelSize"); - configuration.setConfigurationByName("InterestingSmallMakefile_windows_configRelSpeed"); + await configuration.setConfigurationByName("InterestingSmallMakefile_windows_configRelSize"); + await configuration.setConfigurationByName("InterestingSmallMakefile_windows_configRelSpeed"); // InterestingSmallMakefile_windows_configRelSpeed constructs a more interesting build command. - configuration.setTargetByName("Execute_Arch3"); + await configuration.setTargetByName("Execute_Arch3"); make.prepareBuildTarget("Execute_Arch3"); // Compare the output log with the baseline @@ -239,21 +241,18 @@ suite('Fake dryrun parsing', /*async*/() => { test(`8cc - ${systemPlatform}`, async () => { // Settings reset from the previous test run. extension.getState().reset(false); - await configuration.initFromStateAndSettings(); - - // We define extension log here as opposed to in the fake repro .vscode/settings.json - // because the logging produced at the first project load has too few important data to verify and much variations - // that are not worth to be processed when comparing with a baseline. - // Example: when running a test after incomplete debugging or after loading the fake repro project independently of the testing framework, - // which leaves the workspace state not clean, resulting in a different extension output log - // than without debugging/loading the project before. - // If we define extension log here instead of .vscode/settings.json, we also have to clean it up - // because at project load time, there is no makefile log identified and no file is deleted on activation. - let extensionLogPath: string = path.join(vscode.workspace.rootPath || "./", ".vscode/Makefile.out"); - if (util.checkFileExistsSync(extensionLogPath)) { + configuration.setCurrentLaunchConfiguration(undefined); + configuration.setCurrentMakefileConfiguration("Default"); + configuration.setCurrentTarget(undefined); + configuration.initFromState(); + await configuration.initFromSettings(); + + // Extension log is defined in the test .vscode/settings.json but delete it now + // because we are interested to compare against a baseline from this point further. + let extensionLogPath: string = configuration.getExtensionLog() || path.join(vscode.workspace.rootPath || "./", ".vscode/Makefile.out"); + if (extensionLogPath && util.checkFileExistsSync(extensionLogPath)) { util.deleteFileSync(extensionLogPath); } - configuration.setExtensionLog(extensionLogPath); // Run a preconfigure script to include our tests fake compilers path so that we always find gcc/gpp/clang/...etc... // from this extension repository instead of a real installation which may vary from system to system. @@ -261,10 +260,9 @@ suite('Fake dryrun parsing', /*async*/() => { await make.preConfigure(make.TriggeredBy.tests); configuration.prepareConfigurationsQuickPick(); - configuration.setConfigurationByName(process.platform === "linux" ? "8cc_linux" : "8cc_mingw"); + await configuration.setConfigurationByName(process.platform === "linux" ? "8cc_linux" : "8cc_mingw"); const retc: number = await make.cleanConfigure(make.TriggeredBy.tests, true); - configuration.setBuildBeforeLaunch(false); const launchConfigurations: string[] = ["8cc()"]; for (const config of launchConfigurations) { await configuration.setLaunchConfigurationByName(vscode.workspace.rootPath + ">" + config); @@ -280,7 +278,7 @@ suite('Fake dryrun parsing', /*async*/() => { } } - configuration.setTargetByName("all"); + await configuration.setTargetByName("all"); make.prepareBuildTarget("all"); // Compare the output log with the baseline @@ -293,8 +291,8 @@ suite('Fake dryrun parsing', /*async*/() => { let baselineLogContent: string = util.readFile(baselineLogPath) || ""; let extensionRootPath: string = path.resolve(__dirname, "../../../../"); baselineLogContent = baselineLogContent.replace(/{REPO:VSCODE-MAKEFILE-TOOLS}/mg, extensionRootPath); - // fs.writeFileSync(path.join(parsedPath.dir, "base.out"), baselineLogContent); - // fs.writeFileSync(path.join(parsedPath.dir, "diff.out"), extensionLogContent); + // fs.writeFileSync(path.join(parsedPath.dir, "base5.out"), baselineLogContent); + // fs.writeFileSync(path.join(parsedPath.dir, "diff5.out"), extensionLogContent); expect(extensionLogContent).to.be.equal(baselineLogContent); }); } @@ -304,21 +302,18 @@ suite('Fake dryrun parsing', /*async*/() => { test(`Fido - ${systemPlatform}`, async () => { // Settings reset from the previous test run. extension.getState().reset(false); - await configuration.initFromStateAndSettings(); - - // We define extension log here as opposed to in the fake repro .vscode/settings.json - // because the logging produced at the first project load has too few important data to verify and much variations - // that are not worth to be processed when comparing with a baseline. - // Example: when running a test after incomplete debugging or after loading the fake repro project independently of the testing framework, - // which leaves the workspace state not clean, resulting in a different extension output log - // than without debugging/loading the project before. - // If we define extension log here instead of .vscode/settings.json, we also have to clean it up - // because at project load time, there is no makefile log identified and no file is deleted on activation. - let extensionLogPath: string = path.join(vscode.workspace.rootPath || "./", ".vscode/Makefile.out"); - if (util.checkFileExistsSync(extensionLogPath)) { + configuration.setCurrentLaunchConfiguration(undefined); + configuration.setCurrentMakefileConfiguration("Default"); + configuration.setCurrentTarget(undefined); + configuration.initFromState(); + await configuration.initFromSettings(); + + // Extension log is defined in the test .vscode/settings.json but delete it now + // because we are interested to compare against a baseline from this point further. + let extensionLogPath: string = configuration.getExtensionLog() || path.join(vscode.workspace.rootPath || "./", ".vscode/Makefile.out"); + if (extensionLogPath && util.checkFileExistsSync(extensionLogPath)) { util.deleteFileSync(extensionLogPath); } - configuration.setExtensionLog(extensionLogPath); // Run a preconfigure script to include our tests fake compilers path so that we always find gcc/gpp/clang/...etc... // from this extension repository instead of a real installation which may vary from system to system. @@ -326,10 +321,9 @@ suite('Fake dryrun parsing', /*async*/() => { await make.preConfigure(make.TriggeredBy.tests); configuration.prepareConfigurationsQuickPick(); - configuration.setConfigurationByName(process.platform === "linux" ? "Fido_linux" : "Fido_mingw"); + await configuration.setConfigurationByName(process.platform === "linux" ? "Fido_linux" : "Fido_mingw"); const retc: number = await make.cleanConfigure(make.TriggeredBy.tests, true); - configuration.setBuildBeforeLaunch(false); const launchConfigurations: string[] = ["bin/foo.o()"]; for (const config of launchConfigurations) { await configuration.setLaunchConfigurationByName(vscode.workspace.rootPath + ">" + config); @@ -345,7 +339,7 @@ suite('Fake dryrun parsing', /*async*/() => { } } - configuration.setTargetByName("bin/foo.o"); + await configuration.setTargetByName("bin/foo.o"); make.prepareBuildTarget("bin/foo.o"); // Compare the output log with the baseline @@ -358,8 +352,8 @@ suite('Fake dryrun parsing', /*async*/() => { let baselineLogContent: string = util.readFile(baselineLogPath) || ""; let extensionRootPath: string = path.resolve(__dirname, "../../../../"); baselineLogContent = baselineLogContent.replace(/{REPO:VSCODE-MAKEFILE-TOOLS}/mg, extensionRootPath); - // fs.writeFileSync(path.join(parsedPath.dir, "base.out"), baselineLogContent); - // fs.writeFileSync(path.join(parsedPath.dir, "diff.out"), extensionLogContent); + // fs.writeFileSync(path.join(parsedPath.dir, "base4.out"), baselineLogContent); + // fs.writeFileSync(path.join(parsedPath.dir, "diff4.out"), extensionLogContent); expect(extensionLogContent).to.be.equal(baselineLogContent); }); } @@ -369,21 +363,18 @@ suite('Fake dryrun parsing', /*async*/() => { test(`tinyvm - ${systemPlatform}`, async () => { // Settings reset from the previous test run. extension.getState().reset(false); - await configuration.initFromStateAndSettings(); - - // We define extension log here as opposed to in the fake repro .vscode/settings.json - // because the logging produced at the first project load has too few important data to verify and much variations - // that are not worth to be processed when comparing with a baseline. - // Example: when running a test after incomplete debugging or after loading the fake repro project independently of the testing framework, - // which leaves the workspace state not clean, resulting in a different extension output log - // than without debugging/loading the project before. - // If we define extension log here instead of .vscode/settings.json, we also have to clean it up - // because at project load time, there is no makefile log identified and no file is deleted on activation. - let extensionLogPath: string = path.join(vscode.workspace.rootPath || "./", ".vscode/Makefile.out"); - if (util.checkFileExistsSync(extensionLogPath)) { + configuration.setCurrentLaunchConfiguration(undefined); + configuration.setCurrentMakefileConfiguration("Default"); + configuration.setCurrentTarget(undefined); + configuration.initFromState(); + await configuration.initFromSettings(); + + // Extension log is defined in the test .vscode/settings.json but delete it now + // because we are interested to compare against a baseline from this point further. + let extensionLogPath: string = configuration.getExtensionLog() || path.join(vscode.workspace.rootPath || "./", ".vscode/Makefile.out"); + if (extensionLogPath && util.checkFileExistsSync(extensionLogPath)) { util.deleteFileSync(extensionLogPath); } - configuration.setExtensionLog(extensionLogPath); // Run a preconfigure script to include our tests fake compilers path so that we always find gcc/gpp/clang/...etc... // from this extension repository instead of a real installation which may vary from system to system. @@ -391,10 +382,9 @@ suite('Fake dryrun parsing', /*async*/() => { await make.preConfigure(make.TriggeredBy.tests); configuration.prepareConfigurationsQuickPick(); - configuration.setConfigurationByName(process.platform === "linux" ? "tinyvm_linux_pedantic" : "tinyvm_mingw_pedantic"); + await configuration.setConfigurationByName(process.platform === "linux" ? "tinyvm_linux_pedantic" : "tinyvm_mingw_pedantic"); const retc: number = await make.cleanConfigure(make.TriggeredBy.tests, true); - configuration.setBuildBeforeLaunch(false); const launchConfigurations: string[] = ["bin/tvmi()"]; for (const config of launchConfigurations) { await configuration.setLaunchConfigurationByName(vscode.workspace.rootPath + ">" + config); @@ -410,7 +400,7 @@ suite('Fake dryrun parsing', /*async*/() => { } } - configuration.setTargetByName("tvmi"); + await configuration.setTargetByName("tvmi"); make.prepareBuildTarget("tvmi"); // Compare the output log with the baseline @@ -423,8 +413,8 @@ suite('Fake dryrun parsing', /*async*/() => { let baselineLogContent: string = util.readFile(baselineLogPath) || ""; let extensionRootPath: string = path.resolve(__dirname, "../../../../"); baselineLogContent = baselineLogContent.replace(/{REPO:VSCODE-MAKEFILE-TOOLS}/mg, extensionRootPath); - // fs.writeFileSync(path.join(parsedPath.dir, "base.out"), baselineLogContent); - // fs.writeFileSync(path.join(parsedPath.dir, "diff.out"), extensionLogContent); + // fs.writeFileSync(path.join(parsedPath.dir, "base3.out"), baselineLogContent); + // fs.writeFileSync(path.join(parsedPath.dir, "diff3.out"), extensionLogContent); expect(extensionLogContent).to.be.equal(baselineLogContent); }); } @@ -432,28 +422,25 @@ suite('Fake dryrun parsing', /*async*/() => { test(`Test real make - ${systemPlatform}`, async () => { // Settings reset from the previous test run. extension.getState().reset(false); - await configuration.initFromStateAndSettings(); + configuration.setCurrentLaunchConfiguration(undefined); + configuration.setCurrentMakefileConfiguration("Default"); + configuration.setCurrentTarget(undefined); + configuration.initFromState(); + await configuration.initFromSettings(); - // We define extension log here as opposed to in the fake repro .vscode/settings.json - // because the logging produced at the first project load has too few important data to verify and much variations - // that are not worth to be processed when comparing with a baseline. - // Example: when running a test after incomplete debugging or after loading the fake repro project independently of the testing framework, - // which leaves the workspace state not clean, resulting in a different extension output log - // than without debugging/loading the project before. - // If we define extension log here instead of .vscode/settings.json, we also have to clean it up - // because at project load time, there is no makefile log identified and no file is deleted on activation. - let extensionLogPath: string = path.join(vscode.workspace.rootPath || "./", ".vscode/Makefile.out"); - if (util.checkFileExistsSync(extensionLogPath)) { + // Extension log is defined in the test .vscode/settings.json but delete it now + // because we are interested to compare against a baseline from this point further. + let extensionLogPath: string = configuration.getExtensionLog() || path.join(vscode.workspace.rootPath || "./", ".vscode/Makefile.out"); + if (extensionLogPath && util.checkFileExistsSync(extensionLogPath)) { util.deleteFileSync(extensionLogPath); } - configuration.setExtensionLog(extensionLogPath); configuration.prepareConfigurationsQuickPick(); - configuration.setConfigurationByName("test-make-f"); + await configuration.setConfigurationByName("test-make-f"); await make.cleanConfigure(make.TriggeredBy.tests); - configuration.setConfigurationByName("test-make-C"); + await configuration.setConfigurationByName("test-make-C"); await make.buildTarget(make.TriggeredBy.tests, "all", true); // Compare the output log with the baseline @@ -468,9 +455,64 @@ suite('Fake dryrun parsing', /*async*/() => { let extensionRootPath: string = path.resolve(__dirname, "../../../../"); baselineLogContent = baselineLogContent.replace(/{REPO:VSCODE-MAKEFILE-TOOLS}/mg, extensionRootPath); baselineLogContent = baselineLogContent.replace(/\r\n/mg, "\n"); - // fs.writeFileSync(path.join(parsedPath.dir, "base.out"), baselineLogContent); - // fs.writeFileSync(path.join(parsedPath.dir, "diff.out"), extensionLogContent); + // fs.writeFileSync(path.join(parsedPath.dir, "base2.out"), baselineLogContent); + // fs.writeFileSync(path.join(parsedPath.dir, "diff2.out"), extensionLogContent); + expect(extensionLogContent).to.be.equal(baselineLogContent); + }); + test(`Variables expansion - ${systemPlatform}`, async () => { + // Settings reset from the previous test run. + extension.getState().reset(false); + configuration.setCurrentLaunchConfiguration(undefined); + configuration.setCurrentMakefileConfiguration("Default"); + configuration.setCurrentTarget(undefined); + configuration.initFromState(); + await configuration.initFromSettings(); + + configuration.prepareConfigurationsQuickPick(); + await configuration.setConfigurationByName("varexp"); + await configuration.setTargetByName("all"); + + // Delete extension log a bit later than other tests. For this one, we only care to capture varexp. + // All else that happens before, it was covered during the other tests in this suite. + let extensionLogPath: string = configuration.getExtensionLog() || path.join(vscode.workspace.rootPath || "./", ".vscode/Makefile.out"); + if (extensionLogPath && util.checkFileExistsSync(extensionLogPath)) { + util.deleteFileSync(extensionLogPath); + } + + await util.getExpandedSettingVal("buildLog", "./${workspaceFolder}/${configuration}/${buildTarget}/something/${configuration}/${buildTarget}/build.log"); + + let stopAtEntry: string = await util.expandVariablesInSetting("defaultLaunchConfiguration.stopAtEntry", "${config:makefile.panel.visibility.debug}"); + let tmpDefaultLaunchConfiguration: configuration.DefaultLaunchConfiguration = { + miDebuggerPath: "./${workspaceRoot}/${command:makefile.getConfiguration}/${command:makefile.getBuildTarget}", + stopAtEntry: util.booleanify(stopAtEntry) + }; + await util.getExpandedSettingVal("defaultLaunchConfiguration", tmpDefaultLaunchConfiguration); + + let tmpConfigurations: configuration.MakefileConfiguration[] = [{ + name: "MyTmpName", + makePath: "${env:ProgramFiles(x86)}/${workspaceFolderBasename}/make", + makeArgs: ["${command:makefile.getLaunchTargetPath}", + "${SomeUnsupportedVar}", + "try_\\${escape_varexp1}_various_\\${escape_varexp2}_escapes", + "${command:makefile.inexistentCommand}", + "${config:makefile.inexistentSetting}"]}]; + await util.getExpandedSettingVal("configurations", tmpConfigurations); + + // Compare the output log with the baseline + // TODO: incorporate relevant diff snippets into the test log. + // Until then, print into base and diff files for easier viewing + // when the test fails. + let parsedPath: path.ParsedPath = path.parse(extensionLogPath); + let baselineLogPath: string = path.join(parsedPath.dir, process.platform === "win32" ? "../varexp_win32_baseline.out" : "../varexp_baseline.out"); + let extensionLogContent: string = util.readFile(extensionLogPath) || ""; + extensionLogContent = extensionLogContent.replace(/\r\n/mg, "\n"); + let baselineLogContent: string = util.readFile(baselineLogPath) || ""; + let extensionRootPath: string = path.resolve(__dirname, "../../../../"); + baselineLogContent = baselineLogContent.replace(/{REPO:VSCODE-MAKEFILE-TOOLS}/mg, extensionRootPath); + baselineLogContent = baselineLogContent.replace(/\r\n/mg, "\n"); + // fs.writeFileSync(path.join(parsedPath.dir, "base1.out"), baselineLogContent); + // fs.writeFileSync(path.join(parsedPath.dir, "diff1.out"), extensionLogContent); expect(extensionLogContent).to.be.equal(baselineLogContent); }); diff --git a/src/util.ts b/src/util.ts index 64d1ade..f08aa7d 100644 --- a/src/util.ts +++ b/src/util.ts @@ -3,17 +3,18 @@ // Helper APIs used by this extension +import * as configuration from './configuration'; import * as fs from 'fs'; import * as child_process from 'child_process'; import * as logger from './logger'; import * as make from './make'; import * as path from 'path'; +import * as telemetry from './telemetry'; import * as vscode from 'vscode'; // C/CPP standard versions export type StandardVersion = 'c89' | 'c99' | 'c11' | 'c17' | 'c++98' | 'c++03' | 'c++11' | 'c++14' | 'c++17' | 'c++20' | 'c++23' | - 'gnu89' | 'gnu99' | 'gnu11' | 'gnu17' | 'gnu++98' | 'gnu++03' | 'gnu++11' | 'gnu++14' | 'gnu++17' | 'gnu++20' | 'gnu++23' - undefined; + 'gnu89' | 'gnu99' | 'gnu11' | 'gnu17' | 'gnu++98' | 'gnu++03' | 'gnu++11' | 'gnu++14' | 'gnu++17' | 'gnu++20' | 'gnu++23' | undefined; // Supported target architectures (for code generated by the compiler) export type TargetArchitecture = 'x86' | 'x64' | 'arm' | 'arm64' | undefined; @@ -603,9 +604,291 @@ export function resolvePathToRoot(relPath: string): string { return relPath; } -// Helper for substituting workspace paths. -export function resolveSubstitutedPath(path: string): string { - return path.replace(/^\${workspace(Folder|Root)}/, getWorkspaceRoot()); +// Return the string representing the user home location. +// Inspired from CMake Tools. TODO: implement more such paths and refactor into a separate class. +export function userHome(): string { + if (process.platform === 'win32') { + return path.join(process.env['HOMEDRIVE'] || 'C:', process.env['HOMEPATH'] || 'Users\\Public'); + } else { + return process.env['HOME'] || process.env['PROFILE'] || ""; + } + } + + // Helper to correctly interpret boolean values out of strings. + // Currently used during settings variable expansion. + export function booleanify(value: string) : boolean { + const truthy: string[] = ["true", "True", "1"]; + return truthy.includes(value); + } + +// Read setting from workspace settings and expand according to various supported patterns. +// Do this for the simple types (converting to boolean or numerals when the varexp syntax +// is used on such types of settings) and for arrays or objects, expand recursively +// until we reach the simple types for submembers. This handles any structure. +export async function getExpandedSetting(settingId: string, propSchema?: any): Promise { + let workspaceConfiguration: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("makefile"); + let settingVal: any | undefined = workspaceConfiguration.get(settingId); + + if (!propSchema) { + propSchema = thisExtensionPackage().contributes.configuration.properties; + propSchema = propSchema.properties ? propSchema.properties[`makefile.${settingId}`] : propSchema[`makefile.${settingId}`]; + } + + // Read what's at settingId in the workspace settings and for objects and arrays of complex types make sure + // to copy into a new counterpart that we will modify, because we don't want to persist expanded values in settings. + let copySettingVal: any | undefined; + if (propSchema && propSchema.type === "array") { + // A simple .concat() is not enough. We need to push(Object.assign) on all object entries in the array. + copySettingVal = []; + (settingVal as any[]).forEach(element => { + let copyElement: any = {}; + copyElement = (typeof(element) === "object") ? Object.assign(copyElement, element) : element; + copySettingVal.push(copyElement); + }); + } else if (propSchema && propSchema.type === "object") { + copySettingVal = {}; + copySettingVal = Object.assign(copySettingVal, settingVal); + } else { + copySettingVal = settingVal; + } + + return getExpandedSettingVal(settingId, copySettingVal, propSchema); +} + +// Same as above but read from an object instead of the settings (as if we get<> before calling this). +// Such approach was needed for tests. +export async function getExpandedSettingVal(settingId: string, settingVal: any, propSchema?: any): Promise { + // Currently, we have no ${} variables in the default values of our settings. + // Skip expanding defaults to keep things faster simpler and safer. + // Change this when needed. + const typeJson: string | undefined = propSchema ? propSchema.type : undefined; + if (settingVal !== undefined && + ((propSchema && !areEqual(propSchema.default, settingVal)) || + !propSchema)) { // This OR is for variables not defined in the extension package.json + // but the user can define any variable in settings.json to reference later + if (typeof(settingVal) === 'string') { + const expandedVal: string = await expandVariablesInSetting(settingId, settingVal); + let result: T = expandedVal as T; + if (typeJson === "boolean") { + result = booleanify(expandedVal) as T; + } else if (typeJson === "number" || typeJson === "integer") { + result = Number(expandedVal) as T; + } + + return result; + } else if (typeof(settingVal) === 'object') { + // arrays are also seen as objects: + // example: array[5] is seen as property object with index array.5 + // and at the next call we'll see the string. + let properties: string[] = Object.getOwnPropertyNames(settingVal); + for (let p: number = 0; p < properties.length; p++) { + let prop: string = properties[p]; + let childPropSchema: any; + if (propSchema) { + if (typeJson === "array") { + childPropSchema = propSchema.items; + } else { + childPropSchema = propSchema.properties ? propSchema.properties[`${prop}`] : propSchema[`${prop}`]; + } + } + + try { + // The settingVal that was given to this function was already a separate copy from its workspace settings counterpart + // but if that contained an array anywhere in its structure, if we don't copy here, this expansion will modify + // workspace settings which we want to leave untouched. + let copySettingValProp: any = settingVal[prop]; + if (childPropSchema && childPropSchema.type === "array") { + copySettingValProp = [].concat(settingVal[prop]); + } + + let expandedProp: T = await getExpandedSettingVal(settingId + "." + prop, copySettingValProp, childPropSchema); + if (!areEqual(settingVal[prop], expandedProp)) { + settingVal[prop] = expandedProp; + } + } catch (e) { + logger.message(`Exception while expanding string "${settingId}.${prop}": '${e.message}'`); + } + } + } + } + + return settingVal; +} + +// Helper for expanding variables in a setting. The following scenarios are currently supported: +// - predefined VSCode variables (more should be supported with the next release): +// ${workspaceFolder} (which is the same as the deprecated ${workspaceRoot} which we still support), +// ${workspaceFolderBasename}, ${userHome} +// - special Makefile Tools variables (implement more in future): +// ${configuration}, ${buildTarget} (these map to the first two UI elements in the "C/C++" left panel) +// - environment variables: ${env:USERNAME} +// - (any extensions) configuration variables: ${config:extension.setting} +// - command variables: ${command:extension.command} (currently, without commands input variables support) +// - allow for escaping a varexp sequence in case the user wants to pass that through as is. +// The escape character is backslash and in json one backslash is not allowed inside a string, so we'll always get double. +// When used in paths, we can't know if a \\ is wanted as a path separator or an escape character so we assume +// it is always an escape character. Whenever this is not the case, the user can switch to forward slashes in the paths. +// Example: "drive:\\folder1\\folder2_\\${variable}\\folder3" may be wanted as "drive:\\folder1\\folder2_\\value\\folder3" +// or as "drive:\\folder1\\folder2_${variable}\\folder3". $ does not make much sense to be left in a path +// but also the analysis of the meaning of a string (especially if not full path) is not simple. +// Forward slashes are recommended in paths. +// NOTES: +// - ${command:makefile.getConfiguration} is the same as ${configuration} +// - ${command:makefile.getBuildTarget} is the same as ${buildTarget} +// - we need the above two commands because launch.json and tasks.json +// don't work with our predefined variables, only with the VSCode predefined variables. +// Such data is useful to be accessible to launch/tasks jsons too. +// But settings.json works with our predefined variables, VSCode predefined variables +// and any commands. +// TODO: Currently, after applying any expansion pattern, if the result is another expansion pattern +// we log an error but in future let's handle the recursivity and complications of expanding anything +// coming via this entrypoint. +export async function expandVariablesInSetting(settingId: string, settingVal: string): Promise { + // Do some string preprocessing first, related to escaping. + // Since we don't want to change the value persisted in settings but we need to lose the separator + // (so that the final beneficiaries of these settings don't need to handle the separator character) + // we will keep the varexp pattern in the final value without the escape character. + // The escape character is only for our regexp here to know to not expand it. + // Safe to replace \\${ with ESCAPED_VARIABLE_EXPANSION. This will cause the pattern to be skipped + // by the regular expression below and also we will replace in reverse at the end (without \\). + const telemetryProperties: telemetry.Properties = {setting: settingId}; + let preprocStr: string = settingVal.replace(/\\\$\{/mg, "ESCAPED_VARIABLE_EXPANSION"); + if (preprocStr !== settingVal) { + logger.message(`Detected escaped variable expansion patterns in setting '${settingId}', within value '${settingVal}'.`); + telemetryProperties.pattern = "escaped"; + telemetry.logEvent("varexp", telemetryProperties); + settingVal = preprocStr; + } + + // Try the predefined VSCode variable first. The regexp for ${variable} won't fit the others because of the ":". + let expandedSetting: string = settingVal; + let regexpVSCodeVar: RegExp = /(\$\{(\w+)\})|(\$\{(\w+):(.+?)\})/mg; + let result: RegExpExecArray | null = regexpVSCodeVar.exec(expandedSetting); + while (result) { + const telemetryProperties: telemetry.Properties = {setting: settingId}; + let toStr: string = ""; + if (result[2] === "workspaceFolder" || result[2] === "workspaceRoot") { + toStr = getWorkspaceRoot(); + telemetryProperties.pattern = result[2]; + } else if (result[2] === "workspaceFolderBasename") { + toStr = path.basename(getWorkspaceRoot()); + telemetryProperties.pattern = result[2]; + } else if (result[2] === "userHome") { + toStr = userHome(); + telemetryProperties.pattern = result[2]; + } else if (result[2] === "configuration") { + toStr = configuration.getCurrentMakefileConfiguration(); + telemetryProperties.pattern = result[2]; + } else if (result[2] === "buildTarget") { + toStr = configuration.getCurrentTarget() || ""; + telemetryProperties.pattern = result[2]; + } else if (result[4] === "env" && result[5]) { + toStr = process.env[result[5]] || ""; + telemetryProperties.pattern = result[4]; + } else if (result[4] === "command") { + telemetryProperties.pattern = result[4]; + telemetryProperties.info = result[5]; + try { + toStr = await vscode.commands.executeCommand(result[5]); + } catch (e) { + toStr = "unknown"; + logger.message(`Exception while executing command "${result[5]}": '${e.message}'`); + } + } else if (result[4] === "config" && result[5]) { + // Extract the name of the extension we read this setting from (before the dot) + // and the setting follows the first dot. + telemetryProperties.pattern = result[4]; + telemetryProperties.info = result[5]; + const regexpCfg: RegExp = /(\w+)\.(.+)/mg; + const res: RegExpExecArray | null = regexpCfg.exec(result[5]); + if (res && res[1] && res[2]) { + let workspaceCfg: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration(res[1]); + toStr = (workspaceCfg.get(res[2]) as string); + + // The setting is either undefined or maybe we encountered a case with multiple names separated by dot for a property: + // makefile.set1.set2.set3.set4... which cannot be seen if given the whole setting ID at once. + // Example: + // "makefile.set1.set2.set3": { + // "set4.set5": "val" + // "something.else": "other" + // } + // A get on the root workspace cannot see "makefile.set1.set2.set3.set4.set5", returns undefined. + // In the above case, one get of "makefile.set1.set2.set3" returns an object, then an access on "set4.set5" gets the final value "val". + // We don't know at which dot to stop for the first and the subsequent get operations, so starting with the workspace root + // we query for properties and see how much it matches from the full setting id, then we query again on the left over, + // until we get the final value. + // In the above case, the root makefile workspace has a property set1 (not set1.set2.set3), then the object retrieved + // has a set2 property then set3. That last object has a "set4.set5" property (not set4 then set5). + if (toStr === null || toStr === undefined) { + toStr = getSettingMultipleDots(workspaceCfg, res[2]); + } + + if (toStr === null || toStr === undefined) { + toStr = "unknown"; + } + } + } else { + logger.message(`Unrecognized variable format: ${result[0]}`); + toStr = "unknown"; + telemetryProperties.pattern = "unrecognized"; + } + + telemetry.logEvent("varexp", telemetryProperties); + + // Because we replace at the same time as we evaluate possible consecutive $ patterns + // we need to start each time the search from the beginning (otherwise the lastIndex gets messed up). + // It is guaranteed we exit this loop because if we match, we replace with something. + // That is why we cannot leave the ${} as they are and we replace with "unknown" when they can't resolve. + // Replacing with empty string was not an option because we want unrecognized patterns to stand out quickly. + regexpVSCodeVar.lastIndex = 0; + + // Warn if the expanded value contains yet another expansion pattern and leave as is. + // We will address in future multiple passes. + if (regexpVSCodeVar.exec(toStr) !== null) { + logger.message(`"${result[0]}" resolves to "${toStr}" which requires another expansion.` + + " We will support multiple expansion passes in the future. "); + expandedSetting = expandedSetting.replace(result[0], "unknown"); + } else { + expandedSetting = expandedSetting.replace(result[0], toStr); + } + + regexpVSCodeVar.lastIndex = 0; + result = regexpVSCodeVar.exec(expandedSetting); + } + + if (expandedSetting !== settingVal) { + logger.message(`Expanding from '${settingVal}' to '${expandedSetting}' for setting '${settingId}'.`); + } + + // Reverse the preprocessing done at the beginning, except that we don't keep the escape character. + preprocStr = expandedSetting.replace(/ESCAPED_VARIABLE_EXPANSION/mg, "${"); + return preprocStr; +} + +// Function specialized to get properties with multiple dots in their names. +// In case of more possibilities, return last. +// Example: get the value of "makefile.panel.visibility" or a general hypothetic setting like +// "makefile.set1.set2.set3.set4": { +// "set5.set6": "val1", +// "set7.set8": "val2" +// } +// getSettingMultipleDots will return "val2" for "makefile.set1.set2.set3.set4.set7.set8" +// and workspaceConfiguration.get<> will not see it as a whole. +function getSettingMultipleDots(scope: any, settingId: string) : any { + let result: any; + if (scope) { + let rootProps: string[] = Object.getOwnPropertyNames(scope); + rootProps = rootProps.filter(item => (item && (settingId.startsWith(`${item}.`) || settingId === item))); + rootProps.forEach(prop => { + if (settingId === prop) { + result = scope[prop]; + } else { + result = getSettingMultipleDots(scope[prop], settingId.substring(prop.length + 1, settingId.length)); + } + }); + } + + return result; } // Schedule a task to be run at some future time. This allows other pending tasks to