aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core/Compiler_Module.cs
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2019-05-08 14:13:31 -0700
committerRob Mensching <rob@firegiant.com>2019-05-08 14:44:43 -0700
commit75fd55d5a71c492c6ea904768858c51aa97da29f (patch)
tree610047db1d5759a726ce88277bb2dfddcd01da45 /src/WixToolset.Core/Compiler_Module.cs
parentd1dbe29f3856d012acf5f96e8e66c43b74ab490d (diff)
downloadwix-75fd55d5a71c492c6ea904768858c51aa97da29f.tar.gz
wix-75fd55d5a71c492c6ea904768858c51aa97da29f.tar.bz2
wix-75fd55d5a71c492c6ea904768858c51aa97da29f.zip
Use new strongly typed tuples
Diffstat (limited to 'src/WixToolset.Core/Compiler_Module.cs')
-rw-r--r--src/WixToolset.Core/Compiler_Module.cs650
1 files changed, 650 insertions, 0 deletions
diff --git a/src/WixToolset.Core/Compiler_Module.cs b/src/WixToolset.Core/Compiler_Module.cs
new file mode 100644
index 00000000..b95b5f03
--- /dev/null
+++ b/src/WixToolset.Core/Compiler_Module.cs
@@ -0,0 +1,650 @@
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
3namespace WixToolset.Core
4{
5 using System;
6 using System.Globalization;
7 using System.Xml.Linq;
8 using WixToolset.Data;
9 using WixToolset.Data.Tuples;
10 using WixToolset.Extensibility;
11
12 /// <summary>
13 /// Compiler of the WiX toolset.
14 /// </summary>
15 internal partial class Compiler : ICompiler
16 {
17 /// <summary>
18 /// Parses a module element.
19 /// </summary>
20 /// <param name="node">Element to parse.</param>
21 private void ParseModuleElement(XElement node)
22 {
23 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
24 var codepage = 0;
25 string moduleId = null;
26 string version = null;
27
28 this.activeName = null;
29 this.activeLanguage = null;
30
31 foreach (var attrib in node.Attributes())
32 {
33 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
34 {
35 switch (attrib.Name.LocalName)
36 {
37 case "Id":
38 this.activeName = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
39 if ("PUT-MODULE-NAME-HERE" == this.activeName)
40 {
41 this.Core.Write(WarningMessages.PlaceholderValue(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, this.activeName));
42 }
43 else
44 {
45 this.activeName = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
46 }
47 break;
48 case "Codepage":
49 codepage = this.Core.GetAttributeCodePageValue(sourceLineNumbers, attrib);
50 break;
51 case "Guid":
52 moduleId = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, false);
53 this.Core.Write(WarningMessages.DeprecatedModuleGuidAttribute(sourceLineNumbers));
54 break;
55 case "Language":
56 this.activeLanguage = this.Core.GetAttributeLocalizableIntegerValue(sourceLineNumbers, attrib, 0, Int16.MaxValue);
57 break;
58 case "Version":
59 version = this.Core.GetAttributeVersionValue(sourceLineNumbers, attrib);
60 break;
61 default:
62 this.Core.UnexpectedAttribute(node, attrib);
63 break;
64 }
65 }
66 else
67 {
68 this.Core.ParseExtensionAttribute(node, attrib);
69 }
70 }
71
72 if (null == this.activeName)
73 {
74 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id"));
75 }
76
77 if (null == this.activeLanguage)
78 {
79 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Language"));
80 }
81
82 if (null == version)
83 {
84 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Version"));
85 }
86 else if (!CompilerCore.IsValidModuleOrBundleVersion(version))
87 {
88 this.Core.Write(WarningMessages.InvalidModuleOrBundleVersion(sourceLineNumbers, "Module", version));
89 }
90
91 try
92 {
93 this.compilingModule = true; // notice that we are actually building a Merge Module here
94 this.Core.CreateActiveSection(this.activeName, SectionType.Module, codepage, this.Context.CompilationId);
95
96 foreach (var child in node.Elements())
97 {
98 if (CompilerCore.WixNamespace == child.Name.Namespace)
99 {
100 switch (child.Name.LocalName)
101 {
102 case "AdminExecuteSequence":
103 case "AdminUISequence":
104 case "AdvertiseExecuteSequence":
105 case "InstallExecuteSequence":
106 case "InstallUISequence":
107 this.ParseSequenceElement(child, child.Name.LocalName);
108 break;
109 case "AppId":
110 this.ParseAppIdElement(child, null, YesNoType.Yes, null, null, null);
111 break;
112 case "Binary":
113 this.ParseBinaryElement(child);
114 break;
115 case "Component":
116 this.ParseComponentElement(child, ComplexReferenceParentType.Module, this.activeName, this.activeLanguage, CompilerConstants.IntegerNotSet, null, null);
117 break;
118 case "ComponentGroupRef":
119 this.ParseComponentGroupRefElement(child, ComplexReferenceParentType.Module, this.activeName, this.activeLanguage);
120 break;
121 case "ComponentRef":
122 this.ParseComponentRefElement(child, ComplexReferenceParentType.Module, this.activeName, this.activeLanguage);
123 break;
124 case "Configuration":
125 this.ParseConfigurationElement(child);
126 break;
127 case "CustomAction":
128 this.ParseCustomActionElement(child);
129 break;
130 case "CustomActionRef":
131 this.ParseSimpleRefElement(child, "CustomAction");
132 break;
133 case "CustomTable":
134 this.ParseCustomTableElement(child);
135 break;
136 case "Dependency":
137 this.ParseDependencyElement(child);
138 break;
139 case "Directory":
140 this.ParseDirectoryElement(child, null, CompilerConstants.IntegerNotSet, String.Empty);
141 break;
142 case "DirectoryRef":
143 this.ParseDirectoryRefElement(child);
144 break;
145 case "EmbeddedChainer":
146 this.ParseEmbeddedChainerElement(child);
147 break;
148 case "EmbeddedChainerRef":
149 this.ParseSimpleRefElement(child, "MsiEmbeddedChainer");
150 break;
151 case "EnsureTable":
152 this.ParseEnsureTableElement(child);
153 break;
154 case "Exclusion":
155 this.ParseExclusionElement(child);
156 break;
157 case "Icon":
158 this.ParseIconElement(child);
159 break;
160 case "IgnoreModularization":
161 this.ParseIgnoreModularizationElement(child);
162 break;
163 case "IgnoreTable":
164 this.ParseIgnoreTableElement(child);
165 break;
166 case "Package":
167 this.ParsePackageElement(child, null, moduleId);
168 break;
169 case "Property":
170 this.ParsePropertyElement(child);
171 break;
172 case "PropertyRef":
173 this.ParseSimpleRefElement(child, "Property");
174 break;
175 case "SetDirectory":
176 this.ParseSetDirectoryElement(child);
177 break;
178 case "SetProperty":
179 this.ParseSetPropertyElement(child);
180 break;
181 case "SFPCatalog":
182 string parentName = null;
183 this.ParseSFPCatalogElement(child, ref parentName);
184 break;
185 case "Substitution":
186 this.ParseSubstitutionElement(child);
187 break;
188 case "UI":
189 this.ParseUIElement(child);
190 break;
191 case "UIRef":
192 this.ParseSimpleRefElement(child, "WixUI");
193 break;
194 case "WixVariable":
195 this.ParseWixVariableElement(child);
196 break;
197 default:
198 this.Core.UnexpectedElement(node, child);
199 break;
200 }
201 }
202 else
203 {
204 this.Core.ParseExtensionElement(node, child);
205 }
206 }
207
208
209 if (!this.Core.EncounteredError)
210 {
211 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ModuleSignature);
212 row.Set(0, this.activeName);
213 row.Set(1, this.activeLanguage);
214 row.Set(2, version);
215 }
216 }
217 finally
218 {
219 this.compilingModule = false; // notice that we are no longer building a Merge Module here
220 }
221 }
222
223 /// <summary>
224 /// Parses a dependency element.
225 /// </summary>
226 /// <param name="node">Element to parse.</param>
227 private void ParseDependencyElement(XElement node)
228 {
229 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
230 string requiredId = null;
231 var requiredLanguage = CompilerConstants.IntegerNotSet;
232 string requiredVersion = null;
233
234 foreach (var attrib in node.Attributes())
235 {
236 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
237 {
238 switch (attrib.Name.LocalName)
239 {
240 case "RequiredId":
241 requiredId = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
242 break;
243 case "RequiredLanguage":
244 requiredLanguage = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, Int16.MaxValue);
245 break;
246 case "RequiredVersion":
247 requiredVersion = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
248 break;
249 default:
250 this.Core.UnexpectedAttribute(node, attrib);
251 break;
252 }
253 }
254 else
255 {
256 this.Core.ParseExtensionAttribute(node, attrib);
257 }
258 }
259
260 if (null == requiredId)
261 {
262 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "RequiredId"));
263 requiredId = String.Empty;
264 }
265
266 if (CompilerConstants.IntegerNotSet == requiredLanguage)
267 {
268 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "RequiredLanguage"));
269 requiredLanguage = CompilerConstants.IllegalInteger;
270 }
271
272 this.Core.ParseForExtensionElements(node);
273
274 if (!this.Core.EncounteredError)
275 {
276 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ModuleDependency);
277 row.Set(0, this.activeName);
278 row.Set(1, this.activeLanguage);
279 row.Set(2, requiredId);
280 row.Set(3, requiredLanguage.ToString(CultureInfo.InvariantCulture));
281 row.Set(4, requiredVersion);
282 }
283 }
284
285 /// <summary>
286 /// Parses an exclusion element.
287 /// </summary>
288 /// <param name="node">Element to parse.</param>
289 private void ParseExclusionElement(XElement node)
290 {
291 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
292 string excludedId = null;
293 var excludeExceptLanguage = CompilerConstants.IntegerNotSet;
294 var excludeLanguage = CompilerConstants.IntegerNotSet;
295 var excludedLanguageField = "0";
296 string excludedMaxVersion = null;
297 string excludedMinVersion = null;
298
299 foreach (var attrib in node.Attributes())
300 {
301 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
302 {
303 switch (attrib.Name.LocalName)
304 {
305 case "ExcludedId":
306 excludedId = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
307 break;
308 case "ExcludeExceptLanguage":
309 excludeExceptLanguage = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, Int16.MaxValue);
310 break;
311 case "ExcludeLanguage":
312 excludeLanguage = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, Int16.MaxValue);
313 break;
314 case "ExcludedMaxVersion":
315 excludedMaxVersion = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
316 break;
317 case "ExcludedMinVersion":
318 excludedMinVersion = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
319 break;
320 default:
321 this.Core.UnexpectedAttribute(node, attrib);
322 break;
323 }
324 }
325 else
326 {
327 this.Core.ParseExtensionAttribute(node, attrib);
328 }
329 }
330
331 if (null == excludedId)
332 {
333 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "ExcludedId"));
334 excludedId = String.Empty;
335 }
336
337 if (CompilerConstants.IntegerNotSet != excludeExceptLanguage && CompilerConstants.IntegerNotSet != excludeLanguage)
338 {
339 this.Core.Write(ErrorMessages.IllegalModuleExclusionLanguageAttributes(sourceLineNumbers));
340 }
341 else if (CompilerConstants.IntegerNotSet != excludeExceptLanguage)
342 {
343 excludedLanguageField = Convert.ToString(-excludeExceptLanguage, CultureInfo.InvariantCulture);
344 }
345 else if (CompilerConstants.IntegerNotSet != excludeLanguage)
346 {
347 excludedLanguageField = Convert.ToString(excludeLanguage, CultureInfo.InvariantCulture);
348 }
349
350 this.Core.ParseForExtensionElements(node);
351
352 if (!this.Core.EncounteredError)
353 {
354 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ModuleExclusion);
355 row.Set(0, this.activeName);
356 row.Set(1, this.activeLanguage);
357 row.Set(2, excludedId);
358 row.Set(3, excludedLanguageField);
359 row.Set(4, excludedMinVersion);
360 row.Set(5, excludedMaxVersion);
361 }
362 }
363
364 /// <summary>
365 /// Parses a configuration element for a configurable merge module.
366 /// </summary>
367 /// <param name="node">Element to parse.</param>
368 private void ParseConfigurationElement(XElement node)
369 {
370 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
371 string contextData = null;
372 string defaultValue = null;
373 string description = null;
374 string displayName = null;
375 var format = CompilerConstants.IntegerNotSet;
376 string helpKeyword = null;
377 string helpLocation = null;
378 bool keyNoOrphan = false;
379 bool nonNullable = false;
380 Identifier name = null;
381 string type = null;
382
383 foreach (var attrib in node.Attributes())
384 {
385 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
386 {
387 switch (attrib.Name.LocalName)
388 {
389 case "Name":
390 name = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib);
391 break;
392 case "ContextData":
393 contextData = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
394 break;
395 case "Description":
396 description = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
397 break;
398 case "DefaultValue":
399 defaultValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
400 break;
401 case "DisplayName":
402 displayName = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
403 break;
404 case "Format":
405 var formatStr = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
406 switch (formatStr)
407 {
408 case "Text":
409 case "text":
410 format = 0;
411 break;
412 case "Key":
413 case "key":
414 format = 1;
415 break;
416 case "Integer":
417 case "integer":
418 format = 2;
419 break;
420 case "Bitfield":
421 case "bitfield":
422 format = 3;
423 break;
424 case "":
425 break;
426 default:
427 this.Core.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, node.Name.LocalName, "Format", formatStr, "Text", "Key", "Integer", "Bitfield"));
428 break;
429 }
430 break;
431 case "HelpKeyword":
432 helpKeyword = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
433 break;
434 case "HelpLocation":
435 helpLocation = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
436 break;
437 case "KeyNoOrphan":
438 keyNoOrphan = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
439 break;
440 case "NonNullable":
441 nonNullable = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
442 break;
443 case "Type":
444 type = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
445 break;
446 default:
447 this.Core.UnexpectedAttribute(node, attrib);
448 break;
449 }
450 }
451 else
452 {
453 this.Core.ParseExtensionAttribute(node, attrib);
454 }
455 }
456
457 if (null == name)
458 {
459 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Name"));
460 }
461
462 if (CompilerConstants.IntegerNotSet == format)
463 {
464 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Format"));
465 }
466
467 this.Core.ParseForExtensionElements(node);
468
469 if (!this.Core.EncounteredError)
470 {
471 var tuple = new ModuleConfigurationTuple(sourceLineNumbers, name)
472 {
473 Format = format,
474 Type = type,
475 ContextData = contextData,
476 DefaultValue = defaultValue,
477 KeyNoOrphan = keyNoOrphan,
478 NonNullable = nonNullable,
479 DisplayName = displayName,
480 Description = description,
481 HelpLocation = helpLocation,
482 HelpKeyword = helpKeyword
483 };
484
485 this.Core.AddTuple(tuple);
486 }
487 }
488
489 /// <summary>
490 /// Parses a substitution element for a configurable merge module.
491 /// </summary>
492 /// <param name="node">Element to parse.</param>
493 private void ParseSubstitutionElement(XElement node)
494 {
495 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
496 string column = null;
497 string rowKeys = null;
498 string table = null;
499 string value = null;
500
501 foreach (var attrib in node.Attributes())
502 {
503 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
504 {
505 switch (attrib.Name.LocalName)
506 {
507 case "Column":
508 column = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
509 break;
510 case "Row":
511 rowKeys = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
512 break;
513 case "Table":
514 table = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
515 break;
516 case "Value":
517 value = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
518 break;
519 default:
520 this.Core.UnexpectedAttribute(node, attrib);
521 break;
522 }
523 }
524 else
525 {
526 this.Core.ParseExtensionAttribute(node, attrib);
527 }
528 }
529
530 if (null == column)
531 {
532 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Column"));
533 column = String.Empty;
534 }
535
536 if (null == table)
537 {
538 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Table"));
539 table = String.Empty;
540 }
541
542 if (null == rowKeys)
543 {
544 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Row"));
545 }
546
547 this.Core.ParseForExtensionElements(node);
548
549 if (!this.Core.EncounteredError)
550 {
551 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ModuleSubstitution);
552 row.Set(0, table);
553 row.Set(1, rowKeys);
554 row.Set(2, column);
555 row.Set(3, value);
556 }
557 }
558
559 /// <summary>
560 /// Parses an ignore modularization element.
561 /// </summary>
562 /// <param name="node">XmlNode on an IgnoreModulatization element.</param>
563 private void ParseIgnoreModularizationElement(XElement node)
564 {
565 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
566 string name = null;
567
568 this.Core.Write(WarningMessages.DeprecatedIgnoreModularizationElement(sourceLineNumbers));
569
570 foreach (var attrib in node.Attributes())
571 {
572 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
573 {
574 switch (attrib.Name.LocalName)
575 {
576 case "Name":
577 name = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
578 break;
579 case "Type":
580 // this is actually not used
581 break;
582 default:
583 this.Core.UnexpectedAttribute(node, attrib);
584 break;
585 }
586 }
587 else
588 {
589 this.Core.ParseExtensionAttribute(node, attrib);
590 }
591 }
592
593 if (null == name)
594 {
595 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Name"));
596 }
597
598 this.Core.ParseForExtensionElements(node);
599
600 if (!this.Core.EncounteredError)
601 {
602 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixSuppressModularization);
603 row.Set(0, name);
604 }
605 }
606
607 /// <summary>
608 /// Parses an IgnoreTable element.
609 /// </summary>
610 /// <param name="node">Element to parse.</param>
611 private void ParseIgnoreTableElement(XElement node)
612 {
613 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
614 string id = null;
615
616 foreach (var attrib in node.Attributes())
617 {
618 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
619 {
620 switch (attrib.Name.LocalName)
621 {
622 case "Id":
623 id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
624 break;
625 default:
626 this.Core.UnexpectedAttribute(node, attrib);
627 break;
628 }
629 }
630 else
631 {
632 this.Core.ParseExtensionAttribute(node, attrib);
633 }
634 }
635
636 if (null == id)
637 {
638 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id"));
639 }
640
641 this.Core.ParseForExtensionElements(node);
642
643 if (!this.Core.EncounteredError)
644 {
645 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ModuleIgnoreTable);
646 row.Set(0, id);
647 }
648 }
649 }
650}