Clean up unused IVariableResolver functionality.
Handle escaped bind-time variable references.
Bob Arnson committed
Mar 13, 2020 at 20:30 UTC
d097c7deb98803f6e9e46fe20261dd761efeb993
5 files changed
+72
-18
src/WixToolset.Core/Bind/ResolveFieldsCommand.cs
+1
-1
@@ -62,7 +62,7 @@ namespace WixToolset.Core.Bind
62
var original = field.AsString();
63
if (!String.IsNullOrEmpty(original))
64
{
65
- var resolution = this.VariableResolver.ResolveVariables(tuple.SourceLineNumbers, original, false);
65
+ var resolution = this.VariableResolver.ResolveVariables(tuple.SourceLineNumbers, original);
66
if (resolution.UpdatedValue)
67
{
68
field.Set(resolution.Value);
src/WixToolset.Core/Compiler.cs
+1
-1
@@ -251,7 +251,7 @@ namespace WixToolset.Core
251
var data = field.AsString();
252
if (!String.IsNullOrEmpty(data))
253
{
254
- var resolved = this.componentIdPlaceholdersResolver.ResolveVariables(tuple.SourceLineNumbers, data, false, false);
254
+ var resolved = this.componentIdPlaceholdersResolver.ResolveVariables(tuple.SourceLineNumbers, data, errorOnUnknown: false);
255
if (resolved.UpdatedValue)
256
{
257
field.Set(resolved.Value);
src/WixToolset.Core/Librarian.cs
+1
-1
@@ -95,7 +95,7 @@ namespace WixToolset.Core
95
96
if (pathField != null && !String.IsNullOrEmpty(pathField.Path))
97
{
98
- var resolution = variableResolver.ResolveVariables(tuple.SourceLineNumbers, pathField.Path, false);
98
+ var resolution = variableResolver.ResolveVariables(tuple.SourceLineNumbers, pathField.Path);
99
100
var file = fileResolver.Resolve(tuple.SourceLineNumbers, tuple.Definition, resolution.Value);
101
src/WixToolset.Core/VariableResolver.cs
+33
-11
@@ -66,9 +66,9 @@ namespace WixToolset.Core
66
}
67
}
68
69
- public IVariableResolution ResolveVariables(SourceLineNumber sourceLineNumbers, string value, bool localizationOnly)
69
+ public IVariableResolution ResolveVariables(SourceLineNumber sourceLineNumbers, string value)
70
{
71
- return this.ResolveVariables(sourceLineNumbers, value, localizationOnly, true);
71
+ return this.ResolveVariables(sourceLineNumbers, value, errorOnUnknown: true);
72
}
73
74
public bool TryGetLocalizedControl(string dialog, string control, out LocalizedControl localizedControl)
@@ -82,25 +82,27 @@ namespace WixToolset.Core
82
/// </summary>
83
/// <param name="sourceLineNumbers">The source line information for the value.</param>
84
/// <param name="value">The value to resolve.</param>
85
- /// <param name="localizationOnly">true to only resolve localization variables; false otherwise.</param>
85
/// <param name="errorOnUnknown">true if unknown variables should throw errors.</param>
86
/// <returns>The resolved value.</returns>
88
- internal IVariableResolution ResolveVariables(SourceLineNumber sourceLineNumbers, string value, bool localizationOnly, bool errorOnUnknown)
87
+ internal IVariableResolution ResolveVariables(SourceLineNumber sourceLineNumbers, string value, bool errorOnUnknown)
88
{
89
var matches = Common.WixVariableRegex.Matches(value);
90
92
- // the value is the default unless its substituted further down
91
+ // the value is the default unless it's substituted further down
92
var result = this.ServiceProvider.GetService<IVariableResolution>();
93
result.IsDefault = true;
94
result.Value = value;
95
97
- while (!this.Messaging.EncounteredError && !result.DelayedResolve && matches.Count > 0)
96
+ var finalizeEscapes = false;
97
+
98
+ while (matches.Count > 0)
99
{
100
+ var updatedResultThisPass = false;
101
var sb = new StringBuilder(value);
102
103
// notice how this code walks backward through the list
104
// because it modifies the string as we move through it
103
- for (int i = matches.Count - 1; 0 <= i; i--)
105
+ for (var i = matches.Count - 1; 0 <= i; i--)
106
{
107
var variableNamespace = matches[i].Groups["namespace"].Value;
108
var variableId = matches[i].Groups["fullname"].Value;
@@ -130,12 +132,16 @@ namespace WixToolset.Core
132
// check for an escape sequence of !! indicating the match is not a variable expression
133
if (0 < matches[i].Index && '!' == sb[matches[i].Index - 1])
134
{
133
- if (!localizationOnly)
135
+ if (finalizeEscapes)
136
{
137
sb.Remove(matches[i].Index - 1, 1);
138
139
result.UpdatedValue = true;
140
}
141
+ else
142
+ {
143
+ continue;
144
+ }
145
}
146
else
147
{
@@ -154,7 +160,7 @@ namespace WixToolset.Core
160
resolvedValue = bindVariable.Value;
161
}
162
}
157
- else if (!localizationOnly && "wix" == variableNamespace)
163
+ else if ("wix" == variableNamespace)
164
{
165
// illegal syntax of $(wix.var)
166
if ('$' == sb[matches[i].Index])
@@ -189,12 +195,13 @@ namespace WixToolset.Core
195
sb.Insert(matches[i].Index, resolvedValue);
196
197
result.UpdatedValue = true;
198
+ updatedResultThisPass = true;
199
}
200
else if ("loc" == variableNamespace && errorOnUnknown) // unresolved loc variable
201
{
202
this.Messaging.Write(ErrorMessages.LocalizationVariableUnknown(sourceLineNumbers, variableId));
203
}
197
- else if (!localizationOnly && "wix" == variableNamespace && errorOnUnknown) // unresolved wix variable
204
+ else if ("wix" == variableNamespace && errorOnUnknown) // unresolved wix variable
205
{
206
this.Messaging.Write(ErrorMessages.WixVariableUnknown(sourceLineNumbers, variableId));
207
}
@@ -204,7 +211,22 @@ namespace WixToolset.Core
211
212
result.Value = sb.ToString();
213
value = result.Value;
207
- matches = Common.WixVariableRegex.Matches(value);
214
+
215
+ if (finalizeEscapes)
216
+ {
217
+ // escaped references have been un-escaped, so we're done
218
+ break;
219
+ }
220
+ else if (updatedResultThisPass)
221
+ {
222
+ // we substituted loc strings, so make another pass to see if that brought in more loc strings
223
+ matches = Common.WixVariableRegex.Matches(value);
224
+ }
225
+ else
226
+ {
227
+ // make one final pass to un-escape any escaped references
228
+ finalizeEscapes = true;
229
+ }
230
}
231
232
return result;
src/test/WixToolsetTest.CoreIntegration/VariableResolverFixture.cs
+36
-4
@@ -29,10 +29,42 @@ namespace WixToolsetTest.CoreIntegration
29
30
variableResolver.AddLocalization(localization);
31
32
- Assert.Equal("Welcome to Localized Product Name", variableResolver.ResolveVariables(null, "Welcome to !(loc.ProductName)", false).Value);
33
- Assert.Equal("Welcome to Localized Product Name Enterprise Edition", variableResolver.ResolveVariables(null, "Welcome to !(loc.ProductNameEdition)", false).Value);
34
- Assert.Equal("Welcome to Localized Product Name Enterprise Edition v1.2.3", variableResolver.ResolveVariables(null, "Welcome to !(loc.ProductNameEditionVersion)", false).Value);
35
- Assert.Throws<WixException>(() => variableResolver.ResolveVariables(null, "Welcome to !(loc.UnknownLocalizationVariable)", false));
32
+ var result = variableResolver.ResolveVariables(null, "These are not the loc strings you're looking for.");
33
+ Assert.Equal("These are not the loc strings you're looking for.", result.Value);
34
+ Assert.False(result.UpdatedValue);
35
+
36
+ result = variableResolver.ResolveVariables(null, "Welcome to !(loc.ProductName)");
37
+ Assert.Equal("Welcome to Localized Product Name", result.Value);
38
+ Assert.True(result.UpdatedValue);
39
+
40
+ result = variableResolver.ResolveVariables(null, "Welcome to !(loc.ProductNameEdition)");
41
+ Assert.Equal("Welcome to Localized Product Name Enterprise Edition", result.Value);
42
+ Assert.True(result.UpdatedValue);
43
+
44
+ result = variableResolver.ResolveVariables(null, "Welcome to !(loc.ProductNameEditionVersion)");
45
+ Assert.Equal("Welcome to Localized Product Name Enterprise Edition v1.2.3", result.Value);
46
+ Assert.True(result.UpdatedValue);
47
+
48
+ result = variableResolver.ResolveVariables(null, "Welcome to !(bind.property.ProductVersion)");
49
+ Assert.Equal("Welcome to !(bind.property.ProductVersion)", result.Value);
50
+ Assert.False(result.UpdatedValue);
51
+ Assert.True(result.DelayedResolve);
52
+
53
+ Assert.Throws<WixException>(() => variableResolver.ResolveVariables(null, "Welcome to !(loc.UnknownLocalizationVariable)"));
54
+
55
+ result = variableResolver.ResolveVariables(null, "Welcome to !!(loc.UnknownLocalizationVariable)");
56
+ Assert.Equal("Welcome to !(loc.UnknownLocalizationVariable)", result.Value);
57
+ Assert.True(result.UpdatedValue);
58
+
59
+ result = variableResolver.ResolveVariables(null, "Welcome to !!(loc.UnknownLocalizationVariable) v!(bind.property.ProductVersion)");
60
+ Assert.Equal("Welcome to !(loc.UnknownLocalizationVariable) v!(bind.property.ProductVersion)", result.Value);
61
+ Assert.True(result.UpdatedValue);
62
+ Assert.True(result.DelayedResolve);
63
+
64
+ result = variableResolver.ResolveVariables(null, "Welcome to !(loc.ProductNameEditionVersion) !!(loc.UnknownLocalizationVariable) v!(bind.property.ProductVersion)");
65
+ Assert.Equal("Welcome to Localized Product Name Enterprise Edition v1.2.3 !(loc.UnknownLocalizationVariable) v!(bind.property.ProductVersion)", result.Value);
66
+ Assert.True(result.UpdatedValue);
67
+ Assert.True(result.DelayedResolve);
68
}
69
}
70
}