diff options
12 files changed, 251 insertions, 78 deletions
diff --git a/src/api/wix/WixToolset.Data/ErrorMessages.cs b/src/api/wix/WixToolset.Data/ErrorMessages.cs index 889d1762..e149d54a 100644 --- a/src/api/wix/WixToolset.Data/ErrorMessages.cs +++ b/src/api/wix/WixToolset.Data/ErrorMessages.cs | |||
@@ -323,21 +323,6 @@ namespace WixToolset.Data | |||
323 | return Message(null, Ids.DuplicateSourcesForOutput, "Multiple source files ({0}) have resulted in the same output file '{1}'. This is likely because the source files only differ in extension or path. Rename the source files to avoid this problem.", sourceList, outputFile); | 323 | return Message(null, Ids.DuplicateSourcesForOutput, "Multiple source files ({0}) have resulted in the same output file '{1}'. This is likely because the source files only differ in extension or path. Rename the source files to avoid this problem.", sourceList, outputFile); |
324 | } | 324 | } |
325 | 325 | ||
326 | public static Message DuplicateSymbol(SourceLineNumber sourceLineNumbers, string symbolName) | ||
327 | { | ||
328 | return Message(sourceLineNumbers, Ids.DuplicateSymbol, "Duplicate symbol '{0}' found. This typically means that an Id is duplicated. Access modifiers (global, library, file, section) cannot prevent these conflicts. Ensure all your identifiers of a given type (Directory, File, etc.) are unique.", symbolName); | ||
329 | } | ||
330 | |||
331 | public static Message DuplicateSymbol(SourceLineNumber sourceLineNumbers, string symbolName, string referencingSourceLineNumber) | ||
332 | { | ||
333 | return Message(sourceLineNumbers, Ids.DuplicateSymbol, "Duplicate symbol '{0}' referenced by {1}. This typically means that an Id is duplicated. Ensure all your identifiers of a given type (Directory, File, etc.) are unique or use an access modifier to scope the identfier.", symbolName, referencingSourceLineNumber); | ||
334 | } | ||
335 | |||
336 | public static Message DuplicateSymbol2(SourceLineNumber sourceLineNumbers) | ||
337 | { | ||
338 | return Message(sourceLineNumbers, Ids.DuplicateSymbol2, "Location of symbol related to previous error."); | ||
339 | } | ||
340 | |||
341 | public static Message DuplicateTransform(string transform) | 326 | public static Message DuplicateTransform(string transform) |
342 | { | 327 | { |
343 | return Message(null, Ids.DuplicateTransform, "The transform {0} was included twice on the command line. Each transform can be applied to a patch only once.", transform); | 328 | return Message(null, Ids.DuplicateTransform, "The transform {0} was included twice on the command line. Each transform can be applied to a patch only once.", transform); |
@@ -2369,8 +2354,6 @@ namespace WixToolset.Data | |||
2369 | InvalidDateTimeFormat = 88, | 2354 | InvalidDateTimeFormat = 88, |
2370 | MultipleEntrySections = 89, | 2355 | MultipleEntrySections = 89, |
2371 | MultipleEntrySections2 = 90, | 2356 | MultipleEntrySections2 = 90, |
2372 | DuplicateSymbol = 91, | ||
2373 | DuplicateSymbol2 = 92, | ||
2374 | MissingEntrySection = 93, | 2357 | MissingEntrySection = 93, |
2375 | UnresolvedReference = 94, | 2358 | UnresolvedReference = 94, |
2376 | MultiplePrimaryReferences = 95, | 2359 | MultiplePrimaryReferences = 95, |
diff --git a/src/wix/WixToolset.Core/Link/FindEntrySectionAndLoadSymbolsCommand.cs b/src/wix/WixToolset.Core/Link/FindEntrySectionAndLoadSymbolsCommand.cs index e614d4eb..f9d6ab59 100644 --- a/src/wix/WixToolset.Core/Link/FindEntrySectionAndLoadSymbolsCommand.cs +++ b/src/wix/WixToolset.Core/Link/FindEntrySectionAndLoadSymbolsCommand.cs | |||
@@ -36,7 +36,7 @@ namespace WixToolset.Core.Link | |||
36 | /// <summary> | 36 | /// <summary> |
37 | /// Gets the collection of possibly conflicting symbols. | 37 | /// Gets the collection of possibly conflicting symbols. |
38 | /// </summary> | 38 | /// </summary> |
39 | public IEnumerable<SymbolWithSection> PossibleConflicts { get; private set; } | 39 | public IReadOnlyCollection<SymbolWithSection> PossibleConflicts { get; private set; } |
40 | 40 | ||
41 | /// <summary> | 41 | /// <summary> |
42 | /// Gets the collection of redundant symbols that should not be included | 42 | /// Gets the collection of redundant symbols that should not be included |
@@ -140,9 +140,7 @@ namespace WixToolset.Core.Link | |||
140 | { | 140 | { |
141 | if (symbolWithSection.Overrides is null) | 141 | if (symbolWithSection.Overrides is null) |
142 | { | 142 | { |
143 | var fullName = symbolWithSection.GetFullName(); | 143 | this.Messaging.Write(LinkerErrors.VirtualSymbolNotFoundForOverride(symbolWithSection.Symbol)); |
144 | |||
145 | this.Messaging.Write(LinkerErrors.VirtualSymbolNotFoundForOverride(symbolWithSection.Symbol.SourceLineNumbers, fullName)); | ||
146 | } | 144 | } |
147 | } | 145 | } |
148 | 146 | ||
diff --git a/src/wix/WixToolset.Core/Link/ReportConflictingSymbolsCommand.cs b/src/wix/WixToolset.Core/Link/ReportConflictingSymbolsCommand.cs index 3a07d366..2851fa60 100644 --- a/src/wix/WixToolset.Core/Link/ReportConflictingSymbolsCommand.cs +++ b/src/wix/WixToolset.Core/Link/ReportConflictingSymbolsCommand.cs | |||
@@ -9,7 +9,7 @@ namespace WixToolset.Core.Link | |||
9 | 9 | ||
10 | internal class ReportConflictingSymbolsCommand | 10 | internal class ReportConflictingSymbolsCommand |
11 | { | 11 | { |
12 | public ReportConflictingSymbolsCommand(IMessaging messaging, IEnumerable<SymbolWithSection> possibleConflicts, IEnumerable<IntermediateSection> resolvedSections) | 12 | public ReportConflictingSymbolsCommand(IMessaging messaging, IReadOnlyCollection<SymbolWithSection> possibleConflicts, ISet<IntermediateSection> resolvedSections) |
13 | { | 13 | { |
14 | this.Messaging = messaging; | 14 | this.Messaging = messaging; |
15 | this.PossibleConflicts = possibleConflicts; | 15 | this.PossibleConflicts = possibleConflicts; |
@@ -18,35 +18,62 @@ namespace WixToolset.Core.Link | |||
18 | 18 | ||
19 | private IMessaging Messaging { get; } | 19 | private IMessaging Messaging { get; } |
20 | 20 | ||
21 | private IEnumerable<SymbolWithSection> PossibleConflicts { get; } | 21 | private IReadOnlyCollection<SymbolWithSection> PossibleConflicts { get; } |
22 | 22 | ||
23 | private IEnumerable<IntermediateSection> ResolvedSections { get; } | 23 | private ISet<IntermediateSection> ResolvedSections { get; } |
24 | 24 | ||
25 | public void Execute() | 25 | public void Execute() |
26 | { | 26 | { |
27 | // Do a quick check if there are any possibly conflicting symbols that don't come from tables that allow | 27 | // Do a quick check if there are any possibly conflicting symbols. Hopefully the symbols with possible conflicts |
28 | // overriding. Hopefully the symbols with possible conflicts list is usually very short list (empty should | 28 | // list is a very short list (empty should be the most common). |
29 | // be the most common). If we find any matches, we'll do a more costly check to see if the possible conflicting | 29 | // |
30 | // If we have conflicts then we'll do a more costly check to see if the possible conflicting | ||
30 | // symbols are in sections we actually referenced. From the resulting set, show an error for each duplicate | 31 | // symbols are in sections we actually referenced. From the resulting set, show an error for each duplicate |
31 | // (aka: conflicting) symbol. | 32 | // (aka: conflicting) symbol. |
32 | var illegalDuplicates = this.PossibleConflicts.Where(s => s.Symbol.Definition.Type != SymbolDefinitionType.WixAction && s.Symbol.Definition.Type != SymbolDefinitionType.WixVariable).ToList(); | 33 | if (0 < this.PossibleConflicts.Count) |
33 | if (0 < illegalDuplicates.Count) | ||
34 | { | 34 | { |
35 | var referencedSections = new HashSet<IntermediateSection>(this.ResolvedSections); | 35 | foreach (var referencedDuplicate in this.PossibleConflicts.Where(s => this.ResolvedSections.Contains(s.Section))) |
36 | |||
37 | foreach (var referencedDuplicate in illegalDuplicates.Where(s => referencedSections.Contains(s.Section))) | ||
38 | { | 36 | { |
39 | var actuallyReferencedDuplicates = referencedDuplicate.PossiblyConflicts.Where(s => referencedSections.Contains(s.Section)).ToList(); | 37 | var actuallyReferencedDuplicates = referencedDuplicate.PossiblyConflicts.Where(s => this.ResolvedSections.Contains(s.Section)).ToList(); |
40 | 38 | ||
41 | if (actuallyReferencedDuplicates.Any()) | 39 | if (actuallyReferencedDuplicates.Count > 0) |
42 | { | 40 | { |
43 | var fullName = referencedDuplicate.GetFullName(); | 41 | var conflicts = actuallyReferencedDuplicates.Append(referencedDuplicate).ToList(); |
42 | var virtualConflicts = conflicts.Where(s => s.Access == AccessModifier.Virtual).ToList(); | ||
43 | var overrideConflicts = conflicts.Where(s => s.Access == AccessModifier.Override).ToList(); | ||
44 | var otherConflicts = conflicts.Where(s => s.Access != AccessModifier.Virtual && s.Access != AccessModifier.Override).ToList(); | ||
45 | |||
46 | IEnumerable<SymbolWithSection> reportDuplicates = actuallyReferencedDuplicates; | ||
47 | |||
48 | // If multiple symbols are virtual, use the duplicate virtual symbol message. | ||
49 | if (virtualConflicts.Count > 1) | ||
50 | { | ||
51 | var first = virtualConflicts[0]; | ||
52 | var referencingSourceLineNumber = first.DirectReferences.FirstOrDefault()?.SourceLineNumbers; | ||
44 | 53 | ||
45 | this.Messaging.Write(ErrorMessages.DuplicateSymbol(referencedDuplicate.Symbol.SourceLineNumbers, fullName)); | 54 | reportDuplicates = virtualConflicts.Skip(1); |
55 | |||
56 | this.Messaging.Write(LinkerErrors.DuplicateVirtualSymbol(first.Symbol, referencingSourceLineNumber)); | ||
57 | } | ||
58 | else if (virtualConflicts.Count == 1 && otherConflicts.Count > 0) | ||
59 | { | ||
60 | var first = otherConflicts[0]; | ||
61 | var referencingSourceLineNumber = first.DirectReferences.FirstOrDefault()?.SourceLineNumbers; | ||
62 | |||
63 | reportDuplicates = virtualConflicts; | ||
64 | |||
65 | this.Messaging.Write(LinkerErrors.VirtualSymbolMustBeOverridden(first.Symbol, referencingSourceLineNumber)); | ||
66 | } | ||
67 | else | ||
68 | { | ||
69 | var referencingSourceLineNumber = referencedDuplicate.DirectReferences.FirstOrDefault()?.SourceLineNumbers; | ||
70 | |||
71 | this.Messaging.Write(LinkerErrors.DuplicateSymbol(referencedDuplicate.Symbol, referencingSourceLineNumber)); | ||
72 | } | ||
46 | 73 | ||
47 | foreach (var duplicate in actuallyReferencedDuplicates) | 74 | foreach (var duplicate in reportDuplicates) |
48 | { | 75 | { |
49 | this.Messaging.Write(ErrorMessages.DuplicateSymbol2(duplicate.Symbol.SourceLineNumbers)); | 76 | this.Messaging.Write(LinkerErrors.DuplicateSymbol2(duplicate.Symbol)); |
50 | } | 77 | } |
51 | } | 78 | } |
52 | } | 79 | } |
diff --git a/src/wix/WixToolset.Core/Link/ResolveReferencesCommand.cs b/src/wix/WixToolset.Core/Link/ResolveReferencesCommand.cs index 0edbf39c..0e7a7a52 100644 --- a/src/wix/WixToolset.Core/Link/ResolveReferencesCommand.cs +++ b/src/wix/WixToolset.Core/Link/ResolveReferencesCommand.cs | |||
@@ -27,9 +27,9 @@ namespace WixToolset.Core.Link | |||
27 | this.BuildingMergeModule = (SectionType.Module == entrySection.Type); | 27 | this.BuildingMergeModule = (SectionType.Module == entrySection.Type); |
28 | } | 28 | } |
29 | 29 | ||
30 | public IEnumerable<SymbolWithSection> ReferencedSymbolWithSections => this.referencedSymbols; | 30 | public IReadOnlyCollection<SymbolWithSection> ReferencedSymbolWithSections => this.referencedSymbols; |
31 | 31 | ||
32 | public IEnumerable<IntermediateSection> ResolvedSections => this.resolvedSections; | 32 | public ISet<IntermediateSection> ResolvedSections => this.resolvedSections; |
33 | 33 | ||
34 | private bool BuildingMergeModule { get; } | 34 | private bool BuildingMergeModule { get; } |
35 | 35 | ||
@@ -63,22 +63,25 @@ namespace WixToolset.Core.Link | |||
63 | // symbols provided. Then recursively call this method to process the | 63 | // symbols provided. Then recursively call this method to process the |
64 | // located symbol's section. All in all this is a very simple depth-first | 64 | // located symbol's section. All in all this is a very simple depth-first |
65 | // search of the references per-section. | 65 | // search of the references per-section. |
66 | foreach (var wixSimpleReferenceRow in section.Symbols.OfType<WixSimpleReferenceSymbol>()) | 66 | foreach (var reference in section.Symbols.OfType<WixSimpleReferenceSymbol>()) |
67 | { | 67 | { |
68 | // If we're building a Merge Module, ignore all references to the Media table | 68 | // If we're building a Merge Module, ignore all references to the Media table |
69 | // because Merge Modules don't have Media tables. | 69 | // because Merge Modules don't have Media tables. |
70 | if (this.BuildingMergeModule && wixSimpleReferenceRow.Table == "Media") | 70 | if (this.BuildingMergeModule && reference.Table == "Media") |
71 | { | 71 | { |
72 | continue; | 72 | continue; |
73 | } | 73 | } |
74 | 74 | ||
75 | // See if the symbol (and any of its duplicates) are appropriately accessible. | 75 | // See if the symbol (and any of its duplicates) are appropriately accessible. |
76 | if (this.symbolsWithSections.TryGetValue(wixSimpleReferenceRow.SymbolicName, out var symbolWithSection)) | 76 | if (this.symbolsWithSections.TryGetValue(reference.SymbolicName, out var symbolWithSection)) |
77 | { | 77 | { |
78 | var accessible = this.DetermineAccessibleSymbols(section, symbolWithSection); | 78 | var accessible = this.DetermineAccessibleSymbols(section, symbolWithSection); |
79 | if (accessible.Count == 1) | 79 | if (accessible.Count == 1) |
80 | { | 80 | { |
81 | var accessibleSymbol = accessible[0]; | 81 | var accessibleSymbol = accessible[0]; |
82 | |||
83 | accessibleSymbol.AddDirectReference(reference); | ||
84 | |||
82 | if (this.referencedSymbols.Add(accessibleSymbol) && null != accessibleSymbol.Section) | 85 | if (this.referencedSymbols.Add(accessibleSymbol) && null != accessibleSymbol.Section) |
83 | { | 86 | { |
84 | this.RecursivelyResolveReferences(accessibleSymbol.Section); | 87 | this.RecursivelyResolveReferences(accessibleSymbol.Section); |
@@ -86,32 +89,34 @@ namespace WixToolset.Core.Link | |||
86 | } | 89 | } |
87 | else if (accessible.Count == 0) | 90 | else if (accessible.Count == 0) |
88 | { | 91 | { |
89 | this.Messaging.Write(ErrorMessages.UnresolvedReference(wixSimpleReferenceRow.SourceLineNumbers, wixSimpleReferenceRow.SymbolicName, symbolWithSection.Access)); | 92 | this.Messaging.Write(ErrorMessages.UnresolvedReference(reference.SourceLineNumbers, reference.SymbolicName, symbolWithSection.Access)); |
90 | } | 93 | } |
91 | else // display errors for the duplicate symbols. | 94 | else // multiple symbols referenced creates conflicting symbols. |
92 | { | 95 | { |
93 | var accessibleSymbol = accessible[0]; | 96 | // Remember the direct reference to the symbol for the error reporting later, |
94 | var accessibleFullName = accessibleSymbol.GetFullName(); | 97 | // but do NOT continue resolving references found in these conflicting symbols. |
95 | var referencingSourceLineNumber = wixSimpleReferenceRow.SourceLineNumbers?.ToString(); | 98 | foreach (var conflict in accessible) |
96 | |||
97 | if (String.IsNullOrEmpty(referencingSourceLineNumber)) | ||
98 | { | ||
99 | this.Messaging.Write(ErrorMessages.DuplicateSymbol(accessibleSymbol.Symbol.SourceLineNumbers, accessibleFullName)); | ||
100 | } | ||
101 | else | ||
102 | { | 99 | { |
103 | this.Messaging.Write(ErrorMessages.DuplicateSymbol(accessibleSymbol.Symbol.SourceLineNumbers, accessibleFullName, referencingSourceLineNumber)); | 100 | // This should NEVER happen. |
104 | } | 101 | if (!conflict.PossiblyConflicts.Any()) |
102 | { | ||
103 | throw new InvalidOperationException("If a reference can reference multiple symbols, those symbols MUST have already been recognized as possible conflicts."); | ||
104 | } | ||
105 | 105 | ||
106 | foreach (var accessibleDuplicate in accessible.Skip(1)) | 106 | conflict.AddDirectReference(reference); |
107 | { | 107 | |
108 | this.Messaging.Write(ErrorMessages.DuplicateSymbol2(accessibleDuplicate.Symbol.SourceLineNumbers)); | 108 | this.referencedSymbols.Add(conflict); |
109 | |||
110 | if (conflict.Section != null) | ||
111 | { | ||
112 | this.resolvedSections.Add(conflict.Section); | ||
113 | } | ||
109 | } | 114 | } |
110 | } | 115 | } |
111 | } | 116 | } |
112 | else | 117 | else |
113 | { | 118 | { |
114 | this.Messaging.Write(ErrorMessages.UnresolvedReference(wixSimpleReferenceRow.SourceLineNumbers, wixSimpleReferenceRow.SymbolicName)); | 119 | this.Messaging.Write(ErrorMessages.UnresolvedReference(reference.SourceLineNumbers, reference.SymbolicName)); |
115 | } | 120 | } |
116 | } | 121 | } |
117 | } | 122 | } |
@@ -133,14 +138,6 @@ namespace WixToolset.Core.Link | |||
133 | 138 | ||
134 | foreach (var dupe in symbolWithSection.PossiblyConflicts) | 139 | foreach (var dupe in symbolWithSection.PossiblyConflicts) |
135 | { | 140 | { |
136 | //// don't count overridable WixActionSymbols | ||
137 | //var symbolAction = symbolWithSection.Symbol as WixActionSymbol; | ||
138 | //var dupeAction = dupe.Symbol as WixActionSymbol; | ||
139 | //if (symbolAction?.Overridable != dupeAction?.Overridable) | ||
140 | //{ | ||
141 | // continue; | ||
142 | //} | ||
143 | |||
144 | if (this.AccessibleSymbol(referencingSection, dupe)) | 141 | if (this.AccessibleSymbol(referencingSection, dupe)) |
145 | { | 142 | { |
146 | accessibleSymbols.Add(dupe); | 143 | accessibleSymbols.Add(dupe); |
diff --git a/src/wix/WixToolset.Core/Link/SymbolWithSection.cs b/src/wix/WixToolset.Core/Link/SymbolWithSection.cs index 979aa44f..5bdf8360 100644 --- a/src/wix/WixToolset.Core/Link/SymbolWithSection.cs +++ b/src/wix/WixToolset.Core/Link/SymbolWithSection.cs | |||
@@ -6,12 +6,14 @@ namespace WixToolset.Core.Link | |||
6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
7 | using System.Linq; | 7 | using System.Linq; |
8 | using WixToolset.Data; | 8 | using WixToolset.Data; |
9 | using WixToolset.Data.Symbols; | ||
9 | 10 | ||
10 | /// <summary> | 11 | /// <summary> |
11 | /// Symbol with section representing a single unique symbol. | 12 | /// Symbol with section representing a single unique symbol. |
12 | /// </summary> | 13 | /// </summary> |
13 | internal class SymbolWithSection | 14 | internal class SymbolWithSection |
14 | { | 15 | { |
16 | private List<WixSimpleReferenceSymbol> directReferences; | ||
15 | private HashSet<SymbolWithSection> possibleConflicts; | 17 | private HashSet<SymbolWithSection> possibleConflicts; |
16 | 18 | ||
17 | /// <summary> | 19 | /// <summary> |
@@ -46,6 +48,11 @@ namespace WixToolset.Core.Link | |||
46 | /// <summary> | 48 | /// <summary> |
47 | /// Gets any duplicates of this symbol with sections that are possible conflicts. | 49 | /// Gets any duplicates of this symbol with sections that are possible conflicts. |
48 | /// </summary> | 50 | /// </summary> |
51 | public IEnumerable<WixSimpleReferenceSymbol> DirectReferences => this.directReferences ?? Enumerable.Empty<WixSimpleReferenceSymbol>(); | ||
52 | |||
53 | /// <summary> | ||
54 | /// Gets any duplicates of this symbol with sections that are possible conflicts. | ||
55 | /// </summary> | ||
49 | public IEnumerable<SymbolWithSection> PossiblyConflicts => this.possibleConflicts ?? Enumerable.Empty<SymbolWithSection>(); | 56 | public IEnumerable<SymbolWithSection> PossiblyConflicts => this.possibleConflicts ?? Enumerable.Empty<SymbolWithSection>(); |
50 | 57 | ||
51 | /// <summary> | 58 | /// <summary> |
@@ -68,6 +75,20 @@ namespace WixToolset.Core.Link | |||
68 | } | 75 | } |
69 | 76 | ||
70 | /// <summary> | 77 | /// <summary> |
78 | /// Adds a reference that directly points to this symbol. | ||
79 | /// </summary> | ||
80 | /// <param name="reference">The direct reference.</param> | ||
81 | public void AddDirectReference(WixSimpleReferenceSymbol reference) | ||
82 | { | ||
83 | if (null == this.directReferences) | ||
84 | { | ||
85 | this.directReferences = new List<WixSimpleReferenceSymbol>(); | ||
86 | } | ||
87 | |||
88 | this.directReferences.Add(reference); | ||
89 | } | ||
90 | |||
91 | /// <summary> | ||
71 | /// Override a virtual symbol. | 92 | /// Override a virtual symbol. |
72 | /// </summary> | 93 | /// </summary> |
73 | /// <param name="virtualSymbolWithSection">Virtual symbol with section that is being overridden.</param> | 94 | /// <param name="virtualSymbolWithSection">Virtual symbol with section that is being overridden.</param> |
diff --git a/src/wix/WixToolset.Core/LinkerErrors.cs b/src/wix/WixToolset.Core/LinkerErrors.cs index 78cd76f0..c234087e 100644 --- a/src/wix/WixToolset.Core/LinkerErrors.cs +++ b/src/wix/WixToolset.Core/LinkerErrors.cs | |||
@@ -11,6 +11,41 @@ namespace WixToolset.Core | |||
11 | return Message(null, Ids.DuplicateBindPathVariableOnCommandLine, "", argument, bindName, bindValue, collisionValue); | 11 | return Message(null, Ids.DuplicateBindPathVariableOnCommandLine, "", argument, bindName, bindValue, collisionValue); |
12 | } | 12 | } |
13 | 13 | ||
14 | public static Message DuplicateSymbol(IntermediateSymbol symbol) | ||
15 | { | ||
16 | return Message(symbol.SourceLineNumbers, Ids.DuplicateSymbol, "Duplicate {0} with identifier '{1}' found. Access modifiers (global, library, file, section) cannot prevent these conflicts. Ensure all your identifiers of a given type (Directory, File, etc.) are unique.", symbol.Definition.Name, symbol.Id.Id); | ||
17 | } | ||
18 | |||
19 | public static Message DuplicateSymbol(IntermediateSymbol symbol, SourceLineNumber referencingSourceLineNumber) | ||
20 | { | ||
21 | if (referencingSourceLineNumber is null) | ||
22 | { | ||
23 | return DuplicateSymbol(symbol); | ||
24 | } | ||
25 | |||
26 | return Message(symbol.SourceLineNumbers, Ids.DuplicateSymbol, "Duplicate {0} with identifier '{1}' referenced by {2}. Ensure all your identifiers of a given type (Directory, File, etc.) are unique or use an access modifier to scope the identfier.", symbol.Definition.Name, symbol.Id.Id, referencingSourceLineNumber); | ||
27 | } | ||
28 | |||
29 | public static Message DuplicateVirtualSymbol(IntermediateSymbol symbol) | ||
30 | { | ||
31 | return Message(symbol.SourceLineNumbers, Ids.DuplicateSymbol, "The virtual {0} with identifier '{1}' is duplicated. Ensure identifiers of a given type (Directory, File, etc.) are unique or did you mean to make one an override for the virtual symbol?", symbol.Definition.Name, symbol.Id.Id); | ||
32 | } | ||
33 | |||
34 | public static Message DuplicateVirtualSymbol(IntermediateSymbol symbol, SourceLineNumber referencingSourceLineNumber) | ||
35 | { | ||
36 | if (referencingSourceLineNumber is null) | ||
37 | { | ||
38 | return DuplicateVirtualSymbol(symbol); | ||
39 | } | ||
40 | |||
41 | return Message(symbol.SourceLineNumbers, Ids.DuplicateSymbol, "The virtual {0} with identifier '{1}' is duplicated. Ensure identifiers of a given type (Directory, File, etc.) are unique or did you mean to make one an override for the virtual symbol? Referenced from {2}", symbol.Definition.Name, symbol.Id.Id, referencingSourceLineNumber); | ||
42 | } | ||
43 | |||
44 | public static Message DuplicateSymbol2(IntermediateSymbol symbol) | ||
45 | { | ||
46 | return Message(symbol.SourceLineNumbers, Ids.DuplicateSymbol2, "Location of symbol related to previous error."); | ||
47 | } | ||
48 | |||
14 | public static Message OrphanedPayload(SourceLineNumber sourceLineNumbers, string payloadId) | 49 | public static Message OrphanedPayload(SourceLineNumber sourceLineNumbers, string payloadId) |
15 | { | 50 | { |
16 | return Message(sourceLineNumbers, Ids.OrphanedPayload, "Found orphaned Payload '{0}'. Make sure to reference it from a Package, the BootstrapperApplication, or the Bundle or move it into its own Fragment so it only gets linked in when actually used.", payloadId); | 51 | return Message(sourceLineNumbers, Ids.OrphanedPayload, "Found orphaned Payload '{0}'. Make sure to reference it from a Package, the BootstrapperApplication, or the Bundle or move it into its own Fragment so it only gets linked in when actually used.", payloadId); |
@@ -46,9 +81,34 @@ namespace WixToolset.Core | |||
46 | return Message(sourceLineNumbers, Ids.UncompressedPayloadInContainer, "The payload '{0}' is uncompressed and cannot be added to container '{1}'. Remove its Compressed attribute and provide a @SourceFile value to allow it to be added to a container.", payloadId, containerId); | 81 | return Message(sourceLineNumbers, Ids.UncompressedPayloadInContainer, "The payload '{0}' is uncompressed and cannot be added to container '{1}'. Remove its Compressed attribute and provide a @SourceFile value to allow it to be added to a container.", payloadId, containerId); |
47 | } | 82 | } |
48 | 83 | ||
49 | public static Message VirtualSymbolNotFoundForOverride(SourceLineNumber sourceLineNumbers, string id) | 84 | public static Message VirtualSymbolNotFoundForOverride(IntermediateSymbol symbol) |
85 | { | ||
86 | return Message(symbol.SourceLineNumbers, Ids.VirtualSymbolNotFoundForOverride, "Could not find a virtual symbol to override with the {0} symbol '{1}'. Remove the override access modifier or include the code with the virtual symbol.", symbol.Definition.Name, symbol.Id.Id); | ||
87 | } | ||
88 | |||
89 | public static Message VirtualSymbolNotFoundForOverride(IntermediateSymbol symbol, SourceLineNumber referencingSourceLineNumber) | ||
90 | { | ||
91 | if (referencingSourceLineNumber is null) | ||
92 | { | ||
93 | return VirtualSymbolNotFoundForOverride(symbol); | ||
94 | } | ||
95 | |||
96 | return Message(symbol.SourceLineNumbers, Ids.VirtualSymbolNotFoundForOverride, "Could not find a virtual symbol to override with the {0} symbol '{1}'. Remove the override access modifier or include the code with the virtual symbol. Referenced from {2}", symbol.Definition.Name, symbol.Id.Id, referencingSourceLineNumber); | ||
97 | } | ||
98 | |||
99 | public static Message VirtualSymbolMustBeOverridden(IntermediateSymbol symbol) | ||
50 | { | 100 | { |
51 | return Message(sourceLineNumbers, Ids.VirtualSymbolNotFoundForOverride, "Did not find virtual symbol for override symbol '{0}'",id); | 101 | return Message(symbol.SourceLineNumbers, Ids.VirtualSymbolMustBeOverridden, "The {0} symbol '{1}' conflicts with a virtual symbol. Use the 'override' access modifier to override the virtual symbol or use a different Id to avoid the conflict.", symbol.Definition.Name, symbol.Id.Id); |
102 | } | ||
103 | |||
104 | public static Message VirtualSymbolMustBeOverridden(IntermediateSymbol symbol, SourceLineNumber referencingSourceLineNumber) | ||
105 | { | ||
106 | if (referencingSourceLineNumber is null) | ||
107 | { | ||
108 | return VirtualSymbolMustBeOverridden(symbol); | ||
109 | } | ||
110 | |||
111 | return Message(symbol.SourceLineNumbers, Ids.VirtualSymbolMustBeOverridden, "The {0} symbol '{1}' conflicts with a virtual symbol. Use the 'override' access modifier to override the virtual symbol or use a different Id to avoid the conflict. Referenced from {2}", symbol.Definition.Name, symbol.Id.Id, referencingSourceLineNumber); | ||
52 | } | 112 | } |
53 | 113 | ||
54 | private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args) | 114 | private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args) |
@@ -58,6 +118,9 @@ namespace WixToolset.Core | |||
58 | 118 | ||
59 | public enum Ids | 119 | public enum Ids |
60 | { | 120 | { |
121 | DuplicateSymbol = 91, | ||
122 | DuplicateSymbol2 = 92, | ||
123 | |||
61 | OrphanedPayload = 7000, | 124 | OrphanedPayload = 7000, |
62 | PackageInMultipleContainers = 7001, | 125 | PackageInMultipleContainers = 7001, |
63 | PayloadSharedWithBA = 7002, | 126 | PayloadSharedWithBA = 7002, |
@@ -67,6 +130,7 @@ namespace WixToolset.Core | |||
67 | BAContainerCannotContainRemotePayload = 7006, | 130 | BAContainerCannotContainRemotePayload = 7006, |
68 | DuplicateBindPathVariableOnCommandLine = 7007, | 131 | DuplicateBindPathVariableOnCommandLine = 7007, |
69 | VirtualSymbolNotFoundForOverride = 7008, | 132 | VirtualSymbolNotFoundForOverride = 7008, |
133 | VirtualSymbolMustBeOverridden = 7009, | ||
70 | } // last available is 7099. 7100 is WindowsInstallerBackendWarnings. | 134 | } // last available is 7099. 7100 is WindowsInstallerBackendWarnings. |
71 | } | 135 | } |
72 | } | 136 | } |
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/AccessModifierFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/AccessModifierFixture.cs index d0e31760..5e40114f 100644 --- a/src/wix/test/WixToolsetTest.CoreIntegration/AccessModifierFixture.cs +++ b/src/wix/test/WixToolsetTest.CoreIntegration/AccessModifierFixture.cs | |||
@@ -78,8 +78,8 @@ namespace WixToolsetTest.CoreIntegration | |||
78 | var errors = BuildForFailure("TestData", "AccessModifier", "DuplicateCrossFragmentReference.wxs"); | 78 | var errors = BuildForFailure("TestData", "AccessModifier", "DuplicateCrossFragmentReference.wxs"); |
79 | WixAssert.CompareLineByLine(new[] | 79 | WixAssert.CompareLineByLine(new[] |
80 | { | 80 | { |
81 | @"ln 8: Duplicate symbol 'Directory:TestFolder' referenced by <sourceFolder>\DuplicateCrossFragmentReference.wxs(4). This typically means that an Id is duplicated. Ensure all your identifiers of a given type (Directory, File, etc.) are unique or use an access modifier to scope the identfier.", | 81 | "ln 12: Duplicate Directory with identifier 'TestFolder' referenced by <sourceFolder>\\DuplicateCrossFragmentReference.wxs(4). Ensure all your identifiers of a given type (Directory, File, etc.) are unique or use an access modifier to scope the identfier.", |
82 | "ln 12: Location of symbol related to previous error." | 82 | "ln 8: Location of symbol related to previous error." |
83 | }, errors); | 83 | }, errors); |
84 | } | 84 | } |
85 | 85 | ||
@@ -89,7 +89,7 @@ namespace WixToolsetTest.CoreIntegration | |||
89 | var errors = BuildForFailure("TestData", "AccessModifier", "OverrideWithoutVirtualSymbol.wxs"); | 89 | var errors = BuildForFailure("TestData", "AccessModifier", "OverrideWithoutVirtualSymbol.wxs"); |
90 | WixAssert.CompareLineByLine(new[] | 90 | WixAssert.CompareLineByLine(new[] |
91 | { | 91 | { |
92 | "ln 5: Did not find virtual symbol for override symbol 'Directory:TestFolder'", | 92 | "ln 5: Could not find a virtual symbol to override with the Directory symbol 'TestFolder'. Remove the override access modifier or include the code with the virtual symbol.", |
93 | }, errors); | 93 | }, errors); |
94 | } | 94 | } |
95 | 95 | ||
@@ -99,7 +99,40 @@ namespace WixToolsetTest.CoreIntegration | |||
99 | var errors = BuildForFailure("TestData", "AccessModifier", "DuplicatedOverrideVirtualSymbol.wxs"); | 99 | var errors = BuildForFailure("TestData", "AccessModifier", "DuplicatedOverrideVirtualSymbol.wxs"); |
100 | WixAssert.CompareLineByLine(new[] | 100 | WixAssert.CompareLineByLine(new[] |
101 | { | 101 | { |
102 | "ln 14: Duplicate symbol 'Directory:TestFolder' found. This typically means that an Id is duplicated. Access modifiers (global, library, file, section) cannot prevent these conflicts. Ensure all your identifiers of a given type (Directory, File, etc.) are unique.", | 102 | "ln 14: Duplicate Directory with identifier 'TestFolder' found. Access modifiers (global, library, file, section) cannot prevent these conflicts. Ensure all your identifiers of a given type (Directory, File, etc.) are unique.", |
103 | "ln 6: Location of symbol related to previous error." | ||
104 | }, errors); | ||
105 | } | ||
106 | |||
107 | [Fact] | ||
108 | public void CannotCompileDuplicatedVirtual() | ||
109 | { | ||
110 | var errors = BuildForFailure("TestData", "AccessModifier", "DuplicatedVirtualSymbol.wxs"); | ||
111 | WixAssert.CompareLineByLine(new[] | ||
112 | { | ||
113 | "ln 6: The virtual Directory with identifier 'TestFolder' is duplicated. Ensure identifiers of a given type (Directory, File, etc.) are unique or did you mean to make one an override for the virtual symbol?", | ||
114 | "ln 10: Location of symbol related to previous error." | ||
115 | }, errors); | ||
116 | } | ||
117 | |||
118 | [Fact] | ||
119 | public void CannotCompilePublicWithVirtualSymbol() | ||
120 | { | ||
121 | var errors = BuildForFailure("TestData", "AccessModifier", "VirtualSymbolWithoutOverride.wxs"); | ||
122 | WixAssert.CompareLineByLine(new[] | ||
123 | { | ||
124 | "ln 9: The Directory symbol 'TestFolder' conflicts with a virtual symbol. Use the 'override' access modifier to override the virtual symbol or use a different Id to avoid the conflict.", | ||
125 | "ln 5: Location of symbol related to previous error." | ||
126 | }, errors); | ||
127 | } | ||
128 | |||
129 | [Fact] | ||
130 | public void CannotCompilePublicAndOverrideWithVirtualSymbol() | ||
131 | { | ||
132 | var errors = BuildForFailure("TestData", "AccessModifier", "DuplicatePublicOverrideVirtualSymbol.wxs"); | ||
133 | WixAssert.CompareLineByLine(new[] | ||
134 | { | ||
135 | "ln 14: Duplicate Directory with identifier 'TestFolder' found. Access modifiers (global, library, file, section) cannot prevent these conflicts. Ensure all your identifiers of a given type (Directory, File, etc.) are unique.", | ||
103 | "ln 6: Location of symbol related to previous error." | 136 | "ln 6: Location of symbol related to previous error." |
104 | }, errors); | 137 | }, errors); |
105 | } | 138 | } |
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/RegistryFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/RegistryFixture.cs index 7bf10e3f..9931a45a 100644 --- a/src/wix/test/WixToolsetTest.CoreIntegration/RegistryFixture.cs +++ b/src/wix/test/WixToolsetTest.CoreIntegration/RegistryFixture.cs | |||
@@ -4,8 +4,8 @@ namespace WixToolsetTest.CoreIntegration | |||
4 | { | 4 | { |
5 | using System.IO; | 5 | using System.IO; |
6 | using System.Linq; | 6 | using System.Linq; |
7 | using WixInternal.TestSupport; | ||
8 | using WixInternal.Core.TestPackage; | 7 | using WixInternal.Core.TestPackage; |
8 | using WixInternal.TestSupport; | ||
9 | using WixToolset.Data; | 9 | using WixToolset.Data; |
10 | using Xunit; | 10 | using Xunit; |
11 | 11 | ||
@@ -97,8 +97,16 @@ namespace WixToolsetTest.CoreIntegration | |||
97 | "-o", msiPath | 97 | "-o", msiPath |
98 | }, out var messages); | 98 | }, out var messages); |
99 | 99 | ||
100 | Assert.Equal(2, messages.Where(m => m.Id == (int)ErrorMessages.Ids.DuplicateSymbol).Count()); | 100 | var errors = messages.Where(m => m.Level == MessageLevel.Error) |
101 | Assert.Equal(2, messages.Where(m => m.Id == (int)ErrorMessages.Ids.DuplicateSymbol2).Count()); | 101 | .Select(m => $"ln {m.SourceLineNumbers.LineNumber}: {m}".Replace(baseFolder, "<baseFolder>").Replace(folder, "<sourceFolder>")) |
102 | .ToArray(); | ||
103 | WixAssert.CompareLineByLine(new[] | ||
104 | { | ||
105 | "ln 8: Duplicate Registry with identifier 'regJnkjRU9YGaMJhQOqKmivWKf_VdY' found. Access modifiers (global, library, file, section) cannot prevent these conflicts. Ensure all your identifiers of a given type (Directory, File, etc.) are unique.", | ||
106 | "ln 7: Location of symbol related to previous error.", | ||
107 | "ln 9: Duplicate Registry with identifier 'regJnkjRU9YGaMJhQOqKmivWKf_VdY' found. Access modifiers (global, library, file, section) cannot prevent these conflicts. Ensure all your identifiers of a given type (Directory, File, etc.) are unique.", | ||
108 | "ln 7: Location of symbol related to previous error." | ||
109 | }, errors); | ||
102 | } | 110 | } |
103 | } | 111 | } |
104 | 112 | ||
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/RollbackBoundaryFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/RollbackBoundaryFixture.cs index 8d8ac801..54375f67 100644 --- a/src/wix/test/WixToolsetTest.CoreIntegration/RollbackBoundaryFixture.cs +++ b/src/wix/test/WixToolsetTest.CoreIntegration/RollbackBoundaryFixture.cs | |||
@@ -66,7 +66,7 @@ namespace WixToolsetTest.CoreIntegration | |||
66 | 66 | ||
67 | WixAssert.CompareLineByLine(new[] | 67 | WixAssert.CompareLineByLine(new[] |
68 | { | 68 | { |
69 | "Duplicate symbol 'WixChainItem:collision' found. This typically means that an Id is duplicated. Access modifiers (global, library, file, section) cannot prevent these conflicts. Ensure all your identifiers of a given type (Directory, File, etc.) are unique.", | 69 | "Duplicate WixChainItem with identifier 'collision' found. Access modifiers (global, library, file, section) cannot prevent these conflicts. Ensure all your identifiers of a given type (Directory, File, etc.) are unique.", |
70 | "Location of symbol related to previous error.", | 70 | "Location of symbol related to previous error.", |
71 | }, result.Messages.Select(m => m.ToString()).ToArray()); | 71 | }, result.Messages.Select(m => m.ToString()).ToArray()); |
72 | 72 | ||
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/AccessModifier/DuplicatePublicOverrideVirtualSymbol.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/AccessModifier/DuplicatePublicOverrideVirtualSymbol.wxs new file mode 100644 index 00000000..7ecf4445 --- /dev/null +++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/AccessModifier/DuplicatePublicOverrideVirtualSymbol.wxs | |||
@@ -0,0 +1,17 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
3 | <Package Name="Duplicated Override Virtual Symbol" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a"> | ||
4 | |||
5 | <StandardDirectory Id="ProgramFilesFolder"> | ||
6 | <Directory Id="override TestFolder" Name="Override Test Folder" /> | ||
7 | </StandardDirectory> | ||
8 | |||
9 | <StandardDirectory Id="ProgramFilesFolder"> | ||
10 | <Directory Id="virtual TestFolder" Name="Test Folder" /> | ||
11 | </StandardDirectory> | ||
12 | |||
13 | <StandardDirectory Id="ProgramFilesFolder"> | ||
14 | <Directory Id="TestFolder" Name="Collision Test Folder" /> | ||
15 | </StandardDirectory> | ||
16 | </Package> | ||
17 | </Wix> | ||
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/AccessModifier/DuplicatedVirtualSymbol.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/AccessModifier/DuplicatedVirtualSymbol.wxs new file mode 100644 index 00000000..e97d0b57 --- /dev/null +++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/AccessModifier/DuplicatedVirtualSymbol.wxs | |||
@@ -0,0 +1,13 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
3 | <Package Name="Duplicated Override Virtual Symbol" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a"> | ||
4 | |||
5 | <StandardDirectory Id="ProgramFilesFolder"> | ||
6 | <Directory Id="virtual TestFolder" Name="First Virtual Test Folder" /> | ||
7 | </StandardDirectory> | ||
8 | |||
9 | <StandardDirectory Id="ProgramFilesFolder"> | ||
10 | <Directory Id="virtual TestFolder" Name="Second Virtual Test Folder" /> | ||
11 | </StandardDirectory> | ||
12 | </Package> | ||
13 | </Wix> | ||
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/AccessModifier/VirtualSymbolWithoutOverride.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/AccessModifier/VirtualSymbolWithoutOverride.wxs new file mode 100644 index 00000000..3db854f5 --- /dev/null +++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/AccessModifier/VirtualSymbolWithoutOverride.wxs | |||
@@ -0,0 +1,12 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> | ||
3 | <Package Name="Override Without Virtual Symbol" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a"> | ||
4 | <StandardDirectory Id="ProgramFilesFolder"> | ||
5 | <Directory Id="virtual TestFolder" Name="Test Folder" /> | ||
6 | </StandardDirectory> | ||
7 | |||
8 | <StandardDirectory Id="ProgramFilesFolder"> | ||
9 | <Directory Id="TestFolder" Name="Missing Override Access Modifier" /> | ||
10 | </StandardDirectory> | ||
11 | </Package> | ||
12 | </Wix> | ||