aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core/Preprocessor.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/WixToolset.Core/Preprocessor.cs')
-rw-r--r--src/WixToolset.Core/Preprocessor.cs453
1 files changed, 154 insertions, 299 deletions
diff --git a/src/WixToolset.Core/Preprocessor.cs b/src/WixToolset.Core/Preprocessor.cs
index 3aed0735..195ede9e 100644
--- a/src/WixToolset.Core/Preprocessor.cs
+++ b/src/WixToolset.Core/Preprocessor.cs
@@ -4,7 +4,6 @@ namespace WixToolset.Core
4{ 4{
5 using System; 5 using System;
6 using System.Collections.Generic; 6 using System.Collections.Generic;
7 using System.Diagnostics.CodeAnalysis;
8 using System.Globalization; 7 using System.Globalization;
9 using System.IO; 8 using System.IO;
10 using System.Text; 9 using System.Text;
@@ -14,6 +13,7 @@ namespace WixToolset.Core
14 using WixToolset.Data; 13 using WixToolset.Data;
15 using WixToolset.Extensibility; 14 using WixToolset.Extensibility;
16 using WixToolset.Core.Preprocess; 15 using WixToolset.Core.Preprocess;
16 using WixToolset.Extensibility.Services;
17 17
18 /// <summary> 18 /// <summary>
19 /// Preprocessor object 19 /// Preprocessor object
@@ -30,42 +30,22 @@ namespace WixToolset.Core
30 }; 30 };
31 private readonly XmlReaderSettings FragmentXmlReaderSettings = new XmlReaderSettings() 31 private readonly XmlReaderSettings FragmentXmlReaderSettings = new XmlReaderSettings()
32 { 32 {
33 ConformanceLevel = System.Xml.ConformanceLevel.Fragment, 33 ConformanceLevel = ConformanceLevel.Fragment,
34 ValidationFlags = System.Xml.Schema.XmlSchemaValidationFlags.None, 34 ValidationFlags = System.Xml.Schema.XmlSchemaValidationFlags.None,
35 XmlResolver = null, 35 XmlResolver = null,
36 }; 36 };
37 37
38 private List<IPreprocessorExtension> extensions; 38 private IPreprocessContext Context { get; set; }
39 private Dictionary<string, IPreprocessorExtension> extensionsByPrefix;
40 39
41 private SourceLineNumber currentLineNumber; 40 private Stack<string> CurrentFileStack { get; } = new Stack<string>();
42 private Stack<SourceLineNumber> sourceStack;
43 41
44 private PreprocessorCore core; 42 private Dictionary<string, IPreprocessorExtension> ExtensionsByPrefix { get; } = new Dictionary<string, IPreprocessorExtension>();
45 private TextWriter preprocessOut;
46 43
47 private Stack<bool> includeNextStack; 44 private Stack<bool> IncludeNextStack { get; } = new Stack<bool>();
48 private Stack<string> currentFileStack;
49 45
50 private Platform currentPlatform; 46 private Stack<SourceLineNumber> SourceStack { get; } = new Stack<SourceLineNumber>();
51 47
52 /// <summary> 48 private IPreprocessHelper Helper { get; set; }
53 /// Creates a new preprocesor.
54 /// </summary>
55 public Preprocessor()
56 {
57 this.IncludeSearchPaths = new List<string>();
58
59 this.extensions = new List<IPreprocessorExtension>();
60 this.extensionsByPrefix = new Dictionary<string, IPreprocessorExtension>();
61
62 this.sourceStack = new Stack<SourceLineNumber>();
63
64 this.includeNextStack = new Stack<bool>();
65 this.currentFileStack = new Stack<string>();
66
67 this.currentPlatform = Platform.X86;
68 }
69 49
70 /// <summary> 50 /// <summary>
71 /// Event for ifdef/ifndef directives. 51 /// Event for ifdef/ifndef directives.
@@ -88,62 +68,6 @@ namespace WixToolset.Core
88 public event ResolvedVariableEventHandler ResolvedVariable; 68 public event ResolvedVariableEventHandler ResolvedVariable;
89 69
90 /// <summary> 70 /// <summary>
91 /// Enumeration for preprocessor operations in if statements.
92 /// </summary>
93 private enum PreprocessorOperation
94 {
95 /// <summary>The and operator.</summary>
96 And,
97
98 /// <summary>The or operator.</summary>
99 Or,
100
101 /// <summary>The not operator.</summary>
102 Not
103 }
104
105 /// <summary>
106 /// Gets or sets the platform which the compiler will use when defaulting 64-bit attributes and elements.
107 /// </summary>
108 /// <value>The platform which the compiler will use when defaulting 64-bit attributes and elements.</value>
109 public Platform CurrentPlatform
110 {
111 get { return this.currentPlatform; }
112 set { this.currentPlatform = value; }
113 }
114
115 /// <summary>
116 /// Ordered list of search paths that the precompiler uses to find included files.
117 /// </summary>
118 /// <value>List of ordered search paths to use during precompiling.</value>
119 public IList<string> IncludeSearchPaths { get; private set; }
120
121 /// <summary>
122 /// Specifies the text stream to display the postprocessed data to.
123 /// </summary>
124 /// <value>TextWriter to write preprocessed xml to.</value>
125 public TextWriter PreprocessOut
126 {
127 get { return this.preprocessOut; }
128 set { this.preprocessOut = value; }
129 }
130
131 /// <summary>
132 /// Get the source line information for the current element. The precompiler will insert
133 /// special source line number processing instructions before each element that it
134 /// encounters. This is where those line numbers are read and processed. This function
135 /// may return an array of source line numbers because the element may have come from
136 /// an included file, in which case the chain of imports is expressed in the array.
137 /// </summary>
138 /// <param name="node">Element to get source line information for.</param>
139 /// <returns>Returns the stack of imports used to author the element being processed.</returns>
140 [SuppressMessage("Microsoft.Design", "CA1059:MembersShouldNotExposeCertainConcreteTypes")]
141 public static SourceLineNumber GetSourceLineNumbers(XmlNode node)
142 {
143 return null;
144 }
145
146 /// <summary>
147 /// Get the source line information for the current element. The precompiler will insert 71 /// Get the source line information for the current element. The precompiler will insert
148 /// special source line number information for each element that it encounters. 72 /// special source line number information for each element that it encounters.
149 /// </summary> 73 /// </summary>
@@ -159,122 +83,94 @@ namespace WixToolset.Core
159 } 83 }
160 84
161 /// <summary> 85 /// <summary>
162 /// Adds an extension. 86 /// Preprocesses a file.
163 /// </summary> 87 /// </summary>
164 /// <param name="extension">The extension to add.</param> 88 /// <param name="context">The preprocessing context.</param>
165 public void AddExtension(IPreprocessorExtension extension) 89 /// <returns>XDocument with the postprocessed data.</returns>
90 public XDocument Process(IPreprocessContext context)
166 { 91 {
167 this.extensions.Add(extension); 92 this.Context = context ?? throw new ArgumentNullException(nameof(context));
168 93
169 if (null != extension.Prefixes) 94 using (XmlReader reader = XmlReader.Create(context.SourceFile, DocumentXmlReaderSettings))
170 { 95 {
171 foreach (string prefix in extension.Prefixes) 96 return Process(context, reader);
172 {
173 IPreprocessorExtension collidingExtension;
174 if (!this.extensionsByPrefix.TryGetValue(prefix, out collidingExtension))
175 {
176 this.extensionsByPrefix.Add(prefix, extension);
177 }
178 else
179 {
180 Messaging.Instance.OnMessage(WixErrors.DuplicateExtensionPreprocessorType(extension.GetType().ToString(), prefix, collidingExtension.GetType().ToString()));
181 }
182 }
183 } 97 }
184
185 //if (null != extension.InspectorExtension)
186 //{
187 // this.inspectorExtensions.Add(extension.InspectorExtension);
188 //}
189 } 98 }
190 99
191 /// <summary> 100 /// <summary>
192 /// Preprocesses a file. 101 /// Preprocesses a file.
193 /// </summary> 102 /// </summary>
194 /// <param name="sourceFile">The file to preprocess.</param> 103 /// <param name="context">The preprocessing context.</param>
195 /// <param name="variables">The variables defined prior to preprocessing.</param> 104 /// <param name="reader">XmlReader to processing the context.</param>
196 /// <returns>XDocument with the postprocessed data.</returns> 105 /// <returns>XDocument with the postprocessed data.</returns>
197 [SuppressMessage("Microsoft.Design", "CA1059:MembersShouldNotExposeCertainConcreteTypes")] 106 public XDocument Process(IPreprocessContext context, XmlReader reader)
198 public XDocument Process(string sourceFile, IDictionary<string, string> variables)
199 { 107 {
200 using (Stream sourceStream = new FileStream(sourceFile, FileMode.Open, FileAccess.Read, FileShare.Read)) 108 if (this.Context == null)
201 using (XmlReader reader = XmlReader.Create(sourceFile, DocumentXmlReaderSettings))
202 { 109 {
203 return Process(reader, variables, sourceFile); 110 this.Context = context ?? throw new ArgumentNullException(nameof(context));
111 }
112 else if (this.Context != context)
113 {
114 throw new ArgumentException(nameof(context));
204 } 115 }
205 }
206 116
207 /// <summary> 117 if (String.IsNullOrEmpty(this.Context.SourceFile) && !String.IsNullOrEmpty(reader.BaseURI))
208 /// Preprocesses a file.
209 /// </summary>
210 /// <param name="sourceFile">The file to preprocess.</param>
211 /// <param name="variables">The variables defined prior to preprocessing.</param>
212 /// <returns>XDocument with the postprocessed data.</returns>
213 [SuppressMessage("Microsoft.Design", "CA1059:MembersShouldNotExposeCertainConcreteTypes")]
214 public XDocument Process(XmlReader reader, IDictionary<string, string> variables, string sourceFile = null)
215 {
216 if (String.IsNullOrEmpty(sourceFile) && !String.IsNullOrEmpty(reader.BaseURI))
217 { 118 {
218 Uri uri = new Uri(reader.BaseURI); 119 var uri = new Uri(reader.BaseURI);
219 sourceFile = uri.AbsolutePath; 120 this.Context.SourceFile = uri.AbsolutePath;
220 } 121 }
221 122
222 this.core = new PreprocessorCore(this.extensionsByPrefix, sourceFile, variables); 123 this.Context.CurrentSourceLineNumber = new SourceLineNumber(this.Context.SourceFile);
223 this.core.ResolvedVariableHandler = this.ResolvedVariable;
224 this.core.CurrentPlatform = this.currentPlatform;
225 this.currentLineNumber = new SourceLineNumber(sourceFile);
226 this.currentFileStack.Clear();
227 this.currentFileStack.Push(this.core.GetVariableValue(this.currentLineNumber, "sys", "SOURCEFILEDIR"));
228 124
229 // Process the reader into the output. 125 this.Helper = this.Context.ServiceProvider.GetService<IPreprocessHelper>();
230 XDocument output = new XDocument(); 126
231 try 127 foreach (var extension in this.Context.Extensions)
232 { 128 {
233 foreach (PreprocessorExtension extension in this.extensions) 129 if (null != extension.Prefixes)
234 { 130 {
235 extension.Core = this.core; 131 foreach (string prefix in extension.Prefixes)
236 extension.Initialize(); 132 {
133 if (!this.ExtensionsByPrefix.TryGetValue(prefix, out var collidingExtension))
134 {
135 this.ExtensionsByPrefix.Add(prefix, extension);
136 }
137 else
138 {
139 this.Context.Messaging.OnMessage(WixErrors.DuplicateExtensionPreprocessorType(extension.GetType().ToString(), prefix, collidingExtension.GetType().ToString()));
140 }
141 }
237 } 142 }
238 143
239 this.PreprocessReader(false, reader, output, 0); 144 extension.PrePreprocess(context);
240 }
241 catch (XmlException e)
242 {
243 this.UpdateCurrentLineNumber(reader, 0);
244 throw new WixException(WixErrors.InvalidXml(this.currentLineNumber, "source", e.Message));
245 } 145 }
246 146
247 // Fire event with post-processed document. 147 this.CurrentFileStack.Clear();
248 ProcessedStreamEventArgs args = new ProcessedStreamEventArgs(sourceFile, output); 148 this.CurrentFileStack.Push(this.Helper.GetVariableValue(this.Context, "sys", "SOURCEFILEDIR"));
249 this.OnProcessedStream(args);
250 149
251 // preprocess the generated XML Document 150 // Process the reader into the output.
252 foreach (PreprocessorExtension extension in this.extensions) 151 XDocument output = new XDocument();
152 try
253 { 153 {
254 extension.PreprocessDocument(output); 154 this.PreprocessReader(false, reader, output, 0);
255 }
256 155
257 // finalize the preprocessing 156 // Fire event with post-processed document.
258 foreach (PreprocessorExtension extension in this.extensions) 157 this.ProcessedStream?.Invoke(this, new ProcessedStreamEventArgs(this.Context.SourceFile, output));
259 {
260 extension.Finish();
261 extension.Core = null;
262 } 158 }
263 159 catch (XmlException e)
264 if (this.core.EncounteredError)
265 { 160 {
266 return null; 161 this.UpdateCurrentLineNumber(reader, 0);
162 throw new WixException(WixErrors.InvalidXml(this.Context.CurrentSourceLineNumber, "source", e.Message));
267 } 163 }
268 else 164 finally
269 { 165 {
270 if (null != this.preprocessOut) 166 // Finalize the preprocessing.
167 foreach (var extension in this.Context.Extensions)
271 { 168 {
272 output.Save(this.preprocessOut); 169 extension.PostPreprocess(output);
273 this.preprocessOut.Flush();
274 } 170 }
275
276 return output;
277 } 171 }
172
173 return this.Context.Messaging.EncounteredError ? null : output;
278 } 174 }
279 175
280 /// <summary> 176 /// <summary>
@@ -340,42 +236,6 @@ namespace WixToolset.Core
340 } 236 }
341 237
342 /// <summary> 238 /// <summary>
343 /// Fires an event when an ifdef/ifndef directive is processed.
344 /// </summary>
345 /// <param name="ea">ifdef/ifndef event arguments.</param>
346 private void OnIfDef(IfDefEventArgs ea)
347 {
348 if (null != this.IfDef)
349 {
350 this.IfDef(this, ea);
351 }
352 }
353
354 /// <summary>
355 /// Fires an event when an included file is processed.
356 /// </summary>
357 /// <param name="ea">Included file event arguments.</param>
358 private void OnIncludedFile(IncludedFileEventArgs ea)
359 {
360 if (null != this.IncludedFile)
361 {
362 this.IncludedFile(this, ea);
363 }
364 }
365
366 /// <summary>
367 /// Fires an event after the file is preprocessed.
368 /// </summary>
369 /// <param name="ea">Included file event arguments.</param>
370 private void OnProcessedStream(ProcessedStreamEventArgs ea)
371 {
372 if (null != this.ProcessedStream)
373 {
374 this.ProcessedStream(this, ea);
375 }
376 }
377
378 /// <summary>
379 /// Tests expression to see if it starts with a keyword. 239 /// Tests expression to see if it starts with a keyword.
380 /// </summary> 240 /// </summary>
381 /// <param name="expression">Expression to test.</param> 241 /// <param name="expression">Expression to test.</param>
@@ -383,7 +243,7 @@ namespace WixToolset.Core
383 /// <returns>true if expression starts with a keyword.</returns> 243 /// <returns>true if expression starts with a keyword.</returns>
384 private static bool StartsWithKeyword(string expression, PreprocessorOperation operation) 244 private static bool StartsWithKeyword(string expression, PreprocessorOperation operation)
385 { 245 {
386 expression = expression.ToUpper(CultureInfo.InvariantCulture); 246 expression = expression.ToUpperInvariant();
387 switch (operation) 247 switch (operation)
388 { 248 {
389 case PreprocessorOperation.Not: 249 case PreprocessorOperation.Not:
@@ -431,7 +291,7 @@ namespace WixToolset.Core
431 // update information here in case an error occurs before the next read 291 // update information here in case an error occurs before the next read
432 this.UpdateCurrentLineNumber(reader, offset); 292 this.UpdateCurrentLineNumber(reader, offset);
433 293
434 SourceLineNumber sourceLineNumbers = this.currentLineNumber; 294 var sourceLineNumbers = this.Context.CurrentSourceLineNumber;
435 295
436 // check for changes in conditional processing 296 // check for changes in conditional processing
437 if (XmlNodeType.ProcessingInstruction == reader.NodeType) 297 if (XmlNodeType.ProcessingInstruction == reader.NodeType)
@@ -459,14 +319,14 @@ namespace WixToolset.Core
459 name = reader.Value.Trim(); 319 name = reader.Value.Trim();
460 if (ifContext.IsTrue) 320 if (ifContext.IsTrue)
461 { 321 {
462 ifContext = new IfContext(ifContext.IsTrue & ifContext.Active, (null != this.core.GetVariableValue(sourceLineNumbers, name, true)), IfState.If); 322 ifContext = new IfContext(ifContext.IsTrue & ifContext.Active, (null != this.Helper.GetVariableValue(this.Context, name, true)), IfState.If);
463 } 323 }
464 else // Use a default IfContext object so we don't try to evaluate the expression if the context isn't true 324 else // Use a default IfContext object so we don't try to evaluate the expression if the context isn't true
465 { 325 {
466 ifContext = new IfContext(); 326 ifContext = new IfContext();
467 } 327 }
468 ignore = true; 328 ignore = true;
469 OnIfDef(new IfDefEventArgs(sourceLineNumbers, true, ifContext.IsTrue, name)); 329 this.IfDef?.Invoke(this, new IfDefEventArgs(sourceLineNumbers, true, ifContext.IsTrue, name));
470 break; 330 break;
471 331
472 case "ifndef": 332 case "ifndef":
@@ -474,25 +334,25 @@ namespace WixToolset.Core
474 name = reader.Value.Trim(); 334 name = reader.Value.Trim();
475 if (ifContext.IsTrue) 335 if (ifContext.IsTrue)
476 { 336 {
477 ifContext = new IfContext(ifContext.IsTrue & ifContext.Active, (null == this.core.GetVariableValue(sourceLineNumbers, name, true)), IfState.If); 337 ifContext = new IfContext(ifContext.IsTrue & ifContext.Active, (null == this.Helper.GetVariableValue(this.Context, name, true)), IfState.If);
478 } 338 }
479 else // Use a default IfContext object so we don't try to evaluate the expression if the context isn't true 339 else // Use a default IfContext object so we don't try to evaluate the expression if the context isn't true
480 { 340 {
481 ifContext = new IfContext(); 341 ifContext = new IfContext();
482 } 342 }
483 ignore = true; 343 ignore = true;
484 OnIfDef(new IfDefEventArgs(sourceLineNumbers, false, !ifContext.IsTrue, name)); 344 this.IfDef?.Invoke(this, new IfDefEventArgs(sourceLineNumbers, false, !ifContext.IsTrue, name));
485 break; 345 break;
486 346
487 case "elseif": 347 case "elseif":
488 if (0 == ifStack.Count) 348 if (0 == ifStack.Count)
489 { 349 {
490 throw new WixException(WixErrors.UnmatchedPreprocessorInstruction(this.currentLineNumber, "if", "elseif")); 350 throw new WixException(WixErrors.UnmatchedPreprocessorInstruction(sourceLineNumbers, "if", "elseif"));
491 } 351 }
492 352
493 if (IfState.If != ifContext.IfState && IfState.ElseIf != ifContext.IfState) 353 if (IfState.If != ifContext.IfState && IfState.ElseIf != ifContext.IfState)
494 { 354 {
495 throw new WixException(WixErrors.UnmatchedPreprocessorInstruction(this.currentLineNumber, "if", "elseif")); 355 throw new WixException(WixErrors.UnmatchedPreprocessorInstruction(sourceLineNumbers, "if", "elseif"));
496 } 356 }
497 357
498 ifContext.IfState = IfState.ElseIf; // we're now in an elseif 358 ifContext.IfState = IfState.ElseIf; // we're now in an elseif
@@ -510,12 +370,12 @@ namespace WixToolset.Core
510 case "else": 370 case "else":
511 if (0 == ifStack.Count) 371 if (0 == ifStack.Count)
512 { 372 {
513 throw new WixException(WixErrors.UnmatchedPreprocessorInstruction(this.currentLineNumber, "if", "else")); 373 throw new WixException(WixErrors.UnmatchedPreprocessorInstruction(sourceLineNumbers, "if", "else"));
514 } 374 }
515 375
516 if (IfState.If != ifContext.IfState && IfState.ElseIf != ifContext.IfState) 376 if (IfState.If != ifContext.IfState && IfState.ElseIf != ifContext.IfState)
517 { 377 {
518 throw new WixException(WixErrors.UnmatchedPreprocessorInstruction(this.currentLineNumber, "if", "else")); 378 throw new WixException(WixErrors.UnmatchedPreprocessorInstruction(sourceLineNumbers, "if", "else"));
519 } 379 }
520 380
521 ifContext.IfState = IfState.Else; // we're now in an else 381 ifContext.IfState = IfState.Else; // we're now in an else
@@ -526,7 +386,7 @@ namespace WixToolset.Core
526 case "endif": 386 case "endif":
527 if (0 == ifStack.Count) 387 if (0 == ifStack.Count)
528 { 388 {
529 throw new WixException(WixErrors.UnmatchedPreprocessorInstruction(this.currentLineNumber, "if", "endif")); 389 throw new WixException(WixErrors.UnmatchedPreprocessorInstruction(sourceLineNumbers, "if", "endif"));
530 } 390 }
531 391
532 ifContext = (IfContext)ifStack.Pop(); 392 ifContext = (IfContext)ifStack.Pop();
@@ -606,7 +466,7 @@ namespace WixToolset.Core
606 break; 466 break;
607 467
608 case "endforeach": // endforeach is handled in PreprocessForeach, so seeing it here is an error 468 case "endforeach": // endforeach is handled in PreprocessForeach, so seeing it here is an error
609 throw new WixException(WixErrors.UnmatchedPreprocessorInstruction(this.currentLineNumber, "foreach", "endforeach")); 469 throw new WixException(WixErrors.UnmatchedPreprocessorInstruction(sourceLineNumbers, "foreach", "endforeach"));
610 470
611 case "pragma": 471 case "pragma":
612 this.PreprocessPragma(reader.Value, currentContainer); 472 this.PreprocessPragma(reader.Value, currentContainer);
@@ -619,31 +479,33 @@ namespace WixToolset.Core
619 break; 479 break;
620 480
621 case XmlNodeType.Element: 481 case XmlNodeType.Element:
622 if (0 < this.includeNextStack.Count && this.includeNextStack.Peek()) 482 if (0 < this.IncludeNextStack.Count && this.IncludeNextStack.Peek())
623 { 483 {
624 if ("Include" != reader.LocalName) 484 if ("Include" != reader.LocalName)
625 { 485 {
626 this.core.OnMessage(WixErrors.InvalidDocumentElement(this.currentLineNumber, reader.Name, "include", "Include")); 486 this.Context.Messaging.OnMessage(WixErrors.InvalidDocumentElement(sourceLineNumbers, reader.Name, "include", "Include"));
627 } 487 }
628 488
629 this.includeNextStack.Pop(); 489 this.IncludeNextStack.Pop();
630 this.includeNextStack.Push(false); 490 this.IncludeNextStack.Push(false);
631 break; 491 break;
632 } 492 }
633 493
634 bool empty = reader.IsEmptyElement; 494 var empty = reader.IsEmptyElement;
635 XNamespace ns = XNamespace.Get(reader.NamespaceURI); 495 var ns = XNamespace.Get(reader.NamespaceURI);
636 XElement element = new XElement(ns + reader.LocalName); 496 var element = new XElement(ns + reader.LocalName);
637 currentContainer.Add(element); 497 currentContainer.Add(element);
638 498
639 this.UpdateCurrentLineNumber(reader, offset); 499 this.UpdateCurrentLineNumber(reader, offset);
640 element.AddAnnotation(this.currentLineNumber); 500 element.AddAnnotation(sourceLineNumbers);
641 501
642 while (reader.MoveToNextAttribute()) 502 while (reader.MoveToNextAttribute())
643 { 503 {
644 string value = this.core.PreprocessString(this.currentLineNumber, reader.Value); 504 var value = this.Helper.PreprocessString(this.Context, reader.Value);
645 XNamespace attribNamespace = XNamespace.Get(reader.NamespaceURI); 505
506 var attribNamespace = XNamespace.Get(reader.NamespaceURI);
646 attribNamespace = XNamespace.Xmlns == attribNamespace && reader.LocalName.Equals("xmlns") ? XNamespace.None : attribNamespace; 507 attribNamespace = XNamespace.Xmlns == attribNamespace && reader.LocalName.Equals("xmlns") ? XNamespace.None : attribNamespace;
508
647 element.Add(new XAttribute(attribNamespace + reader.LocalName, value)); 509 element.Add(new XAttribute(attribNamespace + reader.LocalName, value));
648 } 510 }
649 511
@@ -662,12 +524,12 @@ namespace WixToolset.Core
662 break; 524 break;
663 525
664 case XmlNodeType.Text: 526 case XmlNodeType.Text:
665 string postprocessedText = this.core.PreprocessString(this.currentLineNumber, reader.Value); 527 string postprocessedText = this.Helper.PreprocessString(this.Context, reader.Value);
666 currentContainer.Add(postprocessedText); 528 currentContainer.Add(postprocessedText);
667 break; 529 break;
668 530
669 case XmlNodeType.CDATA: 531 case XmlNodeType.CDATA:
670 string postprocessedValue = this.core.PreprocessString(this.currentLineNumber, reader.Value); 532 string postprocessedValue = this.Helper.PreprocessString(this.Context, reader.Value);
671 currentContainer.Add(new XCData(postprocessedValue)); 533 currentContainer.Add(new XCData(postprocessedValue));
672 break; 534 break;
673 535
@@ -678,13 +540,13 @@ namespace WixToolset.Core
678 540
679 if (0 != ifStack.Count) 541 if (0 != ifStack.Count)
680 { 542 {
681 throw new WixException(WixErrors.NonterminatedPreprocessorInstruction(this.currentLineNumber, "if", "endif")); 543 throw new WixException(WixErrors.NonterminatedPreprocessorInstruction(this.Context.CurrentSourceLineNumber, "if", "endif"));
682 } 544 }
683 545
684 // TODO: can this actually happen? 546 // TODO: can this actually happen?
685 if (0 != containerStack.Count) 547 if (0 != containerStack.Count)
686 { 548 {
687 throw new WixException(WixErrors.NonterminatedPreprocessorInstruction(this.currentLineNumber, "nodes", "nodes")); 549 throw new WixException(WixErrors.NonterminatedPreprocessorInstruction(this.Context.CurrentSourceLineNumber, "nodes", "nodes"));
688 } 550 }
689 } 551 }
690 552
@@ -694,12 +556,10 @@ namespace WixToolset.Core
694 /// <param name="errorMessage">Text from source.</param> 556 /// <param name="errorMessage">Text from source.</param>
695 private void PreprocessError(string errorMessage) 557 private void PreprocessError(string errorMessage)
696 { 558 {
697 SourceLineNumber sourceLineNumbers = this.currentLineNumber; 559 // Resolve other variables in the error message.
698 560 errorMessage = this.Helper.PreprocessString(this.Context, errorMessage);
699 // resolve other variables in the error message
700 errorMessage = this.core.PreprocessString(sourceLineNumbers, errorMessage);
701 561
702 throw new WixException(WixErrors.PreprocessorError(sourceLineNumbers, errorMessage)); 562 throw new WixException(WixErrors.PreprocessorError(this.Context.CurrentSourceLineNumber, errorMessage));
703 } 563 }
704 564
705 /// <summary> 565 /// <summary>
@@ -708,12 +568,10 @@ namespace WixToolset.Core
708 /// <param name="warningMessage">Text from source.</param> 568 /// <param name="warningMessage">Text from source.</param>
709 private void PreprocessWarning(string warningMessage) 569 private void PreprocessWarning(string warningMessage)
710 { 570 {
711 SourceLineNumber sourceLineNumbers = this.currentLineNumber; 571 // Resolve other variables in the warning message.
712 572 warningMessage = this.Helper.PreprocessString(this.Context, warningMessage);
713 // resolve other variables in the warning message
714 warningMessage = this.core.PreprocessString(sourceLineNumbers, warningMessage);
715 573
716 this.core.OnMessage(WixWarnings.PreprocessorWarning(sourceLineNumbers, warningMessage)); 574 this.Context.Messaging.OnMessage(WixWarnings.PreprocessorWarning(this.Context.CurrentSourceLineNumber, warningMessage));
717 } 575 }
718 576
719 /// <summary> 577 /// <summary>
@@ -722,16 +580,15 @@ namespace WixToolset.Core
722 /// <param name="originalDefine">Text from source.</param> 580 /// <param name="originalDefine">Text from source.</param>
723 private void PreprocessDefine(string originalDefine) 581 private void PreprocessDefine(string originalDefine)
724 { 582 {
725 Match match = defineRegex.Match(originalDefine); 583 var match = defineRegex.Match(originalDefine);
726 SourceLineNumber sourceLineNumbers = this.currentLineNumber;
727 584
728 if (!match.Success) 585 if (!match.Success)
729 { 586 {
730 throw new WixException(WixErrors.IllegalDefineStatement(sourceLineNumbers, originalDefine)); 587 throw new WixException(WixErrors.IllegalDefineStatement(this.Context.CurrentSourceLineNumber, originalDefine));
731 } 588 }
732 589
733 string defineName = match.Groups["varName"].Value; 590 var defineName = match.Groups["varName"].Value;
734 string defineValue = match.Groups["varValue"].Value; 591 var defineValue = match.Groups["varValue"].Value;
735 592
736 // strip off the optional quotes 593 // strip off the optional quotes
737 if (1 < defineValue.Length && 594 if (1 < defineValue.Length &&
@@ -742,15 +599,15 @@ namespace WixToolset.Core
742 } 599 }
743 600
744 // resolve other variables in the variable value 601 // resolve other variables in the variable value
745 defineValue = this.core.PreprocessString(sourceLineNumbers, defineValue); 602 defineValue = this.Helper.PreprocessString(this.Context, defineValue);
746 603
747 if (defineName.StartsWith("var.", StringComparison.Ordinal)) 604 if (defineName.StartsWith("var.", StringComparison.Ordinal))
748 { 605 {
749 this.core.AddVariable(sourceLineNumbers, defineName.Substring(4), defineValue); 606 this.Helper.AddVariable(this.Context, defineName.Substring(4), defineValue);
750 } 607 }
751 else 608 else
752 { 609 {
753 this.core.AddVariable(sourceLineNumbers, defineName, defineValue); 610 this.Helper.AddVariable(this.Context, defineName, defineValue);
754 } 611 }
755 } 612 }
756 613
@@ -760,16 +617,15 @@ namespace WixToolset.Core
760 /// <param name="originalDefine">Text from source.</param> 617 /// <param name="originalDefine">Text from source.</param>
761 private void PreprocessUndef(string originalDefine) 618 private void PreprocessUndef(string originalDefine)
762 { 619 {
763 SourceLineNumber sourceLineNumbers = this.currentLineNumber; 620 var name = this.Helper.PreprocessString(this.Context, originalDefine.Trim());
764 string name = this.core.PreprocessString(sourceLineNumbers, originalDefine.Trim());
765 621
766 if (name.StartsWith("var.", StringComparison.Ordinal)) 622 if (name.StartsWith("var.", StringComparison.Ordinal))
767 { 623 {
768 this.core.RemoveVariable(sourceLineNumbers, name.Substring(4)); 624 this.Helper.RemoveVariable(this.Context, name.Substring(4));
769 } 625 }
770 else 626 else
771 { 627 {
772 this.core.RemoveVariable(sourceLineNumbers, name); 628 this.Helper.RemoveVariable(this.Context, name);
773 } 629 }
774 } 630 }
775 631
@@ -780,12 +636,12 @@ namespace WixToolset.Core
780 /// <param name="parent">Parent container for included content.</param> 636 /// <param name="parent">Parent container for included content.</param>
781 private void PreprocessInclude(string includePath, XContainer parent) 637 private void PreprocessInclude(string includePath, XContainer parent)
782 { 638 {
783 SourceLineNumber sourceLineNumbers = this.currentLineNumber; 639 var sourceLineNumbers = this.Context.CurrentSourceLineNumber;
784 640
785 // preprocess variables in the path 641 // Preprocess variables in the path.
786 includePath = this.core.PreprocessString(sourceLineNumbers, includePath); 642 includePath = this.Helper.PreprocessString(this.Context, includePath);
787 643
788 string includeFile = this.GetIncludeFile(includePath); 644 var includeFile = this.GetIncludeFile(includePath);
789 645
790 if (null == includeFile) 646 if (null == includeFile)
791 { 647 {
@@ -807,7 +663,7 @@ namespace WixToolset.Core
807 throw new WixException(WixErrors.InvalidXml(sourceLineNumbers, "source", e.Message)); 663 throw new WixException(WixErrors.InvalidXml(sourceLineNumbers, "source", e.Message));
808 } 664 }
809 665
810 this.OnIncludedFile(new IncludedFileEventArgs(sourceLineNumbers, includeFile)); 666 this.IncludedFile?.Invoke(this, new IncludedFileEventArgs(sourceLineNumbers, includeFile));
811 667
812 this.PopInclude(); 668 this.PopInclude();
813 } 669 }
@@ -821,11 +677,11 @@ namespace WixToolset.Core
821 /// <param name="offset">Offset for the line numbers.</param> 677 /// <param name="offset">Offset for the line numbers.</param>
822 private void PreprocessForeach(XmlReader reader, XContainer container, int offset) 678 private void PreprocessForeach(XmlReader reader, XContainer container, int offset)
823 { 679 {
824 // find the "in" token 680 // Find the "in" token.
825 int indexOfInToken = reader.Value.IndexOf(" in ", StringComparison.Ordinal); 681 var indexOfInToken = reader.Value.IndexOf(" in ", StringComparison.Ordinal);
826 if (0 > indexOfInToken) 682 if (0 > indexOfInToken)
827 { 683 {
828 throw new WixException(WixErrors.IllegalForeach(this.currentLineNumber, reader.Value)); 684 throw new WixException(WixErrors.IllegalForeach(this.Context.CurrentSourceLineNumber, reader.Value));
829 } 685 }
830 686
831 // parse out the variable name 687 // parse out the variable name
@@ -833,7 +689,7 @@ namespace WixToolset.Core
833 string varValuesString = reader.Value.Substring(indexOfInToken + 4).Trim(); 689 string varValuesString = reader.Value.Substring(indexOfInToken + 4).Trim();
834 690
835 // preprocess the variable values string because it might be a variable itself 691 // preprocess the variable values string because it might be a variable itself
836 varValuesString = this.core.PreprocessString(this.currentLineNumber, varValuesString); 692 varValuesString = this.Helper.PreprocessString(this.Context, varValuesString);
837 693
838 string[] varValues = varValuesString.Split(';'); 694 string[] varValues = varValuesString.Split(';');
839 695
@@ -895,20 +751,20 @@ namespace WixToolset.Core
895 } 751 }
896 else if (reader.NodeType == XmlNodeType.None) 752 else if (reader.NodeType == XmlNodeType.None)
897 { 753 {
898 throw new WixException(WixErrors.ExpectedEndforeach(this.currentLineNumber)); 754 throw new WixException(WixErrors.ExpectedEndforeach(this.Context.CurrentSourceLineNumber));
899 } 755 }
900 756
901 reader.Read(); 757 reader.Read();
902 } 758 }
903 759
904 using (MemoryStream fragmentStream = new MemoryStream(Encoding.UTF8.GetBytes(fragmentBuilder.ToString()))) 760 using (var fragmentStream = new MemoryStream(Encoding.UTF8.GetBytes(fragmentBuilder.ToString())))
905 using (XmlReader loopReader = XmlReader.Create(fragmentStream, FragmentXmlReaderSettings)) 761 using (var loopReader = XmlReader.Create(fragmentStream, FragmentXmlReaderSettings))
906 { 762 {
907 // process each iteration, updating the variable's value each time 763 // process each iteration, updating the variable's value each time
908 foreach (string varValue in varValues) 764 foreach (string varValue in varValues)
909 { 765 {
910 // Always overwrite foreach variables. 766 // Always overwrite foreach variables.
911 this.core.AddVariable(this.currentLineNumber, varName, varValue, false); 767 this.Helper.AddVariable(this.Context, varName, varValue, false);
912 768
913 try 769 try
914 { 770 {
@@ -917,7 +773,7 @@ namespace WixToolset.Core
917 catch (XmlException e) 773 catch (XmlException e)
918 { 774 {
919 this.UpdateCurrentLineNumber(loopReader, offset); 775 this.UpdateCurrentLineNumber(loopReader, offset);
920 throw new WixException(WixErrors.InvalidXml(this.currentLineNumber, "source", e.Message)); 776 throw new WixException(WixErrors.InvalidXml(this.Context.CurrentSourceLineNumber, "source", e.Message));
921 } 777 }
922 778
923 fragmentStream.Position = 0; // seek back to the beginning for the next loop. 779 fragmentStream.Position = 0; // seek back to the beginning for the next loop.
@@ -931,24 +787,23 @@ namespace WixToolset.Core
931 /// <param name="pragmaText">Text from source.</param> 787 /// <param name="pragmaText">Text from source.</param>
932 private void PreprocessPragma(string pragmaText, XContainer parent) 788 private void PreprocessPragma(string pragmaText, XContainer parent)
933 { 789 {
934 Match match = pragmaRegex.Match(pragmaText); 790 var match = pragmaRegex.Match(pragmaText);
935 SourceLineNumber sourceLineNumbers = this.currentLineNumber;
936 791
937 if (!match.Success) 792 if (!match.Success)
938 { 793 {
939 throw new WixException(WixErrors.InvalidPreprocessorPragma(sourceLineNumbers, pragmaText)); 794 throw new WixException(WixErrors.InvalidPreprocessorPragma(this.Context.CurrentSourceLineNumber, pragmaText));
940 } 795 }
941 796
942 // resolve other variables in the pragma argument(s) 797 // resolve other variables in the pragma argument(s)
943 string pragmaArgs = this.core.PreprocessString(sourceLineNumbers, match.Groups["pragmaValue"].Value).Trim(); 798 string pragmaArgs = this.Helper.PreprocessString(this.Context, match.Groups["pragmaValue"].Value).Trim();
944 799
945 try 800 try
946 { 801 {
947 this.core.PreprocessPragma(sourceLineNumbers, match.Groups["pragmaName"].Value.Trim(), pragmaArgs, parent); 802 this.Helper.PreprocessPragma(this.Context, match.Groups["pragmaName"].Value.Trim(), pragmaArgs, parent);
948 } 803 }
949 catch (Exception e) 804 catch (Exception e)
950 { 805 {
951 throw new WixException(WixErrors.PreprocessorExtensionPragmaFailed(sourceLineNumbers, pragmaText, e.Message)); 806 throw new WixException(WixErrors.PreprocessorExtensionPragmaFailed(this.Context.CurrentSourceLineNumber, pragmaText, e.Message));
952 } 807 }
953 } 808 }
954 809
@@ -975,11 +830,11 @@ namespace WixToolset.Core
975 int endingQuotes = expression.IndexOf('\"', 1); 830 int endingQuotes = expression.IndexOf('\"', 1);
976 if (-1 == endingQuotes) 831 if (-1 == endingQuotes)
977 { 832 {
978 throw new WixException(WixErrors.UnmatchedQuotesInExpression(this.currentLineNumber, originalExpression)); 833 throw new WixException(WixErrors.UnmatchedQuotesInExpression(this.Context.CurrentSourceLineNumber, originalExpression));
979 } 834 }
980 835
981 // cut the quotes off the string 836 // cut the quotes off the string
982 token = this.core.PreprocessString(this.currentLineNumber, expression.Substring(1, endingQuotes - 1)); 837 token = this.Helper.PreprocessString(this.Context, expression.Substring(1, endingQuotes - 1));
983 838
984 // advance past this string 839 // advance past this string
985 expression = expression.Substring(endingQuotes + 1).Trim(); 840 expression = expression.Substring(endingQuotes + 1).Trim();
@@ -1009,7 +864,7 @@ namespace WixToolset.Core
1009 864
1010 if (-1 == endingParen) 865 if (-1 == endingParen)
1011 { 866 {
1012 throw new WixException(WixErrors.UnmatchedParenthesisInExpression(this.currentLineNumber, originalExpression)); 867 throw new WixException(WixErrors.UnmatchedParenthesisInExpression(this.Context.CurrentSourceLineNumber, originalExpression));
1013 } 868 }
1014 token = expression.Substring(0, endingParen + 1); 869 token = expression.Substring(0, endingParen + 1);
1015 870
@@ -1115,7 +970,7 @@ namespace WixToolset.Core
1115 { 970 {
1116 try 971 try
1117 { 972 {
1118 varValue = this.core.PreprocessString(this.currentLineNumber, variable); 973 varValue = this.Helper.PreprocessString(this.Context, variable);
1119 } 974 }
1120 catch (ArgumentNullException) 975 catch (ArgumentNullException)
1121 { 976 {
@@ -1126,12 +981,12 @@ namespace WixToolset.Core
1126 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)
1127 { 982 {
1128 // make sure it doesn't contain parenthesis 983 // make sure it doesn't contain parenthesis
1129 throw new WixException(WixErrors.UnmatchedParenthesisInExpression(this.currentLineNumber, originalExpression)); 984 throw new WixException(WixErrors.UnmatchedParenthesisInExpression(this.Context.CurrentSourceLineNumber, originalExpression));
1130 } 985 }
1131 else if (variable.IndexOf("\"", StringComparison.Ordinal) != -1) 986 else if (variable.IndexOf("\"", StringComparison.Ordinal) != -1)
1132 { 987 {
1133 // shouldn't contain quotes 988 // shouldn't contain quotes
1134 throw new WixException(WixErrors.UnmatchedQuotesInExpression(this.currentLineNumber, originalExpression)); 989 throw new WixException(WixErrors.UnmatchedQuotesInExpression(this.Context.CurrentSourceLineNumber, originalExpression));
1135 } 990 }
1136 991
1137 return varValue; 992 return varValue;
@@ -1162,7 +1017,7 @@ namespace WixToolset.Core
1162 { 1017 {
1163 if (stringLiteral) 1018 if (stringLiteral)
1164 { 1019 {
1165 throw new WixException(WixErrors.UnmatchedQuotesInExpression(this.currentLineNumber, originalExpression)); 1020 throw new WixException(WixErrors.UnmatchedQuotesInExpression(this.Context.CurrentSourceLineNumber, originalExpression));
1166 } 1021 }
1167 1022
1168 rightValue = this.GetNextToken(originalExpression, ref expression, out stringLiteral); 1023 rightValue = this.GetNextToken(originalExpression, ref expression, out stringLiteral);
@@ -1213,7 +1068,7 @@ namespace WixToolset.Core
1213 { 1068 {
1214 if (operation.Length > 0) 1069 if (operation.Length > 0)
1215 { 1070 {
1216 throw new WixException(WixErrors.ExpectedVariable(this.currentLineNumber, originalExpression)); 1071 throw new WixException(WixErrors.ExpectedVariable(this.Context.CurrentSourceLineNumber, originalExpression));
1217 } 1072 }
1218 1073
1219 // false expression 1074 // false expression
@@ -1228,7 +1083,7 @@ namespace WixToolset.Core
1228 } 1083 }
1229 else 1084 else
1230 { 1085 {
1231 throw new WixException(WixErrors.UnexpectedLiteral(this.currentLineNumber, originalExpression)); 1086 throw new WixException(WixErrors.UnexpectedLiteral(this.Context.CurrentSourceLineNumber, originalExpression));
1232 } 1087 }
1233 } 1088 }
1234 else 1089 else
@@ -1268,11 +1123,11 @@ namespace WixToolset.Core
1268 } 1123 }
1269 catch (FormatException) 1124 catch (FormatException)
1270 { 1125 {
1271 throw new WixException(WixErrors.IllegalIntegerInExpression(this.currentLineNumber, originalExpression)); 1126 throw new WixException(WixErrors.IllegalIntegerInExpression(this.Context.CurrentSourceLineNumber, originalExpression));
1272 } 1127 }
1273 catch (OverflowException) 1128 catch (OverflowException)
1274 { 1129 {
1275 throw new WixException(WixErrors.IllegalIntegerInExpression(this.currentLineNumber, originalExpression)); 1130 throw new WixException(WixErrors.IllegalIntegerInExpression(this.Context.CurrentSourceLineNumber, originalExpression));
1276 } 1131 }
1277 1132
1278 // Compare the numbers 1133 // Compare the numbers
@@ -1314,7 +1169,7 @@ namespace WixToolset.Core
1314 closeParenIndex = expression.IndexOf(')', closeParenIndex); 1169 closeParenIndex = expression.IndexOf(')', closeParenIndex);
1315 if (closeParenIndex == -1) 1170 if (closeParenIndex == -1)
1316 { 1171 {
1317 throw new WixException(WixErrors.UnmatchedParenthesisInExpression(this.currentLineNumber, originalExpression)); 1172 throw new WixException(WixErrors.UnmatchedParenthesisInExpression(this.Context.CurrentSourceLineNumber, originalExpression));
1318 } 1173 }
1319 1174
1320 if (InsideQuotes(expression, closeParenIndex)) 1175 if (InsideQuotes(expression, closeParenIndex))
@@ -1363,7 +1218,7 @@ namespace WixToolset.Core
1363 currentValue = !currentValue; 1218 currentValue = !currentValue;
1364 break; 1219 break;
1365 default: 1220 default:
1366 throw new WixException(WixErrors.UnexpectedPreprocessorOperator(this.currentLineNumber, operation.ToString())); 1221 throw new WixException(WixErrors.UnexpectedPreprocessorOperator(this.Context.CurrentSourceLineNumber, operation.ToString()));
1367 } 1222 }
1368 } 1223 }
1369 1224
@@ -1412,7 +1267,7 @@ namespace WixToolset.Core
1412 expression = expression.Trim(); 1267 expression = expression.Trim();
1413 if (expression.Length == 0) 1268 if (expression.Length == 0)
1414 { 1269 {
1415 throw new WixException(WixErrors.UnexpectedEmptySubexpression(this.currentLineNumber, originalExpression)); 1270 throw new WixException(WixErrors.UnexpectedEmptySubexpression(this.Context.CurrentSourceLineNumber, originalExpression));
1416 } 1271 }
1417 1272
1418 // If the expression starts with parenthesis, evaluate it 1273 // If the expression starts with parenthesis, evaluate it
@@ -1433,7 +1288,7 @@ namespace WixToolset.Core
1433 expression = expression.Substring(3).Trim(); 1288 expression = expression.Substring(3).Trim();
1434 if (expression.Length == 0) 1289 if (expression.Length == 0)
1435 { 1290 {
1436 throw new WixException(WixErrors.ExpectedExpressionAfterNot(this.currentLineNumber, originalExpression)); 1291 throw new WixException(WixErrors.ExpectedExpressionAfterNot(this.Context.CurrentSourceLineNumber, originalExpression));
1437 } 1292 }
1438 1293
1439 expressionValue = this.EvaluateExpressionRecurse(originalExpression, ref expression, PreprocessorOperation.Not, true); 1294 expressionValue = this.EvaluateExpressionRecurse(originalExpression, ref expression, PreprocessorOperation.Not, true);
@@ -1462,7 +1317,7 @@ namespace WixToolset.Core
1462 } 1317 }
1463 else 1318 else
1464 { 1319 {
1465 throw new WixException(WixErrors.InvalidSubExpression(this.currentLineNumber, expression, originalExpression)); 1320 throw new WixException(WixErrors.InvalidSubExpression(this.Context.CurrentSourceLineNumber, expression, originalExpression));
1466 } 1321 }
1467 } 1322 }
1468 1323
@@ -1481,9 +1336,9 @@ namespace WixToolset.Core
1481 { 1336 {
1482 int newLine = lineInfoReader.LineNumber + offset; 1337 int newLine = lineInfoReader.LineNumber + offset;
1483 1338
1484 if (this.currentLineNumber.LineNumber != newLine) 1339 if (this.Context.CurrentSourceLineNumber.LineNumber != newLine)
1485 { 1340 {
1486 this.currentLineNumber = new SourceLineNumber(this.currentLineNumber.FileName, newLine); 1341 this.Context.CurrentSourceLineNumber = new SourceLineNumber(this.Context.CurrentSourceLineNumber.FileName, newLine);
1487 } 1342 }
1488 } 1343 }
1489 } 1344 }
@@ -1494,15 +1349,15 @@ namespace WixToolset.Core
1494 /// <param name="fileName">Name to push on to the stack of included files.</param> 1349 /// <param name="fileName">Name to push on to the stack of included files.</param>
1495 private void PushInclude(string fileName) 1350 private void PushInclude(string fileName)
1496 { 1351 {
1497 if (1023 < this.currentFileStack.Count) 1352 if (1023 < this.CurrentFileStack.Count)
1498 { 1353 {
1499 throw new WixException(WixErrors.TooDeeplyIncluded(this.currentLineNumber, this.currentFileStack.Count)); 1354 throw new WixException(WixErrors.TooDeeplyIncluded(this.Context.CurrentSourceLineNumber, this.CurrentFileStack.Count));
1500 } 1355 }
1501 1356
1502 this.currentFileStack.Push(fileName); 1357 this.CurrentFileStack.Push(fileName);
1503 this.sourceStack.Push(this.currentLineNumber); 1358 this.SourceStack.Push(this.Context.CurrentSourceLineNumber);
1504 this.currentLineNumber = new SourceLineNumber(fileName); 1359 this.Context.CurrentSourceLineNumber = new SourceLineNumber(fileName);
1505 this.includeNextStack.Push(true); 1360 this.IncludeNextStack.Push(true);
1506 } 1361 }
1507 1362
1508 /// <summary> 1363 /// <summary>
@@ -1510,10 +1365,10 @@ namespace WixToolset.Core
1510 /// </summary> 1365 /// </summary>
1511 private void PopInclude() 1366 private void PopInclude()
1512 { 1367 {
1513 this.currentLineNumber = this.sourceStack.Pop(); 1368 this.Context.CurrentSourceLineNumber = this.SourceStack.Pop();
1514 1369
1515 this.currentFileStack.Pop(); 1370 this.CurrentFileStack.Pop();
1516 this.includeNextStack.Pop(); 1371 this.IncludeNextStack.Pop();
1517 } 1372 }
1518 1373
1519 /// <summary> 1374 /// <summary>
@@ -1548,8 +1403,8 @@ namespace WixToolset.Core
1548 else // relative path 1403 else // relative path
1549 { 1404 {
1550 // build a string to test the directory containing the source file first 1405 // build a string to test the directory containing the source file first
1551 string currentFolder = this.currentFileStack.Peek(); 1406 var currentFolder = this.CurrentFileStack.Peek();
1552 string includeTestPath = Path.Combine(Path.GetDirectoryName(currentFolder) ?? String.Empty, includePath); 1407 var includeTestPath = Path.Combine(Path.GetDirectoryName(currentFolder) , includePath);
1553 1408
1554 // test the source file directory 1409 // test the source file directory
1555 if (File.Exists(includeTestPath)) 1410 if (File.Exists(includeTestPath))
@@ -1558,7 +1413,7 @@ namespace WixToolset.Core
1558 } 1413 }
1559 else // test all search paths in the order specified on the command line 1414 else // test all search paths in the order specified on the command line
1560 { 1415 {
1561 foreach (string includeSearchPath in this.IncludeSearchPaths) 1416 foreach (var includeSearchPath in this.Context.IncludeSearchPaths)
1562 { 1417 {
1563 // if the path exists, we have found the final string 1418 // if the path exists, we have found the final string
1564 includeTestPath = Path.Combine(includeSearchPath, includePath); 1419 includeTestPath = Path.Combine(includeSearchPath, includePath);