diff options
Diffstat (limited to 'src')
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> | ||
