diff options
| author | Rob Mensching <rob@firegiant.com> | 2017-11-01 10:59:45 -0700 |
|---|---|---|
| committer | Rob Mensching <rob@firegiant.com> | 2017-11-01 10:59:45 -0700 |
| commit | 2bb37beda887d120a0ddabf874ad25357101faa1 (patch) | |
| tree | c35e97b03274b86cfc9ff7fd2caeee211165a140 /src/WixToolset.Core/Link | |
| parent | df7413aeed3aea3425dff20ae0c8b1be3a3ab525 (diff) | |
| download | wix-2bb37beda887d120a0ddabf874ad25357101faa1.tar.gz wix-2bb37beda887d120a0ddabf874ad25357101faa1.tar.bz2 wix-2bb37beda887d120a0ddabf874ad25357101faa1.zip | |
Update to WiX Intermediate Representation
Diffstat (limited to 'src/WixToolset.Core/Link')
7 files changed, 277 insertions, 212 deletions
diff --git a/src/WixToolset.Core/Link/ConnectToFeature.cs b/src/WixToolset.Core/Link/ConnectToFeature.cs index 6e046b89..bc85426a 100644 --- a/src/WixToolset.Core/Link/ConnectToFeature.cs +++ b/src/WixToolset.Core/Link/ConnectToFeature.cs | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | 2 | ||
| 3 | namespace WixToolset.Link | 3 | namespace WixToolset.Link |
| 4 | { | 4 | { |
| 5 | using System.Collections.Specialized; | 5 | using System.Collections.Generic; |
| 6 | using WixToolset.Data; | 6 | using WixToolset.Data; |
| 7 | 7 | ||
| 8 | /// <summary> | 8 | /// <summary> |
| @@ -10,19 +10,12 @@ namespace WixToolset.Link | |||
| 10 | /// </summary> | 10 | /// </summary> |
| 11 | public sealed class ConnectToFeature | 11 | public sealed class ConnectToFeature |
| 12 | { | 12 | { |
| 13 | private Section section; | ||
| 14 | private string childId; | ||
| 15 | |||
| 16 | private string primaryFeature; | ||
| 17 | private bool explicitPrimaryFeature; | ||
| 18 | private StringCollection connectFeatures; | ||
| 19 | |||
| 20 | /// <summary> | 13 | /// <summary> |
| 21 | /// Creates a new connect to feature. | 14 | /// Creates a new connect to feature. |
| 22 | /// </summary> | 15 | /// </summary> |
| 23 | /// <param name="section">Section this connect belongs to.</param> | 16 | /// <param name="section">Section this connect belongs to.</param> |
| 24 | /// <param name="childId">Id of the child.</param> | 17 | /// <param name="childId">Id of the child.</param> |
| 25 | public ConnectToFeature(Section section, string childId) : | 18 | public ConnectToFeature(IntermediateSection section, string childId) : |
| 26 | this(section, childId, null, false) | 19 | this(section, childId, null, false) |
| 27 | { | 20 | { |
| 28 | } | 21 | } |
| @@ -34,62 +27,43 @@ namespace WixToolset.Link | |||
| 34 | /// <param name="childId">Id of the child.</param> | 27 | /// <param name="childId">Id of the child.</param> |
| 35 | /// <param name="primaryFeature">Sets the primary feature for the connection.</param> | 28 | /// <param name="primaryFeature">Sets the primary feature for the connection.</param> |
| 36 | /// <param name="explicitPrimaryFeature">Sets if this is explicit primary.</param> | 29 | /// <param name="explicitPrimaryFeature">Sets if this is explicit primary.</param> |
| 37 | public ConnectToFeature(Section section, string childId, string primaryFeature, bool explicitPrimaryFeature) | 30 | public ConnectToFeature(IntermediateSection section, string childId, string primaryFeature, bool explicitPrimaryFeature) |
| 38 | { | 31 | { |
| 39 | this.section = section; | 32 | this.Section = section; |
| 40 | this.childId = childId; | 33 | this.ChildId = childId; |
| 41 | 34 | ||
| 42 | this.primaryFeature = primaryFeature; | 35 | this.PrimaryFeature = primaryFeature; |
| 43 | this.explicitPrimaryFeature = explicitPrimaryFeature; | 36 | this.IsExplicitPrimaryFeature = explicitPrimaryFeature; |
| 44 | |||
| 45 | this.connectFeatures = new StringCollection(); | ||
| 46 | } | 37 | } |
| 47 | 38 | ||
| 48 | /// <summary> | 39 | /// <summary> |
| 49 | /// Gets the section. | 40 | /// Gets the section. |
| 50 | /// </summary> | 41 | /// </summary> |
| 51 | /// <value>Section.</value> | 42 | /// <value>Section.</value> |
| 52 | public Section Section | 43 | public IntermediateSection Section { get; } |
| 53 | { | ||
| 54 | get { return this.section; } | ||
| 55 | } | ||
| 56 | 44 | ||
| 57 | /// <summary> | 45 | /// <summary> |
| 58 | /// Gets the child identifier. | 46 | /// Gets the child identifier. |
| 59 | /// </summary> | 47 | /// </summary> |
| 60 | /// <value>The child identifier.</value> | 48 | /// <value>The child identifier.</value> |
| 61 | public string ChildId | 49 | public string ChildId { get; } |
| 62 | { | ||
| 63 | get { return this.childId; } | ||
| 64 | } | ||
| 65 | 50 | ||
| 66 | /// <summary> | 51 | /// <summary> |
| 67 | /// Gets or sets if the flag for if the primary feature was set explicitly. | 52 | /// Gets or sets if the flag for if the primary feature was set explicitly. |
| 68 | /// </summary> | 53 | /// </summary> |
| 69 | /// <value>The flag for if the primary feature was set explicitly.</value> | 54 | /// <value>The flag for if the primary feature was set explicitly.</value> |
| 70 | public bool IsExplicitPrimaryFeature | 55 | public bool IsExplicitPrimaryFeature { get; set; } |
| 71 | { | ||
| 72 | get { return this.explicitPrimaryFeature; } | ||
| 73 | set { this.explicitPrimaryFeature = value; } | ||
| 74 | } | ||
| 75 | 56 | ||
| 76 | /// <summary> | 57 | /// <summary> |
| 77 | /// Gets or sets the primary feature. | 58 | /// Gets or sets the primary feature. |
| 78 | /// </summary> | 59 | /// </summary> |
| 79 | /// <value>The primary feature.</value> | 60 | /// <value>The primary feature.</value> |
| 80 | public string PrimaryFeature | 61 | public string PrimaryFeature { get; set; } |
| 81 | { | ||
| 82 | get { return this.primaryFeature; } | ||
| 83 | set { this.primaryFeature = value; } | ||
| 84 | } | ||
| 85 | 62 | ||
| 86 | /// <summary> | 63 | /// <summary> |
| 87 | /// Gets the features connected to. | 64 | /// Gets the features connected to. |
| 88 | /// </summary> | 65 | /// </summary> |
| 89 | /// <value>Features connected to.</value> | 66 | /// <value>Features connected to.</value> |
| 90 | public StringCollection ConnectFeatures | 67 | public List<string> ConnectFeatures { get; } = new List<string>(); |
| 91 | { | ||
| 92 | get { return this.connectFeatures; } | ||
| 93 | } | ||
| 94 | } | 68 | } |
| 95 | } | 69 | } |
diff --git a/src/WixToolset.Core/Link/FindEntrySectionAndLoadSymbolsCommand.cs b/src/WixToolset.Core/Link/FindEntrySectionAndLoadSymbolsCommand.cs index effb06e4..00613ca1 100644 --- a/src/WixToolset.Core/Link/FindEntrySectionAndLoadSymbolsCommand.cs +++ b/src/WixToolset.Core/Link/FindEntrySectionAndLoadSymbolsCommand.cs | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
| 2 | 2 | ||
| 3 | namespace WixToolset.Link | 3 | namespace WixToolset.Core.Link |
| 4 | { | 4 | { |
| 5 | using System; | 5 | using System; |
| 6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
| @@ -9,13 +9,13 @@ namespace WixToolset.Link | |||
| 9 | 9 | ||
| 10 | internal class FindEntrySectionAndLoadSymbolsCommand : ICommand | 10 | internal class FindEntrySectionAndLoadSymbolsCommand : ICommand |
| 11 | { | 11 | { |
| 12 | private IEnumerable<Section> sections; | 12 | public FindEntrySectionAndLoadSymbolsCommand(IEnumerable<IntermediateSection> sections) |
| 13 | |||
| 14 | public FindEntrySectionAndLoadSymbolsCommand(IEnumerable<Section> sections) | ||
| 15 | { | 13 | { |
| 16 | this.sections = sections; | 14 | this.Sections = sections; |
| 17 | } | 15 | } |
| 18 | 16 | ||
| 17 | private IEnumerable<IntermediateSection> Sections { get; } | ||
| 18 | |||
| 19 | /// <summary> | 19 | /// <summary> |
| 20 | /// Sets the expected entry output type, based on output file extension provided to the linker. | 20 | /// Sets the expected entry output type, based on output file extension provided to the linker. |
| 21 | /// </summary> | 21 | /// </summary> |
| @@ -24,13 +24,16 @@ namespace WixToolset.Link | |||
| 24 | /// <summary> | 24 | /// <summary> |
| 25 | /// Gets the located entry section after the command is executed. | 25 | /// Gets the located entry section after the command is executed. |
| 26 | /// </summary> | 26 | /// </summary> |
| 27 | public Section EntrySection { get; private set; } | 27 | public IntermediateSection EntrySection { get; private set; } |
| 28 | 28 | ||
| 29 | /// <summary> | 29 | /// <summary> |
| 30 | /// Gets the collection of loaded symbols. | 30 | /// Gets the collection of loaded symbols. |
| 31 | /// </summary> | 31 | /// </summary> |
| 32 | public IDictionary<string, Symbol> Symbols { get; private set; } | 32 | public IDictionary<string, Symbol> Symbols { get; private set; } |
| 33 | 33 | ||
| 34 | /// <summary> | ||
| 35 | /// Gets the collection of possibly conflicting symbols. | ||
| 36 | /// </summary> | ||
| 34 | public IEnumerable<Symbol> PossiblyConflictingSymbols { get; private set; } | 37 | public IEnumerable<Symbol> PossiblyConflictingSymbols { get; private set; } |
| 35 | 38 | ||
| 36 | public void Execute() | 39 | public void Execute() |
| @@ -38,22 +41,22 @@ namespace WixToolset.Link | |||
| 38 | Dictionary<string, Symbol> symbols = new Dictionary<string, Symbol>(); | 41 | Dictionary<string, Symbol> symbols = new Dictionary<string, Symbol>(); |
| 39 | HashSet<Symbol> possibleConflicts = new HashSet<Symbol>(); | 42 | HashSet<Symbol> possibleConflicts = new HashSet<Symbol>(); |
| 40 | 43 | ||
| 41 | SectionType expectedEntrySectionType; | 44 | if (!Enum.TryParse(this.ExpectedOutputType.ToString(), out SectionType expectedEntrySectionType)) |
| 42 | if (!Enum.TryParse<SectionType>(this.ExpectedOutputType.ToString(), out expectedEntrySectionType)) | ||
| 43 | { | 45 | { |
| 44 | expectedEntrySectionType = SectionType.Unknown; | 46 | expectedEntrySectionType = SectionType.Unknown; |
| 45 | } | 47 | } |
| 46 | 48 | ||
| 47 | foreach (Section section in this.sections) | 49 | foreach (var section in this.Sections) |
| 48 | { | 50 | { |
| 49 | // Try to find the one and only entry section. | 51 | // Try to find the one and only entry section. |
| 50 | if (SectionType.Product == section.Type || SectionType.Module == section.Type || SectionType.PatchCreation == section.Type || SectionType.Patch == section.Type || SectionType.Bundle == section.Type) | 52 | if (SectionType.Product == section.Type || SectionType.Module == section.Type || SectionType.PatchCreation == section.Type || SectionType.Patch == section.Type || SectionType.Bundle == section.Type) |
| 51 | { | 53 | { |
| 52 | if (SectionType.Unknown != expectedEntrySectionType && section.Type != expectedEntrySectionType) | 54 | // TODO: remove this? |
| 53 | { | 55 | //if (SectionType.Unknown != expectedEntrySectionType && section.Type != expectedEntrySectionType) |
| 54 | string outputExtension = Output.GetExtension(this.ExpectedOutputType); | 56 | //{ |
| 55 | Messaging.Instance.OnMessage(WixWarnings.UnexpectedEntrySection(section.SourceLineNumbers, section.Type.ToString(), expectedEntrySectionType.ToString(), outputExtension)); | 57 | // string outputExtension = Output.GetExtension(this.ExpectedOutputType); |
| 56 | } | 58 | // Messaging.Instance.OnMessage(WixWarnings.UnexpectedEntrySection(section.SourceLineNumbers, section.Type.ToString(), expectedEntrySectionType.ToString(), outputExtension)); |
| 59 | //} | ||
| 57 | 60 | ||
| 58 | if (null == this.EntrySection) | 61 | if (null == this.EntrySection) |
| 59 | { | 62 | { |
| @@ -61,42 +64,38 @@ namespace WixToolset.Link | |||
| 61 | } | 64 | } |
| 62 | else | 65 | else |
| 63 | { | 66 | { |
| 64 | Messaging.Instance.OnMessage(WixErrors.MultipleEntrySections(this.EntrySection.SourceLineNumbers, this.EntrySection.Id, section.Id)); | 67 | Messaging.Instance.OnMessage(WixErrors.MultipleEntrySections(this.EntrySection.Tuples.FirstOrDefault()?.SourceLineNumbers, this.EntrySection.Id, section.Id)); |
| 65 | Messaging.Instance.OnMessage(WixErrors.MultipleEntrySections2(section.SourceLineNumbers)); | 68 | Messaging.Instance.OnMessage(WixErrors.MultipleEntrySections2(section.Tuples.FirstOrDefault()?.SourceLineNumbers)); |
| 66 | } | 69 | } |
| 67 | } | 70 | } |
| 68 | 71 | ||
| 69 | // Load all the symbols from the section's tables that create symbols. | 72 | // Load all the symbols from the section's tables that create symbols. |
| 70 | foreach (Table table in section.Tables.Where(t => t.Definition.CreateSymbols)) | 73 | foreach (var row in section.Tuples.Where(t => t.Id != null)) |
| 71 | { | 74 | { |
| 72 | foreach (Row row in table.Rows) | 75 | var symbol = new Symbol(section, row); |
| 73 | { | ||
| 74 | Symbol symbol = new Symbol(row); | ||
| 75 | 76 | ||
| 76 | Symbol existingSymbol; | 77 | if (!symbols.TryGetValue(symbol.Name, out var existingSymbol)) |
| 77 | if (!symbols.TryGetValue(symbol.Name, out existingSymbol)) | 78 | { |
| 79 | symbols.Add(symbol.Name, symbol); | ||
| 80 | } | ||
| 81 | else // uh-oh, duplicate symbols. | ||
| 82 | { | ||
| 83 | // If the duplicate symbols are both private directories, there is a chance that they | ||
| 84 | // point to identical tuples. Identical directory tuples are redundant and will not cause | ||
| 85 | // conflicts. | ||
| 86 | if (AccessModifier.Private == existingSymbol.Access && AccessModifier.Private == symbol.Access && | ||
| 87 | TupleDefinitionType.Directory == existingSymbol.Row.Definition.Type && existingSymbol.Row.IsIdentical(symbol.Row)) | ||
| 78 | { | 88 | { |
| 79 | symbols.Add(symbol.Name, symbol); | 89 | // Ensure identical symbol's tuple is marked redundant to ensure (should the tuple be |
| 90 | // referenced into the final output) it will not add duplicate primary keys during | ||
| 91 | // the .IDT importing. | ||
| 92 | //symbol.Row.Redundant = true; - TODO: remove this | ||
| 93 | existingSymbol.AddRedundant(symbol); | ||
| 80 | } | 94 | } |
| 81 | else // uh-oh, duplicate symbols. | 95 | else |
| 82 | { | 96 | { |
| 83 | // If the duplicate symbols are both private directories, there is a chance that they | 97 | existingSymbol.AddPossibleConflict(symbol); |
| 84 | // point to identical rows. Identical directory rows are redundant and will not cause | 98 | possibleConflicts.Add(existingSymbol); |
| 85 | // conflicts. | ||
| 86 | if (AccessModifier.Private == existingSymbol.Access && AccessModifier.Private == symbol.Access && | ||
| 87 | "Directory" == existingSymbol.Row.Table.Name && existingSymbol.Row.IsIdentical(symbol.Row)) | ||
| 88 | { | ||
| 89 | // Ensure identical symbol's row is marked redundant to ensure (should the row be | ||
| 90 | // referenced into the final output) it will not add duplicate primary keys during | ||
| 91 | // the .IDT importing. | ||
| 92 | symbol.Row.Redundant = true; | ||
| 93 | existingSymbol.AddRedundant(symbol); | ||
| 94 | } | ||
| 95 | else | ||
| 96 | { | ||
| 97 | existingSymbol.AddPossibleConflict(symbol); | ||
| 98 | possibleConflicts.Add(existingSymbol); | ||
| 99 | } | ||
| 100 | } | 99 | } |
| 101 | } | 100 | } |
| 102 | } | 101 | } |
diff --git a/src/WixToolset.Core/Link/IntermediateTupleExtensions.cs b/src/WixToolset.Core/Link/IntermediateTupleExtensions.cs new file mode 100644 index 00000000..c4c12e81 --- /dev/null +++ b/src/WixToolset.Core/Link/IntermediateTupleExtensions.cs | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Core.Link | ||
| 4 | { | ||
| 5 | using WixToolset.Data; | ||
| 6 | |||
| 7 | internal static class IntermediateTupleExtensions | ||
| 8 | { | ||
| 9 | public static bool IsIdentical(this IntermediateTuple first, IntermediateTuple second) | ||
| 10 | { | ||
| 11 | var identical = (first.Definition.Type == second.Definition.Type && | ||
| 12 | first.Definition.Name == second.Definition.Name && | ||
| 13 | first.Definition.FieldDefinitions.Length == second.Definition.FieldDefinitions.Length); | ||
| 14 | |||
| 15 | for (int i = 0; identical && i < first.Definition.FieldDefinitions.Length; ++i) | ||
| 16 | { | ||
| 17 | var firstField = first[i]; | ||
| 18 | var secondField = second[i]; | ||
| 19 | |||
| 20 | identical = (firstField.AsString() == secondField.AsString()); | ||
| 21 | } | ||
| 22 | |||
| 23 | return identical; | ||
| 24 | } | ||
| 25 | } | ||
| 26 | } | ||
diff --git a/src/WixToolset.Core/Link/ReportConflictingSymbolsCommand.cs b/src/WixToolset.Core/Link/ReportConflictingSymbolsCommand.cs index 39c3a5c2..ac0dd7ec 100644 --- a/src/WixToolset.Core/Link/ReportConflictingSymbolsCommand.cs +++ b/src/WixToolset.Core/Link/ReportConflictingSymbolsCommand.cs | |||
| @@ -6,17 +6,18 @@ namespace WixToolset.Link | |||
| 6 | using System.Linq; | 6 | using System.Linq; |
| 7 | using WixToolset.Data; | 7 | using WixToolset.Data; |
| 8 | 8 | ||
| 9 | public class ReportConflictingSymbolsCommand : ICommand | 9 | public class ReportConflictingSymbolsCommand |
| 10 | { | 10 | { |
| 11 | private IEnumerable<Symbol> possibleConflicts; | 11 | public ReportConflictingSymbolsCommand(IEnumerable<Symbol> possibleConflicts, IEnumerable<IntermediateSection> resolvedSections) |
| 12 | private IEnumerable<Section> resolvedSections; | ||
| 13 | |||
| 14 | public ReportConflictingSymbolsCommand(IEnumerable<Symbol> possibleConflicts, IEnumerable<Section> resolvedSections) | ||
| 15 | { | 12 | { |
| 16 | this.possibleConflicts = possibleConflicts; | 13 | this.PossibleConflicts = possibleConflicts; |
| 17 | this.resolvedSections = resolvedSections; | 14 | this.ResolvedSections = resolvedSections; |
| 18 | } | 15 | } |
| 19 | 16 | ||
| 17 | private IEnumerable<Symbol> PossibleConflicts { get; } | ||
| 18 | |||
| 19 | private IEnumerable<IntermediateSection> ResolvedSections { get; } | ||
| 20 | |||
| 20 | public void Execute() | 21 | public void Execute() |
| 21 | { | 22 | { |
| 22 | // Do a quick check if there are any possibly conflicting symbols that don't come from tables that allow | 23 | // Do a quick check if there are any possibly conflicting symbols that don't come from tables that allow |
| @@ -25,10 +26,11 @@ namespace WixToolset.Link | |||
| 25 | // symbols are in sections we actually referenced. From the resulting set, show an error for each duplicate | 26 | // symbols are in sections we actually referenced. From the resulting set, show an error for each duplicate |
| 26 | // (aka: conflicting) symbol. This should catch any rows with colliding primary keys (since symbols are based | 27 | // (aka: conflicting) symbol. This should catch any rows with colliding primary keys (since symbols are based |
| 27 | // on the primary keys of rows). | 28 | // on the primary keys of rows). |
| 28 | List<Symbol> illegalDuplicates = possibleConflicts.Where(s => "WixAction" != s.Row.Table.Name && "WixVariable" != s.Row.Table.Name).ToList(); | 29 | var illegalDuplicates = this.PossibleConflicts.Where(s => s.Row.Definition.Type != TupleDefinitionType.WixAction && s.Row.Definition.Type != TupleDefinitionType.WixVariable).ToList(); |
| 29 | if (0 < illegalDuplicates.Count) | 30 | if (0 < illegalDuplicates.Count) |
| 30 | { | 31 | { |
| 31 | HashSet<Section> referencedSections = new HashSet<Section>(resolvedSections); | 32 | var referencedSections = new HashSet<IntermediateSection>(this.ResolvedSections); |
| 33 | |||
| 32 | foreach (Symbol referencedDuplicateSymbol in illegalDuplicates.Where(s => referencedSections.Contains(s.Section))) | 34 | foreach (Symbol referencedDuplicateSymbol in illegalDuplicates.Where(s => referencedSections.Contains(s.Section))) |
| 33 | { | 35 | { |
| 34 | List<Symbol> actuallyReferencedDuplicateSymbols = referencedDuplicateSymbol.PossiblyConflictingSymbols.Where(s => referencedSections.Contains(s.Section)).ToList(); | 36 | List<Symbol> actuallyReferencedDuplicateSymbols = referencedDuplicateSymbol.PossiblyConflictingSymbols.Where(s => referencedSections.Contains(s.Section)).ToList(); |
diff --git a/src/WixToolset.Core/Link/ResolveReferencesCommand.cs b/src/WixToolset.Core/Link/ResolveReferencesCommand.cs index 5a985f3f..9c3b2765 100644 --- a/src/WixToolset.Core/Link/ResolveReferencesCommand.cs +++ b/src/WixToolset.Core/Link/ResolveReferencesCommand.cs | |||
| @@ -4,22 +4,21 @@ namespace WixToolset.Link | |||
| 4 | { | 4 | { |
| 5 | using System; | 5 | using System; |
| 6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
| 7 | using System.Diagnostics; | ||
| 8 | using System.Linq; | 7 | using System.Linq; |
| 9 | using WixToolset.Data; | 8 | using WixToolset.Data; |
| 10 | using WixToolset.Data.Rows; | 9 | using WixToolset.Data.Tuples; |
| 11 | 10 | ||
| 12 | /// <summary> | 11 | /// <summary> |
| 13 | /// Resolves all the simple references in a section. | 12 | /// Resolves all the simple references in a section. |
| 14 | /// </summary> | 13 | /// </summary> |
| 15 | internal class ResolveReferencesCommand : ICommand | 14 | internal class ResolveReferencesCommand : ICommand |
| 16 | { | 15 | { |
| 17 | private Section entrySection; | 16 | private IntermediateSection entrySection; |
| 18 | private IDictionary<string, Symbol> symbols; | 17 | private IDictionary<string, Symbol> symbols; |
| 19 | private HashSet<Symbol> referencedSymbols; | 18 | private HashSet<Symbol> referencedSymbols; |
| 20 | private HashSet<Section> resolvedSections; | 19 | private HashSet<IntermediateSection> resolvedSections; |
| 21 | 20 | ||
| 22 | public ResolveReferencesCommand(Section entrySection, IDictionary<string, Symbol> symbols) | 21 | public ResolveReferencesCommand(IntermediateSection entrySection, IDictionary<string, Symbol> symbols) |
| 23 | { | 22 | { |
| 24 | this.entrySection = entrySection; | 23 | this.entrySection = entrySection; |
| 25 | this.symbols = symbols; | 24 | this.symbols = symbols; |
| @@ -29,14 +28,14 @@ namespace WixToolset.Link | |||
| 29 | 28 | ||
| 30 | public IEnumerable<Symbol> ReferencedSymbols { get { return this.referencedSymbols; } } | 29 | public IEnumerable<Symbol> ReferencedSymbols { get { return this.referencedSymbols; } } |
| 31 | 30 | ||
| 32 | public IEnumerable<Section> ResolvedSections { get { return this.resolvedSections; } } | 31 | public IEnumerable<IntermediateSection> ResolvedSections { get { return this.resolvedSections; } } |
| 33 | 32 | ||
| 34 | /// <summary> | 33 | /// <summary> |
| 35 | /// Resolves all the simple references in a section. | 34 | /// Resolves all the simple references in a section. |
| 36 | /// </summary> | 35 | /// </summary> |
| 37 | public void Execute() | 36 | public void Execute() |
| 38 | { | 37 | { |
| 39 | this.resolvedSections = new HashSet<Section>(); | 38 | this.resolvedSections = new HashSet<IntermediateSection>(); |
| 40 | this.referencedSymbols = new HashSet<Symbol>(); | 39 | this.referencedSymbols = new HashSet<Symbol>(); |
| 41 | 40 | ||
| 42 | this.RecursivelyResolveReferences(this.entrySection); | 41 | this.RecursivelyResolveReferences(this.entrySection); |
| @@ -47,7 +46,7 @@ namespace WixToolset.Link | |||
| 47 | /// </summary> | 46 | /// </summary> |
| 48 | /// <param name="section">Section with references to resolve.</param> | 47 | /// <param name="section">Section with references to resolve.</param> |
| 49 | /// <remarks>Note: recursive function.</remarks> | 48 | /// <remarks>Note: recursive function.</remarks> |
| 50 | private void RecursivelyResolveReferences(Section section) | 49 | private void RecursivelyResolveReferences(IntermediateSection section) |
| 51 | { | 50 | { |
| 52 | // If we already resolved this section, move on to the next. | 51 | // If we already resolved this section, move on to the next. |
| 53 | if (!this.resolvedSections.Add(section)) | 52 | if (!this.resolvedSections.Add(section)) |
| @@ -59,59 +58,53 @@ namespace WixToolset.Link | |||
| 59 | // symbols provided. Then recursively call this method to process the | 58 | // symbols provided. Then recursively call this method to process the |
| 60 | // located symbol's section. All in all this is a very simple depth-first | 59 | // located symbol's section. All in all this is a very simple depth-first |
| 61 | // search of the references per-section. | 60 | // search of the references per-section. |
| 62 | Table wixSimpleReferenceTable; | 61 | foreach (var wixSimpleReferenceRow in section.Tuples.OfType<WixSimpleReferenceTuple>()) |
| 63 | if (section.Tables.TryGetTable("WixSimpleReference", out wixSimpleReferenceTable)) | ||
| 64 | { | 62 | { |
| 65 | foreach (WixSimpleReferenceRow wixSimpleReferenceRow in wixSimpleReferenceTable.Rows) | 63 | // If we're building a Merge Module, ignore all references to the Media table |
| 64 | // because Merge Modules don't have Media tables. | ||
| 65 | if (this.BuildingMergeModule && wixSimpleReferenceRow.Definition.Type == TupleDefinitionType.Media) | ||
| 66 | { | 66 | { |
| 67 | Debug.Assert(wixSimpleReferenceRow.Section == section); | 67 | continue; |
| 68 | } | ||
| 68 | 69 | ||
| 69 | // If we're building a Merge Module, ignore all references to the Media table | 70 | if (!this.symbols.TryGetValue(wixSimpleReferenceRow.SymbolicName, out var symbol)) |
| 70 | // because Merge Modules don't have Media tables. | 71 | { |
| 71 | if (this.BuildingMergeModule && "Media" == wixSimpleReferenceRow.TableName) | 72 | Messaging.Instance.OnMessage(WixErrors.UnresolvedReference(wixSimpleReferenceRow.SourceLineNumbers, wixSimpleReferenceRow.SymbolicName)); |
| 73 | } | ||
| 74 | else // see if the symbol (and any of its duplicates) are appropriately accessible. | ||
| 75 | { | ||
| 76 | IList<Symbol> accessible = DetermineAccessibleSymbols(section, symbol); | ||
| 77 | if (!accessible.Any()) | ||
| 72 | { | 78 | { |
| 73 | continue; | 79 | Messaging.Instance.OnMessage(WixErrors.UnresolvedReference(wixSimpleReferenceRow.SourceLineNumbers, wixSimpleReferenceRow.SymbolicName, symbol.Access)); |
| 74 | } | 80 | } |
| 75 | 81 | else if (1 == accessible.Count) | |
| 76 | Symbol symbol; | ||
| 77 | if (!this.symbols.TryGetValue(wixSimpleReferenceRow.SymbolicName, out symbol)) | ||
| 78 | { | 82 | { |
| 79 | Messaging.Instance.OnMessage(WixErrors.UnresolvedReference(wixSimpleReferenceRow.SourceLineNumbers, wixSimpleReferenceRow.SymbolicName)); | 83 | var accessibleSymbol = accessible[0]; |
| 84 | this.referencedSymbols.Add(accessibleSymbol); | ||
| 85 | |||
| 86 | if (null != accessibleSymbol.Section) | ||
| 87 | { | ||
| 88 | RecursivelyResolveReferences(accessibleSymbol.Section); | ||
| 89 | } | ||
| 80 | } | 90 | } |
| 81 | else // see if the symbol (and any of its duplicates) are appropriately accessible. | 91 | else // display errors for the duplicate symbols. |
| 82 | { | 92 | { |
| 83 | IList<Symbol> accessible = DetermineAccessibleSymbols(section, symbol); | 93 | var accessibleSymbol = accessible[0]; |
| 84 | if (!accessible.Any()) | 94 | var referencingSourceLineNumber = wixSimpleReferenceRow.SourceLineNumbers.ToString(); |
| 95 | |||
| 96 | if (String.IsNullOrEmpty(referencingSourceLineNumber)) | ||
| 85 | { | 97 | { |
| 86 | Messaging.Instance.OnMessage(WixErrors.UnresolvedReference(wixSimpleReferenceRow.SourceLineNumbers, wixSimpleReferenceRow.SymbolicName, symbol.Access)); | 98 | Messaging.Instance.OnMessage(WixErrors.DuplicateSymbol(accessibleSymbol.Row.SourceLineNumbers, accessibleSymbol.Name)); |
| 87 | } | 99 | } |
| 88 | else if (1 == accessible.Count) | 100 | else |
| 89 | { | 101 | { |
| 90 | Symbol accessibleSymbol = accessible[0]; | 102 | Messaging.Instance.OnMessage(WixErrors.DuplicateSymbol(accessibleSymbol.Row.SourceLineNumbers, accessibleSymbol.Name, referencingSourceLineNumber)); |
| 91 | this.referencedSymbols.Add(accessibleSymbol); | ||
| 92 | |||
| 93 | if (null != accessibleSymbol.Section) | ||
| 94 | { | ||
| 95 | RecursivelyResolveReferences(accessibleSymbol.Section); | ||
| 96 | } | ||
| 97 | } | 103 | } |
| 98 | else // display errors for the duplicate symbols. | 104 | |
| 105 | foreach (Symbol accessibleDuplicate in accessible.Skip(1)) | ||
| 99 | { | 106 | { |
| 100 | Symbol accessibleSymbol = accessible[0]; | 107 | Messaging.Instance.OnMessage(WixErrors.DuplicateSymbol2(accessibleDuplicate.Row.SourceLineNumbers)); |
| 101 | string referencingSourceLineNumber = wixSimpleReferenceRow.SourceLineNumbers.ToString(); | ||
| 102 | if (String.IsNullOrEmpty(referencingSourceLineNumber)) | ||
| 103 | { | ||
| 104 | Messaging.Instance.OnMessage(WixErrors.DuplicateSymbol(accessibleSymbol.Row.SourceLineNumbers, accessibleSymbol.Name)); | ||
| 105 | } | ||
| 106 | else | ||
| 107 | { | ||
| 108 | Messaging.Instance.OnMessage(WixErrors.DuplicateSymbol(accessibleSymbol.Row.SourceLineNumbers, accessibleSymbol.Name, referencingSourceLineNumber)); | ||
| 109 | } | ||
| 110 | |||
| 111 | foreach (Symbol accessibleDuplicate in accessible.Skip(1)) | ||
| 112 | { | ||
| 113 | Messaging.Instance.OnMessage(WixErrors.DuplicateSymbol2(accessibleDuplicate.Row.SourceLineNumbers)); | ||
| 114 | } | ||
| 115 | } | 108 | } |
| 116 | } | 109 | } |
| 117 | } | 110 | } |
| @@ -124,7 +117,7 @@ namespace WixToolset.Link | |||
| 124 | /// <param name="referencingSection">Section referencing the symbol.</param> | 117 | /// <param name="referencingSection">Section referencing the symbol.</param> |
| 125 | /// <param name="symbol">Symbol being referenced.</param> | 118 | /// <param name="symbol">Symbol being referenced.</param> |
| 126 | /// <returns>List of symbols accessible by referencing section.</returns> | 119 | /// <returns>List of symbols accessible by referencing section.</returns> |
| 127 | private IList<Symbol> DetermineAccessibleSymbols(Section referencingSection, Symbol symbol) | 120 | private IList<Symbol> DetermineAccessibleSymbols(IntermediateSection referencingSection, Symbol symbol) |
| 128 | { | 121 | { |
| 129 | List<Symbol> symbols = new List<Symbol>(); | 122 | List<Symbol> symbols = new List<Symbol>(); |
| 130 | 123 | ||
| @@ -158,20 +151,20 @@ namespace WixToolset.Link | |||
| 158 | /// <param name="referencingSection">Section referencing the symbol.</param> | 151 | /// <param name="referencingSection">Section referencing the symbol.</param> |
| 159 | /// <param name="symbol">Symbol being referenced.</param> | 152 | /// <param name="symbol">Symbol being referenced.</param> |
| 160 | /// <returns>True if symbol is accessible.</returns> | 153 | /// <returns>True if symbol is accessible.</returns> |
| 161 | private bool AccessibleSymbol(Section referencingSection, Symbol symbol) | 154 | private bool AccessibleSymbol(IntermediateSection referencingSection, Symbol symbol) |
| 162 | { | 155 | { |
| 163 | switch (symbol.Access) | 156 | switch (symbol.Access) |
| 164 | { | 157 | { |
| 165 | case AccessModifier.Public: | 158 | case AccessModifier.Public: |
| 166 | return true; | 159 | return true; |
| 167 | case AccessModifier.Internal: | 160 | case AccessModifier.Internal: |
| 168 | return symbol.Row.Section.IntermediateId.Equals(referencingSection.IntermediateId) || (null != symbol.Row.Section.LibraryId && symbol.Row.Section.LibraryId.Equals(referencingSection.LibraryId)); | 161 | return symbol.Section.CompilationId.Equals(referencingSection.CompilationId) || (null != symbol.Section.LibraryId && symbol.Section.LibraryId.Equals(referencingSection.LibraryId)); |
| 169 | case AccessModifier.Protected: | 162 | case AccessModifier.Protected: |
| 170 | return symbol.Row.Section.IntermediateId.Equals(referencingSection.IntermediateId); | 163 | return symbol.Section.CompilationId.Equals(referencingSection.CompilationId); |
| 171 | case AccessModifier.Private: | 164 | case AccessModifier.Private: |
| 172 | return referencingSection == symbol.Section; | 165 | return referencingSection == symbol.Section; |
| 173 | default: | 166 | default: |
| 174 | throw new InvalidOperationException(); | 167 | throw new ArgumentOutOfRangeException(nameof(symbol.Access)); |
| 175 | } | 168 | } |
| 176 | } | 169 | } |
| 177 | } | 170 | } |
diff --git a/src/WixToolset.Core/Link/WixComplexReferenceTupleExtensions.cs b/src/WixToolset.Core/Link/WixComplexReferenceTupleExtensions.cs new file mode 100644 index 00000000..80cafa50 --- /dev/null +++ b/src/WixToolset.Core/Link/WixComplexReferenceTupleExtensions.cs | |||
| @@ -0,0 +1,73 @@ | |||
| 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
| 2 | |||
| 3 | namespace WixToolset.Core.Link | ||
| 4 | { | ||
| 5 | using System; | ||
| 6 | using WixToolset.Data.Tuples; | ||
| 7 | |||
| 8 | internal static class WixComplexReferenceTupleExtensions | ||
| 9 | { | ||
| 10 | /// <summary> | ||
| 11 | /// Creates a shallow copy of the ComplexReference. | ||
| 12 | /// </summary> | ||
| 13 | /// <returns>A shallow copy of the ComplexReference.</returns> | ||
| 14 | public static WixComplexReferenceTuple Clone(this WixComplexReferenceTuple source) | ||
| 15 | { | ||
| 16 | var clone = new WixComplexReferenceTuple(source.SourceLineNumbers, source.Id); | ||
| 17 | clone.ParentType = source.ParentType; | ||
| 18 | clone.Parent = source.Parent; | ||
| 19 | clone.ParentLanguage = source.ParentLanguage; | ||
| 20 | clone.ChildType = source.ChildType; | ||
| 21 | clone.Child = source.Child; | ||
| 22 | clone.IsPrimary = source.IsPrimary; | ||
| 23 | |||
| 24 | return clone; | ||
| 25 | } | ||
| 26 | |||
| 27 | /// <summary> | ||
| 28 | /// Compares two complex references without considering the primary bit. | ||
| 29 | /// </summary> | ||
| 30 | /// <param name="obj">Complex reference to compare to.</param> | ||
| 31 | /// <returns>Zero if the objects are equivalent, negative number if the provided object is less, positive if greater.</returns> | ||
| 32 | public static int CompareToWithoutConsideringPrimary(this WixComplexReferenceTuple tuple, WixComplexReferenceTuple other) | ||
| 33 | { | ||
| 34 | var comparison = tuple.ChildType - other.ChildType; | ||
| 35 | if (0 == comparison) | ||
| 36 | { | ||
| 37 | comparison = String.Compare(tuple.Child, other.Child, StringComparison.Ordinal); | ||
| 38 | if (0 == comparison) | ||
| 39 | { | ||
| 40 | comparison = tuple.ParentType - other.ParentType; | ||
| 41 | if (0 == comparison) | ||
| 42 | { | ||
| 43 | string thisParentLanguage = null == tuple.ParentLanguage ? String.Empty : tuple.ParentLanguage; | ||
| 44 | string otherParentLanguage = null == other.ParentLanguage ? String.Empty : other.ParentLanguage; | ||
| 45 | comparison = String.Compare(thisParentLanguage, otherParentLanguage, StringComparison.Ordinal); | ||
| 46 | if (0 == comparison) | ||
| 47 | { | ||
| 48 | comparison = String.Compare(tuple.Parent, other.Parent, StringComparison.Ordinal); | ||
| 49 | } | ||
| 50 | } | ||
| 51 | } | ||
| 52 | } | ||
| 53 | |||
| 54 | return comparison; | ||
| 55 | } | ||
| 56 | |||
| 57 | /// <summary> | ||
| 58 | /// Changes all of the parent references to point to the passed in parent reference. | ||
| 59 | /// </summary> | ||
| 60 | /// <param name="parent">New parent complex reference.</param> | ||
| 61 | public static void Reparent(this WixComplexReferenceTuple tuple, WixComplexReferenceTuple parent) | ||
| 62 | { | ||
| 63 | tuple.Parent = parent.Parent; | ||
| 64 | tuple.ParentLanguage = parent.ParentLanguage; | ||
| 65 | tuple.ParentType = parent.ParentType; | ||
| 66 | |||
| 67 | if (!tuple.IsPrimary) | ||
| 68 | { | ||
| 69 | tuple.IsPrimary = parent.IsPrimary; | ||
| 70 | } | ||
| 71 | } | ||
| 72 | } | ||
| 73 | } | ||
diff --git a/src/WixToolset.Core/Link/WixGroupingOrdering.cs b/src/WixToolset.Core/Link/WixGroupingOrdering.cs index fc0ce43b..4dd1596c 100644 --- a/src/WixToolset.Core/Link/WixGroupingOrdering.cs +++ b/src/WixToolset.Core/Link/WixGroupingOrdering.cs | |||
| @@ -12,13 +12,13 @@ namespace WixToolset.Link | |||
| 12 | using System.Text; | 12 | using System.Text; |
| 13 | using WixToolset.Extensibility; | 13 | using WixToolset.Extensibility; |
| 14 | using WixToolset.Data; | 14 | using WixToolset.Data; |
| 15 | using WixToolset.Data.Tuples; | ||
| 15 | 16 | ||
| 16 | /// <summary> | 17 | /// <summary> |
| 17 | /// Grouping and Ordering class of the WiX toolset. | 18 | /// Grouping and Ordering class of the WiX toolset. |
| 18 | /// </summary> | 19 | /// </summary> |
| 19 | internal sealed class WixGroupingOrdering : IMessageHandler | 20 | internal sealed class WixGroupingOrdering : IMessageHandler |
| 20 | { | 21 | { |
| 21 | private Output output; | ||
| 22 | private IMessageHandler messageHandler; | 22 | private IMessageHandler messageHandler; |
| 23 | private List<string> groupTypes; | 23 | private List<string> groupTypes; |
| 24 | private List<string> itemTypes; | 24 | private List<string> itemTypes; |
| @@ -34,9 +34,9 @@ namespace WixToolset.Link | |||
| 34 | /// <param name="messageHandler">Handler for any error messages.</param> | 34 | /// <param name="messageHandler">Handler for any error messages.</param> |
| 35 | /// <param name="groupTypes">Group types to include.</param> | 35 | /// <param name="groupTypes">Group types to include.</param> |
| 36 | /// <param name="itemTypes">Item types to include.</param> | 36 | /// <param name="itemTypes">Item types to include.</param> |
| 37 | public WixGroupingOrdering(Output output, IMessageHandler messageHandler) | 37 | public WixGroupingOrdering(IntermediateSection entrySections, IMessageHandler messageHandler) |
| 38 | { | 38 | { |
| 39 | this.output = output; | 39 | this.EntrySection = entrySections; |
| 40 | this.messageHandler = messageHandler; | 40 | this.messageHandler = messageHandler; |
| 41 | 41 | ||
| 42 | this.rowsUsed = new List<int>(); | 42 | this.rowsUsed = new List<int>(); |
| @@ -44,6 +44,8 @@ namespace WixToolset.Link | |||
| 44 | this.encounteredError = false; | 44 | this.encounteredError = false; |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | private IntermediateSection EntrySection { get; } | ||
| 48 | |||
| 47 | /// <summary> | 49 | /// <summary> |
| 48 | /// Switches a WixGroupingOrdering object to operate on a new set of groups/items. | 50 | /// Switches a WixGroupingOrdering object to operate on a new set of groups/items. |
| 49 | /// </summary> | 51 | /// </summary> |
| @@ -91,8 +93,7 @@ namespace WixToolset.Link | |||
| 91 | { | 93 | { |
| 92 | Debug.Assert(this.groupTypes.Contains(parentType)); | 94 | Debug.Assert(this.groupTypes.Contains(parentType)); |
| 93 | 95 | ||
| 94 | List<Item> orderedItems; | 96 | this.CreateOrderedList(parentType, parentId, out var orderedItems); |
| 95 | this.CreateOrderedList(parentType, parentId, out orderedItems); | ||
| 96 | if (this.encounteredError) | 97 | if (this.encounteredError) |
| 97 | { | 98 | { |
| 98 | return; | 99 | return; |
| @@ -170,15 +171,16 @@ namespace WixToolset.Link | |||
| 170 | /// </summary> | 171 | /// </summary> |
| 171 | public void RemoveUsedGroupRows() | 172 | public void RemoveUsedGroupRows() |
| 172 | { | 173 | { |
| 173 | List<int> sortedIndexes = this.rowsUsed.Distinct().OrderByDescending(i => i).ToList(); | 174 | var sortedIndexes = this.rowsUsed.Distinct().OrderByDescending(i => i).ToList(); |
| 174 | 175 | ||
| 175 | Table wixGroupTable = this.output.Tables["WixGroup"]; | 176 | //Table wixGroupTable = this.output.Tables["WixGroup"]; |
| 176 | Debug.Assert(null != wixGroupTable); | 177 | //Debug.Assert(null != wixGroupTable); |
| 177 | Debug.Assert(sortedIndexes[0] < wixGroupTable.Rows.Count); | 178 | //Debug.Assert(sortedIndexes[0] < wixGroupTable.Rows.Count); |
| 178 | 179 | ||
| 179 | foreach (int rowIndex in sortedIndexes) | 180 | foreach (int rowIndex in sortedIndexes) |
| 180 | { | 181 | { |
| 181 | wixGroupTable.Rows.RemoveAt(rowIndex); | 182 | //wixGroupTable.Rows.RemoveAt(rowIndex); |
| 183 | this.EntrySection.Tuples.RemoveAt(rowIndex); | ||
| 182 | } | 184 | } |
| 183 | } | 185 | } |
| 184 | 186 | ||
| @@ -194,16 +196,15 @@ namespace WixToolset.Link | |||
| 194 | // does WiX (although they do, currently). We probably want to "upgrade" this to a new | 196 | // does WiX (although they do, currently). We probably want to "upgrade" this to a new |
| 195 | // table that includes a sequence number, and then change the code that uses ordered | 197 | // table that includes a sequence number, and then change the code that uses ordered |
| 196 | // groups to read from that table instead. | 198 | // groups to read from that table instead. |
| 197 | Table wixGroupTable = this.output.Tables["WixGroup"]; | ||
| 198 | Debug.Assert(null != wixGroupTable); | ||
| 199 | |||
| 200 | foreach (Item item in orderedItems) | 199 | foreach (Item item in orderedItems) |
| 201 | { | 200 | { |
| 202 | Row row = wixGroupTable.CreateRow(item.Row.SourceLineNumbers); | 201 | var row = new WixGroupTuple(item.Row.SourceLineNumbers); |
| 203 | row[0] = parentId; | 202 | row.ParentId = parentId; |
| 204 | row[1] = parentType; | 203 | row.ParentType = (ComplexReferenceParentType)Enum.Parse(typeof(ComplexReferenceParentType), parentType); |
| 205 | row[2] = item.Id; | 204 | row.ChildId = item.Id; |
| 206 | row[3] = item.Type; | 205 | row.ChildType = (ComplexReferenceChildType)Enum.Parse(typeof(ComplexReferenceChildType), item.Type); |
| 206 | |||
| 207 | this.EntrySection.Tuples.Add(row); | ||
| 207 | } | 208 | } |
| 208 | } | 209 | } |
| 209 | 210 | ||
| @@ -254,47 +255,47 @@ namespace WixToolset.Link | |||
| 254 | /// </summary> | 255 | /// </summary> |
| 255 | private void LoadGroups() | 256 | private void LoadGroups() |
| 256 | { | 257 | { |
| 257 | Table wixGroupTable = this.output.Tables["WixGroup"]; | 258 | //Table wixGroupTable = this.output.Tables["WixGroup"]; |
| 258 | if (null == wixGroupTable || 0 == wixGroupTable.Rows.Count) | 259 | //if (null == wixGroupTable || 0 == wixGroupTable.Rows.Count) |
| 259 | { | 260 | //{ |
| 260 | // TODO: Change message name to make it *not* Bundle specific? | 261 | // // TODO: Change message name to make it *not* Bundle specific? |
| 261 | this.OnMessage(WixErrors.MissingBundleInformation("WixGroup")); | 262 | // this.OnMessage(WixErrors.MissingBundleInformation("WixGroup")); |
| 262 | } | 263 | //} |
| 263 | 264 | ||
| 264 | // Collect all of the groups | 265 | // Collect all of the groups |
| 265 | for (int rowIndex = 0; rowIndex < wixGroupTable.Rows.Count; ++rowIndex) | 266 | for (int rowIndex = 0; rowIndex < this.EntrySection.Tuples.Count; ++rowIndex) |
| 266 | { | 267 | { |
| 267 | Row row = wixGroupTable.Rows[rowIndex]; | 268 | if (this.EntrySection.Tuples[rowIndex] is WixGroupTuple row) |
| 268 | string rowParentName = (string)row[0]; | ||
| 269 | string rowParentType = (string)row[1]; | ||
| 270 | string rowChildName = (string)row[2]; | ||
| 271 | string rowChildType = (string)row[3]; | ||
| 272 | |||
| 273 | // If this row specifies a parent or child type that's not in our | ||
| 274 | // lists, we assume it's not a row that we're concerned about. | ||
| 275 | if (!this.groupTypes.Contains(rowParentType) || | ||
| 276 | !this.itemTypes.Contains(rowChildType)) | ||
| 277 | { | 269 | { |
| 278 | continue; | 270 | var rowParentName = row.ParentId; |
| 279 | } | 271 | var rowParentType = row.ParentType.ToString(); |
| 272 | var rowChildName = row.ChildId; | ||
| 273 | var rowChildType = row.ChildType.ToString(); | ||
| 274 | |||
| 275 | // If this row specifies a parent or child type that's not in our | ||
| 276 | // lists, we assume it's not a row that we're concerned about. | ||
| 277 | if (!this.groupTypes.Contains(rowParentType) || | ||
| 278 | !this.itemTypes.Contains(rowChildType)) | ||
| 279 | { | ||
| 280 | continue; | ||
| 281 | } | ||
| 280 | 282 | ||
| 281 | this.rowsUsed.Add(rowIndex); | 283 | this.rowsUsed.Add(rowIndex); |
| 282 | 284 | ||
| 283 | Item parentItem; | 285 | if (!this.items.TryGetValue(rowParentType, rowParentName, out var parentItem)) |
| 284 | if (!this.items.TryGetValue(rowParentType, rowParentName, out parentItem)) | 286 | { |
| 285 | { | 287 | parentItem = new Item(row, rowParentType, rowParentName); |
| 286 | parentItem = new Item(row, rowParentType, rowParentName); | 288 | this.items.Add(parentItem); |
| 287 | this.items.Add(parentItem); | 289 | } |
| 288 | } | ||
| 289 | 290 | ||
| 290 | Item childItem; | 291 | if (!this.items.TryGetValue(rowChildType, rowChildName, out var childItem)) |
| 291 | if (!this.items.TryGetValue(rowChildType, rowChildName, out childItem)) | 292 | { |
| 292 | { | 293 | childItem = new Item(row, rowChildType, rowChildName); |
| 293 | childItem = new Item(row, rowChildType, rowChildName); | 294 | this.items.Add(childItem); |
| 294 | this.items.Add(childItem); | 295 | } |
| 295 | } | ||
| 296 | 296 | ||
| 297 | parentItem.ChildItems.Add(childItem); | 297 | parentItem.ChildItems.Add(childItem); |
| 298 | } | ||
| 298 | } | 299 | } |
| 299 | } | 300 | } |
| 300 | 301 | ||
| @@ -374,19 +375,19 @@ namespace WixToolset.Link | |||
| 374 | /// </summary> | 375 | /// </summary> |
| 375 | private void LoadOrdering() | 376 | private void LoadOrdering() |
| 376 | { | 377 | { |
| 377 | Table wixOrderingTable = output.Tables["WixOrdering"]; | 378 | //Table wixOrderingTable = output.Tables["WixOrdering"]; |
| 378 | if (null == wixOrderingTable || 0 == wixOrderingTable.Rows.Count) | 379 | //if (null == wixOrderingTable || 0 == wixOrderingTable.Rows.Count) |
| 379 | { | 380 | //{ |
| 380 | // TODO: Do we need a message here? | 381 | // // TODO: Do we need a message here? |
| 381 | return; | 382 | // return; |
| 382 | } | 383 | //} |
| 383 | 384 | ||
| 384 | foreach (Row row in wixOrderingTable.Rows) | 385 | foreach (var row in this.EntrySection.Tuples.OfType<WixOrderingTuple>()) |
| 385 | { | 386 | { |
| 386 | string rowItemType = (string)row[0]; | 387 | var rowItemType = row.ItemType; |
| 387 | string rowItemName = (string)row[1]; | 388 | var rowItemName = row.ItemId_; |
| 388 | string rowDependsOnType = (string)row[2]; | 389 | var rowDependsOnType = row.DependsOnType; |
| 389 | string rowDependsOnName = (string)row[3]; | 390 | var rowDependsOnName = row.DependsOnId_; |
| 390 | 391 | ||
| 391 | // If this row specifies some other (unknown) type in either | 392 | // If this row specifies some other (unknown) type in either |
| 392 | // position, we assume it's not a row that we're concerned about. | 393 | // position, we assume it's not a row that we're concerned about. |
| @@ -397,15 +398,12 @@ namespace WixToolset.Link | |||
| 397 | continue; | 398 | continue; |
| 398 | } | 399 | } |
| 399 | 400 | ||
| 400 | Item item = null; | 401 | if (!this.items.TryGetValue(rowItemType, rowItemName, out var item)) |
| 401 | Item dependsOn = null; | ||
| 402 | |||
| 403 | if (!this.items.TryGetValue(rowItemType, rowItemName, out item)) | ||
| 404 | { | 402 | { |
| 405 | this.OnMessage(WixErrors.IdentifierNotFound(rowItemType, rowItemName)); | 403 | this.OnMessage(WixErrors.IdentifierNotFound(rowItemType, rowItemName)); |
| 406 | } | 404 | } |
| 407 | 405 | ||
| 408 | if (!this.items.TryGetValue(rowDependsOnType, rowDependsOnName, out dependsOn)) | 406 | if (!this.items.TryGetValue(rowDependsOnType, rowDependsOnName, out var dependsOn)) |
| 409 | { | 407 | { |
| 410 | this.OnMessage(WixErrors.IdentifierNotFound(rowDependsOnType, rowDependsOnName)); | 408 | this.OnMessage(WixErrors.IdentifierNotFound(rowDependsOnType, rowDependsOnName)); |
| 411 | } | 409 | } |
| @@ -540,7 +538,7 @@ namespace WixToolset.Link | |||
| 540 | private ItemCollection beforeItems; // for checking for circular references | 538 | private ItemCollection beforeItems; // for checking for circular references |
| 541 | private bool flattenedAfterItems; | 539 | private bool flattenedAfterItems; |
| 542 | 540 | ||
| 543 | public Item(Row row, string type, string id) | 541 | public Item(IntermediateTuple row, string type, string id) |
| 544 | { | 542 | { |
| 545 | this.Row = row; | 543 | this.Row = row; |
| 546 | this.Type = type; | 544 | this.Type = type; |
| @@ -553,7 +551,7 @@ namespace WixToolset.Link | |||
| 553 | flattenedAfterItems = false; | 551 | flattenedAfterItems = false; |
| 554 | } | 552 | } |
| 555 | 553 | ||
| 556 | public Row Row { get; private set; } | 554 | public IntermediateTuple Row { get; private set; } |
| 557 | public string Type { get; private set; } | 555 | public string Type { get; private set; } |
| 558 | public string Id { get; private set; } | 556 | public string Id { get; private set; } |
| 559 | public string Key { get; private set; } | 557 | public string Key { get; private set; } |
| @@ -718,7 +716,7 @@ namespace WixToolset.Link | |||
| 718 | return -1; | 716 | return -1; |
| 719 | } | 717 | } |
| 720 | 718 | ||
| 721 | return string.CompareOrdinal(x.Id, y.Id); | 719 | return String.CompareOrdinal(x.Id, y.Id); |
| 722 | } | 720 | } |
| 723 | } | 721 | } |
| 724 | } | 722 | } |
