Refactor CompilerCore to ParserHelper and other clean up
Rob Mensching committed
Nov 14, 2017 at 23:21 UTC
aa6f15ec4998a77622fafe9c510b3b547c595679
19 files changed
+946
-747
src/WixToolset.Core/AppCommon.cs
+1
-2
@@ -1,10 +1,9 @@
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
3
+namespace WixToolset.Core
4
{
5
using System;
6
using System.Collections.Specialized;
7
- using System.Configuration;
7
using System.Globalization;
8
using System.IO;
9
using System.Reflection;
src/WixToolset.Core/BinderCore.cs
deleted
-44
@@ -1,44 +0,0 @@
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
4
-{
5
- using WixToolset.Data;
6
- using WixToolset.Extensibility;
7
-
8
- /// <summary>
9
- /// Core class for the binder.
10
- /// </summary>
11
- internal class BinderCore : IBinderCore
12
- {
13
- public IBinderFileManagerCore FileManagerCore { get; set; }
14
-
15
- /// <summary>
16
- /// Gets whether the binder core encountered an error while processing.
17
- /// </summary>
18
- /// <value>Flag if core encountered an error during processing.</value>
19
- public bool EncounteredError
20
- {
21
- get { return Messaging.Instance.EncounteredError; }
22
- }
23
-
24
- /// <summary>
25
- /// Generate an identifier by hashing data from the row.
26
- /// </summary>
27
- /// <param name="prefix">Three letter or less prefix for generated row identifier.</param>
28
- /// <param name="args">Information to hash.</param>
29
- /// <returns>The generated identifier.</returns>
30
- public string CreateIdentifier(string prefix, params string[] args)
31
- {
32
- return Common.GenerateIdentifier(prefix, args);
33
- }
34
-
35
- /// <summary>
36
- /// Sends a message to the message delegate if there is one.
37
- /// </summary>
38
- /// <param name="mea">Message event arguments.</param>
39
- public void OnMessage(MessageEventArgs e)
40
- {
41
- Messaging.Instance.OnMessage(e);
42
- }
43
- }
44
-}
src/WixToolset.Core/Common.cs
+4
-3
@@ -1,6 +1,6 @@
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
3
+namespace WixToolset.Core
4
{
5
using System;
6
using System.Diagnostics;
@@ -13,6 +13,7 @@ namespace WixToolset
13
using System.Xml;
14
using System.Xml.Linq;
15
using WixToolset.Data;
16
+ using WixToolset.Extensibility;
17
18
/// <summary>
19
/// Common Wix utility methods and types.
@@ -766,8 +767,8 @@ namespace WixToolset
767
/// <returns>The attribute's YesNoType value.</returns>
768
internal static string GetInnerText(XElement node)
769
{
769
- XText text = node.Nodes().Where(n => XmlNodeType.Text == n.NodeType || XmlNodeType.CDATA == n.NodeType).Cast<XText>().FirstOrDefault();
770
- return (null == text) ? null : text.Value;
770
+ var text = node.Nodes().Where(n => XmlNodeType.Text == n.NodeType || XmlNodeType.CDATA == n.NodeType).Cast<XText>().FirstOrDefault();
771
+ return text?.Value;
772
}
773
774
/// <summary>
src/WixToolset.Core/Compiler.cs
+5
-8
@@ -1,6 +1,6 @@
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
3
+namespace WixToolset.Core
4
{
5
using System;
6
using System.Collections;
@@ -11,7 +11,6 @@ namespace WixToolset
11
using System.IO;
12
using System.Text.RegularExpressions;
13
using System.Xml.Linq;
14
- using WixToolset.Core;
14
using WixToolset.Core.Native;
15
using WixToolset.Data;
16
using WixToolset.Data.Tuples;
@@ -22,7 +21,6 @@ namespace WixToolset
21
/// <summary>
22
/// Compiler of the WiX toolset.
23
/// </summary>
25
- [SuppressMessage("Microsoft.Naming", "CA1724:TypeNamesShouldNotMatchNamespaces")]
24
public sealed class Compiler
25
{
26
public const string UpgradeDetectedProperty = "WIX_UPGRADE_DETECTED";
@@ -40,7 +38,7 @@ namespace WixToolset
38
private const string BURN_BUNDLE_ORIGINAL_SOURCE_FOLDER = "WixBundleOriginalSourceFolder";
39
private const string BURN_BUNDLE_LAST_USED_SOURCE = "WixBundleLastUsedSource";
40
43
- // if these are true you know you are building a module or product
41
+ // If these are true you know you are building a module or product
42
// but if they are false you cannot not be sure they will not end
43
// up a product or module. Use these flags carefully.
44
private bool compilingModule;
@@ -123,16 +121,15 @@ namespace WixToolset
121
// Try to compile it.
122
try
123
{
126
- var creator = context.ServiceProvider.GetService<ITupleDefinitionCreator>();
124
+ var parseHelper = context.ServiceProvider.GetService<IParseHelper>();
125
128
- this.Core = new CompilerCore(target, creator, extensionsByNamespace);
129
- this.Core.CurrentPlatform = this.Context.Platform;
126
+ this.Core = new CompilerCore(target, parseHelper, extensionsByNamespace);
127
this.Core.ShowPedanticMessages = this.ShowPedanticMessages;
128
this.componentIdPlaceholdersResolver = new WixVariableResolver();
129
130
// parse the document
131
var source = context.Source;
135
- SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(source.Root);
132
+ var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(source.Root);
133
if ("Wix" == source.Root.Name.LocalName)
134
{
135
if (CompilerCore.WixNamespace == source.Root.Name.Namespace)
src/WixToolset.Core/CompilerCore.cs
+92
-668
@@ -1,6 +1,6 @@
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
3
+namespace WixToolset.Core
4
{
5
using System;
6
using System.Collections;
@@ -17,6 +17,7 @@ namespace WixToolset
17
using WixToolset.Data;
18
using WixToolset.Data.Tuples;
19
using WixToolset.Extensibility;
20
+ using WixToolset.Extensibility.Services;
21
using Wix = WixToolset.Data.Serialize;
22
23
internal enum ValueListKind
@@ -40,7 +41,7 @@ namespace WixToolset
41
/// <summary>
42
/// Core class for the compiler.
43
/// </summary>
43
- internal sealed class CompilerCore //: ICompilerCore
44
+ internal sealed class CompilerCore
45
{
46
internal static readonly XNamespace W3SchemaPrefix = "http://www.w3.org/";
47
internal static readonly XNamespace WixNamespace = "http://wixtoolset.org/schemas/v4/wxs";
@@ -50,19 +51,6 @@ namespace WixToolset
51
private const string IllegalLongFilenameCharacters = @"[\\\?|><:/\*""]"; // illegal: \ ? | > < : / * "
52
private static readonly Regex IllegalLongFilename = new Regex(IllegalLongFilenameCharacters, RegexOptions.Compiled);
53
53
- private const string LegalLongFilenameCharacters = @"[^\\\?|><:/\*""]"; // opposite of illegal above.
54
- private static readonly Regex LegalLongFilename = new Regex(String.Concat("^", LegalLongFilenameCharacters, @"{1,259}$"), RegexOptions.Compiled);
55
-
56
- private const string LegalRelativeLongFilenameCharacters = @"[^\?|><:/\*""]"; // (like legal long, but we allow '\') illegal: ? | > < : / * "
57
- private static readonly Regex LegalRelativeLongFilename = new Regex(String.Concat("^", LegalRelativeLongFilenameCharacters, @"{1,259}$"), RegexOptions.Compiled);
58
-
59
- private const string LegalWildcardLongFilenameCharacters = @"[^\\|><:/""]"; // illegal: \ | > < : / "
60
- private static readonly Regex LegalWildcardLongFilename = new Regex(String.Concat("^", LegalWildcardLongFilenameCharacters, @"{1,259}$"));
61
-
62
- private static readonly Regex PutGuidHere = new Regex(@"PUT\-GUID\-(?:\d+\-)?HERE", RegexOptions.Singleline);
63
-
64
- private static readonly Regex LegalIdentifierWithAccess = new Regex(@"^((?<access>public|internal|protected|private)\s+)?(?<id>[_A-Za-z][0-9A-Za-z_\.]*)$", RegexOptions.Compiled | RegexOptions.ExplicitCapture);
65
-
54
public const int DefaultMaximumUncompressedMediaSize = 200; // Default value is 200 MB
55
public const int MinValueOfMaxCabSizeForLargeFileSplitting = 20; // 20 MB
56
public const int MaxValueOfMaxCabSizeForLargeFileSplitting = 2 * 1024; // 2048 MB (i.e. 2 GB)
@@ -141,7 +129,7 @@ namespace WixToolset
129
});
130
131
private Dictionary<XNamespace, ICompilerExtension> extensions;
144
- private ITupleDefinitionCreator creator;
132
+ private IParseHelper parseHelper;
133
private Intermediate intermediate;
134
135
private HashSet<string> activeSectionInlinedDirectoryIds;
@@ -152,10 +140,10 @@ namespace WixToolset
140
/// </summary>
141
/// <param name="intermediate">The Intermediate object representing compiled source document.</param>
142
/// <param name="extensions">The WiX extensions collection.</param>
155
- internal CompilerCore(Intermediate intermediate, ITupleDefinitionCreator creator, Dictionary<XNamespace, ICompilerExtension> extensions)
143
+ internal CompilerCore(Intermediate intermediate, IParseHelper parseHelper, Dictionary<XNamespace, ICompilerExtension> extensions)
144
{
145
this.extensions = extensions;
158
- this.creator = creator;
146
+ this.parseHelper = parseHelper;
147
this.intermediate = intermediate;
148
}
149
@@ -165,12 +153,6 @@ namespace WixToolset
153
/// <value>The section the compiler is currently emitting symbols into.</value>
154
public IntermediateSection ActiveSection { get; private set; }
155
168
- /// <summary>
169
- /// Gets or sets the platform which the compiler will use when defaulting 64-bit attributes and elements.
170
- /// </summary>
171
- /// <value>The platform which the compiler will use when defaulting 64-bit attributes and elements.</value>
172
- public Platform CurrentPlatform { get; set; }
173
-
156
/// <summary>
157
/// Gets whether the compiler core encountered an error while processing.
158
/// </summary>
@@ -231,12 +213,7 @@ namespace WixToolset
213
/// <returns>true if the filename is ambiguous; false otherwise.</returns>
214
public static bool IsAmbiguousFilename(string filename)
215
{
234
- if (null == filename || 0 == filename.Length)
235
- {
236
- return false;
237
- }
238
-
239
- return CompilerCore.AmbiguousFilename.IsMatch(filename);
216
+ return String.IsNullOrEmpty(filename) ? false : CompilerCore.AmbiguousFilename.IsMatch(filename);
217
}
218
219
/// <summary>
@@ -246,7 +223,7 @@ namespace WixToolset
223
/// <returns>true if the value is an identifier; false otherwise.</returns>
224
public bool IsValidIdentifier(string value)
225
{
249
- return Common.IsIdentifier(value);
226
+ return this.parseHelper.IsValidIdentifier(value);
227
}
228
229
/// <summary>
@@ -256,14 +233,7 @@ namespace WixToolset
233
/// <returns>True if the identifier is a valid loc identifier.</returns>
234
public bool IsValidLocIdentifier(string identifier)
235
{
259
- if (String.IsNullOrEmpty(identifier))
260
- {
261
- return false;
262
- }
263
-
264
- Match match = Common.WixVariableRegex.Match(identifier);
265
-
266
- return (match.Success && "loc" == match.Groups["namespace"].Value && 0 == match.Index && identifier.Length == match.Length);
236
+ return this.parseHelper.IsValidIdentifier(identifier);
237
}
238
239
/// <summary>
@@ -275,34 +245,7 @@ namespace WixToolset
245
/// <returns>True if the filename is a valid long filename</returns>
246
public bool IsValidLongFilename(string filename, bool allowWildcards = false, bool allowRelative = false)
247
{
278
- if (String.IsNullOrEmpty(filename))
279
- {
280
- return false;
281
- }
282
-
283
- // check for a non-period character (all periods is not legal)
284
- bool nonPeriodFound = false;
285
- foreach (char character in filename)
286
- {
287
- if ('.' != character)
288
- {
289
- nonPeriodFound = true;
290
- break;
291
- }
292
- }
293
-
294
- if (allowWildcards)
295
- {
296
- return (nonPeriodFound && CompilerCore.LegalWildcardLongFilename.IsMatch(filename));
297
- }
298
- else if (allowRelative)
299
- {
300
- return (nonPeriodFound && CompilerCore.LegalRelativeLongFilename.IsMatch(filename));
301
- }
302
- else
303
- {
304
- return (nonPeriodFound && CompilerCore.LegalLongFilename.IsMatch(filename));
305
- }
248
+ return this.parseHelper.IsValidLongFilename(filename, allowWildcards, allowRelative);
249
}
250
251
/// <summary>
@@ -313,7 +256,7 @@ namespace WixToolset
256
/// <returns>True if the filename is a valid short filename</returns>
257
public bool IsValidShortFilename(string filename, bool allowWildcards)
258
{
316
- return Common.IsValidShortFilename(filename, allowWildcards);
259
+ return this.parseHelper.IsValidShortFilename(filename, allowWildcards);
260
}
261
262
/// <summary>
@@ -337,52 +280,7 @@ namespace WixToolset
280
/// <returns>The generated 8.3-compliant short file/directory name.</returns>
281
public string CreateShortName(string longName, bool keepExtension, bool allowWildcards, params string[] args)
282
{
340
- // canonicalize the long name if its not a localization identifier (they are case-sensitive)
341
- if (!this.IsValidLocIdentifier(longName))
342
- {
343
- longName = longName.ToLowerInvariant();
344
- }
345
-
346
- // collect all the data
347
- List<string> strings = new List<string>(1 + args.Length);
348
- strings.Add(longName);
349
- strings.AddRange(args);
350
-
351
- // prepare for hashing
352
- string stringData = String.Join("|", strings);
353
- byte[] data = Encoding.UTF8.GetBytes(stringData);
354
-
355
- // hash the data
356
- byte[] hash;
357
- using (SHA1 sha1 = new SHA1CryptoServiceProvider())
358
- {
359
- hash = sha1.ComputeHash(data);
360
- }
361
-
362
- // generate the short file/directory name without an extension
363
- StringBuilder shortName = new StringBuilder(Convert.ToBase64String(hash));
364
- shortName.Remove(8, shortName.Length - 8).Replace('+', '-').Replace('/', '_');
365
-
366
- if (keepExtension)
367
- {
368
- string extension = Path.GetExtension(longName);
369
-
370
- if (4 < extension.Length)
371
- {
372
- extension = extension.Substring(0, 4);
373
- }
374
-
375
- shortName.Append(extension);
376
-
377
- // check the generated short name to ensure its still legal (the extension may not be legal)
378
- if (!this.IsValidShortFilename(shortName.ToString(), allowWildcards))
379
- {
380
- // remove the extension (by truncating the generated file name back to the generated characters)
381
- shortName.Length -= extension.Length;
382
- }
383
- }
384
-
385
- return shortName.ToString().ToLowerInvariant();
283
+ return this.parseHelper.CreateShortName(longName, keepExtension, allowWildcards, args);
284
}
285
286
/// <summary>
@@ -422,8 +320,7 @@ namespace WixToolset
320
/// <returns>The node's inner text trimmed.</returns>
321
public string GetTrimmedInnerText(XElement element)
322
{
425
- string value = Common.GetInnerText(element);
426
- return (null == value) ? null : value.Trim();
323
+ return this.parseHelper.GetTrimmedInnerText(element);
324
}
325
326
/// <summary>
@@ -431,23 +328,9 @@ namespace WixToolset
328
/// </summary>
329
/// <param name="element">The element to ensure inner text is a condition.</param>
330
/// <returns>The value converted into a safe condition.</returns>
434
- [SuppressMessage("Microsoft.Design", "CA1059:MembersShouldNotExposeCertainConcreteTypes")]
331
public string GetConditionInnerText(XElement element)
332
{
437
- string value = element.Value;
438
- if (0 < value.Length)
439
- {
440
- value = value.Trim();
441
- value = value.Replace('\t', ' ');
442
- value = value.Replace('\r', ' ');
443
- value = value.Replace('\n', ' ');
444
- }
445
- else // return null for a non-existant condition
446
- {
447
- value = null;
448
- }
449
-
450
- return value;
333
+ return this.parseHelper.GetConditionInnerText(element);
334
}
335
336
/// <summary>
@@ -458,7 +341,7 @@ namespace WixToolset
341
/// <returns>The generated GUID for the given namespace and value.</returns>
342
public string CreateGuid(Guid namespaceGuid, string value)
343
{
461
- return Uuid.NewUuid(namespaceGuid, value).ToString("B").ToUpperInvariant();
344
+ return this.parseHelper.CreateGuid(namespaceGuid, value);
345
}
346
347
/// <summary>
@@ -510,46 +393,7 @@ namespace WixToolset
393
/// <returns>Identifier of the leaf directory created.</returns>
394
public string CreateDirectoryReferenceFromInlineSyntax(SourceLineNumber sourceLineNumbers, XAttribute attribute, string parentId)
395
{
513
- string id = null;
514
- string[] inlineSyntax = this.GetAttributeInlineDirectorySyntax(sourceLineNumbers, attribute, true);
515
-
516
- if (null != inlineSyntax)
517
- {
518
- // Special case the single entry in the inline syntax since it is the most common case
519
- // and needs no extra processing. It's just a reference to an existing directory.
520
- if (1 == inlineSyntax.Length)
521
- {
522
- id = inlineSyntax[0];
523
- this.CreateSimpleReference(sourceLineNumbers, "Directory", id);
524
- }
525
- else // start creating rows for the entries in the inline syntax
526
- {
527
- id = parentId;
528
-
529
- int pathStartsAt = 0;
530
- if (inlineSyntax[0].EndsWith(":"))
531
- {
532
- // TODO: should overriding the parent identifier with a specific id be an error or a warning or just let it slide?
533
- //if (null != parentId)
534
- //{
535
- // this.core.OnMessage(WixErrors.Xxx(sourceLineNumbers));
536
- //}
537
-
538
- id = inlineSyntax[0].TrimEnd(':');
539
- this.CreateSimpleReference(sourceLineNumbers, "Directory", id);
540
-
541
- pathStartsAt = 1;
542
- }
543
-
544
- for (int i = pathStartsAt; i < inlineSyntax.Length; ++i)
545
- {
546
- Identifier inlineId = this.CreateDirectoryRow(sourceLineNumbers, null, id, inlineSyntax[i]);
547
- id = inlineId.Id;
548
- }
549
- }
550
- }
551
-
552
- return id;
396
+ return this.parseHelper.CreateDirectoryReferenceFromInlineSyntax(this.ActiveSection, sourceLineNumbers, attribute, parentId);
397
}
398
399
/// <summary>
@@ -566,56 +410,6 @@ namespace WixToolset
410
patchReferenceRow.Set(1, String.Join("/", primaryKeys));
411
}
412
569
- /// <summary>
570
- /// Creates a Registry row in the active section.
571
- /// </summary>
572
- /// <param name="sourceLineNumbers">Source and line number of the current row.</param>
573
- /// <param name="root">The registry entry root.</param>
574
- /// <param name="key">The registry entry key.</param>
575
- /// <param name="name">The registry entry name.</param>
576
- /// <param name="value">The registry entry value.</param>
577
- /// <param name="componentId">The component which will control installation/uninstallation of the registry entry.</param>
578
- /// <param name="escapeLeadingHash">If true, "escape" leading '#' characters so the value is written as a REG_SZ.</param>
579
- public Identifier CreateRegistryRow(SourceLineNumber sourceLineNumbers, int root, string key, string name, string value, string componentId, bool escapeLeadingHash)
580
- {
581
- Identifier id = null;
582
-
583
- if (!this.EncounteredError)
584
- {
585
- if (-1 > root || 3 < root)
586
- {
587
- throw new ArgumentOutOfRangeException("root");
588
- }
589
-
590
- if (null == key)
591
- {
592
- throw new ArgumentNullException("key");
593
- }
594
-
595
- if (null == componentId)
596
- {
597
- throw new ArgumentNullException("componentId");
598
- }
599
-
600
- // escape the leading '#' character for string registry values
601
- if (escapeLeadingHash && null != value && value.StartsWith("#", StringComparison.Ordinal))
602
- {
603
- value = String.Concat("#", value);
604
- }
605
-
606
- id = this.CreateIdentifier("reg", componentId, root.ToString(CultureInfo.InvariantCulture.NumberFormat), key.ToLowerInvariant(), (null != name ? name.ToLowerInvariant() : name));
607
-
608
- var row = this.CreateRow(sourceLineNumbers, TupleDefinitionType.Registry, id);
609
- row.Set(1, root);
610
- row.Set(2, key);
611
- row.Set(3, name);
612
- row.Set(4, value);
613
- row.Set(5, componentId);
614
- }
615
-
616
- return id;
617
- }
618
-
413
/// <summary>
414
/// Creates a Registry row in the active section.
415
/// </summary>
@@ -627,7 +421,7 @@ namespace WixToolset
421
/// <param name="componentId">The component which will control installation/uninstallation of the registry entry.</param>
422
public Identifier CreateRegistryRow(SourceLineNumber sourceLineNumbers, int root, string key, string name, string value, string componentId)
423
{
630
- return this.CreateRegistryRow(sourceLineNumbers, root, key, name, value, componentId, true);
424
+ return this.parseHelper.CreateRegistryRow(this.ActiveSection, sourceLineNumbers, root, key, name, value, componentId, true);
425
}
426
427
/// <summary>
@@ -646,9 +440,7 @@ namespace WixToolset
440
// If this simple reference hasn't been added to the active section already, add it.
441
if (this.activeSectionSimpleReferences.Add(id))
442
{
649
- var wixSimpleReferenceRow = (WixSimpleReferenceTuple)this.CreateRow(sourceLineNumbers, TupleDefinitionType.WixSimpleReference);
650
- wixSimpleReferenceRow.Table = tableName;
651
- wixSimpleReferenceRow.PrimaryKeys = joinedKeys;
443
+ this.parseHelper.CreateSimpleReference(this.ActiveSection, sourceLineNumbers, tableName, primaryKeys);
444
}
445
}
446
}
@@ -665,21 +457,7 @@ namespace WixToolset
457
{
458
if (!this.EncounteredError)
459
{
668
- if (null == parentId || ComplexReferenceParentType.Unknown == parentType)
669
- {
670
- return;
671
- }
672
-
673
- if (null == childId)
674
- {
675
- throw new ArgumentNullException("childId");
676
- }
677
-
678
- var row = (WixGroupTuple)this.CreateRow(sourceLineNumbers, TupleDefinitionType.WixGroup);
679
- row.ParentId = parentId;
680
- row.ParentType = parentType;
681
- row.ChildId = childId;
682
- row.ChildType = childType;
460
+ this.parseHelper.CreateWixGroupRow(this.ActiveSection, sourceLineNumbers, parentType, parentId, childType, childId);
461
}
462
}
463
@@ -693,16 +471,7 @@ namespace WixToolset
471
{
472
if (!this.EncounteredError)
473
{
696
- var row = this.CreateRow(sourceLineNumbers, TupleDefinitionType.WixEnsureTable);
697
- row.Set(0, tableName);
698
-
699
- // We don't add custom table definitions to the tableDefinitions collection,
700
- // so if it's not in there, it better be a custom table. If the Id is just wrong,
701
- // instead of a custom table, we get an unresolved reference at link time.
702
- if (!this.creator.TryGetTupleDefinitionByName(tableName, out var ignored))
703
- {
704
- this.CreateSimpleReference(sourceLineNumbers, "WixCustomTable", tableName);
705
- }
474
+ this.parseHelper.EnsureTable(this.ActiveSection, sourceLineNumbers, tableName);
475
}
476
}
477
@@ -716,7 +485,7 @@ namespace WixToolset
485
[SuppressMessage("Microsoft.Design", "CA1059:MembersShouldNotExposeCertainConcreteTypes")]
486
public string GetAttributeValue(SourceLineNumber sourceLineNumbers, XAttribute attribute, EmptyRule emptyRule = EmptyRule.CanBeWhitespaceOnly)
487
{
719
- return Common.GetAttributeValue(sourceLineNumbers, attribute, emptyRule);
488
+ return this.parseHelper.GetAttributeValue(sourceLineNumbers, attribute, emptyRule);
489
}
490
491
/// <summary>
@@ -800,7 +569,7 @@ namespace WixToolset
569
[SuppressMessage("Microsoft.Design", "CA1059:MembersShouldNotExposeCertainConcreteTypes")]
570
public int GetAttributeIntegerValue(SourceLineNumber sourceLineNumbers, XAttribute attribute, int minimum, int maximum)
571
{
803
- return Common.GetAttributeIntegerValue(sourceLineNumbers, attribute, minimum, maximum);
572
+ return this.parseHelper.GetAttributeIntegerValue(sourceLineNumbers, attribute, minimum, maximum);
573
}
574
575
/// <summary>
@@ -813,39 +582,7 @@ namespace WixToolset
582
/// <returns>The attribute's long value or a special value if an error occurred during conversion.</returns>
583
public long GetAttributeLongValue(SourceLineNumber sourceLineNumbers, XAttribute attribute, long minimum, long maximum)
584
{
816
- Debug.Assert(minimum > CompilerConstants.LongNotSet && minimum > CompilerConstants.IllegalLong, "The legal values for this attribute collide with at least one sentinel used during parsing.");
817
-
818
- string value = this.GetAttributeValue(sourceLineNumbers, attribute);
819
-
820
- if (0 < value.Length)
821
- {
822
- try
823
- {
824
- long longValue = Convert.ToInt64(value, CultureInfo.InvariantCulture.NumberFormat);
825
-
826
- if (CompilerConstants.LongNotSet == longValue || CompilerConstants.IllegalLong == longValue)
827
- {
828
- this.OnMessage(WixErrors.IntegralValueSentinelCollision(sourceLineNumbers, longValue));
829
- }
830
- else if (minimum > longValue || maximum < longValue)
831
- {
832
- this.OnMessage(WixErrors.IntegralValueOutOfRange(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, longValue, minimum, maximum));
833
- longValue = CompilerConstants.IllegalLong;
834
- }
835
-
836
- return longValue;
837
- }
838
- catch (FormatException)
839
- {
840
- this.OnMessage(WixErrors.IllegalLongValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
841
- }
842
- catch (OverflowException)
843
- {
844
- this.OnMessage(WixErrors.IllegalLongValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
845
- }
846
- }
847
-
848
- return CompilerConstants.IllegalLong;
585
+ return this.parseHelper.GetAttributeLongValue(sourceLineNumbers, attribute, minimum, maximum);
586
}
587
588
/// <summary>
@@ -956,73 +693,9 @@ namespace WixToolset
693
/// <param name="generatable">Determines whether the guid can be automatically generated.</param>
694
/// <param name="canBeEmpty">If true, no error is raised on empty value. If false, an error is raised.</param>
695
/// <returns>The attribute's guid value or a special value if an error occurred.</returns>
959
- [SuppressMessage("Microsoft.Design", "CA1059:MembersShouldNotExposeCertainConcreteTypes")]
960
- [SuppressMessage("Microsoft.Performance", "CA1807:AvoidUnnecessaryStringCreation")]
696
public string GetAttributeGuidValue(SourceLineNumber sourceLineNumbers, XAttribute attribute, bool generatable = false, bool canBeEmpty = false)
697
{
963
- if (null == attribute)
964
- {
965
- throw new ArgumentNullException("attribute");
966
- }
967
-
968
- EmptyRule emptyRule = canBeEmpty ? EmptyRule.CanBeEmpty : EmptyRule.CanBeWhitespaceOnly;
969
- string value = this.GetAttributeValue(sourceLineNumbers, attribute, emptyRule);
970
-
971
- if (String.IsNullOrEmpty(value) && canBeEmpty)
972
- {
973
- return String.Empty;
974
- }
975
- else if (!String.IsNullOrEmpty(value))
976
- {
977
- // If the value starts and ends with braces or parenthesis, accept that and strip them off.
978
- if ((value.StartsWith("{", StringComparison.Ordinal) && value.EndsWith("}", StringComparison.Ordinal))
979
- || (value.StartsWith("(", StringComparison.Ordinal) && value.EndsWith(")", StringComparison.Ordinal)))
980
- {
981
- value = value.Substring(1, value.Length - 2);
982
- }
983
-
984
- try
985
- {
986
- Guid guid;
987
-
988
- if (generatable && "*".Equals(value, StringComparison.Ordinal))
989
- {
990
- return value;
991
- }
992
-
993
- if (CompilerCore.PutGuidHere.IsMatch(value))
994
- {
995
- this.OnMessage(WixErrors.ExampleGuid(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
996
- return CompilerConstants.IllegalGuid;
997
- }
998
- else if (value.StartsWith("!(loc", StringComparison.Ordinal) || value.StartsWith("$(loc", StringComparison.Ordinal) || value.StartsWith("!(wix", StringComparison.Ordinal))
999
- {
1000
- return value;
1001
- }
1002
- else
1003
- {
1004
- guid = new Guid(value);
1005
- }
1006
-
1007
- string uppercaseGuid = guid.ToString().ToUpper(CultureInfo.InvariantCulture);
1008
-
1009
- if (this.ShowPedanticMessages)
1010
- {
1011
- if (uppercaseGuid != value)
1012
- {
1013
- this.OnMessage(WixErrors.GuidContainsLowercaseLetters(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
1014
- }
1015
- }
1016
-
1017
- return String.Concat("{", uppercaseGuid, "}");
1018
- }
1019
- catch (FormatException)
1020
- {
1021
- this.OnMessage(WixErrors.IllegalGuidValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
1022
- }
1023
- }
1024
-
1025
- return CompilerConstants.IllegalGuid;
698
+ return this.parseHelper.GetAttributeGuidValue(sourceLineNumbers, attribute, generatable, canBeEmpty);
699
}
700
701
/// <summary>
@@ -1033,27 +706,7 @@ namespace WixToolset
706
/// <returns>The attribute's identifier value or a special value if an error occurred.</returns>
707
public Identifier GetAttributeIdentifier(SourceLineNumber sourceLineNumbers, XAttribute attribute)
708
{
1036
- string value = Common.GetAttributeValue(sourceLineNumbers, attribute, EmptyRule.CanBeEmpty);
1037
- AccessModifier access = AccessModifier.Public;
1038
-
1039
- Match match = CompilerCore.LegalIdentifierWithAccess.Match(value);
1040
- if (!match.Success)
1041
- {
1042
- return null;
1043
- }
1044
- else if (match.Groups["access"].Success)
1045
- {
1046
- access = (AccessModifier)Enum.Parse(typeof(AccessModifier), match.Groups["access"].Value, true);
1047
- }
1048
-
1049
- value = match.Groups["id"].Value;
1050
-
1051
- if (Common.IsIdentifier(value) && 72 < value.Length)
1052
- {
1053
- this.OnMessage(WixWarnings.IdentifierTooLong(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
1054
- }
1055
-
1056
- return new Identifier(value, access);
709
+ return this.parseHelper.GetAttributeIdentifier(sourceLineNumbers, attribute);
710
}
711
712
/// <summary>
@@ -1064,7 +717,7 @@ namespace WixToolset
717
/// <returns>The attribute's identifier value or a special value if an error occurred.</returns>
718
public string GetAttributeIdentifierValue(SourceLineNumber sourceLineNumbers, XAttribute attribute)
719
{
1067
- return Common.GetAttributeIdentifierValue(sourceLineNumbers, attribute);
720
+ return this.parseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attribute);
721
}
722
723
/// <summary>
@@ -1075,23 +728,7 @@ namespace WixToolset
728
/// <returns>The attribute's YesNoType value.</returns>
729
public YesNoType GetAttributeYesNoValue(SourceLineNumber sourceLineNumbers, XAttribute attribute)
730
{
1078
- string value = this.GetAttributeValue(sourceLineNumbers, attribute);
1079
-
1080
- YesNoType result = YesNoType.IllegalValue;
1081
- if (value.Equals("yes") || value.Equals("true"))
1082
- {
1083
- result = YesNoType.Yes;
1084
- }
1085
- else if (value.Equals("no") || value.Equals("false"))
1086
- {
1087
- result = YesNoType.No;
1088
- }
1089
- else
1090
- {
1091
- this.OnMessage(WixErrors.IllegalYesNoValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
1092
- }
1093
-
1094
- return result;
731
+ return this.parseHelper.GetAttributeYesNoValue(sourceLineNumbers, attribute);
732
}
733
734
/// <summary>
@@ -1103,28 +740,7 @@ namespace WixToolset
740
[SuppressMessage("Microsoft.Design", "CA1059:MembersShouldNotExposeCertainConcreteTypes")]
741
public YesNoDefaultType GetAttributeYesNoDefaultValue(SourceLineNumber sourceLineNumbers, XAttribute attribute)
742
{
1106
- string value = this.GetAttributeValue(sourceLineNumbers, attribute);
1107
-
1108
- if (0 < value.Length)
1109
- {
1110
- switch (Wix.Enums.ParseYesNoDefaultType(value))
1111
- {
1112
- case Wix.YesNoDefaultType.@default:
1113
- return YesNoDefaultType.Default;
1114
- case Wix.YesNoDefaultType.no:
1115
- return YesNoDefaultType.No;
1116
- case Wix.YesNoDefaultType.yes:
1117
- return YesNoDefaultType.Yes;
1118
- case Wix.YesNoDefaultType.NotSet:
1119
- // Previous code never returned 'NotSet'!
1120
- break;
1121
- default:
1122
- this.OnMessage(WixErrors.IllegalYesNoDefaultValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
1123
- break;
1124
- }
1125
- }
1126
-
1127
- return YesNoDefaultType.IllegalValue;
743
+ return this.parseHelper.GetAttributeYesNoDefaultValue(sourceLineNumbers, attribute);
744
}
745
746
/// <summary>
@@ -1202,41 +818,7 @@ namespace WixToolset
818
[SuppressMessage("Microsoft.Design", "CA1059:MembersShouldNotExposeCertainConcreteTypes")]
819
public string GetAttributeLongFilename(SourceLineNumber sourceLineNumbers, XAttribute attribute, bool allowWildcards = false, bool allowRelative = false)
820
{
1205
- if (null == attribute)
1206
- {
1207
- throw new ArgumentNullException("attribute");
1208
- }
1209
-
1210
- string value = this.GetAttributeValue(sourceLineNumbers, attribute);
1211
-
1212
- if (0 < value.Length)
1213
- {
1214
- if (!this.IsValidLongFilename(value, allowWildcards, allowRelative) && !this.IsValidLocIdentifier(value))
1215
- {
1216
- if (allowRelative)
1217
- {
1218
- this.OnMessage(WixErrors.IllegalRelativeLongFilename(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
1219
- }
1220
- else
1221
- {
1222
- this.OnMessage(WixErrors.IllegalLongFilename(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
1223
- }
1224
- }
1225
- else if (allowRelative)
1226
- {
1227
- string normalizedPath = value.Replace('\\', '/');
1228
- if (normalizedPath.StartsWith("../", StringComparison.Ordinal) || normalizedPath.Contains("/../"))
1229
- {
1230
- this.OnMessage(WixErrors.PayloadMustBeRelativeToCache(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
1231
- }
1232
- }
1233
- else if (CompilerCore.IsAmbiguousFilename(value))
1234
- {
1235
- this.OnMessage(WixWarnings.AmbiguousFileOrDirectoryName(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
1236
- }
1237
- }
1238
-
1239
- return value;
821
+ return this.parseHelper.GetAttributeLongFilename(sourceLineNumbers, attribute, allowWildcards, allowRelative);
822
}
823
824
/// <summary>
@@ -1247,31 +829,7 @@ namespace WixToolset
829
/// <returns>The attribute's version value.</returns>
830
public string GetAttributeVersionValue(SourceLineNumber sourceLineNumbers, XAttribute attribute)
831
{
1250
- string value = this.GetAttributeValue(sourceLineNumbers, attribute);
1251
-
1252
- if (!String.IsNullOrEmpty(value))
1253
- {
1254
- try
1255
- {
1256
- return new Version(value).ToString();
1257
- }
1258
- catch (FormatException) // illegal integer in version
1259
- {
1260
- // Allow versions to contain binder variables.
1261
- if (Common.ContainsValidBinderVariable(value))
1262
- {
1263
- return value;
1264
- }
1265
-
1266
- this.OnMessage(WixErrors.IllegalVersionValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
1267
- }
1268
- catch (ArgumentException)
1269
- {
1270
- this.OnMessage(WixErrors.IllegalVersionValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
1271
- }
1272
- }
1273
-
1274
- return null;
832
+ return this.parseHelper.GetAttributeVersionValue(sourceLineNumbers, attribute);
833
}
834
835
/// <summary>
@@ -1453,7 +1011,7 @@ namespace WixToolset
1011
/// <returns>True if a property is found in the string.</returns>
1012
public bool ContainsProperty(string possibleProperty)
1013
{
1456
- return Common.ContainsProperty(possibleProperty);
1014
+ return this.parseHelper.ContainsProperty(possibleProperty);
1015
}
1016
1017
/// <summary>
@@ -1465,8 +1023,7 @@ namespace WixToolset
1023
[SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters", MessageId = "System.InvalidOperationException.#ctor(System.String)")]
1024
public Identifier CreateIdentifier(string prefix, params string[] args)
1025
{
1468
- string id = Common.GenerateIdentifier(prefix, args);
1469
- return new Identifier(id, AccessModifier.Private);
1026
+ return this.parseHelper.CreateIdentifier(prefix, args);
1027
}
1028
1029
/// <summary>
@@ -1476,8 +1033,7 @@ namespace WixToolset
1033
/// <returns></returns>
1034
public Identifier CreateIdentifierFromFilename(string filename)
1035
{
1479
- string id = Common.GetIdentifierFromName(filename);
1480
- return new Identifier(id, AccessModifier.Private);
1036
+ return this.parseHelper.CreateIdentifierFromFilename(filename);
1037
}
1038
1039
/// <summary>
@@ -1488,22 +1044,7 @@ namespace WixToolset
1044
/// <param name="context">Extra information about the context in which this element is being parsed.</param>
1045
public void ParseExtensionAttribute(XElement element, XAttribute attribute, IDictionary<string, string> context = null)
1046
{
1491
- // Ignore attributes defined by the W3C because we'll assume they are always right.
1492
- if ((String.IsNullOrEmpty(attribute.Name.NamespaceName) && attribute.Name.LocalName.Equals("xmlns", StringComparison.Ordinal)) ||
1493
- attribute.Name.NamespaceName.StartsWith(CompilerCore.W3SchemaPrefix.NamespaceName, StringComparison.Ordinal))
1494
- {
1495
- return;
1496
- }
1497
-
1498
- if (this.TryFindExtension(attribute.Name.NamespaceName, out var extension))
1499
- {
1500
- extension.ParseAttribute(element, attribute, context);
1501
- }
1502
- else
1503
- {
1504
- SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(element);
1505
- this.OnMessage(WixErrors.UnhandledExtensionAttribute(sourceLineNumbers, element.Name.LocalName, attribute.Name.LocalName, attribute.Name.NamespaceName));
1506
- }
1047
+ this.parseHelper.ParseExtensionAttribute(this.extensions.Values, this.intermediate, this.ActiveSection, element, attribute, context);
1048
}
1049
1050
/// <summary>
@@ -1514,16 +1055,7 @@ namespace WixToolset
1055
/// <param name="context">Extra information about the context in which this element is being parsed.</param>
1056
public void ParseExtensionElement(XElement parentElement, XElement element, IDictionary<string, string> context = null)
1057
{
1517
- if (this.TryFindExtension(element.Name.Namespace, out var extension))
1518
- {
1519
- SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(parentElement);
1520
- extension.ParseElement(parentElement, element, context);
1521
- }
1522
- else
1523
- {
1524
- SourceLineNumber childSourceLineNumbers = Preprocessor.GetSourceLineNumbers(element);
1525
- this.OnMessage(WixErrors.UnhandledExtensionElement(childSourceLineNumbers, parentElement.Name.LocalName, element.Name.LocalName, element.Name.NamespaceName));
1526
- }
1058
+ this.parseHelper.ParseExtensionElement(this.extensions.Values, this.intermediate, this.ActiveSection, parentElement, element, context);
1059
}
1060
1061
/// <summary>
@@ -1532,17 +1064,7 @@ namespace WixToolset
1064
/// <param name="element">Element to parse children.</param>
1065
public void ParseForExtensionElements(XElement element)
1066
{
1535
- foreach (XElement child in element.Elements())
1536
- {
1537
- if (element.Name.Namespace == child.Name.Namespace)
1538
- {
1539
- this.UnexpectedElement(element, child);
1540
- }
1541
- else
1542
- {
1543
- this.ParseExtensionElement(element, child);
1544
- }
1545
- }
1067
+ this.parseHelper.ParseForExtensionElements(this.extensions.Values, this.intermediate, this.ActiveSection, element);
1068
}
1069
1070
/// <summary>
@@ -1553,20 +1075,7 @@ namespace WixToolset
1075
/// <param name="contextValues">Extra information about the context in which this element is being parsed.</param>
1076
public ComponentKeyPath ParsePossibleKeyPathExtensionElement(XElement parentElement, XElement element, IDictionary<string, string> context)
1077
{
1556
- ComponentKeyPath keyPath = null;
1557
-
1558
- ICompilerExtension extension;
1559
- if (this.TryFindExtension(element.Name.Namespace, out extension))
1560
- {
1561
- keyPath = extension.ParsePossibleKeyPathElement(parentElement, element, context);
1562
- }
1563
- else
1564
- {
1565
- SourceLineNumber childSourceLineNumbers = Preprocessor.GetSourceLineNumbers(element);
1566
- this.OnMessage(WixErrors.UnhandledExtensionElement(childSourceLineNumbers, parentElement.Name.LocalName, element.Name.LocalName, element.Name.NamespaceName));
1567
- }
1568
-
1569
- return keyPath;
1078
+ return this.parseHelper.ParsePossibleKeyPathExtensionElement(this.extensions.Values, this.intermediate, this.ActiveSection, parentElement, element, context);
1079
}
1080
1081
/// <summary>
@@ -1576,8 +1085,7 @@ namespace WixToolset
1085
/// <param name="attribute">The unexpected attribute.</param>
1086
public void UnexpectedAttribute(XElement element, XAttribute attribute)
1087
{
1579
- SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(element);
1580
- Common.UnexpectedAttribute(sourceLineNumbers, attribute);
1088
+ this.parseHelper.UnexpectedAttribute(element, attribute);
1089
}
1090
1091
/// <summary>
@@ -1587,9 +1095,7 @@ namespace WixToolset
1095
/// <param name="childElement">The unexpected child element.</param>
1096
public void UnexpectedElement(XElement parentElement, XElement childElement)
1097
{
1590
- SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(childElement);
1591
-
1592
- this.OnMessage(WixErrors.UnexpectedElement(sourceLineNumbers, parentElement.Name.LocalName, childElement.Name.LocalName));
1098
+ this.parseHelper.UnexpectedElement(parentElement, childElement);
1099
}
1100
1101
/// <summary>
@@ -1666,30 +1172,6 @@ namespace WixToolset
1172
return section;
1173
}
1174
1669
- /// <summary>
1670
- /// Creates a WiX complex reference in the active section.
1671
- /// </summary>
1672
- /// <param name="sourceLineNumbers">Source line information.</param>
1673
- /// <param name="parentType">The parent type.</param>
1674
- /// <param name="parentId">The parent id.</param>
1675
- /// <param name="parentLanguage">The parent language.</param>
1676
- /// <param name="childType">The child type.</param>
1677
- /// <param name="childId">The child id.</param>
1678
- /// <param name="isPrimary">Whether the child is primary.</param>
1679
- internal void CreateWixComplexReferenceRow(SourceLineNumber sourceLineNumbers, ComplexReferenceParentType parentType, string parentId, string parentLanguage, ComplexReferenceChildType childType, string childId, bool isPrimary)
1680
- {
1681
- if (!this.EncounteredError)
1682
- {
1683
- var wixComplexReferenceRow = (WixComplexReferenceTuple)this.CreateRow(sourceLineNumbers, TupleDefinitionType.WixComplexReference);
1684
- wixComplexReferenceRow.Parent = parentId;
1685
- wixComplexReferenceRow.ParentType = parentType;
1686
- wixComplexReferenceRow.ParentLanguage = parentLanguage;
1687
- wixComplexReferenceRow.Child = childId;
1688
- wixComplexReferenceRow.ChildType = childType;
1689
- wixComplexReferenceRow.IsPrimary = isPrimary;
1690
- }
1691
- }
1692
-
1175
/// <summary>
1176
/// Creates WixComplexReference and WixGroup rows in the active section.
1177
/// </summary>
@@ -1702,8 +1184,7 @@ namespace WixToolset
1184
/// <param name="isPrimary">Whether the child is primary.</param>
1185
public void CreateComplexReference(SourceLineNumber sourceLineNumbers, ComplexReferenceParentType parentType, string parentId, string parentLanguage, ComplexReferenceChildType childType, string childId, bool isPrimary)
1186
{
1705
- this.CreateWixComplexReferenceRow(sourceLineNumbers, parentType, parentId, parentLanguage, childType, childId, isPrimary);
1706
- this.CreateWixGroupRow(sourceLineNumbers, parentType, parentId, childType, childId);
1187
+ this.parseHelper.CreateComplexReference(this.ActiveSection, sourceLineNumbers, parentType, parentId, parentLanguage, childType, childId, isPrimary);
1188
}
1189
1190
/// <summary>
@@ -1719,56 +1200,57 @@ namespace WixToolset
1200
/// <returns>Identifier for the newly created row.</returns>
1201
internal Identifier CreateDirectoryRow(SourceLineNumber sourceLineNumbers, Identifier id, string parentId, string name, string shortName = null, string sourceName = null, string shortSourceName = null)
1202
{
1722
- string defaultDir = null;
1723
-
1724
- if (name.Equals("SourceDir") || this.IsValidShortFilename(name, false))
1725
- {
1726
- defaultDir = name;
1727
- }
1728
- else
1729
- {
1730
- if (String.IsNullOrEmpty(shortName))
1731
- {
1732
- shortName = this.CreateShortName(name, false, false, "Directory", parentId);
1733
- }
1734
-
1735
- defaultDir = String.Concat(shortName, "|", name);
1736
- }
1737
-
1738
- if (!String.IsNullOrEmpty(sourceName))
1739
- {
1740
- if (this.IsValidShortFilename(sourceName, false))
1741
- {
1742
- defaultDir = String.Concat(defaultDir, ":", sourceName);
1743
- }
1744
- else
1745
- {
1746
- if (String.IsNullOrEmpty(shortSourceName))
1747
- {
1748
- shortSourceName = this.CreateShortName(sourceName, false, false, "Directory", parentId);
1749
- }
1750
-
1751
- defaultDir = String.Concat(defaultDir, ":", shortSourceName, "|", sourceName);
1752
- }
1753
- }
1754
-
1755
- // For anonymous directories, create the identifier. If this identifier already exists in the
1756
- // active section, bail so we don't add duplicate anonymous directory rows (which are legal
1757
- // but bloat the intermediate and ultimately make the linker do "busy work").
1758
- if (null == id)
1759
- {
1760
- id = this.CreateIdentifier("dir", parentId, name, shortName, sourceName, shortSourceName);
1761
-
1762
- if (!this.activeSectionInlinedDirectoryIds.Add(id.Id))
1763
- {
1764
- return id;
1765
- }
1766
- }
1767
-
1768
- var row = this.CreateRow(sourceLineNumbers, TupleDefinitionType.Directory, id);
1769
- row.Set(1, parentId);
1770
- row.Set(2, defaultDir);
1771
- return id;
1203
+ //string defaultDir = null;
1204
+
1205
+ //if (name.Equals("SourceDir") || this.IsValidShortFilename(name, false))
1206
+ //{
1207
+ // defaultDir = name;
1208
+ //}
1209
+ //else
1210
+ //{
1211
+ // if (String.IsNullOrEmpty(shortName))
1212
+ // {
1213
+ // shortName = this.CreateShortName(name, false, false, "Directory", parentId);
1214
+ // }
1215
+
1216
+ // defaultDir = String.Concat(shortName, "|", name);
1217
+ //}
1218
+
1219
+ //if (!String.IsNullOrEmpty(sourceName))
1220
+ //{
1221
+ // if (this.IsValidShortFilename(sourceName, false))
1222
+ // {
1223
+ // defaultDir = String.Concat(defaultDir, ":", sourceName);
1224
+ // }
1225
+ // else
1226
+ // {
1227
+ // if (String.IsNullOrEmpty(shortSourceName))
1228
+ // {
1229
+ // shortSourceName = this.CreateShortName(sourceName, false, false, "Directory", parentId);
1230
+ // }
1231
+
1232
+ // defaultDir = String.Concat(defaultDir, ":", shortSourceName, "|", sourceName);
1233
+ // }
1234
+ //}
1235
+
1236
+ //// For anonymous directories, create the identifier. If this identifier already exists in the
1237
+ //// active section, bail so we don't add duplicate anonymous directory rows (which are legal
1238
+ //// but bloat the intermediate and ultimately make the linker do "busy work").
1239
+ //if (null == id)
1240
+ //{
1241
+ // id = this.CreateIdentifier("dir", parentId, name, shortName, sourceName, shortSourceName);
1242
+
1243
+ // if (!this.activeSectionInlinedDirectoryIds.Add(id.Id))
1244
+ // {
1245
+ // return id;
1246
+ // }
1247
+ //}
1248
+
1249
+ //var row = this.CreateRow(sourceLineNumbers, TupleDefinitionType.Directory, id);
1250
+ //row.Set(1, parentId);
1251
+ //row.Set(2, defaultDir);
1252
+ //return id;
1253
+ return this.parseHelper.CreateDirectoryRow(this.ActiveSection, sourceLineNumbers, id, parentId, name, shortName, sourceName, shortSourceName, this.activeSectionInlinedDirectoryIds);
1254
}
1255
1256
/// <summary>
@@ -1780,65 +1262,7 @@ namespace WixToolset
1262
/// <returns>Inline directory syntax split into array of strings or null if the syntax did not parse.</returns>
1263
internal string[] GetAttributeInlineDirectorySyntax(SourceLineNumber sourceLineNumbers, XAttribute attribute, bool resultUsedToCreateReference = false)
1264
{
1783
- string[] result = null;
1784
- string value = this.GetAttributeValue(sourceLineNumbers, attribute);
1785
-
1786
- if (!String.IsNullOrEmpty(value))
1787
- {
1788
- int pathStartsAt = 0;
1789
- result = value.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries);
1790
- if (result[0].EndsWith(":", StringComparison.Ordinal))
1791
- {
1792
- string id = result[0].TrimEnd(':');
1793
- if (1 == result.Length)
1794
- {
1795
- this.OnMessage(WixErrors.InlineDirectorySyntaxRequiresPath(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value, id));
1796
- return null;
1797
- }
1798
- else if (!this.IsValidIdentifier(id))
1799
- {
1800
- this.OnMessage(WixErrors.IllegalIdentifier(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value, id));
1801
- return null;
1802
- }
1803
-
1804
- pathStartsAt = 1;
1805
- }
1806
- else if (resultUsedToCreateReference && 1 == result.Length)
1807
- {
1808
- if (value.EndsWith("\\"))
1809
- {
1810
- if (!this.IsValidLongFilename(result[0]))
1811
- {
1812
- this.OnMessage(WixErrors.IllegalLongFilename(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value, result[0]));
1813
- return null;
1814
- }
1815
- }
1816
- else if (!this.IsValidIdentifier(result[0]))
1817
- {
1818
- this.OnMessage(WixErrors.IllegalIdentifier(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value, result[0]));
1819
- return null;
1820
- }
1821
-
1822
- return result; // return early to avoid additional checks below.
1823
- }
1824
-
1825
- // Check each part of the relative path to ensure that it is a valid directory name.
1826
- for (int i = pathStartsAt; i < result.Length; ++i)
1827
- {
1828
- if (!this.IsValidLongFilename(result[i]))
1829
- {
1830
- this.OnMessage(WixErrors.IllegalLongFilename(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value, result[i]));
1831
- return null;
1832
- }
1833
- }
1834
-
1835
- if (1 < result.Length && !value.EndsWith("\\"))
1836
- {
1837
- this.OnMessage(WixWarnings.BackslashTerminateInlineDirectorySyntax(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
1838
- }
1839
- }
1840
-
1841
- return result;
1265
+ return this.parseHelper.GetAttributeInlineDirectorySyntax(sourceLineNumbers, attribute, resultUsedToCreateReference);
1266
}
1267
1268
/// <summary>
src/WixToolset.Core/Converter.cs
+1
-1
@@ -1,6 +1,6 @@
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
3
+namespace WixToolset.Core
4
{
5
using System;
6
using System.Collections.Generic;
src/WixToolset.Core/Extensibility/HeatExtension.cs
+1
-1
@@ -1,6 +1,6 @@
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.Extensibility
3
+namespace WixToolset.Core.Extensibility
4
{
5
using System;
6
using System.IO;
src/WixToolset.Core/Extensibility/IHeatCore.cs
+1
-1
@@ -1,6 +1,6 @@
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.Extensibility
3
+namespace WixToolset.Core.Extensibility
4
{
5
using WixToolset.Data;
6
src/WixToolset.Core/Extensibility/MutatorExtension.cs
+1
-1
@@ -1,6 +1,6 @@
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.Extensibility
3
+namespace WixToolset.Core.Extensibility
4
{
5
using System;
6
using System.Collections.Generic;
src/WixToolset.Core/ExtensibilityServices/ParseHelper.cs
new
+824
@@ -0,0 +1,824 @@
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.ExtensibilityServices
4
+{
5
+ using System;
6
+ using System.Collections.Generic;
7
+ using System.Diagnostics;
8
+ using System.Globalization;
9
+ using System.IO;
10
+ using System.Security.Cryptography;
11
+ using System.Text;
12
+ using System.Text.RegularExpressions;
13
+ using System.Xml.Linq;
14
+ using WixToolset.Data;
15
+ using WixToolset.Data.Tuples;
16
+ using WixToolset.Extensibility;
17
+ using WixToolset.Extensibility.Services;
18
+
19
+ internal class ParseHelper : IParseHelper
20
+ {
21
+ private const string LegalLongFilenameCharacters = @"[^\\\?|><:/\*""]"; // opposite of illegal above.
22
+ private static readonly Regex LegalLongFilename = new Regex(String.Concat("^", LegalLongFilenameCharacters, @"{1,259}$"), RegexOptions.Compiled);
23
+
24
+ private const string LegalRelativeLongFilenameCharacters = @"[^\?|><:/\*""]"; // (like legal long, but we allow '\') illegal: ? | > < : / * "
25
+ private static readonly Regex LegalRelativeLongFilename = new Regex(String.Concat("^", LegalRelativeLongFilenameCharacters, @"{1,259}$"), RegexOptions.Compiled);
26
+
27
+ private const string LegalWildcardLongFilenameCharacters = @"[^\\|><:/""]"; // illegal: \ | > < : / "
28
+ private static readonly Regex LegalWildcardLongFilename = new Regex(String.Concat("^", LegalWildcardLongFilenameCharacters, @"{1,259}$"));
29
+
30
+ private static readonly Regex LegalIdentifierWithAccess = new Regex(@"^((?<access>public|internal|protected|private)\s+)?(?<id>[_A-Za-z][0-9A-Za-z_\.]*)$", RegexOptions.Compiled | RegexOptions.ExplicitCapture);
31
+
32
+ private static readonly Regex PutGuidHere = new Regex(@"PUT\-GUID\-(?:\d+\-)?HERE", RegexOptions.Singleline);
33
+
34
+ public ParseHelper(IServiceProvider serviceProvider)
35
+ {
36
+ this.ServiceProvider = serviceProvider;
37
+ }
38
+
39
+ private IServiceProvider ServiceProvider { get; }
40
+
41
+ private ITupleDefinitionCreator Creator { get; set; }
42
+
43
+ public bool ContainsProperty(string possibleProperty)
44
+ {
45
+ return Common.ContainsProperty(possibleProperty);
46
+ }
47
+
48
+ public void CreateComplexReference(IntermediateSection section, SourceLineNumber sourceLineNumbers, ComplexReferenceParentType parentType, string parentId, string parentLanguage, ComplexReferenceChildType childType, string childId, bool isPrimary)
49
+ {
50
+ var wixComplexReferenceRow = (WixComplexReferenceTuple)this.CreateRow(section, sourceLineNumbers, TupleDefinitionType.WixComplexReference);
51
+ wixComplexReferenceRow.Parent = parentId;
52
+ wixComplexReferenceRow.ParentType = parentType;
53
+ wixComplexReferenceRow.ParentLanguage = parentLanguage;
54
+ wixComplexReferenceRow.Child = childId;
55
+ wixComplexReferenceRow.ChildType = childType;
56
+ wixComplexReferenceRow.IsPrimary = isPrimary;
57
+
58
+ this.CreateWixGroupRow(section, sourceLineNumbers, parentType, parentId, childType, childId);
59
+ }
60
+
61
+ public Identifier CreateDirectoryRow(IntermediateSection section, SourceLineNumber sourceLineNumbers, Identifier id, string parentId, string name, string shortName = null, string sourceName = null, string shortSourceName = null, ISet<string> sectionInlinedDirectoryIds = null)
62
+ {
63
+ string defaultDir = null;
64
+
65
+ if (name.Equals("SourceDir") || this.IsValidShortFilename(name, false))
66
+ {
67
+ defaultDir = name;
68
+ }
69
+ else
70
+ {
71
+ if (String.IsNullOrEmpty(shortName))
72
+ {
73
+ shortName = this.CreateShortName(name, false, false, "Directory", parentId);
74
+ }
75
+
76
+ defaultDir = String.Concat(shortName, "|", name);
77
+ }
78
+
79
+ if (!String.IsNullOrEmpty(sourceName))
80
+ {
81
+ if (this.IsValidShortFilename(sourceName, false))
82
+ {
83
+ defaultDir = String.Concat(defaultDir, ":", sourceName);
84
+ }
85
+ else
86
+ {
87
+ if (String.IsNullOrEmpty(shortSourceName))
88
+ {
89
+ shortSourceName = this.CreateShortName(sourceName, false, false, "Directory", parentId);
90
+ }
91
+
92
+ defaultDir = String.Concat(defaultDir, ":", shortSourceName, "|", sourceName);
93
+ }
94
+ }
95
+
96
+ // For anonymous directories, create the identifier. If this identifier already exists in the
97
+ // active section, bail so we don't add duplicate anonymous directory rows (which are legal
98
+ // but bloat the intermediate and ultimately make the linker do "busy work").
99
+ if (null == id)
100
+ {
101
+ id = this.CreateIdentifier("dir", parentId, name, shortName, sourceName, shortSourceName);
102
+
103
+ if (!sectionInlinedDirectoryIds.Add(id.Id))
104
+ {
105
+ return id;
106
+ }
107
+ }
108
+
109
+ var row = this.CreateRow(section, sourceLineNumbers, TupleDefinitionType.Directory, id);
110
+ row.Set(1, parentId);
111
+ row.Set(2, defaultDir);
112
+ return id;
113
+ }
114
+
115
+ public string CreateDirectoryReferenceFromInlineSyntax(IntermediateSection section, SourceLineNumber sourceLineNumbers, XAttribute attribute, string parentId)
116
+ {
117
+ string id = null;
118
+ string[] inlineSyntax = this.GetAttributeInlineDirectorySyntax(sourceLineNumbers, attribute, true);
119
+
120
+ if (null != inlineSyntax)
121
+ {
122
+ // Special case the single entry in the inline syntax since it is the most common case
123
+ // and needs no extra processing. It's just a reference to an existing directory.
124
+ if (1 == inlineSyntax.Length)
125
+ {
126
+ id = inlineSyntax[0];
127
+ this.CreateSimpleReference(section, sourceLineNumbers, "Directory", id);
128
+ }
129
+ else // start creating rows for the entries in the inline syntax
130
+ {
131
+ id = parentId;
132
+
133
+ int pathStartsAt = 0;
134
+ if (inlineSyntax[0].EndsWith(":"))
135
+ {
136
+ // TODO: should overriding the parent identifier with a specific id be an error or a warning or just let it slide?
137
+ //if (null != parentId)
138
+ //{
139
+ // this.core.OnMessage(WixErrors.Xxx(sourceLineNumbers));
140
+ //}
141
+
142
+ id = inlineSyntax[0].TrimEnd(':');
143
+ this.CreateSimpleReference(section, sourceLineNumbers, "Directory", id);
144
+
145
+ pathStartsAt = 1;
146
+ }
147
+
148
+ for (int i = pathStartsAt; i < inlineSyntax.Length; ++i)
149
+ {
150
+ Identifier inlineId = this.CreateDirectoryRow(section, sourceLineNumbers, null, id, inlineSyntax[i]);
151
+ id = inlineId.Id;
152
+ }
153
+ }
154
+ }
155
+
156
+ return id;
157
+ }
158
+
159
+ public string CreateGuid(Guid namespaceGuid, string value)
160
+ {
161
+ return Uuid.NewUuid(namespaceGuid, value).ToString("B").ToUpperInvariant();
162
+ }
163
+
164
+ public Identifier CreateIdentifier(string prefix, params string[] args)
165
+ {
166
+ var id = Common.GenerateIdentifier(prefix, args);
167
+ return new Identifier(id, AccessModifier.Private);
168
+ }
169
+
170
+ public Identifier CreateIdentifierFromFilename(string filename)
171
+ {
172
+ var id = Common.GetIdentifierFromName(filename);
173
+ return new Identifier(id, AccessModifier.Private);
174
+ }
175
+
176
+ public Identifier CreateRegistryRow(IntermediateSection section, SourceLineNumber sourceLineNumbers, int root, string key, string name, string value, string componentId, bool escapeLeadingHash)
177
+ {
178
+ Identifier id = null;
179
+
180
+ if (-1 > root || 3 < root)
181
+ {
182
+ throw new ArgumentOutOfRangeException("root");
183
+ }
184
+
185
+ if (null == key)
186
+ {
187
+ throw new ArgumentNullException("key");
188
+ }
189
+
190
+ if (null == componentId)
191
+ {
192
+ throw new ArgumentNullException("componentId");
193
+ }
194
+
195
+ // Escape the leading '#' character for string registry values.
196
+ if (escapeLeadingHash && null != value && value.StartsWith("#", StringComparison.Ordinal))
197
+ {
198
+ value = String.Concat("#", value);
199
+ }
200
+
201
+ id = this.CreateIdentifier("reg", componentId, root.ToString(CultureInfo.InvariantCulture.NumberFormat), key.ToLowerInvariant(), (null != name ? name.ToLowerInvariant() : name));
202
+
203
+ var row = this.CreateRow(section, sourceLineNumbers, TupleDefinitionType.Registry, id);
204
+ row.Set(1, root);
205
+ row.Set(2, key);
206
+ row.Set(3, name);
207
+ row.Set(4, value);
208
+ row.Set(5, componentId);
209
+
210
+ return id;
211
+ }
212
+
213
+ public void CreateSimpleReference(IntermediateSection section, SourceLineNumber sourceLineNumbers, string tableName, params string[] primaryKeys)
214
+ {
215
+ var joinedKeys = String.Join("/", primaryKeys);
216
+ var id = String.Concat(tableName, ":", joinedKeys);
217
+
218
+ var wixSimpleReferenceRow = (WixSimpleReferenceTuple)this.CreateRow(section, sourceLineNumbers, TupleDefinitionType.WixSimpleReference);
219
+ wixSimpleReferenceRow.Table = tableName;
220
+ wixSimpleReferenceRow.PrimaryKeys = joinedKeys;
221
+ }
222
+
223
+ public void CreateWixGroupRow(IntermediateSection section, SourceLineNumber sourceLineNumbers, ComplexReferenceParentType parentType, string parentId, ComplexReferenceChildType childType, string childId)
224
+ {
225
+ if (null == parentId || ComplexReferenceParentType.Unknown == parentType)
226
+ {
227
+ return;
228
+ }
229
+
230
+ if (null == childId)
231
+ {
232
+ throw new ArgumentNullException("childId");
233
+ }
234
+
235
+ var row = (WixGroupTuple)this.CreateRow(section, sourceLineNumbers, TupleDefinitionType.WixGroup);
236
+ row.ParentId = parentId;
237
+ row.ParentType = parentType;
238
+ row.ChildId = childId;
239
+ row.ChildType = childType;
240
+ }
241
+
242
+ public IntermediateTuple CreateRow(IntermediateSection section, SourceLineNumber sourceLineNumbers, string tableName, Identifier identifier = null)
243
+ {
244
+ if (this.Creator == null)
245
+ {
246
+ this.CreateTupleDefinitionCreator();
247
+ }
248
+
249
+ if (!this.Creator.TryGetTupleDefinitionByName(tableName, out var tupleDefinition))
250
+ {
251
+ throw new ArgumentException(nameof(tableName));
252
+ }
253
+
254
+ return CreateRow(section, sourceLineNumbers, tupleDefinition, identifier);
255
+ }
256
+
257
+ public IntermediateTuple CreateRow(IntermediateSection section, SourceLineNumber sourceLineNumbers, TupleDefinitionType tupleType, Identifier identifier = null)
258
+ {
259
+ var tupleDefinition = TupleDefinitions.ByType(tupleType);
260
+
261
+ return CreateRow(section, sourceLineNumbers, tupleDefinition, identifier);
262
+ }
263
+
264
+ public string CreateShortName(string longName, bool keepExtension, bool allowWildcards, params string[] args)
265
+ {
266
+ // canonicalize the long name if its not a localization identifier (they are case-sensitive)
267
+ if (!this.IsValidLocIdentifier(longName))
268
+ {
269
+ longName = longName.ToLowerInvariant();
270
+ }
271
+
272
+ // collect all the data
273
+ List<string> strings = new List<string>(1 + args.Length);
274
+ strings.Add(longName);
275
+ strings.AddRange(args);
276
+
277
+ // prepare for hashing
278
+ string stringData = String.Join("|", strings);
279
+ byte[] data = Encoding.UTF8.GetBytes(stringData);
280
+
281
+ // hash the data
282
+ byte[] hash;
283
+ using (var sha1 = new SHA1CryptoServiceProvider())
284
+ {
285
+ hash = sha1.ComputeHash(data);
286
+ }
287
+
288
+ // generate the short file/directory name without an extension
289
+ StringBuilder shortName = new StringBuilder(Convert.ToBase64String(hash));
290
+ shortName.Remove(8, shortName.Length - 8).Replace('+', '-').Replace('/', '_');
291
+
292
+ if (keepExtension)
293
+ {
294
+ string extension = Path.GetExtension(longName);
295
+
296
+ if (4 < extension.Length)
297
+ {
298
+ extension = extension.Substring(0, 4);
299
+ }
300
+
301
+ shortName.Append(extension);
302
+
303
+ // check the generated short name to ensure its still legal (the extension may not be legal)
304
+ if (!this.IsValidShortFilename(shortName.ToString(), allowWildcards))
305
+ {
306
+ // remove the extension (by truncating the generated file name back to the generated characters)
307
+ shortName.Length -= extension.Length;
308
+ }
309
+ }
310
+
311
+ return shortName.ToString().ToLowerInvariant();
312
+ }
313
+
314
+ public void EnsureTable(IntermediateSection section, SourceLineNumber sourceLineNumbers, string tableName)
315
+ {
316
+ var row = this.CreateRow(section, sourceLineNumbers, TupleDefinitionType.WixEnsureTable);
317
+ row.Set(0, tableName);
318
+
319
+ if (this.Creator == null)
320
+ {
321
+ this.CreateTupleDefinitionCreator();
322
+ }
323
+
324
+ // We don't add custom table definitions to the tableDefinitions collection,
325
+ // so if it's not in there, it better be a custom table. If the Id is just wrong,
326
+ // instead of a custom table, we get an unresolved reference at link time.
327
+ if (!this.Creator.TryGetTupleDefinitionByName(tableName, out var ignored))
328
+ {
329
+ this.CreateSimpleReference(section, sourceLineNumbers, "WixCustomTable", tableName);
330
+ }
331
+ }
332
+
333
+ public string GetAttributeGuidValue(SourceLineNumber sourceLineNumbers, XAttribute attribute, bool generatable = false, bool canBeEmpty = false)
334
+ {
335
+ if (null == attribute)
336
+ {
337
+ throw new ArgumentNullException("attribute");
338
+ }
339
+
340
+ EmptyRule emptyRule = canBeEmpty ? EmptyRule.CanBeEmpty : EmptyRule.CanBeWhitespaceOnly;
341
+ string value = this.GetAttributeValue(sourceLineNumbers, attribute, emptyRule);
342
+
343
+ if (String.IsNullOrEmpty(value) && canBeEmpty)
344
+ {
345
+ return String.Empty;
346
+ }
347
+ else if (!String.IsNullOrEmpty(value))
348
+ {
349
+ // If the value starts and ends with braces or parenthesis, accept that and strip them off.
350
+ if ((value.StartsWith("{", StringComparison.Ordinal) && value.EndsWith("}", StringComparison.Ordinal))
351
+ || (value.StartsWith("(", StringComparison.Ordinal) && value.EndsWith(")", StringComparison.Ordinal)))
352
+ {
353
+ value = value.Substring(1, value.Length - 2);
354
+ }
355
+
356
+ if (generatable && "*".Equals(value, StringComparison.Ordinal))
357
+ {
358
+ return value;
359
+ }
360
+
361
+ if (ParseHelper.PutGuidHere.IsMatch(value))
362
+ {
363
+ Messaging.Instance.OnMessage(WixErrors.ExampleGuid(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
364
+ return CompilerConstants.IllegalGuid;
365
+ }
366
+ else if (value.StartsWith("!(loc", StringComparison.Ordinal) || value.StartsWith("$(loc", StringComparison.Ordinal) || value.StartsWith("!(wix", StringComparison.Ordinal))
367
+ {
368
+ return value;
369
+ }
370
+ else if (Guid.TryParse(value, out var guid))
371
+ {
372
+ var uppercaseGuid = guid.ToString().ToUpperInvariant();
373
+
374
+ // TODO: This used to be a pedantic error, what should it be now?
375
+ //if (uppercaseGuid != value)
376
+ //{
377
+ // Messaging.Instance.OnMessage(WixErrors.GuidContainsLowercaseLetters(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
378
+ //}
379
+
380
+ return String.Concat("{", uppercaseGuid, "}");
381
+ }
382
+ else
383
+ {
384
+ Messaging.Instance.OnMessage(WixErrors.IllegalGuidValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
385
+ }
386
+ }
387
+
388
+ return CompilerConstants.IllegalGuid;
389
+ }
390
+
391
+ public Identifier GetAttributeIdentifier(SourceLineNumber sourceLineNumbers, XAttribute attribute)
392
+ {
393
+ var access = AccessModifier.Public;
394
+ var value = Common.GetAttributeValue(sourceLineNumbers, attribute, EmptyRule.CanBeEmpty);
395
+
396
+ var match = ParseHelper.LegalIdentifierWithAccess.Match(value);
397
+ if (!match.Success)
398
+ {
399
+ return null;
400
+ }
401
+ else if (match.Groups["access"].Success)
402
+ {
403
+ access = (AccessModifier)Enum.Parse(typeof(AccessModifier), match.Groups["access"].Value, true);
404
+ }
405
+
406
+ value = match.Groups["id"].Value;
407
+
408
+ if (Common.IsIdentifier(value) && 72 < value.Length)
409
+ {
410
+ Messaging.Instance.OnMessage(WixWarnings.IdentifierTooLong(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
411
+ }
412
+
413
+ return new Identifier(value, access);
414
+ }
415
+
416
+ public string GetAttributeIdentifierValue(SourceLineNumber sourceLineNumbers, XAttribute attribute)
417
+ {
418
+ return Common.GetAttributeIdentifierValue(sourceLineNumbers, attribute);
419
+ }
420
+
421
+ public string[] GetAttributeInlineDirectorySyntax(SourceLineNumber sourceLineNumbers, XAttribute attribute, bool resultUsedToCreateReference = false)
422
+ {
423
+ string[] result = null;
424
+ string value = this.GetAttributeValue(sourceLineNumbers, attribute);
425
+
426
+ if (!String.IsNullOrEmpty(value))
427
+ {
428
+ int pathStartsAt = 0;
429
+ result = value.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries);
430
+ if (result[0].EndsWith(":", StringComparison.Ordinal))
431
+ {
432
+ string id = result[0].TrimEnd(':');
433
+ if (1 == result.Length)
434
+ {
435
+ Messaging.Instance.OnMessage(WixErrors.InlineDirectorySyntaxRequiresPath(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value, id));
436
+ return null;
437
+ }
438
+ else if (!this.IsValidIdentifier(id))
439
+ {
440
+ Messaging.Instance.OnMessage(WixErrors.IllegalIdentifier(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value, id));
441
+ return null;
442
+ }
443
+
444
+ pathStartsAt = 1;
445
+ }
446
+ else if (resultUsedToCreateReference && 1 == result.Length)
447
+ {
448
+ if (value.EndsWith("\\"))
449
+ {
450
+ if (!this.IsValidLongFilename(result[0], false, false))
451
+ {
452
+ Messaging.Instance.OnMessage(WixErrors.IllegalLongFilename(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value, result[0]));
453
+ return null;
454
+ }
455
+ }
456
+ else if (!this.IsValidIdentifier(result[0]))
457
+ {
458
+ Messaging.Instance.OnMessage(WixErrors.IllegalIdentifier(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value, result[0]));
459
+ return null;
460
+ }
461
+
462
+ return result; // return early to avoid additional checks below.
463
+ }
464
+
465
+ // Check each part of the relative path to ensure that it is a valid directory name.
466
+ for (int i = pathStartsAt; i < result.Length; ++i)
467
+ {
468
+ if (!this.IsValidLongFilename(result[i], false, false))
469
+ {
470
+ Messaging.Instance.OnMessage(WixErrors.IllegalLongFilename(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value, result[i]));
471
+ return null;
472
+ }
473
+ }
474
+
475
+ if (1 < result.Length && !value.EndsWith("\\"))
476
+ {
477
+ Messaging.Instance.OnMessage(WixWarnings.BackslashTerminateInlineDirectorySyntax(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
478
+ }
479
+ }
480
+
481
+ return result;
482
+ }
483
+
484
+ public int GetAttributeIntegerValue(SourceLineNumber sourceLineNumbers, XAttribute attribute, int minimum, int maximum)
485
+ {
486
+ return Common.GetAttributeIntegerValue(sourceLineNumbers, attribute, minimum, maximum);
487
+ }
488
+
489
+ public string GetAttributeLongFilename(SourceLineNumber sourceLineNumbers, XAttribute attribute, bool allowWildcards, bool allowRelative)
490
+ {
491
+ if (null == attribute)
492
+ {
493
+ throw new ArgumentNullException("attribute");
494
+ }
495
+
496
+ string value = this.GetAttributeValue(sourceLineNumbers, attribute);
497
+
498
+ if (0 < value.Length)
499
+ {
500
+ if (!this.IsValidLongFilename(value, allowWildcards, allowRelative) && !this.IsValidLocIdentifier(value))
501
+ {
502
+ if (allowRelative)
503
+ {
504
+ Messaging.Instance.OnMessage(WixErrors.IllegalRelativeLongFilename(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
505
+ }
506
+ else
507
+ {
508
+ Messaging.Instance.OnMessage(WixErrors.IllegalLongFilename(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
509
+ }
510
+ }
511
+ else if (allowRelative)
512
+ {
513
+ string normalizedPath = value.Replace('\\', '/');
514
+ if (normalizedPath.StartsWith("../", StringComparison.Ordinal) || normalizedPath.Contains("/../"))
515
+ {
516
+ Messaging.Instance.OnMessage(WixErrors.PayloadMustBeRelativeToCache(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
517
+ }
518
+ }
519
+ else if (CompilerCore.IsAmbiguousFilename(value))
520
+ {
521
+ Messaging.Instance.OnMessage(WixWarnings.AmbiguousFileOrDirectoryName(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
522
+ }
523
+ }
524
+
525
+ return value;
526
+ }
527
+
528
+ public long GetAttributeLongValue(SourceLineNumber sourceLineNumbers, XAttribute attribute, long minimum, long maximum)
529
+ {
530
+ Debug.Assert(minimum > CompilerConstants.LongNotSet && minimum > CompilerConstants.IllegalLong, "The legal values for this attribute collide with at least one sentinel used during parsing.");
531
+
532
+ string value = this.GetAttributeValue(sourceLineNumbers, attribute);
533
+
534
+ if (0 < value.Length)
535
+ {
536
+ try
537
+ {
538
+ long longValue = Convert.ToInt64(value, CultureInfo.InvariantCulture.NumberFormat);
539
+
540
+ if (CompilerConstants.LongNotSet == longValue || CompilerConstants.IllegalLong == longValue)
541
+ {
542
+ Messaging.Instance.OnMessage(WixErrors.IntegralValueSentinelCollision(sourceLineNumbers, longValue));
543
+ }
544
+ else if (minimum > longValue || maximum < longValue)
545
+ {
546
+ Messaging.Instance.OnMessage(WixErrors.IntegralValueOutOfRange(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, longValue, minimum, maximum));
547
+ longValue = CompilerConstants.IllegalLong;
548
+ }
549
+
550
+ return longValue;
551
+ }
552
+ catch (FormatException)
553
+ {
554
+ Messaging.Instance.OnMessage(WixErrors.IllegalLongValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
555
+ }
556
+ catch (OverflowException)
557
+ {
558
+ Messaging.Instance.OnMessage(WixErrors.IllegalLongValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
559
+ }
560
+ }
561
+
562
+ return CompilerConstants.IllegalLong;
563
+ }
564
+
565
+ public string GetAttributeValue(SourceLineNumber sourceLineNumbers, XAttribute attribute, EmptyRule emptyRule = EmptyRule.CanBeWhitespaceOnly)
566
+ {
567
+ return Common.GetAttributeValue(sourceLineNumbers, attribute, emptyRule);
568
+ }
569
+
570
+ public string GetAttributeVersionValue(SourceLineNumber sourceLineNumbers, XAttribute attribute)
571
+ {
572
+ var value = this.GetAttributeValue(sourceLineNumbers, attribute);
573
+
574
+ if (!String.IsNullOrEmpty(value))
575
+ {
576
+ if (Version.TryParse(value, out var version))
577
+ {
578
+ return version.ToString();
579
+ }
580
+
581
+ // Allow versions to contain binder variables.
582
+ if (Common.ContainsValidBinderVariable(value))
583
+ {
584
+ return value;
585
+ }
586
+
587
+ Messaging.Instance.OnMessage(WixErrors.IllegalVersionValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
588
+ }
589
+
590
+ return null;
591
+ }
592
+
593
+ public YesNoDefaultType GetAttributeYesNoDefaultValue(SourceLineNumber sourceLineNumbers, XAttribute attribute)
594
+ {
595
+ var value = this.GetAttributeValue(sourceLineNumbers, attribute);
596
+
597
+ switch (value)
598
+ {
599
+ case "yes":
600
+ case "true":
601
+ return YesNoDefaultType.Yes;
602
+
603
+ case "no":
604
+ case "false":
605
+ return YesNoDefaultType.No;
606
+
607
+ case "default":
608
+ return YesNoDefaultType.Default;
609
+
610
+ default:
611
+ Messaging.Instance.OnMessage(WixErrors.IllegalYesNoDefaultValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
612
+ return YesNoDefaultType.IllegalValue;
613
+ }
614
+ }
615
+
616
+ public YesNoType GetAttributeYesNoValue(SourceLineNumber sourceLineNumbers, XAttribute attribute)
617
+ {
618
+ var value = this.GetAttributeValue(sourceLineNumbers, attribute);
619
+
620
+ switch (value)
621
+ {
622
+ case "yes":
623
+ case "true":
624
+ return YesNoType.Yes;
625
+
626
+ case "no":
627
+ case "false":
628
+ return YesNoType.No;
629
+
630
+ default:
631
+ Messaging.Instance.OnMessage(WixErrors.IllegalYesNoValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
632
+ return YesNoType.IllegalValue;
633
+ }
634
+ }
635
+
636
+ public string GetConditionInnerText(XElement element)
637
+ {
638
+ var value = Common.GetInnerText(element)?.Trim().Replace('\t', ' ').Replace('\r', ' ').Replace('\n', ' ');
639
+
640
+ // Return null for a non-existant condition.
641
+ return String.IsNullOrEmpty(value) ? null : value;
642
+ }
643
+
644
+ public string GetTrimmedInnerText(XElement element)
645
+ {
646
+ var value = Common.GetInnerText(element);
647
+ return value?.Trim();
648
+ }
649
+
650
+ public bool IsValidIdentifier(string value)
651
+ {
652
+ return Common.IsIdentifier(value);
653
+ }
654
+
655
+ public bool IsValidLocIdentifier(string identifier)
656
+ {
657
+ if (String.IsNullOrEmpty(identifier))
658
+ {
659
+ return false;
660
+ }
661
+
662
+ var match = Common.WixVariableRegex.Match(identifier);
663
+
664
+ return (match.Success && "loc" == match.Groups["namespace"].Value && 0 == match.Index && identifier.Length == match.Length);
665
+ }
666
+
667
+ public bool IsValidLongFilename(string filename, bool allowWildcards, bool allowRelative)
668
+ {
669
+ if (String.IsNullOrEmpty(filename))
670
+ {
671
+ return false;
672
+ }
673
+
674
+ // Check for a non-period character (all periods is not legal)
675
+ bool nonPeriodFound = false;
676
+ foreach (char character in filename)
677
+ {
678
+ if ('.' != character)
679
+ {
680
+ nonPeriodFound = true;
681
+ break;
682
+ }
683
+ }
684
+
685
+ if (allowWildcards)
686
+ {
687
+ return (nonPeriodFound && ParseHelper.LegalWildcardLongFilename.IsMatch(filename));
688
+ }
689
+ else if (allowRelative)
690
+ {
691
+ return (nonPeriodFound && ParseHelper.LegalRelativeLongFilename.IsMatch(filename));
692
+ }
693
+ else
694
+ {
695
+ return (nonPeriodFound && ParseHelper.LegalLongFilename.IsMatch(filename));
696
+ }
697
+ }
698
+
699
+ public bool IsValidShortFilename(string filename, bool allowWildcards = false)
700
+ {
701
+ return Common.IsValidShortFilename(filename, allowWildcards);
702
+ }
703
+
704
+ public void ParseExtensionAttribute(IEnumerable<ICompilerExtension> extensions, Intermediate intermediate, IntermediateSection section, XElement element, XAttribute attribute, IDictionary<string, string> context = null)
705
+ {
706
+ // Ignore attributes defined by the W3C because we'll assume they are always right.
707
+ if ((String.IsNullOrEmpty(attribute.Name.NamespaceName) && attribute.Name.LocalName.Equals("xmlns", StringComparison.Ordinal)) ||
708
+ attribute.Name.NamespaceName.StartsWith(CompilerCore.W3SchemaPrefix.NamespaceName, StringComparison.Ordinal))
709
+ {
710
+ return;
711
+ }
712
+
713
+ if (ParseHelper.TryFindExtension(extensions, attribute.Name.NamespaceName, out var extension))
714
+ {
715
+ extension.ParseAttribute(intermediate, section, element, attribute, context);
716
+ }
717
+ else
718
+ {
719
+ var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(element);
720
+ Messaging.Instance.OnMessage(WixErrors.UnhandledExtensionAttribute(sourceLineNumbers, element.Name.LocalName, attribute.Name.LocalName, attribute.Name.NamespaceName));
721
+ }
722
+ }
723
+
724
+ public void ParseExtensionElement(IEnumerable<ICompilerExtension> extensions, Intermediate intermediate, IntermediateSection section, XElement parentElement, XElement element, IDictionary<string, string> context = null)
725
+ {
726
+ if (ParseHelper.TryFindExtension(extensions, element.Name.Namespace, out var extension))
727
+ {
728
+ SourceLineNumber sourceLineNumbers = Preprocessor.GetSourceLineNumbers(parentElement);
729
+ extension.ParseElement(intermediate, section, parentElement, element, context);
730
+ }
731
+ else
732
+ {
733
+ var childSourceLineNumbers = Preprocessor.GetSourceLineNumbers(element);
734
+ Messaging.Instance.OnMessage(WixErrors.UnhandledExtensionElement(childSourceLineNumbers, parentElement.Name.LocalName, element.Name.LocalName, element.Name.NamespaceName));
735
+ }
736
+ }
737
+
738
+ public ComponentKeyPath ParsePossibleKeyPathExtensionElement(IEnumerable<ICompilerExtension> extensions, Intermediate intermediate, IntermediateSection section, XElement parentElement, XElement element, IDictionary<string, string> context)
739
+ {
740
+ ComponentKeyPath keyPath = null;
741
+
742
+ if (ParseHelper.TryFindExtension(extensions, element.Name.Namespace, out var extension))
743
+ {
744
+ keyPath = extension.ParsePossibleKeyPathElement(intermediate, section, parentElement, element, context);
745
+ }
746
+ else
747
+ {
748
+ var childSourceLineNumbers = Preprocessor.GetSourceLineNumbers(element);
749
+ Messaging.Instance.OnMessage(WixErrors.UnhandledExtensionElement(childSourceLineNumbers, parentElement.Name.LocalName, element.Name.LocalName, element.Name.NamespaceName));
750
+ }
751
+
752
+ return keyPath;
753
+ }
754
+
755
+ public void ParseForExtensionElements(IEnumerable<ICompilerExtension> extensions, Intermediate intermediate, IntermediateSection section, XElement element)
756
+ {
757
+ foreach (XElement child in element.Elements())
758
+ {
759
+ if (element.Name.Namespace == child.Name.Namespace)
760
+ {
761
+ this.UnexpectedElement(element, child);
762
+ }
763
+ else
764
+ {
765
+ this.ParseExtensionElement(extensions, intermediate, section, element, child);
766
+ }
767
+ }
768
+ }
769
+
770
+ public void UnexpectedAttribute(XElement element, XAttribute attribute)
771
+ {
772
+ var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(element);
773
+ Common.UnexpectedAttribute(sourceLineNumbers, attribute);
774
+ }
775
+
776
+ public void UnexpectedElement(XElement parentElement, XElement childElement)
777
+ {
778
+ var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(childElement);
779
+ Messaging.Instance.OnMessage(WixErrors.UnexpectedElement(sourceLineNumbers, parentElement.Name.LocalName, childElement.Name.LocalName));
780
+ }
781
+
782
+ private void CreateTupleDefinitionCreator()
783
+ {
784
+ this.Creator = (ITupleDefinitionCreator)this.ServiceProvider.GetService(typeof(ITupleDefinitionCreator));
785
+ }
786
+
787
+ private static IntermediateTuple CreateRow(IntermediateSection section, SourceLineNumber sourceLineNumbers, IntermediateTupleDefinition tupleDefinition, Identifier identifier)
788
+ {
789
+ var row = tupleDefinition.CreateTuple(sourceLineNumbers, identifier);
790
+
791
+ if (null != identifier)
792
+ {
793
+ if (row.Definition.FieldDefinitions[0].Type == IntermediateFieldType.Number)
794
+ {
795
+ row.Set(0, Convert.ToInt32(identifier.Id));
796
+ }
797
+ else
798
+ {
799
+ row.Set(0, identifier.Id);
800
+ }
801
+ }
802
+
803
+ section.Tuples.Add(row);
804
+
805
+ return row;
806
+ }
807
+
808
+ private static bool TryFindExtension(IEnumerable<ICompilerExtension> extensions, XNamespace ns, out ICompilerExtension extension)
809
+ {
810
+ extension = null;
811
+
812
+ foreach (var ext in extensions)
813
+ {
814
+ if (ext.Namespace == ns)
815
+ {
816
+ extension = ext;
817
+ break;
818
+ }
819
+ }
820
+
821
+ return extension != null;
822
+ }
823
+ }
824
+}
src/WixToolset.Core/ExtensibilityServices/TupleDefinitionCreator.cs
renamed
+1
-1
@@ -1,6 +1,6 @@
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
3
+namespace WixToolset.Core.ExtensibilityServices
4
{
5
using System;
6
using System.Collections.Generic;
src/WixToolset.Core/HarvesterCore.cs
+1
-2
@@ -1,12 +1,11 @@
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
3
+namespace WixToolset.Core
4
{
5
using System;
6
using System.Diagnostics.CodeAnalysis;
7
using System.IO;
8
using WixToolset.Data;
9
- using Wix = WixToolset.Data.Serialize;
9
10
/// <summary>
11
/// The WiX Toolset harvester core.
src/WixToolset.Core/HeatCore.cs
+2
-2
@@ -1,9 +1,9 @@
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.Tools
3
+namespace WixToolset.Core
4
{
5
+ using WixToolset.Core.Extensibility;
6
using WixToolset.Data;
6
- using WixToolset.Extensibility;
7
8
/// <summary>
9
/// The WiX Toolset Harvester application core.
src/WixToolset.Core/Link/WixGroupingOrdering.cs
+1
-3
@@ -1,16 +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.Link
3
+namespace WixToolset.Core.Link
4
{
5
using System;
6
- using System.Collections;
6
using System.Collections.ObjectModel;
7
using System.Collections.Generic;
8
using System.Diagnostics;
9
using System.Globalization;
10
using System.Linq;
11
using System.Text;
13
- using WixToolset.Extensibility;
12
using WixToolset.Data;
13
using WixToolset.Data.Tuples;
14
src/WixToolset.Core/Localizer.cs
+1
-1
@@ -1,6 +1,6 @@
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
3
+namespace WixToolset.Core
4
{
5
using System;
6
using System.Collections.Generic;
src/WixToolset.Core/Mutator.cs
+2
-2
@@ -1,10 +1,10 @@
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
3
+namespace WixToolset.Core
4
{
5
using System;
6
using System.Collections;
7
- using WixToolset.Extensibility;
7
+ using WixToolset.Core.Extensibility;
8
using Wix = WixToolset.Data.Serialize;
9
10
/// <summary>
src/WixToolset.Core/Preprocessor.cs
+1
-2
@@ -1,9 +1,8 @@
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
3
+namespace WixToolset.Core
4
{
5
using System;
6
- using System.Collections;
6
using System.Collections.Generic;
7
using System.Diagnostics.CodeAnalysis;
8
using System.Globalization;
src/WixToolset.Core/WixToolsetServiceProvider.cs
+7
@@ -3,6 +3,7 @@
3
namespace WixToolset.Core
4
{
5
using System;
6
+ using WixToolset.Core.ExtensibilityServices;
7
using WixToolset.Data;
8
using WixToolset.Extensibility;
9
using WixToolset.Extensibility.Services;
@@ -10,6 +11,7 @@ namespace WixToolset.Core
11
public class WixToolsetServiceProvider : IServiceProvider
12
{
13
private ExtensionManager extensionManager;
14
+ private ParseHelper parseHelper;
15
private TupleDefinitionCreator tupleDefinitionCreator;
16
17
public object GetService(Type serviceType)
@@ -58,6 +60,11 @@ namespace WixToolset.Core
60
return this.tupleDefinitionCreator = this.tupleDefinitionCreator ?? new TupleDefinitionCreator(this);
61
}
62
63
+ if (serviceType == typeof(IParseHelper))
64
+ {
65
+ return this.parseHelper = this.parseHelper ?? new ParseHelper(this);
66
+ }
67
+
68
throw new ArgumentException($"Unknown service type: {serviceType.Name}", nameof(serviceType));
69
}
70
}
src/WixToolset.Data.WindowsInstaller/Output.cs
-5
@@ -186,7 +186,6 @@ namespace WixToolset.Data
186
187
bool empty = reader.IsEmptyElement;
188
Output output = new Output(SourceLineNumber.CreateFromUri(reader.BaseURI));
189
- SectionType sectionType = SectionType.Unknown;
189
Version version = null;
190
191
while (reader.MoveToNextAttribute())
@@ -201,22 +200,18 @@ namespace WixToolset.Data
200
{
201
case "Bundle":
202
output.Type = OutputType.Bundle;
204
- sectionType = SectionType.Bundle;
203
break;
204
case "Module":
205
output.Type = OutputType.Module;
208
- sectionType = SectionType.Module;
206
break;
207
case "Patch":
208
output.Type = OutputType.Patch;
209
break;
210
case "PatchCreation":
211
output.Type = OutputType.PatchCreation;
215
- sectionType = SectionType.PatchCreation;
212
break;
213
case "Product":
214
output.Type = OutputType.Product;
219
- sectionType = SectionType.Product;
215
break;
216
case "Transform":
217
output.Type = OutputType.Transform;