diff options
author | Jake Petroules <jake.petroules@qt.io> | 2017-09-19 00:41:19 -0700 |
---|---|---|
committer | Jake Petroules <jake.petroules@qt.io> | 2017-09-20 00:39:43 +0000 |
commit | 923854e45bb29f3adb045c73ed0841730d838867 (patch) | |
tree | 152bbcf73eefd008f9329019b3fba2e5b205ed1e | |
parent | 848ce26d155ac4fe79399c93bf455cae816bdc47 (diff) |
Add a PropertyListVariableExpander class
This allows us to control exactly what warning message is displayed when
the expandPlistEnvironmentVariables function encounters an unknown
variable replacement, as opposed to whether or not a hardcoded message
is shown. We use this new functionality in the Info.plist processor in
order to give a much clearer message what went wrong and where the user
might look to correct it.
Change-Id: I967ea87c837f9aa2b67bad292e392b356fee8bed
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
-rw-r--r-- | share/qbs/imports/qbs/DarwinTools/darwin-tools.js | 161 | ||||
-rw-r--r-- | share/qbs/modules/bundle/BundleModule.qbs | 17 |
2 files changed, 105 insertions, 73 deletions
diff --git a/share/qbs/imports/qbs/DarwinTools/darwin-tools.js b/share/qbs/imports/qbs/DarwinTools/darwin-tools.js index b0f0bdc52..95e8dab25 100644 --- a/share/qbs/imports/qbs/DarwinTools/darwin-tools.js +++ b/share/qbs/imports/qbs/DarwinTools/darwin-tools.js @@ -139,87 +139,104 @@ function _resourceFileProperties(path) { return [ undefined, '.' ]; } -/** - * Recursively perform variable replacements in an environment dictionary. - * - * JSON.stringify(expandPlistEnvironmentVariables({a:"$(x)3$$(y)",b:{t:"%$(y) $(k)"}}, - * {x:"X",y:"Y"}, true)) - * Warning undefined variable k in variable expansion - * => {"a":"X3$Y","b":{"t":"%Y $(k)"}} - */ -function expandPlistEnvironmentVariables(obj, env, warn) { - // Possible syntaxes for wrapping an environment variable name - var syntaxes = [ - {"open": "${", "close": "}"}, - {"open": "$(", "close": ")"}, - {"open": "@", "close": "@"} - ]; - +var PropertyListVariableExpander = (function () { + function PropertyListVariableExpander() { + } /** - * Finds the first index of a replacement starting with one of the supported syntaxes - * This is needed so we don't do recursive substitutions + * Recursively perform variable replacements in an environment dictionary. */ - function indexOfReplacementStart(syntaxes, str, offset) { - var syntax; - var idx = str.length; - for (var i in syntaxes) { - var j = str.indexOf(syntaxes[i].open, offset); - if (j !== -1 && j < idx) { - syntax = syntaxes[i]; - idx = j; + PropertyListVariableExpander.prototype.expand = function (obj, env) { + var $this = this; + + // Possible syntaxes for wrapping an environment variable name + var syntaxes = [ + {"open": "${", "close": "}"}, + {"open": "$(", "close": ")"}, + {"open": "@", "close": "@"} + ]; + + /** + * Finds the first index of a replacement starting with one of the supported syntaxes + * This is needed so we don't do recursive substitutions + */ + function indexOfReplacementStart(syntaxes, str, offset) { + var syntax; + var idx = str.length; + for (var i in syntaxes) { + var j = str.indexOf(syntaxes[i].open, offset); + if (j !== -1 && j < idx) { + syntax = syntaxes[i]; + idx = j; + } } + return { "syntax": syntax, "index": idx === str.length ? -1 : idx }; } - return { "syntax": syntax, "index": idx === str.length ? -1 : idx }; - } - function expandRecursive(obj, env, checked) { - checked.push(obj); - for (var key in obj) { - var value = obj[key]; - var type = typeof(value); - if (type === "object") { - if (checked.indexOf(value) !== -1) + function expandRecursive(obj, env, checked) { + checked.push(obj); + for (var key in obj) { + var value = obj[key]; + var type = typeof(value); + if (type === "object") { + if (checked.indexOf(value) !== -1) + continue; + expandRecursive(value, env, checked); + } + if (type !== "string") continue; - expandRecursive(value, env, checked); - } - if (type !== "string") - continue; - var repl = indexOfReplacementStart(syntaxes, value); - var i = repl.index; - var changes = false; - while (i !== -1) { - var j = value.indexOf(repl.syntax.close, i + repl.syntax.open.length); - if (j === -1) - break; - var varParts = value.slice(i + repl.syntax.open.length, j).split(':'); - var varName = varParts[0]; - var varFormatter = varParts[1]; - var varValue = env[varName]; - if (undefined === varValue) { - // skip replacement - if (warn) - console.warn("undefined variable " + varName + " in variable expansion"); - i = j + repl.syntax.close.length; - } else { - changes = true; - varValue = String(varValue); - if (varFormatter !== undefined) - varFormatter = varFormatter.toLowerCase(); - if (varFormatter === "rfc1034identifier") - varValue = Utilities.rfc1034Identifier(varValue); - value = value.slice(0, i) + varValue + value.slice(j + repl.syntax.close.length); - // avoid recursive substitutions to avoid potentially infinite loops - i += varValue.length; + var repl = indexOfReplacementStart(syntaxes, value); + var i = repl.index; + var changes = false; + while (i !== -1) { + var j = value.indexOf(repl.syntax.close, i + repl.syntax.open.length); + if (j === -1) + break; + var varParts = value.slice(i + repl.syntax.open.length, j).split(':'); + var varName = varParts[0]; + var varFormatter = varParts[1]; + var varValue = env[varName]; + if (undefined === varValue) { + // skip replacement + if ($this.undefinedVariableFunction) + $this.undefinedVariableFunction(key, varName); + i = j + repl.syntax.close.length; + } else { + changes = true; + varValue = String(varValue); + if (varFormatter !== undefined) + varFormatter = varFormatter.toLowerCase(); + if (varFormatter === "rfc1034identifier") + varValue = Utilities.rfc1034Identifier(varValue); + value = value.slice(0, i) + varValue + value.slice(j + repl.syntax.close.length); + // avoid recursive substitutions to avoid potentially infinite loops + i += varValue.length; + } + repl = indexOfReplacementStart(syntaxes, value, i); + i = repl.index; } - repl = indexOfReplacementStart(syntaxes, value, i); - i = repl.index; + if (changes) + obj[key] = value; } - if (changes) - obj[key] = value; } - } - expandRecursive(obj, env, []); - return obj; + expandRecursive(obj, env, []); + return obj; + }; + return PropertyListVariableExpander; +}()); + +/** + * JSON.stringify(expandPlistEnvironmentVariables({a:"$(x)3$$(y)",b:{t:"%$(y) $(k)"}}, + * {x:"X",y:"Y"}, true)) + * Warning undefined variable k in variable expansion + * => {"a":"X3$Y","b":{"t":"%Y $(k)"}} + */ +function expandPlistEnvironmentVariables(obj, env, warn) { + var expander = new PropertyListVariableExpander(); + expander.undefinedVariableFunction = function (key, varName) { + if (warn) + console.warn("undefined variable " + varName + " in variable expansion"); + }; + return expander.expand(obj, env); } /** diff --git a/share/qbs/modules/bundle/BundleModule.qbs b/share/qbs/modules/bundle/BundleModule.qbs index e9f9128e2..b7f38559c 100644 --- a/share/qbs/modules/bundle/BundleModule.qbs +++ b/share/qbs/modules/bundle/BundleModule.qbs @@ -395,7 +395,22 @@ Module { for (key in qmakeEnv) env[key] = qmakeEnv[key]; - DarwinTools.expandPlistEnvironmentVariables(aggregatePlist, env, true); + var expander = new DarwinTools.PropertyListVariableExpander(); + expander.undefinedVariableFunction = function (key, varName) { + var msg = "Info.plist variable expansion encountered undefined variable '" + + varName + "' when expanding value for key '" + key + + "', defined in one of the following files:\n\t"; + var allFilePaths = []; + for (i in infoPlistFiles) + allFilePaths.push(infoPlistFiles[i].filePath); + if (platformInfoPlist) + allFilePaths.push(platformInfoPlist); + msg += allFilePaths.join("\n\t") + "\n"; + msg += "or in the bundle.infoPlist property of product '" + + product.name + "'"; + console.warn(msg); + }; + aggregatePlist = expander.expand(aggregatePlist, env); // Add keys from partial Info.plists from asset catalogs, XIBs, and storyboards for (i in partialInfoPlistFiles) { |