From 2bb37beda887d120a0ddabf874ad25357101faa1 Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Wed, 1 Nov 2017 10:59:45 -0700 Subject: Update to WiX Intermediate Representation --- src/WixToolset.Core/Link/ConnectToFeature.cs | 50 ++------ .../Link/FindEntrySectionAndLoadSymbolsCommand.cs | 81 ++++++------ .../Link/IntermediateTupleExtensions.cs | 26 ++++ .../Link/ReportConflictingSymbolsCommand.cs | 20 +-- .../Link/ResolveReferencesCommand.cs | 99 +++++++-------- .../Link/WixComplexReferenceTupleExtensions.cs | 73 +++++++++++ src/WixToolset.Core/Link/WixGroupingOrdering.cs | 140 ++++++++++----------- 7 files changed, 277 insertions(+), 212 deletions(-) create mode 100644 src/WixToolset.Core/Link/IntermediateTupleExtensions.cs create mode 100644 src/WixToolset.Core/Link/WixComplexReferenceTupleExtensions.cs (limited to 'src/WixToolset.Core/Link') 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 @@ namespace WixToolset.Link { - using System.Collections.Specialized; + using System.Collections.Generic; using WixToolset.Data; /// @@ -10,19 +10,12 @@ namespace WixToolset.Link /// public sealed class ConnectToFeature { - private Section section; - private string childId; - - private string primaryFeature; - private bool explicitPrimaryFeature; - private StringCollection connectFeatures; - /// /// Creates a new connect to feature. /// /// Section this connect belongs to. /// Id of the child. - public ConnectToFeature(Section section, string childId) : + public ConnectToFeature(IntermediateSection section, string childId) : this(section, childId, null, false) { } @@ -34,62 +27,43 @@ namespace WixToolset.Link /// Id of the child. /// Sets the primary feature for the connection. /// Sets if this is explicit primary. - public ConnectToFeature(Section section, string childId, string primaryFeature, bool explicitPrimaryFeature) + public ConnectToFeature(IntermediateSection section, string childId, string primaryFeature, bool explicitPrimaryFeature) { - this.section = section; - this.childId = childId; + this.Section = section; + this.ChildId = childId; - this.primaryFeature = primaryFeature; - this.explicitPrimaryFeature = explicitPrimaryFeature; - - this.connectFeatures = new StringCollection(); + this.PrimaryFeature = primaryFeature; + this.IsExplicitPrimaryFeature = explicitPrimaryFeature; } /// /// Gets the section. /// /// Section. - public Section Section - { - get { return this.section; } - } + public IntermediateSection Section { get; } /// /// Gets the child identifier. /// /// The child identifier. - public string ChildId - { - get { return this.childId; } - } + public string ChildId { get; } /// /// Gets or sets if the flag for if the primary feature was set explicitly. /// /// The flag for if the primary feature was set explicitly. - public bool IsExplicitPrimaryFeature - { - get { return this.explicitPrimaryFeature; } - set { this.explicitPrimaryFeature = value; } - } + public bool IsExplicitPrimaryFeature { get; set; } /// /// Gets or sets the primary feature. /// /// The primary feature. - public string PrimaryFeature - { - get { return this.primaryFeature; } - set { this.primaryFeature = value; } - } + public string PrimaryFeature { get; set; } /// /// Gets the features connected to. /// /// Features connected to. - public StringCollection ConnectFeatures - { - get { return this.connectFeatures; } - } + public List ConnectFeatures { get; } = new List(); } } 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 @@ // 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. -namespace WixToolset.Link +namespace WixToolset.Core.Link { using System; using System.Collections.Generic; @@ -9,13 +9,13 @@ namespace WixToolset.Link internal class FindEntrySectionAndLoadSymbolsCommand : ICommand { - private IEnumerable
sections; - - public FindEntrySectionAndLoadSymbolsCommand(IEnumerable
sections) + public FindEntrySectionAndLoadSymbolsCommand(IEnumerable sections) { - this.sections = sections; + this.Sections = sections; } + private IEnumerable Sections { get; } + /// /// Sets the expected entry output type, based on output file extension provided to the linker. /// @@ -24,13 +24,16 @@ namespace WixToolset.Link /// /// Gets the located entry section after the command is executed. /// - public Section EntrySection { get; private set; } + public IntermediateSection EntrySection { get; private set; } /// /// Gets the collection of loaded symbols. /// public IDictionary Symbols { get; private set; } + /// + /// Gets the collection of possibly conflicting symbols. + /// public IEnumerable PossiblyConflictingSymbols { get; private set; } public void Execute() @@ -38,22 +41,22 @@ namespace WixToolset.Link Dictionary symbols = new Dictionary(); HashSet possibleConflicts = new HashSet(); - SectionType expectedEntrySectionType; - if (!Enum.TryParse(this.ExpectedOutputType.ToString(), out expectedEntrySectionType)) + if (!Enum.TryParse(this.ExpectedOutputType.ToString(), out SectionType expectedEntrySectionType)) { expectedEntrySectionType = SectionType.Unknown; } - foreach (Section section in this.sections) + foreach (var section in this.Sections) { // Try to find the one and only entry section. if (SectionType.Product == section.Type || SectionType.Module == section.Type || SectionType.PatchCreation == section.Type || SectionType.Patch == section.Type || SectionType.Bundle == section.Type) { - if (SectionType.Unknown != expectedEntrySectionType && section.Type != expectedEntrySectionType) - { - string outputExtension = Output.GetExtension(this.ExpectedOutputType); - Messaging.Instance.OnMessage(WixWarnings.UnexpectedEntrySection(section.SourceLineNumbers, section.Type.ToString(), expectedEntrySectionType.ToString(), outputExtension)); - } + // TODO: remove this? + //if (SectionType.Unknown != expectedEntrySectionType && section.Type != expectedEntrySectionType) + //{ + // string outputExtension = Output.GetExtension(this.ExpectedOutputType); + // Messaging.Instance.OnMessage(WixWarnings.UnexpectedEntrySection(section.SourceLineNumbers, section.Type.ToString(), expectedEntrySectionType.ToString(), outputExtension)); + //} if (null == this.EntrySection) { @@ -61,42 +64,38 @@ namespace WixToolset.Link } else { - Messaging.Instance.OnMessage(WixErrors.MultipleEntrySections(this.EntrySection.SourceLineNumbers, this.EntrySection.Id, section.Id)); - Messaging.Instance.OnMessage(WixErrors.MultipleEntrySections2(section.SourceLineNumbers)); + Messaging.Instance.OnMessage(WixErrors.MultipleEntrySections(this.EntrySection.Tuples.FirstOrDefault()?.SourceLineNumbers, this.EntrySection.Id, section.Id)); + Messaging.Instance.OnMessage(WixErrors.MultipleEntrySections2(section.Tuples.FirstOrDefault()?.SourceLineNumbers)); } } // Load all the symbols from the section's tables that create symbols. - foreach (Table table in section.Tables.Where(t => t.Definition.CreateSymbols)) + foreach (var row in section.Tuples.Where(t => t.Id != null)) { - foreach (Row row in table.Rows) - { - Symbol symbol = new Symbol(row); + var symbol = new Symbol(section, row); - Symbol existingSymbol; - if (!symbols.TryGetValue(symbol.Name, out existingSymbol)) + if (!symbols.TryGetValue(symbol.Name, out var existingSymbol)) + { + symbols.Add(symbol.Name, symbol); + } + else // uh-oh, duplicate symbols. + { + // If the duplicate symbols are both private directories, there is a chance that they + // point to identical tuples. Identical directory tuples are redundant and will not cause + // conflicts. + if (AccessModifier.Private == existingSymbol.Access && AccessModifier.Private == symbol.Access && + TupleDefinitionType.Directory == existingSymbol.Row.Definition.Type && existingSymbol.Row.IsIdentical(symbol.Row)) { - symbols.Add(symbol.Name, symbol); + // Ensure identical symbol's tuple is marked redundant to ensure (should the tuple be + // referenced into the final output) it will not add duplicate primary keys during + // the .IDT importing. + //symbol.Row.Redundant = true; - TODO: remove this + existingSymbol.AddRedundant(symbol); } - else // uh-oh, duplicate symbols. + else { - // If the duplicate symbols are both private directories, there is a chance that they - // point to identical rows. Identical directory rows are redundant and will not cause - // conflicts. - if (AccessModifier.Private == existingSymbol.Access && AccessModifier.Private == symbol.Access && - "Directory" == existingSymbol.Row.Table.Name && existingSymbol.Row.IsIdentical(symbol.Row)) - { - // Ensure identical symbol's row is marked redundant to ensure (should the row be - // referenced into the final output) it will not add duplicate primary keys during - // the .IDT importing. - symbol.Row.Redundant = true; - existingSymbol.AddRedundant(symbol); - } - else - { - existingSymbol.AddPossibleConflict(symbol); - possibleConflicts.Add(existingSymbol); - } + existingSymbol.AddPossibleConflict(symbol); + possibleConflicts.Add(existingSymbol); } } } 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 @@ +// 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. + +namespace WixToolset.Core.Link +{ + using WixToolset.Data; + + internal static class IntermediateTupleExtensions + { + public static bool IsIdentical(this IntermediateTuple first, IntermediateTuple second) + { + var identical = (first.Definition.Type == second.Definition.Type && + first.Definition.Name == second.Definition.Name && + first.Definition.FieldDefinitions.Length == second.Definition.FieldDefinitions.Length); + + for (int i = 0; identical && i < first.Definition.FieldDefinitions.Length; ++i) + { + var firstField = first[i]; + var secondField = second[i]; + + identical = (firstField.AsString() == secondField.AsString()); + } + + return identical; + } + } +} 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 using System.Linq; using WixToolset.Data; - public class ReportConflictingSymbolsCommand : ICommand + public class ReportConflictingSymbolsCommand { - private IEnumerable possibleConflicts; - private IEnumerable
resolvedSections; - - public ReportConflictingSymbolsCommand(IEnumerable possibleConflicts, IEnumerable
resolvedSections) + public ReportConflictingSymbolsCommand(IEnumerable possibleConflicts, IEnumerable resolvedSections) { - this.possibleConflicts = possibleConflicts; - this.resolvedSections = resolvedSections; + this.PossibleConflicts = possibleConflicts; + this.ResolvedSections = resolvedSections; } + private IEnumerable PossibleConflicts { get; } + + private IEnumerable ResolvedSections { get; } + public void Execute() { // 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 // symbols are in sections we actually referenced. From the resulting set, show an error for each duplicate // (aka: conflicting) symbol. This should catch any rows with colliding primary keys (since symbols are based // on the primary keys of rows). - List illegalDuplicates = possibleConflicts.Where(s => "WixAction" != s.Row.Table.Name && "WixVariable" != s.Row.Table.Name).ToList(); + var illegalDuplicates = this.PossibleConflicts.Where(s => s.Row.Definition.Type != TupleDefinitionType.WixAction && s.Row.Definition.Type != TupleDefinitionType.WixVariable).ToList(); if (0 < illegalDuplicates.Count) { - HashSet
referencedSections = new HashSet
(resolvedSections); + var referencedSections = new HashSet(this.ResolvedSections); + foreach (Symbol referencedDuplicateSymbol in illegalDuplicates.Where(s => referencedSections.Contains(s.Section))) { List 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 { using System; using System.Collections.Generic; - using System.Diagnostics; using System.Linq; using WixToolset.Data; - using WixToolset.Data.Rows; + using WixToolset.Data.Tuples; /// /// Resolves all the simple references in a section. /// internal class ResolveReferencesCommand : ICommand { - private Section entrySection; + private IntermediateSection entrySection; private IDictionary symbols; private HashSet referencedSymbols; - private HashSet
resolvedSections; + private HashSet resolvedSections; - public ResolveReferencesCommand(Section entrySection, IDictionary symbols) + public ResolveReferencesCommand(IntermediateSection entrySection, IDictionary symbols) { this.entrySection = entrySection; this.symbols = symbols; @@ -29,14 +28,14 @@ namespace WixToolset.Link public IEnumerable ReferencedSymbols { get { return this.referencedSymbols; } } - public IEnumerable
ResolvedSections { get { return this.resolvedSections; } } + public IEnumerable ResolvedSections { get { return this.resolvedSections; } } /// /// Resolves all the simple references in a section. /// public void Execute() { - this.resolvedSections = new HashSet
(); + this.resolvedSections = new HashSet(); this.referencedSymbols = new HashSet(); this.RecursivelyResolveReferences(this.entrySection); @@ -47,7 +46,7 @@ namespace WixToolset.Link /// /// Section with references to resolve. /// Note: recursive function. - private void RecursivelyResolveReferences(Section section) + private void RecursivelyResolveReferences(IntermediateSection section) { // If we already resolved this section, move on to the next. if (!this.resolvedSections.Add(section)) @@ -59,59 +58,53 @@ namespace WixToolset.Link // symbols provided. Then recursively call this method to process the // located symbol's section. All in all this is a very simple depth-first // search of the references per-section. - Table wixSimpleReferenceTable; - if (section.Tables.TryGetTable("WixSimpleReference", out wixSimpleReferenceTable)) + foreach (var wixSimpleReferenceRow in section.Tuples.OfType()) { - foreach (WixSimpleReferenceRow wixSimpleReferenceRow in wixSimpleReferenceTable.Rows) + // If we're building a Merge Module, ignore all references to the Media table + // because Merge Modules don't have Media tables. + if (this.BuildingMergeModule && wixSimpleReferenceRow.Definition.Type == TupleDefinitionType.Media) { - Debug.Assert(wixSimpleReferenceRow.Section == section); + continue; + } - // If we're building a Merge Module, ignore all references to the Media table - // because Merge Modules don't have Media tables. - if (this.BuildingMergeModule && "Media" == wixSimpleReferenceRow.TableName) + if (!this.symbols.TryGetValue(wixSimpleReferenceRow.SymbolicName, out var symbol)) + { + Messaging.Instance.OnMessage(WixErrors.UnresolvedReference(wixSimpleReferenceRow.SourceLineNumbers, wixSimpleReferenceRow.SymbolicName)); + } + else // see if the symbol (and any of its duplicates) are appropriately accessible. + { + IList accessible = DetermineAccessibleSymbols(section, symbol); + if (!accessible.Any()) { - continue; + Messaging.Instance.OnMessage(WixErrors.UnresolvedReference(wixSimpleReferenceRow.SourceLineNumbers, wixSimpleReferenceRow.SymbolicName, symbol.Access)); } - - Symbol symbol; - if (!this.symbols.TryGetValue(wixSimpleReferenceRow.SymbolicName, out symbol)) + else if (1 == accessible.Count) { - Messaging.Instance.OnMessage(WixErrors.UnresolvedReference(wixSimpleReferenceRow.SourceLineNumbers, wixSimpleReferenceRow.SymbolicName)); + var accessibleSymbol = accessible[0]; + this.referencedSymbols.Add(accessibleSymbol); + + if (null != accessibleSymbol.Section) + { + RecursivelyResolveReferences(accessibleSymbol.Section); + } } - else // see if the symbol (and any of its duplicates) are appropriately accessible. + else // display errors for the duplicate symbols. { - IList accessible = DetermineAccessibleSymbols(section, symbol); - if (!accessible.Any()) + var accessibleSymbol = accessible[0]; + var referencingSourceLineNumber = wixSimpleReferenceRow.SourceLineNumbers.ToString(); + + if (String.IsNullOrEmpty(referencingSourceLineNumber)) { - Messaging.Instance.OnMessage(WixErrors.UnresolvedReference(wixSimpleReferenceRow.SourceLineNumbers, wixSimpleReferenceRow.SymbolicName, symbol.Access)); + Messaging.Instance.OnMessage(WixErrors.DuplicateSymbol(accessibleSymbol.Row.SourceLineNumbers, accessibleSymbol.Name)); } - else if (1 == accessible.Count) + else { - Symbol accessibleSymbol = accessible[0]; - this.referencedSymbols.Add(accessibleSymbol); - - if (null != accessibleSymbol.Section) - { - RecursivelyResolveReferences(accessibleSymbol.Section); - } + Messaging.Instance.OnMessage(WixErrors.DuplicateSymbol(accessibleSymbol.Row.SourceLineNumbers, accessibleSymbol.Name, referencingSourceLineNumber)); } - else // display errors for the duplicate symbols. + + foreach (Symbol accessibleDuplicate in accessible.Skip(1)) { - Symbol accessibleSymbol = accessible[0]; - string referencingSourceLineNumber = wixSimpleReferenceRow.SourceLineNumbers.ToString(); - if (String.IsNullOrEmpty(referencingSourceLineNumber)) - { - Messaging.Instance.OnMessage(WixErrors.DuplicateSymbol(accessibleSymbol.Row.SourceLineNumbers, accessibleSymbol.Name)); - } - else - { - Messaging.Instance.OnMessage(WixErrors.DuplicateSymbol(accessibleSymbol.Row.SourceLineNumbers, accessibleSymbol.Name, referencingSourceLineNumber)); - } - - foreach (Symbol accessibleDuplicate in accessible.Skip(1)) - { - Messaging.Instance.OnMessage(WixErrors.DuplicateSymbol2(accessibleDuplicate.Row.SourceLineNumbers)); - } + Messaging.Instance.OnMessage(WixErrors.DuplicateSymbol2(accessibleDuplicate.Row.SourceLineNumbers)); } } } @@ -124,7 +117,7 @@ namespace WixToolset.Link /// Section referencing the symbol. /// Symbol being referenced. /// List of symbols accessible by referencing section. - private IList DetermineAccessibleSymbols(Section referencingSection, Symbol symbol) + private IList DetermineAccessibleSymbols(IntermediateSection referencingSection, Symbol symbol) { List symbols = new List(); @@ -158,20 +151,20 @@ namespace WixToolset.Link /// Section referencing the symbol. /// Symbol being referenced. /// True if symbol is accessible. - private bool AccessibleSymbol(Section referencingSection, Symbol symbol) + private bool AccessibleSymbol(IntermediateSection referencingSection, Symbol symbol) { switch (symbol.Access) { case AccessModifier.Public: return true; case AccessModifier.Internal: - return symbol.Row.Section.IntermediateId.Equals(referencingSection.IntermediateId) || (null != symbol.Row.Section.LibraryId && symbol.Row.Section.LibraryId.Equals(referencingSection.LibraryId)); + return symbol.Section.CompilationId.Equals(referencingSection.CompilationId) || (null != symbol.Section.LibraryId && symbol.Section.LibraryId.Equals(referencingSection.LibraryId)); case AccessModifier.Protected: - return symbol.Row.Section.IntermediateId.Equals(referencingSection.IntermediateId); + return symbol.Section.CompilationId.Equals(referencingSection.CompilationId); case AccessModifier.Private: return referencingSection == symbol.Section; default: - throw new InvalidOperationException(); + throw new ArgumentOutOfRangeException(nameof(symbol.Access)); } } } 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 @@ +// 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. + +namespace WixToolset.Core.Link +{ + using System; + using WixToolset.Data.Tuples; + + internal static class WixComplexReferenceTupleExtensions + { + /// + /// Creates a shallow copy of the ComplexReference. + /// + /// A shallow copy of the ComplexReference. + public static WixComplexReferenceTuple Clone(this WixComplexReferenceTuple source) + { + var clone = new WixComplexReferenceTuple(source.SourceLineNumbers, source.Id); + clone.ParentType = source.ParentType; + clone.Parent = source.Parent; + clone.ParentLanguage = source.ParentLanguage; + clone.ChildType = source.ChildType; + clone.Child = source.Child; + clone.IsPrimary = source.IsPrimary; + + return clone; + } + + /// + /// Compares two complex references without considering the primary bit. + /// + /// Complex reference to compare to. + /// Zero if the objects are equivalent, negative number if the provided object is less, positive if greater. + public static int CompareToWithoutConsideringPrimary(this WixComplexReferenceTuple tuple, WixComplexReferenceTuple other) + { + var comparison = tuple.ChildType - other.ChildType; + if (0 == comparison) + { + comparison = String.Compare(tuple.Child, other.Child, StringComparison.Ordinal); + if (0 == comparison) + { + comparison = tuple.ParentType - other.ParentType; + if (0 == comparison) + { + string thisParentLanguage = null == tuple.ParentLanguage ? String.Empty : tuple.ParentLanguage; + string otherParentLanguage = null == other.ParentLanguage ? String.Empty : other.ParentLanguage; + comparison = String.Compare(thisParentLanguage, otherParentLanguage, StringComparison.Ordinal); + if (0 == comparison) + { + comparison = String.Compare(tuple.Parent, other.Parent, StringComparison.Ordinal); + } + } + } + } + + return comparison; + } + + /// + /// Changes all of the parent references to point to the passed in parent reference. + /// + /// New parent complex reference. + public static void Reparent(this WixComplexReferenceTuple tuple, WixComplexReferenceTuple parent) + { + tuple.Parent = parent.Parent; + tuple.ParentLanguage = parent.ParentLanguage; + tuple.ParentType = parent.ParentType; + + if (!tuple.IsPrimary) + { + tuple.IsPrimary = parent.IsPrimary; + } + } + } +} 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 using System.Text; using WixToolset.Extensibility; using WixToolset.Data; + using WixToolset.Data.Tuples; /// /// Grouping and Ordering class of the WiX toolset. /// internal sealed class WixGroupingOrdering : IMessageHandler { - private Output output; private IMessageHandler messageHandler; private List groupTypes; private List itemTypes; @@ -34,9 +34,9 @@ namespace WixToolset.Link /// Handler for any error messages. /// Group types to include. /// Item types to include. - public WixGroupingOrdering(Output output, IMessageHandler messageHandler) + public WixGroupingOrdering(IntermediateSection entrySections, IMessageHandler messageHandler) { - this.output = output; + this.EntrySection = entrySections; this.messageHandler = messageHandler; this.rowsUsed = new List(); @@ -44,6 +44,8 @@ namespace WixToolset.Link this.encounteredError = false; } + private IntermediateSection EntrySection { get; } + /// /// Switches a WixGroupingOrdering object to operate on a new set of groups/items. /// @@ -91,8 +93,7 @@ namespace WixToolset.Link { Debug.Assert(this.groupTypes.Contains(parentType)); - List orderedItems; - this.CreateOrderedList(parentType, parentId, out orderedItems); + this.CreateOrderedList(parentType, parentId, out var orderedItems); if (this.encounteredError) { return; @@ -170,15 +171,16 @@ namespace WixToolset.Link /// public void RemoveUsedGroupRows() { - List sortedIndexes = this.rowsUsed.Distinct().OrderByDescending(i => i).ToList(); + var sortedIndexes = this.rowsUsed.Distinct().OrderByDescending(i => i).ToList(); - Table wixGroupTable = this.output.Tables["WixGroup"]; - Debug.Assert(null != wixGroupTable); - Debug.Assert(sortedIndexes[0] < wixGroupTable.Rows.Count); + //Table wixGroupTable = this.output.Tables["WixGroup"]; + //Debug.Assert(null != wixGroupTable); + //Debug.Assert(sortedIndexes[0] < wixGroupTable.Rows.Count); foreach (int rowIndex in sortedIndexes) { - wixGroupTable.Rows.RemoveAt(rowIndex); + //wixGroupTable.Rows.RemoveAt(rowIndex); + this.EntrySection.Tuples.RemoveAt(rowIndex); } } @@ -194,16 +196,15 @@ namespace WixToolset.Link // does WiX (although they do, currently). We probably want to "upgrade" this to a new // table that includes a sequence number, and then change the code that uses ordered // groups to read from that table instead. - Table wixGroupTable = this.output.Tables["WixGroup"]; - Debug.Assert(null != wixGroupTable); - foreach (Item item in orderedItems) { - Row row = wixGroupTable.CreateRow(item.Row.SourceLineNumbers); - row[0] = parentId; - row[1] = parentType; - row[2] = item.Id; - row[3] = item.Type; + var row = new WixGroupTuple(item.Row.SourceLineNumbers); + row.ParentId = parentId; + row.ParentType = (ComplexReferenceParentType)Enum.Parse(typeof(ComplexReferenceParentType), parentType); + row.ChildId = item.Id; + row.ChildType = (ComplexReferenceChildType)Enum.Parse(typeof(ComplexReferenceChildType), item.Type); + + this.EntrySection.Tuples.Add(row); } } @@ -254,47 +255,47 @@ namespace WixToolset.Link /// private void LoadGroups() { - Table wixGroupTable = this.output.Tables["WixGroup"]; - if (null == wixGroupTable || 0 == wixGroupTable.Rows.Count) - { - // TODO: Change message name to make it *not* Bundle specific? - this.OnMessage(WixErrors.MissingBundleInformation("WixGroup")); - } + //Table wixGroupTable = this.output.Tables["WixGroup"]; + //if (null == wixGroupTable || 0 == wixGroupTable.Rows.Count) + //{ + // // TODO: Change message name to make it *not* Bundle specific? + // this.OnMessage(WixErrors.MissingBundleInformation("WixGroup")); + //} // Collect all of the groups - for (int rowIndex = 0; rowIndex < wixGroupTable.Rows.Count; ++rowIndex) - { - Row row = wixGroupTable.Rows[rowIndex]; - string rowParentName = (string)row[0]; - string rowParentType = (string)row[1]; - string rowChildName = (string)row[2]; - string rowChildType = (string)row[3]; - - // If this row specifies a parent or child type that's not in our - // lists, we assume it's not a row that we're concerned about. - if (!this.groupTypes.Contains(rowParentType) || - !this.itemTypes.Contains(rowChildType)) + for (int rowIndex = 0; rowIndex < this.EntrySection.Tuples.Count; ++rowIndex) + { + if (this.EntrySection.Tuples[rowIndex] is WixGroupTuple row) { - continue; - } + var rowParentName = row.ParentId; + var rowParentType = row.ParentType.ToString(); + var rowChildName = row.ChildId; + var rowChildType = row.ChildType.ToString(); + + // If this row specifies a parent or child type that's not in our + // lists, we assume it's not a row that we're concerned about. + if (!this.groupTypes.Contains(rowParentType) || + !this.itemTypes.Contains(rowChildType)) + { + continue; + } - this.rowsUsed.Add(rowIndex); + this.rowsUsed.Add(rowIndex); - Item parentItem; - if (!this.items.TryGetValue(rowParentType, rowParentName, out parentItem)) - { - parentItem = new Item(row, rowParentType, rowParentName); - this.items.Add(parentItem); - } + if (!this.items.TryGetValue(rowParentType, rowParentName, out var parentItem)) + { + parentItem = new Item(row, rowParentType, rowParentName); + this.items.Add(parentItem); + } - Item childItem; - if (!this.items.TryGetValue(rowChildType, rowChildName, out childItem)) - { - childItem = new Item(row, rowChildType, rowChildName); - this.items.Add(childItem); - } + if (!this.items.TryGetValue(rowChildType, rowChildName, out var childItem)) + { + childItem = new Item(row, rowChildType, rowChildName); + this.items.Add(childItem); + } - parentItem.ChildItems.Add(childItem); + parentItem.ChildItems.Add(childItem); + } } } @@ -374,19 +375,19 @@ namespace WixToolset.Link /// private void LoadOrdering() { - Table wixOrderingTable = output.Tables["WixOrdering"]; - if (null == wixOrderingTable || 0 == wixOrderingTable.Rows.Count) - { - // TODO: Do we need a message here? - return; - } + //Table wixOrderingTable = output.Tables["WixOrdering"]; + //if (null == wixOrderingTable || 0 == wixOrderingTable.Rows.Count) + //{ + // // TODO: Do we need a message here? + // return; + //} - foreach (Row row in wixOrderingTable.Rows) + foreach (var row in this.EntrySection.Tuples.OfType()) { - string rowItemType = (string)row[0]; - string rowItemName = (string)row[1]; - string rowDependsOnType = (string)row[2]; - string rowDependsOnName = (string)row[3]; + var rowItemType = row.ItemType; + var rowItemName = row.ItemId_; + var rowDependsOnType = row.DependsOnType; + var rowDependsOnName = row.DependsOnId_; // If this row specifies some other (unknown) type in either // position, we assume it's not a row that we're concerned about. @@ -397,15 +398,12 @@ namespace WixToolset.Link continue; } - Item item = null; - Item dependsOn = null; - - if (!this.items.TryGetValue(rowItemType, rowItemName, out item)) + if (!this.items.TryGetValue(rowItemType, rowItemName, out var item)) { this.OnMessage(WixErrors.IdentifierNotFound(rowItemType, rowItemName)); } - if (!this.items.TryGetValue(rowDependsOnType, rowDependsOnName, out dependsOn)) + if (!this.items.TryGetValue(rowDependsOnType, rowDependsOnName, out var dependsOn)) { this.OnMessage(WixErrors.IdentifierNotFound(rowDependsOnType, rowDependsOnName)); } @@ -540,7 +538,7 @@ namespace WixToolset.Link private ItemCollection beforeItems; // for checking for circular references private bool flattenedAfterItems; - public Item(Row row, string type, string id) + public Item(IntermediateTuple row, string type, string id) { this.Row = row; this.Type = type; @@ -553,7 +551,7 @@ namespace WixToolset.Link flattenedAfterItems = false; } - public Row Row { get; private set; } + public IntermediateTuple Row { get; private set; } public string Type { get; private set; } public string Id { get; private set; } public string Key { get; private set; } @@ -718,7 +716,7 @@ namespace WixToolset.Link return -1; } - return string.CompareOrdinal(x.Id, y.Id); + return String.CompareOrdinal(x.Id, y.Id); } } } -- cgit v1.2.3-55-g6feb