@joebigelow / wix-1 / commits / d097c7de

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 }