diff options
Diffstat (limited to 'src/WixToolset.Core/ExtensibilityServices/ParseHelper.cs')
-rw-r--r-- | src/WixToolset.Core/ExtensibilityServices/ParseHelper.cs | 216 |
1 files changed, 105 insertions, 111 deletions
diff --git a/src/WixToolset.Core/ExtensibilityServices/ParseHelper.cs b/src/WixToolset.Core/ExtensibilityServices/ParseHelper.cs index d9087ce3..e75f5fe5 100644 --- a/src/WixToolset.Core/ExtensibilityServices/ParseHelper.cs +++ b/src/WixToolset.Core/ExtensibilityServices/ParseHelper.cs | |||
@@ -19,6 +19,8 @@ namespace WixToolset.Core.ExtensibilityServices | |||
19 | 19 | ||
20 | internal class ParseHelper : IParseHelper | 20 | internal class ParseHelper : IParseHelper |
21 | { | 21 | { |
22 | private static readonly char[] InlineDirectorySeparators = new char[] { ':', '\\', '/' }; | ||
23 | |||
22 | public ParseHelper(IWixToolsetServiceProvider serviceProvider) | 24 | public ParseHelper(IWixToolsetServiceProvider serviceProvider) |
23 | { | 25 | { |
24 | this.ServiceProvider = serviceProvider; | 26 | this.ServiceProvider = serviceProvider; |
@@ -53,13 +55,7 @@ namespace WixToolset.Core.ExtensibilityServices | |||
53 | this.CreateWixGroupSymbol(section, sourceLineNumbers, parentType, parentId, childType, childId); | 55 | this.CreateWixGroupSymbol(section, sourceLineNumbers, parentType, parentId, childType, childId); |
54 | } | 56 | } |
55 | 57 | ||
56 | [Obsolete] | 58 | public Identifier CreateDirectorySymbol(IntermediateSection section, SourceLineNumber sourceLineNumbers, Identifier id, string parentId, string name, string shortName = null, string sourceName = null, string shortSourceName = null) |
57 | public Identifier CreateDirectoryRow(IntermediateSection section, SourceLineNumber sourceLineNumbers, Identifier id, string parentId, string name, ISet<string> sectionInlinedDirectoryIds, string shortName = null, string sourceName = null, string shortSourceName = null) | ||
58 | { | ||
59 | return this.CreateDirectorySymbol(section, sourceLineNumbers, id, parentId, name, sectionInlinedDirectoryIds, shortName, sourceName, shortSourceName); | ||
60 | } | ||
61 | |||
62 | public Identifier CreateDirectorySymbol(IntermediateSection section, SourceLineNumber sourceLineNumbers, Identifier id, string parentId, string name, ISet<string> sectionInlinedDirectoryIds, string shortName = null, string sourceName = null, string shortSourceName = null) | ||
63 | { | 59 | { |
64 | // For anonymous directories, create the identifier. If this identifier already exists in the | 60 | // For anonymous directories, create the identifier. If this identifier already exists in the |
65 | // active section, bail so we don't add duplicate anonymous directory symbols (which are legal | 61 | // active section, bail so we don't add duplicate anonymous directory symbols (which are legal |
@@ -67,11 +63,6 @@ namespace WixToolset.Core.ExtensibilityServices | |||
67 | if (null == id) | 63 | if (null == id) |
68 | { | 64 | { |
69 | id = this.CreateIdentifier("dir", parentId, name, shortName, sourceName, shortSourceName); | 65 | id = this.CreateIdentifier("dir", parentId, name, shortName, sourceName, shortSourceName); |
70 | |||
71 | if (!sectionInlinedDirectoryIds.Add(id.Id)) | ||
72 | { | ||
73 | return id; | ||
74 | } | ||
75 | } | 66 | } |
76 | 67 | ||
77 | var symbol = section.AddSymbol(new DirectorySymbol(sourceLineNumbers, id) | 68 | var symbol = section.AddSymbol(new DirectorySymbol(sourceLineNumbers, id) |
@@ -86,48 +77,30 @@ namespace WixToolset.Core.ExtensibilityServices | |||
86 | return symbol.Id; | 77 | return symbol.Id; |
87 | } | 78 | } |
88 | 79 | ||
89 | public string CreateDirectoryReferenceFromInlineSyntax(IntermediateSection section, SourceLineNumber sourceLineNumbers, string parentId, XAttribute attribute, ISet<string> sectionInlinedDirectoryIds) | 80 | public string CreateDirectoryReferenceFromInlineSyntax(IntermediateSection section, SourceLineNumber sourceLineNumbers, XAttribute attribute, string parentId, string inlineSyntax, IDictionary<string, string> sectionCachedInlinedDirectoryIds) |
90 | { | 81 | { |
91 | string id = null; | 82 | if (String.IsNullOrEmpty(inlineSyntax)) |
92 | var inlineSyntax = this.GetAttributeInlineDirectorySyntax(sourceLineNumbers, attribute, true); | ||
93 | |||
94 | if (null != inlineSyntax) | ||
95 | { | 83 | { |
96 | // Special case the single entry in the inline syntax since it is the most common case | 84 | inlineSyntax = attribute.Value; |
97 | // and needs no extra processing. It's just a reference to an existing directory. | 85 | } |
98 | if (1 == inlineSyntax.Length) | ||
99 | { | ||
100 | id = inlineSyntax[0]; | ||
101 | this.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.Directory, id); | ||
102 | } | ||
103 | else // start creating symbols for the entries in the inline syntax | ||
104 | { | ||
105 | id = parentId; | ||
106 | |||
107 | var pathStartsAt = 0; | ||
108 | if (inlineSyntax[0].EndsWith(":", StringComparison.Ordinal)) | ||
109 | { | ||
110 | // TODO: should overriding the parent identifier with a specific id be an error or a warning or just let it slide? | ||
111 | //if (null != parentId) | ||
112 | //{ | ||
113 | // this.core.Write(WixErrors.Xxx(sourceLineNumbers)); | ||
114 | //} | ||
115 | |||
116 | id = inlineSyntax[0].TrimEnd(':'); | ||
117 | this.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.Directory, id); | ||
118 | 86 | ||
119 | pathStartsAt = 1; | 87 | // If no separator is found, the string is a simple reference. |
120 | } | 88 | var separatorFound = inlineSyntax.IndexOfAny(InlineDirectorySeparators); |
89 | if (separatorFound == -1) | ||
90 | { | ||
91 | this.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.Directory, inlineSyntax); | ||
92 | return inlineSyntax; | ||
93 | } | ||
121 | 94 | ||
122 | for (var i = pathStartsAt; i < inlineSyntax.Length; ++i) | 95 | // If a parent id was provided and the inline syntax does not start with a directory reference, prepend the parent id. |
123 | { | 96 | if (!String.IsNullOrEmpty(parentId) && inlineSyntax[separatorFound] != ':') |
124 | var inlineId = this.CreateDirectorySymbol(section, sourceLineNumbers, null, id, inlineSyntax[i], sectionInlinedDirectoryIds); | 97 | { |
125 | id = inlineId.Id; | 98 | inlineSyntax = String.Concat(parentId, ":", inlineSyntax); |
126 | } | ||
127 | } | ||
128 | } | 99 | } |
129 | 100 | ||
130 | return id; | 101 | inlineSyntax = inlineSyntax.TrimEnd('\\', '/'); |
102 | |||
103 | return this.ParseInlineSyntax(section, sourceLineNumbers, attribute, inlineSyntax, sectionCachedInlinedDirectoryIds); | ||
131 | } | 104 | } |
132 | 105 | ||
133 | public string CreateGuid(Guid namespaceGuid, string value) | 106 | public string CreateGuid(Guid namespaceGuid, string value) |
@@ -544,69 +517,6 @@ namespace WixToolset.Core.ExtensibilityServices | |||
544 | return Common.GetAttributeIdentifierValue(this.Messaging, sourceLineNumbers, attribute); | 517 | return Common.GetAttributeIdentifierValue(this.Messaging, sourceLineNumbers, attribute); |
545 | } | 518 | } |
546 | 519 | ||
547 | public string[] GetAttributeInlineDirectorySyntax(SourceLineNumber sourceLineNumbers, XAttribute attribute, bool resultUsedToCreateReference = false) | ||
548 | { | ||
549 | string[] result = null; | ||
550 | var value = this.GetAttributeValue(sourceLineNumbers, attribute); | ||
551 | |||
552 | if (!String.IsNullOrEmpty(value)) | ||
553 | { | ||
554 | var pathStartsAt = 0; | ||
555 | result = value.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries); | ||
556 | if (result[0].EndsWith(":", StringComparison.Ordinal)) | ||
557 | { | ||
558 | var id = result[0].TrimEnd(':'); | ||
559 | if (1 == result.Length) | ||
560 | { | ||
561 | this.Messaging.Write(ErrorMessages.InlineDirectorySyntaxRequiresPath(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value, id)); | ||
562 | return null; | ||
563 | } | ||
564 | else if (!this.IsValidIdentifier(id)) | ||
565 | { | ||
566 | this.Messaging.Write(ErrorMessages.IllegalIdentifier(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value, id)); | ||
567 | return null; | ||
568 | } | ||
569 | |||
570 | pathStartsAt = 1; | ||
571 | } | ||
572 | else if (resultUsedToCreateReference && 1 == result.Length) | ||
573 | { | ||
574 | if (value.EndsWith("\\", StringComparison.Ordinal)) | ||
575 | { | ||
576 | if (!this.IsValidLongFilename(result[0], false, false)) | ||
577 | { | ||
578 | this.Messaging.Write(ErrorMessages.IllegalLongFilename(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value, result[0])); | ||
579 | return null; | ||
580 | } | ||
581 | } | ||
582 | else if (!this.IsValidIdentifier(result[0])) | ||
583 | { | ||
584 | this.Messaging.Write(ErrorMessages.IllegalIdentifier(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value, result[0])); | ||
585 | return null; | ||
586 | } | ||
587 | |||
588 | return result; // return early to avoid additional checks below. | ||
589 | } | ||
590 | |||
591 | // Check each part of the relative path to ensure that it is a valid directory name. | ||
592 | for (var i = pathStartsAt; i < result.Length; ++i) | ||
593 | { | ||
594 | if (!this.IsValidLongFilename(result[i], false, false)) | ||
595 | { | ||
596 | this.Messaging.Write(ErrorMessages.IllegalLongFilename(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value, result[i])); | ||
597 | return null; | ||
598 | } | ||
599 | } | ||
600 | |||
601 | if (1 < result.Length && !value.EndsWith("\\", StringComparison.Ordinal)) | ||
602 | { | ||
603 | this.Messaging.Write(WarningMessages.BackslashTerminateInlineDirectorySyntax(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value)); | ||
604 | } | ||
605 | } | ||
606 | |||
607 | return result; | ||
608 | } | ||
609 | |||
610 | public int GetAttributeIntegerValue(SourceLineNumber sourceLineNumbers, XAttribute attribute, int minimum, int maximum) | 520 | public int GetAttributeIntegerValue(SourceLineNumber sourceLineNumbers, XAttribute attribute, int minimum, int maximum) |
611 | { | 521 | { |
612 | return Common.GetAttributeIntegerValue(this.Messaging, sourceLineNumbers, attribute, minimum, maximum); | 522 | return Common.GetAttributeIntegerValue(this.Messaging, sourceLineNumbers, attribute, minimum, maximum); |
@@ -1032,6 +942,90 @@ namespace WixToolset.Core.ExtensibilityServices | |||
1032 | this.Creator = this.ServiceProvider.GetService<ISymbolDefinitionCreator>(); | 942 | this.Creator = this.ServiceProvider.GetService<ISymbolDefinitionCreator>(); |
1033 | } | 943 | } |
1034 | 944 | ||
945 | private string ParseInlineSyntax(IntermediateSection section, SourceLineNumber sourceLineNumbers, XAttribute attribute, string inlineSyntax, IDictionary<string, string> sectionCachedInlinedDirectoryIds) | ||
946 | { | ||
947 | if (!sectionCachedInlinedDirectoryIds.TryGetValue(inlineSyntax, out var id)) | ||
948 | { | ||
949 | string parentId; | ||
950 | int nameIndex; | ||
951 | |||
952 | var separatorIndex = inlineSyntax.LastIndexOfAny(InlineDirectorySeparators); | ||
953 | if (separatorIndex == -1) | ||
954 | { | ||
955 | nameIndex = 0; | ||
956 | parentId = "TARGETDIR"; | ||
957 | } | ||
958 | else if (inlineSyntax[separatorIndex] == '\\' || inlineSyntax[separatorIndex] == '/') | ||
959 | { | ||
960 | nameIndex = separatorIndex + 1; | ||
961 | |||
962 | if (separatorIndex == 0) | ||
963 | { | ||
964 | parentId = "TARGETDIR"; | ||
965 | } | ||
966 | else if (inlineSyntax[separatorIndex - 1] == ':') | ||
967 | { | ||
968 | parentId = this.ParseParentReference(section, sourceLineNumbers, attribute, inlineSyntax, separatorIndex - 1); | ||
969 | } | ||
970 | else | ||
971 | { | ||
972 | var parentInlineDirectory = inlineSyntax.Substring(0, separatorIndex); | ||
973 | parentId = this.ParseInlineSyntax(section, sourceLineNumbers, attribute, parentInlineDirectory.TrimEnd('\\', '/'), sectionCachedInlinedDirectoryIds); | ||
974 | } | ||
975 | } | ||
976 | else | ||
977 | { | ||
978 | nameIndex = separatorIndex + 1; | ||
979 | parentId = this.ParseParentReference(section, sourceLineNumbers, attribute, inlineSyntax, separatorIndex); | ||
980 | } | ||
981 | |||
982 | if (nameIndex == inlineSyntax.Length) | ||
983 | { | ||
984 | id = parentId; | ||
985 | } | ||
986 | else | ||
987 | { | ||
988 | var name = nameIndex != -1 ? inlineSyntax.Substring(nameIndex) : null; | ||
989 | |||
990 | if (!this.IsValidLongFilename(name, false, false)) | ||
991 | { | ||
992 | this.Messaging.Write(ErrorMessages.IllegalLongFilename(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, attribute.Value, name)); | ||
993 | return null; | ||
994 | } | ||
995 | |||
996 | var identifier = this.CreateDirectorySymbol(section, sourceLineNumbers, null, parentId, name); | ||
997 | |||
998 | id = identifier.Id; | ||
999 | } | ||
1000 | |||
1001 | sectionCachedInlinedDirectoryIds.Add(inlineSyntax, id); | ||
1002 | } | ||
1003 | |||
1004 | return id; | ||
1005 | } | ||
1006 | |||
1007 | private string ParseParentReference(IntermediateSection section, SourceLineNumber sourceLineNumbers, XAttribute attribute, string reference, int colonIndex) | ||
1008 | { | ||
1009 | if (colonIndex == 0) | ||
1010 | { | ||
1011 | this.Messaging.Write(ErrorMessages.IllegalIdentifier(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, attribute.Value, String.Empty)); | ||
1012 | return null; | ||
1013 | } | ||
1014 | else | ||
1015 | { | ||
1016 | var parentId = reference.Substring(0, colonIndex); | ||
1017 | |||
1018 | if (!Common.IsIdentifier(parentId)) | ||
1019 | { | ||
1020 | this.Messaging.Write(ErrorMessages.IllegalIdentifier(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, attribute.Value, parentId)); | ||
1021 | return null; | ||
1022 | } | ||
1023 | |||
1024 | this.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.Directory, parentId); | ||
1025 | return parentId; | ||
1026 | } | ||
1027 | } | ||
1028 | |||
1035 | private static bool TryFindExtension(IEnumerable<ICompilerExtension> extensions, XNamespace ns, out ICompilerExtension extension) | 1029 | private static bool TryFindExtension(IEnumerable<ICompilerExtension> extensions, XNamespace ns, out ICompilerExtension extension) |
1036 | { | 1030 | { |
1037 | extension = null; | 1031 | extension = null; |