diff options
author | Rob Mensching <rob@firegiant.com> | 2019-03-01 16:45:55 -0800 |
---|---|---|
committer | Rob Mensching <rob@robmensching.com> | 2019-03-01 16:51:02 -0800 |
commit | 615bc202834ac45a9a107e5fccd900081a4abf74 (patch) | |
tree | ceebc5b3652f0274bee745701a3538439b0275d1 /src/WixToolset.Core | |
parent | 009f11ca9cf8674b40b74888aae90bcd4817828b (diff) | |
download | wix-615bc202834ac45a9a107e5fccd900081a4abf74.tar.gz wix-615bc202834ac45a9a107e5fccd900081a4abf74.tar.bz2 wix-615bc202834ac45a9a107e5fccd900081a4abf74.zip |
Include the preprocessed include files with the processed document
This change also cleans up the internal state handling of the preprocesor
to pass the processing state around rather than depend on "global state"
in member variables. This removes the need to "reset" the member
variables before preprocessing which is much cleaner.
Diffstat (limited to 'src/WixToolset.Core')
-rw-r--r-- | src/WixToolset.Core/CommandLine/BuildCommand.cs | 6 | ||||
-rw-r--r-- | src/WixToolset.Core/CommandLine/CompileCommand.cs | 6 | ||||
-rw-r--r-- | src/WixToolset.Core/IPreprocessor.cs | 5 | ||||
-rw-r--r-- | src/WixToolset.Core/IncludedFile.cs | 14 | ||||
-rw-r--r-- | src/WixToolset.Core/PreprocessResult.cs | 15 | ||||
-rw-r--r-- | src/WixToolset.Core/Preprocessor.cs | 362 | ||||
-rw-r--r-- | src/WixToolset.Core/WixToolsetServiceProvider.cs | 2 |
7 files changed, 237 insertions, 173 deletions
diff --git a/src/WixToolset.Core/CommandLine/BuildCommand.cs b/src/WixToolset.Core/CommandLine/BuildCommand.cs index b83aaec4..7e6ddd64 100644 --- a/src/WixToolset.Core/CommandLine/BuildCommand.cs +++ b/src/WixToolset.Core/CommandLine/BuildCommand.cs | |||
@@ -377,18 +377,18 @@ namespace WixToolset.Core.CommandLine | |||
377 | context.SourcePath = sourcePath; | 377 | context.SourcePath = sourcePath; |
378 | context.Variables = preprocessorVariables; | 378 | context.Variables = preprocessorVariables; |
379 | 379 | ||
380 | XDocument document = null; | 380 | IPreprocessResult result = null; |
381 | try | 381 | try |
382 | { | 382 | { |
383 | var preprocessor = this.ServiceProvider.GetService<IPreprocessor>(); | 383 | var preprocessor = this.ServiceProvider.GetService<IPreprocessor>(); |
384 | document = preprocessor.Preprocess(context); | 384 | result = preprocessor.Preprocess(context); |
385 | } | 385 | } |
386 | catch (WixException e) | 386 | catch (WixException e) |
387 | { | 387 | { |
388 | this.Messaging.Write(e.Error); | 388 | this.Messaging.Write(e.Error); |
389 | } | 389 | } |
390 | 390 | ||
391 | return document; | 391 | return result?.Document; |
392 | } | 392 | } |
393 | 393 | ||
394 | private class CommandLine | 394 | private class CommandLine |
diff --git a/src/WixToolset.Core/CommandLine/CompileCommand.cs b/src/WixToolset.Core/CommandLine/CompileCommand.cs index 69e35cab..bc37ee8c 100644 --- a/src/WixToolset.Core/CommandLine/CompileCommand.cs +++ b/src/WixToolset.Core/CommandLine/CompileCommand.cs | |||
@@ -63,11 +63,11 @@ namespace WixToolset.Core.CommandLine | |||
63 | context.SourcePath = sourceFile.SourcePath; | 63 | context.SourcePath = sourceFile.SourcePath; |
64 | context.Variables = this.PreprocessorVariables; | 64 | context.Variables = this.PreprocessorVariables; |
65 | 65 | ||
66 | XDocument document = null; | 66 | IPreprocessResult result = null; |
67 | try | 67 | try |
68 | { | 68 | { |
69 | var preprocessor = this.ServiceProvider.GetService<IPreprocessor>(); | 69 | var preprocessor = this.ServiceProvider.GetService<IPreprocessor>(); |
70 | document = preprocessor.Preprocess(context); | 70 | result = preprocessor.Preprocess(context); |
71 | } | 71 | } |
72 | catch (WixException e) | 72 | catch (WixException e) |
73 | { | 73 | { |
@@ -83,7 +83,7 @@ namespace WixToolset.Core.CommandLine | |||
83 | compileContext.Extensions = this.ExtensionManager.Create<ICompilerExtension>(); | 83 | compileContext.Extensions = this.ExtensionManager.Create<ICompilerExtension>(); |
84 | compileContext.OutputPath = sourceFile.OutputPath; | 84 | compileContext.OutputPath = sourceFile.OutputPath; |
85 | compileContext.Platform = this.Platform; | 85 | compileContext.Platform = this.Platform; |
86 | compileContext.Source = document; | 86 | compileContext.Source = result?.Document; |
87 | 87 | ||
88 | var compiler = this.ServiceProvider.GetService<ICompiler>(); | 88 | var compiler = this.ServiceProvider.GetService<ICompiler>(); |
89 | var intermediate = compiler.Compile(compileContext); | 89 | var intermediate = compiler.Compile(compileContext); |
diff --git a/src/WixToolset.Core/IPreprocessor.cs b/src/WixToolset.Core/IPreprocessor.cs index d892399c..151f8111 100644 --- a/src/WixToolset.Core/IPreprocessor.cs +++ b/src/WixToolset.Core/IPreprocessor.cs | |||
@@ -3,13 +3,12 @@ | |||
3 | namespace WixToolset.Core | 3 | namespace WixToolset.Core |
4 | { | 4 | { |
5 | using System.Xml; | 5 | using System.Xml; |
6 | using System.Xml.Linq; | ||
7 | using WixToolset.Extensibility.Data; | 6 | using WixToolset.Extensibility.Data; |
8 | 7 | ||
9 | public interface IPreprocessor | 8 | public interface IPreprocessor |
10 | { | 9 | { |
11 | XDocument Preprocess(IPreprocessContext context); | 10 | IPreprocessResult Preprocess(IPreprocessContext context); |
12 | 11 | ||
13 | XDocument Preprocess(IPreprocessContext context, XmlReader reader); | 12 | IPreprocessResult Preprocess(IPreprocessContext context, XmlReader reader); |
14 | } | 13 | } |
15 | } | 14 | } |
diff --git a/src/WixToolset.Core/IncludedFile.cs b/src/WixToolset.Core/IncludedFile.cs new file mode 100644 index 00000000..25d51191 --- /dev/null +++ b/src/WixToolset.Core/IncludedFile.cs | |||
@@ -0,0 +1,14 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | namespace WixToolset.Core | ||
4 | { | ||
5 | using WixToolset.Data; | ||
6 | using WixToolset.Extensibility.Data; | ||
7 | |||
8 | internal class IncludedFile : IIncludedFile | ||
9 | { | ||
10 | public string Path { get; set; } | ||
11 | |||
12 | public SourceLineNumber SourceLineNumbers { get; set; } | ||
13 | } | ||
14 | } | ||
diff --git a/src/WixToolset.Core/PreprocessResult.cs b/src/WixToolset.Core/PreprocessResult.cs new file mode 100644 index 00000000..8595d21d --- /dev/null +++ b/src/WixToolset.Core/PreprocessResult.cs | |||
@@ -0,0 +1,15 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | namespace WixToolset.Core | ||
4 | { | ||
5 | using System.Collections.Generic; | ||
6 | using System.Xml.Linq; | ||
7 | using WixToolset.Extensibility.Data; | ||
8 | |||
9 | public class PreprocessResult : IPreprocessResult | ||
10 | { | ||
11 | public XDocument Document { get; set; } | ||
12 | |||
13 | public IEnumerable<IIncludedFile> IncludedFiles { get; set; } | ||
14 | } | ||
15 | } | ||
diff --git a/src/WixToolset.Core/Preprocessor.cs b/src/WixToolset.Core/Preprocessor.cs index a829f7c4..5a255234 100644 --- a/src/WixToolset.Core/Preprocessor.cs +++ b/src/WixToolset.Core/Preprocessor.cs | |||
@@ -48,18 +48,6 @@ namespace WixToolset.Core | |||
48 | 48 | ||
49 | private IMessaging Messaging { get; } | 49 | private IMessaging Messaging { get; } |
50 | 50 | ||
51 | private IPreprocessContext Context { get; set; } | ||
52 | |||
53 | private Stack<string> CurrentFileStack { get; } = new Stack<string>(); | ||
54 | |||
55 | private Dictionary<string, IPreprocessorExtension> ExtensionsByPrefix { get; } = new Dictionary<string, IPreprocessorExtension>(); | ||
56 | |||
57 | private Stack<bool> IncludeNextStack { get; } = new Stack<bool>(); | ||
58 | |||
59 | private Stack<SourceLineNumber> SourceStack { get; } = new Stack<SourceLineNumber>(); | ||
60 | |||
61 | private IPreprocessHelper Helper { get; set; } | ||
62 | |||
63 | /// <summary> | 51 | /// <summary> |
64 | /// Event for ifdef/ifndef directives. | 52 | /// Event for ifdef/ifndef directives. |
65 | /// </summary> | 53 | /// </summary> |
@@ -100,21 +88,21 @@ namespace WixToolset.Core | |||
100 | /// </summary> | 88 | /// </summary> |
101 | /// <param name="context">The preprocessing context.</param> | 89 | /// <param name="context">The preprocessing context.</param> |
102 | /// <returns>XDocument with the postprocessed data.</returns> | 90 | /// <returns>XDocument with the postprocessed data.</returns> |
103 | public XDocument Preprocess(IPreprocessContext context) | 91 | public IPreprocessResult Preprocess(IPreprocessContext context) |
104 | { | 92 | { |
105 | this.Context = context; | 93 | var state = new ProcessingState(this.ServiceProvider, context); |
106 | this.Context.CurrentSourceLineNumber = new SourceLineNumber(context.SourcePath); | ||
107 | this.Context.Variables = this.Context.Variables == null ? new Dictionary<string, string>() : new Dictionary<string, string>(this.Context.Variables); | ||
108 | 94 | ||
109 | this.PreProcess(); | 95 | this.PreProcess(state); |
110 | 96 | ||
111 | XDocument document; | 97 | IPreprocessResult result; |
112 | using (var reader = XmlReader.Create(this.Context.SourcePath, DocumentXmlReaderSettings)) | 98 | using (var reader = XmlReader.Create(state.Context.SourcePath, DocumentXmlReaderSettings)) |
113 | { | 99 | { |
114 | document = this.Process(reader); | 100 | result = this.Process(state, reader); |
115 | } | 101 | } |
116 | 102 | ||
117 | return this.PostProcess(document); | 103 | this.PostProcess(state, result); |
104 | |||
105 | return result; | ||
118 | } | 106 | } |
119 | 107 | ||
120 | /// <summary> | 108 | /// <summary> |
@@ -123,7 +111,7 @@ namespace WixToolset.Core | |||
123 | /// <param name="context">The preprocessing context.</param> | 111 | /// <param name="context">The preprocessing context.</param> |
124 | /// <param name="reader">XmlReader to processing the context.</param> | 112 | /// <param name="reader">XmlReader to processing the context.</param> |
125 | /// <returns>XDocument with the postprocessed data.</returns> | 113 | /// <returns>XDocument with the postprocessed data.</returns> |
126 | public XDocument Preprocess(IPreprocessContext context, XmlReader reader) | 114 | public IPreprocessResult Preprocess(IPreprocessContext context, XmlReader reader) |
127 | { | 115 | { |
128 | if (String.IsNullOrEmpty(context.SourcePath) && !String.IsNullOrEmpty(reader.BaseURI)) | 116 | if (String.IsNullOrEmpty(context.SourcePath) && !String.IsNullOrEmpty(reader.BaseURI)) |
129 | { | 117 | { |
@@ -131,15 +119,15 @@ namespace WixToolset.Core | |||
131 | context.SourcePath = uri.AbsolutePath; | 119 | context.SourcePath = uri.AbsolutePath; |
132 | } | 120 | } |
133 | 121 | ||
134 | this.Context = context; | 122 | var state = new ProcessingState(this.ServiceProvider, context); |
135 | this.Context.CurrentSourceLineNumber = new SourceLineNumber(context.SourcePath); | ||
136 | this.Context.Variables = (this.Context.Variables == null) ? new Dictionary<string, string>() : new Dictionary<string, string>(this.Context.Variables); | ||
137 | 123 | ||
138 | this.PreProcess(); | 124 | this.PreProcess(state); |
139 | 125 | ||
140 | var document = this.Process(reader); | 126 | var result = this.Process(state, reader); |
141 | 127 | ||
142 | return this.PostProcess(document); | 128 | this.PostProcess(state, result); |
129 | |||
130 | return result; | ||
143 | } | 131 | } |
144 | 132 | ||
145 | /// <summary> | 133 | /// <summary> |
@@ -148,29 +136,33 @@ namespace WixToolset.Core | |||
148 | /// <param name="context">The preprocessing context.</param> | 136 | /// <param name="context">The preprocessing context.</param> |
149 | /// <param name="reader">XmlReader to processing the context.</param> | 137 | /// <param name="reader">XmlReader to processing the context.</param> |
150 | /// <returns>XDocument with the postprocessed data.</returns> | 138 | /// <returns>XDocument with the postprocessed data.</returns> |
151 | private XDocument Process(XmlReader reader) | 139 | private IPreprocessResult Process(ProcessingState state, XmlReader reader) |
152 | { | 140 | { |
153 | this.Helper = this.ServiceProvider.GetService<IPreprocessHelper>(); | 141 | state.CurrentFileStack.Push(state.Helper.GetVariableValue(state.Context, "sys", "SOURCEFILEDIR")); |
154 | |||
155 | this.CurrentFileStack.Clear(); | ||
156 | this.CurrentFileStack.Push(this.Helper.GetVariableValue(this.Context, "sys", "SOURCEFILEDIR")); | ||
157 | 142 | ||
158 | // Process the reader into the output. | 143 | // Process the reader into the output. |
159 | var output = new XDocument(); | 144 | IPreprocessResult result = null; |
160 | try | 145 | try |
161 | { | 146 | { |
162 | this.PreprocessReader(false, reader, output, 0); | 147 | this.PreprocessReader(state, false, reader, state.Output, 0); |
163 | 148 | ||
164 | // Fire event with post-processed document. | 149 | // Fire event with post-processed document. |
165 | this.ProcessedStream?.Invoke(this, new ProcessedStreamEventArgs(this.Context.SourcePath, output)); | 150 | this.ProcessedStream?.Invoke(this, new ProcessedStreamEventArgs(state.Context.SourcePath, state.Output)); |
151 | |||
152 | if (!this.Messaging.EncounteredError) | ||
153 | { | ||
154 | result = this.ServiceProvider.GetService<IPreprocessResult>(); | ||
155 | result.Document = state.Output; | ||
156 | result.IncludedFiles = state.IncludedFiles; | ||
157 | } | ||
166 | } | 158 | } |
167 | catch (XmlException e) | 159 | catch (XmlException e) |
168 | { | 160 | { |
169 | this.UpdateCurrentLineNumber(reader, 0); | 161 | this.UpdateCurrentLineNumber(state, reader, 0); |
170 | throw new WixException(ErrorMessages.InvalidXml(this.Context.CurrentSourceLineNumber, "source", e.Message)); | 162 | throw new WixException(ErrorMessages.InvalidXml(state.Context.CurrentSourceLineNumber, "source", e.Message)); |
171 | } | 163 | } |
172 | 164 | ||
173 | return this.Messaging.EncounteredError ? null : output; | 165 | return result; |
174 | } | 166 | } |
175 | 167 | ||
176 | /// <summary> | 168 | /// <summary> |
@@ -277,7 +269,7 @@ namespace WixToolset.Core | |||
277 | /// <param name="reader">Reader for the source document.</param> | 269 | /// <param name="reader">Reader for the source document.</param> |
278 | /// <param name="container">Node where content should be added.</param> | 270 | /// <param name="container">Node where content should be added.</param> |
279 | /// <param name="offset">Original offset for the line numbers being processed.</param> | 271 | /// <param name="offset">Original offset for the line numbers being processed.</param> |
280 | private void PreprocessReader(bool include, XmlReader reader, XContainer container, int offset) | 272 | private void PreprocessReader(ProcessingState state, bool include, XmlReader reader, XContainer container, int offset) |
281 | { | 273 | { |
282 | var currentContainer = container; | 274 | var currentContainer = container; |
283 | var containerStack = new Stack<XContainer>(); | 275 | var containerStack = new Stack<XContainer>(); |
@@ -289,9 +281,9 @@ namespace WixToolset.Core | |||
289 | while (reader.Read()) | 281 | while (reader.Read()) |
290 | { | 282 | { |
291 | // update information here in case an error occurs before the next read | 283 | // update information here in case an error occurs before the next read |
292 | this.UpdateCurrentLineNumber(reader, offset); | 284 | this.UpdateCurrentLineNumber(state, reader, offset); |
293 | 285 | ||
294 | var sourceLineNumbers = this.Context.CurrentSourceLineNumber; | 286 | var sourceLineNumbers = state.Context.CurrentSourceLineNumber; |
295 | 287 | ||
296 | // check for changes in conditional processing | 288 | // check for changes in conditional processing |
297 | if (XmlNodeType.ProcessingInstruction == reader.NodeType) | 289 | if (XmlNodeType.ProcessingInstruction == reader.NodeType) |
@@ -305,7 +297,7 @@ namespace WixToolset.Core | |||
305 | ifStack.Push(ifContext); | 297 | ifStack.Push(ifContext); |
306 | if (ifContext.IsTrue) | 298 | if (ifContext.IsTrue) |
307 | { | 299 | { |
308 | ifContext = new IfContext(ifContext.IsTrue & ifContext.Active, this.EvaluateExpression(reader.Value), IfState.If); | 300 | ifContext = new IfContext(ifContext.IsTrue & ifContext.Active, this.EvaluateExpression(state, reader.Value), IfState.If); |
309 | } | 301 | } |
310 | else // Use a default IfContext object so we don't try to evaluate the expression if the context isn't true | 302 | else // Use a default IfContext object so we don't try to evaluate the expression if the context isn't true |
311 | { | 303 | { |
@@ -319,7 +311,7 @@ namespace WixToolset.Core | |||
319 | name = reader.Value.Trim(); | 311 | name = reader.Value.Trim(); |
320 | if (ifContext.IsTrue) | 312 | if (ifContext.IsTrue) |
321 | { | 313 | { |
322 | ifContext = new IfContext(ifContext.IsTrue & ifContext.Active, (null != this.Helper.GetVariableValue(this.Context, name, true)), IfState.If); | 314 | ifContext = new IfContext(ifContext.IsTrue & ifContext.Active, (null != state.Helper.GetVariableValue(state.Context, name, true)), IfState.If); |
323 | } | 315 | } |
324 | else // Use a default IfContext object so we don't try to evaluate the expression if the context isn't true | 316 | else // Use a default IfContext object so we don't try to evaluate the expression if the context isn't true |
325 | { | 317 | { |
@@ -334,7 +326,7 @@ namespace WixToolset.Core | |||
334 | name = reader.Value.Trim(); | 326 | name = reader.Value.Trim(); |
335 | if (ifContext.IsTrue) | 327 | if (ifContext.IsTrue) |
336 | { | 328 | { |
337 | ifContext = new IfContext(ifContext.IsTrue & ifContext.Active, (null == this.Helper.GetVariableValue(this.Context, name, true)), IfState.If); | 329 | ifContext = new IfContext(ifContext.IsTrue & ifContext.Active, (null == state.Helper.GetVariableValue(state.Context, name, true)), IfState.If); |
338 | } | 330 | } |
339 | else // Use a default IfContext object so we don't try to evaluate the expression if the context isn't true | 331 | else // Use a default IfContext object so we don't try to evaluate the expression if the context isn't true |
340 | { | 332 | { |
@@ -358,7 +350,7 @@ namespace WixToolset.Core | |||
358 | ifContext.IfState = IfState.ElseIf; // we're now in an elseif | 350 | ifContext.IfState = IfState.ElseIf; // we're now in an elseif |
359 | if (!ifContext.WasEverTrue) // if we've never evaluated the if context to true, then we can try this test | 351 | if (!ifContext.WasEverTrue) // if we've never evaluated the if context to true, then we can try this test |
360 | { | 352 | { |
361 | ifContext.IsTrue = this.EvaluateExpression(reader.Value); | 353 | ifContext.IsTrue = this.EvaluateExpression(state, reader.Value); |
362 | } | 354 | } |
363 | else if (ifContext.IsTrue) | 355 | else if (ifContext.IsTrue) |
364 | { | 356 | { |
@@ -441,35 +433,35 @@ namespace WixToolset.Core | |||
441 | switch (reader.LocalName) | 433 | switch (reader.LocalName) |
442 | { | 434 | { |
443 | case "define": | 435 | case "define": |
444 | this.PreprocessDefine(reader.Value); | 436 | this.PreprocessDefine(state, reader.Value); |
445 | break; | 437 | break; |
446 | 438 | ||
447 | case "error": | 439 | case "error": |
448 | this.PreprocessError(reader.Value); | 440 | this.PreprocessError(state, reader.Value); |
449 | break; | 441 | break; |
450 | 442 | ||
451 | case "warning": | 443 | case "warning": |
452 | this.PreprocessWarning(reader.Value); | 444 | this.PreprocessWarning(state, reader.Value); |
453 | break; | 445 | break; |
454 | 446 | ||
455 | case "undef": | 447 | case "undef": |
456 | this.PreprocessUndef(reader.Value); | 448 | this.PreprocessUndef(state, reader.Value); |
457 | break; | 449 | break; |
458 | 450 | ||
459 | case "include": | 451 | case "include": |
460 | this.UpdateCurrentLineNumber(reader, offset); | 452 | this.UpdateCurrentLineNumber(state, reader, offset); |
461 | this.PreprocessInclude(reader.Value, currentContainer); | 453 | this.PreprocessInclude(state, reader.Value, currentContainer); |
462 | break; | 454 | break; |
463 | 455 | ||
464 | case "foreach": | 456 | case "foreach": |
465 | this.PreprocessForeach(reader, currentContainer, offset); | 457 | this.PreprocessForeach(state, reader, currentContainer, offset); |
466 | break; | 458 | break; |
467 | 459 | ||
468 | case "endforeach": // endforeach is handled in PreprocessForeach, so seeing it here is an error | 460 | case "endforeach": // endforeach is handled in PreprocessForeach, so seeing it here is an error |
469 | throw new WixException(ErrorMessages.UnmatchedPreprocessorInstruction(sourceLineNumbers, "foreach", "endforeach")); | 461 | throw new WixException(ErrorMessages.UnmatchedPreprocessorInstruction(sourceLineNumbers, "foreach", "endforeach")); |
470 | 462 | ||
471 | case "pragma": | 463 | case "pragma": |
472 | this.PreprocessPragma(reader.Value, currentContainer); | 464 | this.PreprocessPragma(state, reader.Value, currentContainer); |
473 | break; | 465 | break; |
474 | 466 | ||
475 | default: | 467 | default: |
@@ -479,15 +471,15 @@ namespace WixToolset.Core | |||
479 | break; | 471 | break; |
480 | 472 | ||
481 | case XmlNodeType.Element: | 473 | case XmlNodeType.Element: |
482 | if (0 < this.IncludeNextStack.Count && this.IncludeNextStack.Peek()) | 474 | if (0 < state.IncludeNextStack.Count && state.IncludeNextStack.Peek()) |
483 | { | 475 | { |
484 | if ("Include" != reader.LocalName) | 476 | if ("Include" != reader.LocalName) |
485 | { | 477 | { |
486 | this.Messaging.Write(ErrorMessages.InvalidDocumentElement(sourceLineNumbers, reader.Name, "include", "Include")); | 478 | this.Messaging.Write(ErrorMessages.InvalidDocumentElement(sourceLineNumbers, reader.Name, "include", "Include")); |
487 | } | 479 | } |
488 | 480 | ||
489 | this.IncludeNextStack.Pop(); | 481 | state.IncludeNextStack.Pop(); |
490 | this.IncludeNextStack.Push(false); | 482 | state.IncludeNextStack.Push(false); |
491 | break; | 483 | break; |
492 | } | 484 | } |
493 | 485 | ||
@@ -496,12 +488,12 @@ namespace WixToolset.Core | |||
496 | var element = new XElement(ns + reader.LocalName); | 488 | var element = new XElement(ns + reader.LocalName); |
497 | currentContainer.Add(element); | 489 | currentContainer.Add(element); |
498 | 490 | ||
499 | this.UpdateCurrentLineNumber(reader, offset); | 491 | this.UpdateCurrentLineNumber(state, reader, offset); |
500 | element.AddAnnotation(sourceLineNumbers); | 492 | element.AddAnnotation(sourceLineNumbers); |
501 | 493 | ||
502 | while (reader.MoveToNextAttribute()) | 494 | while (reader.MoveToNextAttribute()) |
503 | { | 495 | { |
504 | var value = this.Helper.PreprocessString(this.Context, reader.Value); | 496 | var value = state.Helper.PreprocessString(state.Context, reader.Value); |
505 | 497 | ||
506 | var attribNamespace = XNamespace.Get(reader.NamespaceURI); | 498 | var attribNamespace = XNamespace.Get(reader.NamespaceURI); |
507 | attribNamespace = XNamespace.Xmlns == attribNamespace && reader.LocalName.Equals("xmlns") ? XNamespace.None : attribNamespace; | 499 | attribNamespace = XNamespace.Xmlns == attribNamespace && reader.LocalName.Equals("xmlns") ? XNamespace.None : attribNamespace; |
@@ -524,12 +516,12 @@ namespace WixToolset.Core | |||
524 | break; | 516 | break; |
525 | 517 | ||
526 | case XmlNodeType.Text: | 518 | case XmlNodeType.Text: |
527 | var postprocessedText = this.Helper.PreprocessString(this.Context, reader.Value); | 519 | var postprocessedText = state.Helper.PreprocessString(state.Context, reader.Value); |
528 | currentContainer.Add(postprocessedText); | 520 | currentContainer.Add(postprocessedText); |
529 | break; | 521 | break; |
530 | 522 | ||
531 | case XmlNodeType.CDATA: | 523 | case XmlNodeType.CDATA: |
532 | var postprocessedValue = this.Helper.PreprocessString(this.Context, reader.Value); | 524 | var postprocessedValue = state.Helper.PreprocessString(state.Context, reader.Value); |
533 | currentContainer.Add(new XCData(postprocessedValue)); | 525 | currentContainer.Add(new XCData(postprocessedValue)); |
534 | break; | 526 | break; |
535 | 527 | ||
@@ -540,13 +532,13 @@ namespace WixToolset.Core | |||
540 | 532 | ||
541 | if (0 != ifStack.Count) | 533 | if (0 != ifStack.Count) |
542 | { | 534 | { |
543 | throw new WixException(ErrorMessages.NonterminatedPreprocessorInstruction(this.Context.CurrentSourceLineNumber, "if", "endif")); | 535 | throw new WixException(ErrorMessages.NonterminatedPreprocessorInstruction(state.Context.CurrentSourceLineNumber, "if", "endif")); |
544 | } | 536 | } |
545 | 537 | ||
546 | // TODO: can this actually happen? | 538 | // TODO: can this actually happen? |
547 | if (0 != containerStack.Count) | 539 | if (0 != containerStack.Count) |
548 | { | 540 | { |
549 | throw new WixException(ErrorMessages.NonterminatedPreprocessorInstruction(this.Context.CurrentSourceLineNumber, "nodes", "nodes")); | 541 | throw new WixException(ErrorMessages.NonterminatedPreprocessorInstruction(state.Context.CurrentSourceLineNumber, "nodes", "nodes")); |
550 | } | 542 | } |
551 | } | 543 | } |
552 | 544 | ||
@@ -554,37 +546,37 @@ namespace WixToolset.Core | |||
554 | /// Processes an error processing instruction. | 546 | /// Processes an error processing instruction. |
555 | /// </summary> | 547 | /// </summary> |
556 | /// <param name="errorMessage">Text from source.</param> | 548 | /// <param name="errorMessage">Text from source.</param> |
557 | private void PreprocessError(string errorMessage) | 549 | private void PreprocessError(ProcessingState state, string errorMessage) |
558 | { | 550 | { |
559 | // Resolve other variables in the error message. | 551 | // Resolve other variables in the error message. |
560 | errorMessage = this.Helper.PreprocessString(this.Context, errorMessage); | 552 | errorMessage = state.Helper.PreprocessString(state.Context, errorMessage); |
561 | 553 | ||
562 | throw new WixException(ErrorMessages.PreprocessorError(this.Context.CurrentSourceLineNumber, errorMessage)); | 554 | throw new WixException(ErrorMessages.PreprocessorError(state.Context.CurrentSourceLineNumber, errorMessage)); |
563 | } | 555 | } |
564 | 556 | ||
565 | /// <summary> | 557 | /// <summary> |
566 | /// Processes a warning processing instruction. | 558 | /// Processes a warning processing instruction. |
567 | /// </summary> | 559 | /// </summary> |
568 | /// <param name="warningMessage">Text from source.</param> | 560 | /// <param name="warningMessage">Text from source.</param> |
569 | private void PreprocessWarning(string warningMessage) | 561 | private void PreprocessWarning(ProcessingState state, string warningMessage) |
570 | { | 562 | { |
571 | // Resolve other variables in the warning message. | 563 | // Resolve other variables in the warning message. |
572 | warningMessage = this.Helper.PreprocessString(this.Context, warningMessage); | 564 | warningMessage = state.Helper.PreprocessString(state.Context, warningMessage); |
573 | 565 | ||
574 | this.Messaging.Write(WarningMessages.PreprocessorWarning(this.Context.CurrentSourceLineNumber, warningMessage)); | 566 | this.Messaging.Write(WarningMessages.PreprocessorWarning(state.Context.CurrentSourceLineNumber, warningMessage)); |
575 | } | 567 | } |
576 | 568 | ||
577 | /// <summary> | 569 | /// <summary> |
578 | /// Processes a define processing instruction and creates the appropriate parameter. | 570 | /// Processes a define processing instruction and creates the appropriate parameter. |
579 | /// </summary> | 571 | /// </summary> |
580 | /// <param name="originalDefine">Text from source.</param> | 572 | /// <param name="originalDefine">Text from source.</param> |
581 | private void PreprocessDefine(string originalDefine) | 573 | private void PreprocessDefine(ProcessingState state, string originalDefine) |
582 | { | 574 | { |
583 | var match = DefineRegex.Match(originalDefine); | 575 | var match = DefineRegex.Match(originalDefine); |
584 | 576 | ||
585 | if (!match.Success) | 577 | if (!match.Success) |
586 | { | 578 | { |
587 | throw new WixException(ErrorMessages.IllegalDefineStatement(this.Context.CurrentSourceLineNumber, originalDefine)); | 579 | throw new WixException(ErrorMessages.IllegalDefineStatement(state.Context.CurrentSourceLineNumber, originalDefine)); |
588 | } | 580 | } |
589 | 581 | ||
590 | var defineName = match.Groups["varName"].Value; | 582 | var defineName = match.Groups["varName"].Value; |
@@ -599,15 +591,15 @@ namespace WixToolset.Core | |||
599 | } | 591 | } |
600 | 592 | ||
601 | // resolve other variables in the variable value | 593 | // resolve other variables in the variable value |
602 | defineValue = this.Helper.PreprocessString(this.Context, defineValue); | 594 | defineValue = state.Helper.PreprocessString(state.Context, defineValue); |
603 | 595 | ||
604 | if (defineName.StartsWith("var.", StringComparison.Ordinal)) | 596 | if (defineName.StartsWith("var.", StringComparison.Ordinal)) |
605 | { | 597 | { |
606 | this.Helper.AddVariable(this.Context, defineName.Substring(4), defineValue); | 598 | state.Helper.AddVariable(state.Context, defineName.Substring(4), defineValue); |
607 | } | 599 | } |
608 | else | 600 | else |
609 | { | 601 | { |
610 | this.Helper.AddVariable(this.Context, defineName, defineValue); | 602 | state.Helper.AddVariable(state.Context, defineName, defineValue); |
611 | } | 603 | } |
612 | } | 604 | } |
613 | 605 | ||
@@ -615,17 +607,17 @@ namespace WixToolset.Core | |||
615 | /// Processes an undef processing instruction and creates the appropriate parameter. | 607 | /// Processes an undef processing instruction and creates the appropriate parameter. |
616 | /// </summary> | 608 | /// </summary> |
617 | /// <param name="originalDefine">Text from source.</param> | 609 | /// <param name="originalDefine">Text from source.</param> |
618 | private void PreprocessUndef(string originalDefine) | 610 | private void PreprocessUndef(ProcessingState state, string originalDefine) |
619 | { | 611 | { |
620 | var name = this.Helper.PreprocessString(this.Context, originalDefine.Trim()); | 612 | var name = state.Helper.PreprocessString(state.Context, originalDefine.Trim()); |
621 | 613 | ||
622 | if (name.StartsWith("var.", StringComparison.Ordinal)) | 614 | if (name.StartsWith("var.", StringComparison.Ordinal)) |
623 | { | 615 | { |
624 | this.Helper.RemoveVariable(this.Context, name.Substring(4)); | 616 | state.Helper.RemoveVariable(state.Context, name.Substring(4)); |
625 | } | 617 | } |
626 | else | 618 | else |
627 | { | 619 | { |
628 | this.Helper.RemoveVariable(this.Context, name); | 620 | state.Helper.RemoveVariable(state.Context, name); |
629 | } | 621 | } |
630 | } | 622 | } |
631 | 623 | ||
@@ -634,14 +626,14 @@ namespace WixToolset.Core | |||
634 | /// </summary> | 626 | /// </summary> |
635 | /// <param name="includePath">Path to included file.</param> | 627 | /// <param name="includePath">Path to included file.</param> |
636 | /// <param name="parent">Parent container for included content.</param> | 628 | /// <param name="parent">Parent container for included content.</param> |
637 | private void PreprocessInclude(string includePath, XContainer parent) | 629 | private void PreprocessInclude(ProcessingState state, string includePath, XContainer parent) |
638 | { | 630 | { |
639 | var sourceLineNumbers = this.Context.CurrentSourceLineNumber; | 631 | var sourceLineNumbers = state.Context.CurrentSourceLineNumber; |
640 | 632 | ||
641 | // Preprocess variables in the path. | 633 | // Preprocess variables in the path. |
642 | includePath = this.Helper.PreprocessString(this.Context, includePath); | 634 | includePath = state.Helper.PreprocessString(state.Context, includePath); |
643 | 635 | ||
644 | var includeFile = this.GetIncludeFile(includePath); | 636 | var includeFile = this.GetIncludeFile(state, includePath); |
645 | 637 | ||
646 | if (null == includeFile) | 638 | if (null == includeFile) |
647 | { | 639 | { |
@@ -650,22 +642,28 @@ namespace WixToolset.Core | |||
650 | 642 | ||
651 | using (var reader = XmlReader.Create(includeFile, DocumentXmlReaderSettings)) | 643 | using (var reader = XmlReader.Create(includeFile, DocumentXmlReaderSettings)) |
652 | { | 644 | { |
653 | this.PushInclude(includeFile); | 645 | this.PushInclude(state, includeFile); |
654 | 646 | ||
655 | // process the included reader into the writer | 647 | // process the included reader into the writer |
656 | try | 648 | try |
657 | { | 649 | { |
658 | this.PreprocessReader(true, reader, parent, 0); | 650 | this.PreprocessReader(state, true, reader, parent, 0); |
659 | } | 651 | } |
660 | catch (XmlException e) | 652 | catch (XmlException e) |
661 | { | 653 | { |
662 | this.UpdateCurrentLineNumber(reader, 0); | 654 | this.UpdateCurrentLineNumber(state, reader, 0); |
663 | throw new WixException(ErrorMessages.InvalidXml(sourceLineNumbers, "source", e.Message)); | 655 | throw new WixException(ErrorMessages.InvalidXml(sourceLineNumbers, "source", e.Message)); |
664 | } | 656 | } |
665 | 657 | ||
666 | this.IncludedFile?.Invoke(this, new IncludedFileEventArgs(sourceLineNumbers, includeFile)); | 658 | this.IncludedFile?.Invoke(this, new IncludedFileEventArgs(sourceLineNumbers, includeFile)); |
667 | 659 | ||
668 | this.PopInclude(); | 660 | var includedFile = this.ServiceProvider.GetService<IIncludedFile>(); |
661 | includedFile.Path = includeFile; | ||
662 | includedFile.SourceLineNumbers = sourceLineNumbers; | ||
663 | |||
664 | state.IncludedFiles.Add(includedFile); | ||
665 | |||
666 | this.PopInclude(state); | ||
669 | } | 667 | } |
670 | } | 668 | } |
671 | 669 | ||
@@ -675,13 +673,13 @@ namespace WixToolset.Core | |||
675 | /// <param name="reader">The xml reader.</param> | 673 | /// <param name="reader">The xml reader.</param> |
676 | /// <param name="container">The container where to output processed data.</param> | 674 | /// <param name="container">The container where to output processed data.</param> |
677 | /// <param name="offset">Offset for the line numbers.</param> | 675 | /// <param name="offset">Offset for the line numbers.</param> |
678 | private void PreprocessForeach(XmlReader reader, XContainer container, int offset) | 676 | private void PreprocessForeach(ProcessingState state, XmlReader reader, XContainer container, int offset) |
679 | { | 677 | { |
680 | // Find the "in" token. | 678 | // Find the "in" token. |
681 | var indexOfInToken = reader.Value.IndexOf(" in ", StringComparison.Ordinal); | 679 | var indexOfInToken = reader.Value.IndexOf(" in ", StringComparison.Ordinal); |
682 | if (0 > indexOfInToken) | 680 | if (0 > indexOfInToken) |
683 | { | 681 | { |
684 | throw new WixException(ErrorMessages.IllegalForeach(this.Context.CurrentSourceLineNumber, reader.Value)); | 682 | throw new WixException(ErrorMessages.IllegalForeach(state.Context.CurrentSourceLineNumber, reader.Value)); |
685 | } | 683 | } |
686 | 684 | ||
687 | // parse out the variable name | 685 | // parse out the variable name |
@@ -689,7 +687,7 @@ namespace WixToolset.Core | |||
689 | var varValuesString = reader.Value.Substring(indexOfInToken + 4).Trim(); | 687 | var varValuesString = reader.Value.Substring(indexOfInToken + 4).Trim(); |
690 | 688 | ||
691 | // preprocess the variable values string because it might be a variable itself | 689 | // preprocess the variable values string because it might be a variable itself |
692 | varValuesString = this.Helper.PreprocessString(this.Context, varValuesString); | 690 | varValuesString = state.Helper.PreprocessString(state.Context, varValuesString); |
693 | 691 | ||
694 | var varValues = varValuesString.Split(';'); | 692 | var varValues = varValuesString.Split(';'); |
695 | 693 | ||
@@ -751,7 +749,7 @@ namespace WixToolset.Core | |||
751 | } | 749 | } |
752 | else if (reader.NodeType == XmlNodeType.None) | 750 | else if (reader.NodeType == XmlNodeType.None) |
753 | { | 751 | { |
754 | throw new WixException(ErrorMessages.ExpectedEndforeach(this.Context.CurrentSourceLineNumber)); | 752 | throw new WixException(ErrorMessages.ExpectedEndforeach(state.Context.CurrentSourceLineNumber)); |
755 | } | 753 | } |
756 | 754 | ||
757 | reader.Read(); | 755 | reader.Read(); |
@@ -765,16 +763,16 @@ namespace WixToolset.Core | |||
765 | using (var loopReader = XmlReader.Create(fragmentStream, FragmentXmlReaderSettings)) | 763 | using (var loopReader = XmlReader.Create(fragmentStream, FragmentXmlReaderSettings)) |
766 | { | 764 | { |
767 | // Always overwrite foreach variables. | 765 | // Always overwrite foreach variables. |
768 | this.Helper.AddVariable(this.Context, varName, varValue, false); | 766 | state.Helper.AddVariable(state.Context, varName, varValue, false); |
769 | 767 | ||
770 | try | 768 | try |
771 | { | 769 | { |
772 | this.PreprocessReader(false, loopReader, container, offset); | 770 | this.PreprocessReader(state, false, loopReader, container, offset); |
773 | } | 771 | } |
774 | catch (XmlException e) | 772 | catch (XmlException e) |
775 | { | 773 | { |
776 | this.UpdateCurrentLineNumber(loopReader, offset); | 774 | this.UpdateCurrentLineNumber(state, loopReader, offset); |
777 | throw new WixException(ErrorMessages.InvalidXml(this.Context.CurrentSourceLineNumber, "source", e.Message)); | 775 | throw new WixException(ErrorMessages.InvalidXml(state.Context.CurrentSourceLineNumber, "source", e.Message)); |
778 | } | 776 | } |
779 | 777 | ||
780 | fragmentStream.Position = 0; // seek back to the beginning for the next loop. | 778 | fragmentStream.Position = 0; // seek back to the beginning for the next loop. |
@@ -787,25 +785,25 @@ namespace WixToolset.Core | |||
787 | /// Processes a pragma processing instruction | 785 | /// Processes a pragma processing instruction |
788 | /// </summary> | 786 | /// </summary> |
789 | /// <param name="pragmaText">Text from source.</param> | 787 | /// <param name="pragmaText">Text from source.</param> |
790 | private void PreprocessPragma(string pragmaText, XContainer parent) | 788 | private void PreprocessPragma(ProcessingState state, string pragmaText, XContainer parent) |
791 | { | 789 | { |
792 | var match = PragmaRegex.Match(pragmaText); | 790 | var match = PragmaRegex.Match(pragmaText); |
793 | 791 | ||
794 | if (!match.Success) | 792 | if (!match.Success) |
795 | { | 793 | { |
796 | throw new WixException(ErrorMessages.InvalidPreprocessorPragma(this.Context.CurrentSourceLineNumber, pragmaText)); | 794 | throw new WixException(ErrorMessages.InvalidPreprocessorPragma(state.Context.CurrentSourceLineNumber, pragmaText)); |
797 | } | 795 | } |
798 | 796 | ||
799 | // resolve other variables in the pragma argument(s) | 797 | // resolve other variables in the pragma argument(s) |
800 | var pragmaArgs = this.Helper.PreprocessString(this.Context, match.Groups["pragmaValue"].Value).Trim(); | 798 | var pragmaArgs = state.Helper.PreprocessString(state.Context, match.Groups["pragmaValue"].Value).Trim(); |
801 | 799 | ||
802 | try | 800 | try |
803 | { | 801 | { |
804 | this.Helper.PreprocessPragma(this.Context, match.Groups["pragmaName"].Value.Trim(), pragmaArgs, parent); | 802 | state.Helper.PreprocessPragma(state.Context, match.Groups["pragmaName"].Value.Trim(), pragmaArgs, parent); |
805 | } | 803 | } |
806 | catch (Exception e) | 804 | catch (Exception e) |
807 | { | 805 | { |
808 | throw new WixException(ErrorMessages.PreprocessorExtensionPragmaFailed(this.Context.CurrentSourceLineNumber, pragmaText, e.Message)); | 806 | throw new WixException(ErrorMessages.PreprocessorExtensionPragmaFailed(state.Context.CurrentSourceLineNumber, pragmaText, e.Message)); |
809 | } | 807 | } |
810 | } | 808 | } |
811 | 809 | ||
@@ -816,7 +814,7 @@ namespace WixToolset.Core | |||
816 | /// <param name="expression">Expression with token removed.</param> | 814 | /// <param name="expression">Expression with token removed.</param> |
817 | /// <param name="stringLiteral">Flag if token is a string literal instead of a variable.</param> | 815 | /// <param name="stringLiteral">Flag if token is a string literal instead of a variable.</param> |
818 | /// <returns>Next token.</returns> | 816 | /// <returns>Next token.</returns> |
819 | private string GetNextToken(string originalExpression, ref string expression, out bool stringLiteral) | 817 | private string GetNextToken(ProcessingState state, string originalExpression, ref string expression, out bool stringLiteral) |
820 | { | 818 | { |
821 | stringLiteral = false; | 819 | stringLiteral = false; |
822 | var token = String.Empty; | 820 | var token = String.Empty; |
@@ -832,11 +830,11 @@ namespace WixToolset.Core | |||
832 | var endingQuotes = expression.IndexOf('\"', 1); | 830 | var endingQuotes = expression.IndexOf('\"', 1); |
833 | if (-1 == endingQuotes) | 831 | if (-1 == endingQuotes) |
834 | { | 832 | { |
835 | throw new WixException(ErrorMessages.UnmatchedQuotesInExpression(this.Context.CurrentSourceLineNumber, originalExpression)); | 833 | throw new WixException(ErrorMessages.UnmatchedQuotesInExpression(state.Context.CurrentSourceLineNumber, originalExpression)); |
836 | } | 834 | } |
837 | 835 | ||
838 | // cut the quotes off the string | 836 | // cut the quotes off the string |
839 | token = this.Helper.PreprocessString(this.Context, expression.Substring(1, endingQuotes - 1)); | 837 | token = state.Helper.PreprocessString(state.Context, expression.Substring(1, endingQuotes - 1)); |
840 | 838 | ||
841 | // advance past this string | 839 | // advance past this string |
842 | expression = expression.Substring(endingQuotes + 1).Trim(); | 840 | expression = expression.Substring(endingQuotes + 1).Trim(); |
@@ -866,7 +864,7 @@ namespace WixToolset.Core | |||
866 | 864 | ||
867 | if (-1 == endingParen) | 865 | if (-1 == endingParen) |
868 | { | 866 | { |
869 | throw new WixException(ErrorMessages.UnmatchedParenthesisInExpression(this.Context.CurrentSourceLineNumber, originalExpression)); | 867 | throw new WixException(ErrorMessages.UnmatchedParenthesisInExpression(state.Context.CurrentSourceLineNumber, originalExpression)); |
870 | } | 868 | } |
871 | token = expression.Substring(0, endingParen + 1); | 869 | token = expression.Substring(0, endingParen + 1); |
872 | 870 | ||
@@ -962,7 +960,7 @@ namespace WixToolset.Core | |||
962 | /// <param name="originalExpression">Original expression for error message.</param> | 960 | /// <param name="originalExpression">Original expression for error message.</param> |
963 | /// <param name="variable">Variable to evaluate.</param> | 961 | /// <param name="variable">Variable to evaluate.</param> |
964 | /// <returns>Value of variable.</returns> | 962 | /// <returns>Value of variable.</returns> |
965 | private string EvaluateVariable(string originalExpression, string variable) | 963 | private string EvaluateVariable(ProcessingState state, string originalExpression, string variable) |
966 | { | 964 | { |
967 | // By default it's a literal and will only be evaluated if it | 965 | // By default it's a literal and will only be evaluated if it |
968 | // matches the variable format | 966 | // matches the variable format |
@@ -972,7 +970,7 @@ namespace WixToolset.Core | |||
972 | { | 970 | { |
973 | try | 971 | try |
974 | { | 972 | { |
975 | varValue = this.Helper.PreprocessString(this.Context, variable); | 973 | varValue = state.Helper.PreprocessString(state.Context, variable); |
976 | } | 974 | } |
977 | catch (ArgumentNullException) | 975 | catch (ArgumentNullException) |
978 | { | 976 | { |
@@ -983,12 +981,12 @@ namespace WixToolset.Core | |||
983 | else if (variable.IndexOf("(", StringComparison.Ordinal) != -1 || variable.IndexOf(")", StringComparison.Ordinal) != -1) | 981 | else if (variable.IndexOf("(", StringComparison.Ordinal) != -1 || variable.IndexOf(")", StringComparison.Ordinal) != -1) |
984 | { | 982 | { |
985 | // make sure it doesn't contain parenthesis | 983 | // make sure it doesn't contain parenthesis |
986 | throw new WixException(ErrorMessages.UnmatchedParenthesisInExpression(this.Context.CurrentSourceLineNumber, originalExpression)); | 984 | throw new WixException(ErrorMessages.UnmatchedParenthesisInExpression(state.Context.CurrentSourceLineNumber, originalExpression)); |
987 | } | 985 | } |
988 | else if (variable.IndexOf("\"", StringComparison.Ordinal) != -1) | 986 | else if (variable.IndexOf("\"", StringComparison.Ordinal) != -1) |
989 | { | 987 | { |
990 | // shouldn't contain quotes | 988 | // shouldn't contain quotes |
991 | throw new WixException(ErrorMessages.UnmatchedQuotesInExpression(this.Context.CurrentSourceLineNumber, originalExpression)); | 989 | throw new WixException(ErrorMessages.UnmatchedQuotesInExpression(state.Context.CurrentSourceLineNumber, originalExpression)); |
992 | } | 990 | } |
993 | 991 | ||
994 | return varValue; | 992 | return varValue; |
@@ -1002,31 +1000,31 @@ namespace WixToolset.Core | |||
1002 | /// <param name="leftValue">Left side value from expression.</param> | 1000 | /// <param name="leftValue">Left side value from expression.</param> |
1003 | /// <param name="operation">Operation in expression.</param> | 1001 | /// <param name="operation">Operation in expression.</param> |
1004 | /// <param name="rightValue">Right side value from expression.</param> | 1002 | /// <param name="rightValue">Right side value from expression.</param> |
1005 | private void GetNameValuePair(string originalExpression, ref string expression, out string leftValue, out string operation, out string rightValue) | 1003 | private void GetNameValuePair(ProcessingState state, string originalExpression, ref string expression, out string leftValue, out string operation, out string rightValue) |
1006 | { | 1004 | { |
1007 | leftValue = this.GetNextToken(originalExpression, ref expression, out var stringLiteral); | 1005 | leftValue = this.GetNextToken(state, originalExpression, ref expression, out var stringLiteral); |
1008 | 1006 | ||
1009 | // If it wasn't a string literal, evaluate it | 1007 | // If it wasn't a string literal, evaluate it |
1010 | if (!stringLiteral) | 1008 | if (!stringLiteral) |
1011 | { | 1009 | { |
1012 | leftValue = this.EvaluateVariable(originalExpression, leftValue); | 1010 | leftValue = this.EvaluateVariable(state, originalExpression, leftValue); |
1013 | } | 1011 | } |
1014 | 1012 | ||
1015 | // Get the operation | 1013 | // Get the operation |
1016 | operation = this.GetNextToken(originalExpression, ref expression, out stringLiteral); | 1014 | operation = this.GetNextToken(state, originalExpression, ref expression, out stringLiteral); |
1017 | if (IsOperator(operation)) | 1015 | if (IsOperator(operation)) |
1018 | { | 1016 | { |
1019 | if (stringLiteral) | 1017 | if (stringLiteral) |
1020 | { | 1018 | { |
1021 | throw new WixException(ErrorMessages.UnmatchedQuotesInExpression(this.Context.CurrentSourceLineNumber, originalExpression)); | 1019 | throw new WixException(ErrorMessages.UnmatchedQuotesInExpression(state.Context.CurrentSourceLineNumber, originalExpression)); |
1022 | } | 1020 | } |
1023 | 1021 | ||
1024 | rightValue = this.GetNextToken(originalExpression, ref expression, out stringLiteral); | 1022 | rightValue = this.GetNextToken(state, originalExpression, ref expression, out stringLiteral); |
1025 | 1023 | ||
1026 | // If it wasn't a string literal, evaluate it | 1024 | // If it wasn't a string literal, evaluate it |
1027 | if (!stringLiteral) | 1025 | if (!stringLiteral) |
1028 | { | 1026 | { |
1029 | rightValue = this.EvaluateVariable(originalExpression, rightValue); | 1027 | rightValue = this.EvaluateVariable(state, originalExpression, rightValue); |
1030 | } | 1028 | } |
1031 | } | 1029 | } |
1032 | else | 1030 | else |
@@ -1052,11 +1050,11 @@ namespace WixToolset.Core | |||
1052 | /// <param name="originalExpression">Original expression to evaluate.</param> | 1050 | /// <param name="originalExpression">Original expression to evaluate.</param> |
1053 | /// <param name="expression">Expression modified while processing.</param> | 1051 | /// <param name="expression">Expression modified while processing.</param> |
1054 | /// <returns>true if expression evaluates to true.</returns> | 1052 | /// <returns>true if expression evaluates to true.</returns> |
1055 | private bool EvaluateAtomicExpression(string originalExpression, ref string expression) | 1053 | private bool EvaluateAtomicExpression(ProcessingState state, string originalExpression, ref string expression) |
1056 | { | 1054 | { |
1057 | // Quick test to see if the first token is a variable | 1055 | // Quick test to see if the first token is a variable |
1058 | var startsWithVariable = expression.StartsWith("$(", StringComparison.Ordinal); | 1056 | var startsWithVariable = expression.StartsWith("$(", StringComparison.Ordinal); |
1059 | this.GetNameValuePair(originalExpression, ref expression, out var leftValue, out var operation, out var rightValue); | 1057 | this.GetNameValuePair(state, originalExpression, ref expression, out var leftValue, out var operation, out var rightValue); |
1060 | 1058 | ||
1061 | var expressionValue = false; | 1059 | var expressionValue = false; |
1062 | 1060 | ||
@@ -1065,7 +1063,7 @@ namespace WixToolset.Core | |||
1065 | { | 1063 | { |
1066 | if (operation.Length > 0) | 1064 | if (operation.Length > 0) |
1067 | { | 1065 | { |
1068 | throw new WixException(ErrorMessages.ExpectedVariable(this.Context.CurrentSourceLineNumber, originalExpression)); | 1066 | throw new WixException(ErrorMessages.ExpectedVariable(state.Context.CurrentSourceLineNumber, originalExpression)); |
1069 | } | 1067 | } |
1070 | 1068 | ||
1071 | // false expression | 1069 | // false expression |
@@ -1080,7 +1078,7 @@ namespace WixToolset.Core | |||
1080 | } | 1078 | } |
1081 | else | 1079 | else |
1082 | { | 1080 | { |
1083 | throw new WixException(ErrorMessages.UnexpectedLiteral(this.Context.CurrentSourceLineNumber, originalExpression)); | 1081 | throw new WixException(ErrorMessages.UnexpectedLiteral(state.Context.CurrentSourceLineNumber, originalExpression)); |
1084 | } | 1082 | } |
1085 | } | 1083 | } |
1086 | else | 1084 | else |
@@ -1120,11 +1118,11 @@ namespace WixToolset.Core | |||
1120 | } | 1118 | } |
1121 | catch (FormatException) | 1119 | catch (FormatException) |
1122 | { | 1120 | { |
1123 | throw new WixException(ErrorMessages.IllegalIntegerInExpression(this.Context.CurrentSourceLineNumber, originalExpression)); | 1121 | throw new WixException(ErrorMessages.IllegalIntegerInExpression(state.Context.CurrentSourceLineNumber, originalExpression)); |
1124 | } | 1122 | } |
1125 | catch (OverflowException) | 1123 | catch (OverflowException) |
1126 | { | 1124 | { |
1127 | throw new WixException(ErrorMessages.IllegalIntegerInExpression(this.Context.CurrentSourceLineNumber, originalExpression)); | 1125 | throw new WixException(ErrorMessages.IllegalIntegerInExpression(state.Context.CurrentSourceLineNumber, originalExpression)); |
1128 | } | 1126 | } |
1129 | 1127 | ||
1130 | // Compare the numbers | 1128 | // Compare the numbers |
@@ -1148,7 +1146,7 @@ namespace WixToolset.Core | |||
1148 | /// <param name="expression">Expression modified while processing.</param> | 1146 | /// <param name="expression">Expression modified while processing.</param> |
1149 | /// <param name="endSubExpression">Index of end of sub-expression.</param> | 1147 | /// <param name="endSubExpression">Index of end of sub-expression.</param> |
1150 | /// <returns>Sub-expression in parenthesis.</returns> | 1148 | /// <returns>Sub-expression in parenthesis.</returns> |
1151 | private string GetParenthesisExpression(string originalExpression, string expression, out int endSubExpression) | 1149 | private string GetParenthesisExpression(ProcessingState state, string originalExpression, string expression, out int endSubExpression) |
1152 | { | 1150 | { |
1153 | endSubExpression = 0; | 1151 | endSubExpression = 0; |
1154 | 1152 | ||
@@ -1166,7 +1164,7 @@ namespace WixToolset.Core | |||
1166 | closeParenIndex = expression.IndexOf(')', closeParenIndex); | 1164 | closeParenIndex = expression.IndexOf(')', closeParenIndex); |
1167 | if (closeParenIndex == -1) | 1165 | if (closeParenIndex == -1) |
1168 | { | 1166 | { |
1169 | throw new WixException(ErrorMessages.UnmatchedParenthesisInExpression(this.Context.CurrentSourceLineNumber, originalExpression)); | 1167 | throw new WixException(ErrorMessages.UnmatchedParenthesisInExpression(state.Context.CurrentSourceLineNumber, originalExpression)); |
1170 | } | 1168 | } |
1171 | 1169 | ||
1172 | if (InsideQuotes(expression, closeParenIndex)) | 1170 | if (InsideQuotes(expression, closeParenIndex)) |
@@ -1201,7 +1199,7 @@ namespace WixToolset.Core | |||
1201 | /// <param name="currentValue">State to update.</param> | 1199 | /// <param name="currentValue">State to update.</param> |
1202 | /// <param name="operation">Operation to apply to current value.</param> | 1200 | /// <param name="operation">Operation to apply to current value.</param> |
1203 | /// <param name="prevResult">Previous result.</param> | 1201 | /// <param name="prevResult">Previous result.</param> |
1204 | private void UpdateExpressionValue(ref bool currentValue, PreprocessorOperation operation, bool prevResult) | 1202 | private void UpdateExpressionValue(ProcessingState state, ref bool currentValue, PreprocessorOperation operation, bool prevResult) |
1205 | { | 1203 | { |
1206 | switch (operation) | 1204 | switch (operation) |
1207 | { | 1205 | { |
@@ -1215,7 +1213,7 @@ namespace WixToolset.Core | |||
1215 | currentValue = !currentValue; | 1213 | currentValue = !currentValue; |
1216 | break; | 1214 | break; |
1217 | default: | 1215 | default: |
1218 | throw new WixException(ErrorMessages.UnexpectedPreprocessorOperator(this.Context.CurrentSourceLineNumber, operation.ToString())); | 1216 | throw new WixException(ErrorMessages.UnexpectedPreprocessorOperator(state.Context.CurrentSourceLineNumber, operation.ToString())); |
1219 | } | 1217 | } |
1220 | } | 1218 | } |
1221 | 1219 | ||
@@ -1224,10 +1222,10 @@ namespace WixToolset.Core | |||
1224 | /// </summary> | 1222 | /// </summary> |
1225 | /// <param name="expression">Expression to evaluate.</param> | 1223 | /// <param name="expression">Expression to evaluate.</param> |
1226 | /// <returns>Boolean result of expression.</returns> | 1224 | /// <returns>Boolean result of expression.</returns> |
1227 | private bool EvaluateExpression(string expression) | 1225 | private bool EvaluateExpression(ProcessingState state, string expression) |
1228 | { | 1226 | { |
1229 | var tmpExpression = expression; | 1227 | var tmpExpression = expression; |
1230 | return this.EvaluateExpressionRecurse(expression, ref tmpExpression, PreprocessorOperation.And, true); | 1228 | return this.EvaluateExpressionRecurse(state, expression, ref tmpExpression, PreprocessorOperation.And, true); |
1231 | } | 1229 | } |
1232 | 1230 | ||
1233 | /// <summary> | 1231 | /// <summary> |
@@ -1258,20 +1256,20 @@ namespace WixToolset.Core | |||
1258 | /// <param name="prevResultOperation">The operation to apply to this result</param> | 1256 | /// <param name="prevResultOperation">The operation to apply to this result</param> |
1259 | /// <param name="prevResult">The previous result to apply to this result</param> | 1257 | /// <param name="prevResult">The previous result to apply to this result</param> |
1260 | /// <returns>Boolean to indicate if the expression is true or false</returns> | 1258 | /// <returns>Boolean to indicate if the expression is true or false</returns> |
1261 | private bool EvaluateExpressionRecurse(string originalExpression, ref string expression, PreprocessorOperation prevResultOperation, bool prevResult) | 1259 | private bool EvaluateExpressionRecurse(ProcessingState state, string originalExpression, ref string expression, PreprocessorOperation prevResultOperation, bool prevResult) |
1262 | { | 1260 | { |
1263 | var expressionValue = false; | 1261 | var expressionValue = false; |
1264 | expression = expression.Trim(); | 1262 | expression = expression.Trim(); |
1265 | if (expression.Length == 0) | 1263 | if (expression.Length == 0) |
1266 | { | 1264 | { |
1267 | throw new WixException(ErrorMessages.UnexpectedEmptySubexpression(this.Context.CurrentSourceLineNumber, originalExpression)); | 1265 | throw new WixException(ErrorMessages.UnexpectedEmptySubexpression(state.Context.CurrentSourceLineNumber, originalExpression)); |
1268 | } | 1266 | } |
1269 | 1267 | ||
1270 | // If the expression starts with parenthesis, evaluate it | 1268 | // If the expression starts with parenthesis, evaluate it |
1271 | if (expression.IndexOf('(') == 0) | 1269 | if (expression.IndexOf('(') == 0) |
1272 | { | 1270 | { |
1273 | var subExpression = this.GetParenthesisExpression(originalExpression, expression, out var endSubExpressionIndex); | 1271 | var subExpression = this.GetParenthesisExpression(state, originalExpression, expression, out var endSubExpressionIndex); |
1274 | expressionValue = this.EvaluateExpressionRecurse(originalExpression, ref subExpression, PreprocessorOperation.And, true); | 1272 | expressionValue = this.EvaluateExpressionRecurse(state, originalExpression, ref subExpression, PreprocessorOperation.And, true); |
1275 | 1273 | ||
1276 | // Now get the rest of the expression that hasn't been evaluated | 1274 | // Now get the rest of the expression that hasn't been evaluated |
1277 | expression = expression.Substring(endSubExpressionIndex).Trim(); | 1275 | expression = expression.Substring(endSubExpressionIndex).Trim(); |
@@ -1284,19 +1282,19 @@ namespace WixToolset.Core | |||
1284 | expression = expression.Substring(3).Trim(); | 1282 | expression = expression.Substring(3).Trim(); |
1285 | if (expression.Length == 0) | 1283 | if (expression.Length == 0) |
1286 | { | 1284 | { |
1287 | throw new WixException(ErrorMessages.ExpectedExpressionAfterNot(this.Context.CurrentSourceLineNumber, originalExpression)); | 1285 | throw new WixException(ErrorMessages.ExpectedExpressionAfterNot(state.Context.CurrentSourceLineNumber, originalExpression)); |
1288 | } | 1286 | } |
1289 | 1287 | ||
1290 | expressionValue = this.EvaluateExpressionRecurse(originalExpression, ref expression, PreprocessorOperation.Not, true); | 1288 | expressionValue = this.EvaluateExpressionRecurse(state, originalExpression, ref expression, PreprocessorOperation.Not, true); |
1291 | } | 1289 | } |
1292 | else // Expect a literal | 1290 | else // Expect a literal |
1293 | { | 1291 | { |
1294 | expressionValue = this.EvaluateAtomicExpression(originalExpression, ref expression); | 1292 | expressionValue = this.EvaluateAtomicExpression(state, originalExpression, ref expression); |
1295 | 1293 | ||
1296 | // Expect the literal that was just evaluated to already be cut off | 1294 | // Expect the literal that was just evaluated to already be cut off |
1297 | } | 1295 | } |
1298 | } | 1296 | } |
1299 | this.UpdateExpressionValue(ref expressionValue, prevResultOperation, prevResult); | 1297 | this.UpdateExpressionValue(state, ref expressionValue, prevResultOperation, prevResult); |
1300 | 1298 | ||
1301 | // If there's still an expression left, it must start with AND or OR. | 1299 | // If there's still an expression left, it must start with AND or OR. |
1302 | if (expression.Trim().Length > 0) | 1300 | if (expression.Trim().Length > 0) |
@@ -1304,16 +1302,16 @@ namespace WixToolset.Core | |||
1304 | if (StartsWithKeyword(expression, PreprocessorOperation.And)) | 1302 | if (StartsWithKeyword(expression, PreprocessorOperation.And)) |
1305 | { | 1303 | { |
1306 | expression = expression.Substring(3); | 1304 | expression = expression.Substring(3); |
1307 | return this.EvaluateExpressionRecurse(originalExpression, ref expression, PreprocessorOperation.And, expressionValue); | 1305 | return this.EvaluateExpressionRecurse(state, originalExpression, ref expression, PreprocessorOperation.And, expressionValue); |
1308 | } | 1306 | } |
1309 | else if (StartsWithKeyword(expression, PreprocessorOperation.Or)) | 1307 | else if (StartsWithKeyword(expression, PreprocessorOperation.Or)) |
1310 | { | 1308 | { |
1311 | expression = expression.Substring(2); | 1309 | expression = expression.Substring(2); |
1312 | return this.EvaluateExpressionRecurse(originalExpression, ref expression, PreprocessorOperation.Or, expressionValue); | 1310 | return this.EvaluateExpressionRecurse(state, originalExpression, ref expression, PreprocessorOperation.Or, expressionValue); |
1313 | } | 1311 | } |
1314 | else | 1312 | else |
1315 | { | 1313 | { |
1316 | throw new WixException(ErrorMessages.InvalidSubExpression(this.Context.CurrentSourceLineNumber, expression, originalExpression)); | 1314 | throw new WixException(ErrorMessages.InvalidSubExpression(state.Context.CurrentSourceLineNumber, expression, originalExpression)); |
1317 | } | 1315 | } |
1318 | } | 1316 | } |
1319 | 1317 | ||
@@ -1325,16 +1323,16 @@ namespace WixToolset.Core | |||
1325 | /// </summary> | 1323 | /// </summary> |
1326 | /// <param name="reader">The xml reader for the preprocessor.</param> | 1324 | /// <param name="reader">The xml reader for the preprocessor.</param> |
1327 | /// <param name="offset">This is the artificial offset of the line numbers from the reader. Used for the foreach processing.</param> | 1325 | /// <param name="offset">This is the artificial offset of the line numbers from the reader. Used for the foreach processing.</param> |
1328 | private void UpdateCurrentLineNumber(XmlReader reader, int offset) | 1326 | private void UpdateCurrentLineNumber(ProcessingState state, XmlReader reader, int offset) |
1329 | { | 1327 | { |
1330 | var lineInfoReader = reader as IXmlLineInfo; | 1328 | var lineInfoReader = reader as IXmlLineInfo; |
1331 | if (null != lineInfoReader) | 1329 | if (null != lineInfoReader) |
1332 | { | 1330 | { |
1333 | var newLine = lineInfoReader.LineNumber + offset; | 1331 | var newLine = lineInfoReader.LineNumber + offset; |
1334 | 1332 | ||
1335 | if (this.Context.CurrentSourceLineNumber.LineNumber != newLine) | 1333 | if (state.Context.CurrentSourceLineNumber.LineNumber != newLine) |
1336 | { | 1334 | { |
1337 | this.Context.CurrentSourceLineNumber = new SourceLineNumber(this.Context.CurrentSourceLineNumber.FileName, newLine); | 1335 | state.Context.CurrentSourceLineNumber = new SourceLineNumber(state.Context.CurrentSourceLineNumber.FileName, newLine); |
1338 | } | 1336 | } |
1339 | } | 1337 | } |
1340 | } | 1338 | } |
@@ -1343,28 +1341,28 @@ namespace WixToolset.Core | |||
1343 | /// Pushes a file name on the stack of included files. | 1341 | /// Pushes a file name on the stack of included files. |
1344 | /// </summary> | 1342 | /// </summary> |
1345 | /// <param name="fileName">Name to push on to the stack of included files.</param> | 1343 | /// <param name="fileName">Name to push on to the stack of included files.</param> |
1346 | private void PushInclude(string fileName) | 1344 | private void PushInclude(ProcessingState state, string fileName) |
1347 | { | 1345 | { |
1348 | if (1023 < this.CurrentFileStack.Count) | 1346 | if (1023 < state.CurrentFileStack.Count) |
1349 | { | 1347 | { |
1350 | throw new WixException(ErrorMessages.TooDeeplyIncluded(this.Context.CurrentSourceLineNumber, this.CurrentFileStack.Count)); | 1348 | throw new WixException(ErrorMessages.TooDeeplyIncluded(state.Context.CurrentSourceLineNumber, state.CurrentFileStack.Count)); |
1351 | } | 1349 | } |
1352 | 1350 | ||
1353 | this.CurrentFileStack.Push(fileName); | 1351 | state.CurrentFileStack.Push(fileName); |
1354 | this.SourceStack.Push(this.Context.CurrentSourceLineNumber); | 1352 | state.SourceStack.Push(state.Context.CurrentSourceLineNumber); |
1355 | this.Context.CurrentSourceLineNumber = new SourceLineNumber(fileName); | 1353 | state.Context.CurrentSourceLineNumber = new SourceLineNumber(fileName); |
1356 | this.IncludeNextStack.Push(true); | 1354 | state.IncludeNextStack.Push(true); |
1357 | } | 1355 | } |
1358 | 1356 | ||
1359 | /// <summary> | 1357 | /// <summary> |
1360 | /// Pops a file name from the stack of included files. | 1358 | /// Pops a file name from the stack of included files. |
1361 | /// </summary> | 1359 | /// </summary> |
1362 | private void PopInclude() | 1360 | private void PopInclude(ProcessingState state) |
1363 | { | 1361 | { |
1364 | this.Context.CurrentSourceLineNumber = this.SourceStack.Pop(); | 1362 | state.Context.CurrentSourceLineNumber = state.SourceStack.Pop(); |
1365 | 1363 | ||
1366 | this.CurrentFileStack.Pop(); | 1364 | state.CurrentFileStack.Pop(); |
1367 | this.IncludeNextStack.Pop(); | 1365 | state.IncludeNextStack.Pop(); |
1368 | } | 1366 | } |
1369 | 1367 | ||
1370 | /// <summary> | 1368 | /// <summary> |
@@ -1375,7 +1373,7 @@ namespace WixToolset.Core | |||
1375 | /// </summary> | 1373 | /// </summary> |
1376 | /// <param name="includePath">User-specified path to the included file (usually just the file name).</param> | 1374 | /// <param name="includePath">User-specified path to the included file (usually just the file name).</param> |
1377 | /// <returns>Returns a FileInfo for the found include file, or null if the file cannot be found.</returns> | 1375 | /// <returns>Returns a FileInfo for the found include file, or null if the file cannot be found.</returns> |
1378 | private string GetIncludeFile(string includePath) | 1376 | private string GetIncludeFile(ProcessingState state, string includePath) |
1379 | { | 1377 | { |
1380 | string finalIncludePath = null; | 1378 | string finalIncludePath = null; |
1381 | 1379 | ||
@@ -1399,7 +1397,7 @@ namespace WixToolset.Core | |||
1399 | else // relative path | 1397 | else // relative path |
1400 | { | 1398 | { |
1401 | // build a string to test the directory containing the source file first | 1399 | // build a string to test the directory containing the source file first |
1402 | var currentFolder = this.CurrentFileStack.Peek(); | 1400 | var currentFolder = state.CurrentFileStack.Peek(); |
1403 | var includeTestPath = Path.Combine(Path.GetDirectoryName(currentFolder), includePath); | 1401 | var includeTestPath = Path.Combine(Path.GetDirectoryName(currentFolder), includePath); |
1404 | 1402 | ||
1405 | // test the source file directory | 1403 | // test the source file directory |
@@ -1407,9 +1405,9 @@ namespace WixToolset.Core | |||
1407 | { | 1405 | { |
1408 | finalIncludePath = includeTestPath; | 1406 | finalIncludePath = includeTestPath; |
1409 | } | 1407 | } |
1410 | else // test all search paths in the order specified on the command line | 1408 | else if (state.Context.IncludeSearchPaths != null) // test all search paths in the order specified on the command line |
1411 | { | 1409 | { |
1412 | foreach (var includeSearchPath in this.Context.IncludeSearchPaths) | 1410 | foreach (var includeSearchPath in state.Context.IncludeSearchPaths) |
1413 | { | 1411 | { |
1414 | // if the path exists, we have found the final string | 1412 | // if the path exists, we have found the final string |
1415 | includeTestPath = Path.Combine(includeSearchPath, includePath); | 1413 | includeTestPath = Path.Combine(includeSearchPath, includePath); |
@@ -1425,17 +1423,22 @@ namespace WixToolset.Core | |||
1425 | return finalIncludePath; | 1423 | return finalIncludePath; |
1426 | } | 1424 | } |
1427 | 1425 | ||
1428 | private void PreProcess() | 1426 | private void PreProcess(ProcessingState state) |
1429 | { | 1427 | { |
1430 | foreach (var extension in this.Context.Extensions) | 1428 | if (state.Context.Extensions == null) |
1429 | { | ||
1430 | return; | ||
1431 | } | ||
1432 | |||
1433 | foreach (var extension in state.Context.Extensions) | ||
1431 | { | 1434 | { |
1432 | if (extension.Prefixes != null) | 1435 | if (extension.Prefixes != null) |
1433 | { | 1436 | { |
1434 | foreach (var prefix in extension.Prefixes) | 1437 | foreach (var prefix in extension.Prefixes) |
1435 | { | 1438 | { |
1436 | if (!this.ExtensionsByPrefix.TryGetValue(prefix, out var collidingExtension)) | 1439 | if (!state.ExtensionsByPrefix.TryGetValue(prefix, out var collidingExtension)) |
1437 | { | 1440 | { |
1438 | this.ExtensionsByPrefix.Add(prefix, extension); | 1441 | state.ExtensionsByPrefix.Add(prefix, extension); |
1439 | } | 1442 | } |
1440 | else | 1443 | else |
1441 | { | 1444 | { |
@@ -1444,18 +1447,49 @@ namespace WixToolset.Core | |||
1444 | } | 1447 | } |
1445 | } | 1448 | } |
1446 | 1449 | ||
1447 | extension.PrePreprocess(this.Context); | 1450 | extension.PrePreprocess(state.Context); |
1448 | } | 1451 | } |
1449 | } | 1452 | } |
1450 | 1453 | ||
1451 | private XDocument PostProcess(XDocument document) | 1454 | private void PostProcess(ProcessingState state, IPreprocessResult result) |
1452 | { | 1455 | { |
1453 | foreach (var extension in this.Context.Extensions) | 1456 | if (state.Context.Extensions == null) |
1454 | { | 1457 | { |
1455 | extension.PostPreprocess(document); | 1458 | return; |
1456 | } | 1459 | } |
1457 | 1460 | ||
1458 | return document; | 1461 | foreach (var extension in state.Context.Extensions) |
1462 | { | ||
1463 | extension.PostPreprocess(result); | ||
1464 | } | ||
1465 | } | ||
1466 | |||
1467 | private class ProcessingState | ||
1468 | { | ||
1469 | public ProcessingState(IServiceProvider serviceProvider, IPreprocessContext context) | ||
1470 | { | ||
1471 | this.Context = context; | ||
1472 | this.Context.CurrentSourceLineNumber = new SourceLineNumber(context.SourcePath); | ||
1473 | this.Context.Variables = this.Context.Variables == null ? new Dictionary<string, string>() : new Dictionary<string, string>(this.Context.Variables); | ||
1474 | |||
1475 | this.Helper = serviceProvider.GetService<IPreprocessHelper>(); | ||
1476 | } | ||
1477 | |||
1478 | public IPreprocessContext Context { get; } | ||
1479 | |||
1480 | public IPreprocessHelper Helper { get; } | ||
1481 | |||
1482 | public List<IIncludedFile> IncludedFiles { get; } = new List<IIncludedFile>(); | ||
1483 | |||
1484 | public XDocument Output { get; } = new XDocument(); | ||
1485 | |||
1486 | public Stack<string> CurrentFileStack { get; } = new Stack<string>(); | ||
1487 | |||
1488 | public Dictionary<string, IPreprocessorExtension> ExtensionsByPrefix { get; } = new Dictionary<string, IPreprocessorExtension>(); | ||
1489 | |||
1490 | public Stack<bool> IncludeNextStack { get; } = new Stack<bool>(); | ||
1491 | |||
1492 | public Stack<SourceLineNumber> SourceStack { get; } = new Stack<SourceLineNumber>(); | ||
1459 | } | 1493 | } |
1460 | } | 1494 | } |
1461 | } | 1495 | } |
diff --git a/src/WixToolset.Core/WixToolsetServiceProvider.cs b/src/WixToolset.Core/WixToolsetServiceProvider.cs index e03be0b2..267e4524 100644 --- a/src/WixToolset.Core/WixToolsetServiceProvider.cs +++ b/src/WixToolset.Core/WixToolsetServiceProvider.cs | |||
@@ -45,6 +45,8 @@ namespace WixToolset.Core | |||
45 | this.AddService<IBindResult>((provider, singletons) => new BindResult()); | 45 | this.AddService<IBindResult>((provider, singletons) => new BindResult()); |
46 | this.AddService<IComponentKeyPath>((provider, singletons) => new ComponentKeyPath()); | 46 | this.AddService<IComponentKeyPath>((provider, singletons) => new ComponentKeyPath()); |
47 | this.AddService<IDecompileResult>((provider, singletons) => new DecompileResult()); | 47 | this.AddService<IDecompileResult>((provider, singletons) => new DecompileResult()); |
48 | this.AddService<IIncludedFile>((provider, singletons) => new IncludedFile()); | ||
49 | this.AddService<IPreprocessResult>((provider, singletons) => new PreprocessResult()); | ||
48 | this.AddService<IResolveFileResult>((provider, singletons) => new ResolveFileResult()); | 50 | this.AddService<IResolveFileResult>((provider, singletons) => new ResolveFileResult()); |
49 | this.AddService<IResolveResult>((provider, singletons) => new ResolveResult()); | 51 | this.AddService<IResolveResult>((provider, singletons) => new ResolveResult()); |
50 | this.AddService<IResolvedCabinet>((provider, singletons) => new ResolvedCabinet()); | 52 | this.AddService<IResolvedCabinet>((provider, singletons) => new ResolvedCabinet()); |