diff options
Diffstat (limited to 'src/WixToolset.Core/Linker.cs')
-rw-r--r-- | src/WixToolset.Core/Linker.cs | 1164 |
1 files changed, 578 insertions, 586 deletions
diff --git a/src/WixToolset.Core/Linker.cs b/src/WixToolset.Core/Linker.cs index c1c9f848..59481387 100644 --- a/src/WixToolset.Core/Linker.cs +++ b/src/WixToolset.Core/Linker.cs | |||
@@ -1,21 +1,18 @@ | |||
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 | 3 | namespace WixToolset.Core |
4 | { | 4 | { |
5 | using System; | 5 | using System; |
6 | using System.Collections; | 6 | using System.Collections; |
7 | using System.Collections.Generic; | 7 | using System.Collections.Generic; |
8 | using System.Collections.Specialized; | ||
9 | using System.Diagnostics; | 8 | using System.Diagnostics; |
10 | using System.Diagnostics.CodeAnalysis; | ||
11 | using System.Globalization; | 9 | using System.Globalization; |
12 | using System.Linq; | 10 | using System.Linq; |
13 | using System.Text; | ||
14 | using WixToolset.Data; | 11 | using WixToolset.Data; |
15 | using WixToolset.Data.Rows; | ||
16 | using WixToolset.Extensibility; | ||
17 | using WixToolset.Link; | 12 | using WixToolset.Link; |
18 | using WixToolset.Core.Native; | 13 | using WixToolset.Core.Link; |
14 | using WixToolset.Data.Tuples; | ||
15 | using WixToolset.Extensibility.Services; | ||
19 | 16 | ||
20 | /// <summary> | 17 | /// <summary> |
21 | /// Linker core of the WiX toolset. | 18 | /// Linker core of the WiX toolset. |
@@ -25,13 +22,10 @@ namespace WixToolset | |||
25 | private static readonly char[] colonCharacter = ":".ToCharArray(); | 22 | private static readonly char[] colonCharacter = ":".ToCharArray(); |
26 | private static readonly string emptyGuid = Guid.Empty.ToString("B"); | 23 | private static readonly string emptyGuid = Guid.Empty.ToString("B"); |
27 | 24 | ||
28 | private List<IExtensionData> extensionData; | ||
29 | |||
30 | private List<InspectorExtension> inspectorExtensions; | ||
31 | private bool sectionIdOnRows; | 25 | private bool sectionIdOnRows; |
32 | private WixActionRowCollection standardActions; | 26 | //private WixActionRowCollection standardActions; |
33 | private Output activeOutput; | 27 | //private Output activeOutput; |
34 | private TableDefinitionCollection tableDefinitions; | 28 | //private TableDefinitionCollection tableDefinitions; |
35 | 29 | ||
36 | /// <summary> | 30 | /// <summary> |
37 | /// Creates a linker. | 31 | /// Creates a linker. |
@@ -40,18 +34,14 @@ namespace WixToolset | |||
40 | { | 34 | { |
41 | this.sectionIdOnRows = true; // TODO: what is the correct value for this? | 35 | this.sectionIdOnRows = true; // TODO: what is the correct value for this? |
42 | 36 | ||
43 | this.standardActions = WindowsInstallerStandard.GetStandardActions(); | 37 | //this.standardActions = WindowsInstallerStandard.GetStandardActions(); |
44 | this.tableDefinitions = new TableDefinitionCollection(WindowsInstallerStandard.GetTableDefinitions()); | 38 | //this.tableDefinitions = new TableDefinitionCollection(WindowsInstallerStandard.GetTableDefinitions()); |
45 | 39 | ||
46 | this.extensionData = new List<IExtensionData>(); | 40 | //this.extensionData = new List<IExtensionData>(); |
47 | this.inspectorExtensions = new List<InspectorExtension>(); | 41 | //this.inspectorExtensions = new List<InspectorExtension>(); |
48 | } | 42 | } |
49 | 43 | ||
50 | /// <summary> | 44 | private ILinkContext Context { get; set; } |
51 | /// Gets or sets the localizer. | ||
52 | /// </summary> | ||
53 | /// <value>The localizer.</value> | ||
54 | public Localizer Localizer { get; set; } | ||
55 | 45 | ||
56 | /// <summary> | 46 | /// <summary> |
57 | /// Gets or sets the path to output unreferenced symbols to. If null or empty, there is no output. | 47 | /// Gets or sets the path to output unreferenced symbols to. If null or empty, there is no output. |
@@ -66,45 +56,36 @@ namespace WixToolset | |||
66 | public bool ShowPedanticMessages { get; set; } | 56 | public bool ShowPedanticMessages { get; set; } |
67 | 57 | ||
68 | /// <summary> | 58 | /// <summary> |
69 | /// Gets the table definitions used by the linker. | ||
70 | /// </summary> | ||
71 | /// <value>Table definitions used by the linker.</value> | ||
72 | public TableDefinitionCollection TableDefinitions | ||
73 | { | ||
74 | get { return this.tableDefinitions; } | ||
75 | } | ||
76 | |||
77 | /// <summary> | ||
78 | /// Gets or sets the Wix variable resolver. | 59 | /// Gets or sets the Wix variable resolver. |
79 | /// </summary> | 60 | /// </summary> |
80 | /// <value>The Wix variable resolver.</value> | 61 | /// <value>The Wix variable resolver.</value> |
81 | internal IBindVariableResolver WixVariableResolver { get; set; } | 62 | //internal IBindVariableResolver WixVariableResolver { get; set; } |
82 | 63 | ||
83 | /// <summary> | 64 | /// <summary> |
84 | /// Adds an extension. | 65 | /// Adds an extension. |
85 | /// </summary> | 66 | /// </summary> |
86 | /// <param name="extension">The extension to add.</param> | 67 | /// <param name="extension">The extension to add.</param> |
87 | public void AddExtensionData(IExtensionData extension) | 68 | //public void AddExtensionData(IExtensionData extension) |
88 | { | 69 | //{ |
89 | if (null != extension.TableDefinitions) | 70 | // if (null != extension.TableDefinitions) |
90 | { | 71 | // { |
91 | foreach (TableDefinition tableDefinition in extension.TableDefinitions) | 72 | // foreach (TableDefinition tableDefinition in extension.TableDefinitions) |
92 | { | 73 | // { |
93 | if (!this.tableDefinitions.Contains(tableDefinition.Name)) | 74 | // if (!this.tableDefinitions.Contains(tableDefinition.Name)) |
94 | { | 75 | // { |
95 | this.tableDefinitions.Add(tableDefinition); | 76 | // this.tableDefinitions.Add(tableDefinition); |
96 | } | 77 | // } |
97 | else | 78 | // else |
98 | { | 79 | // { |
99 | throw new WixException(WixErrors.DuplicateExtensionTable(extension.GetType().ToString(), tableDefinition.Name)); | 80 | // throw new WixException(WixErrors.DuplicateExtensionTable(extension.GetType().ToString(), tableDefinition.Name)); |
100 | } | 81 | // } |
101 | } | 82 | // } |
102 | } | 83 | // } |
103 | 84 | ||
104 | // keep track of extension data so the libraries can be loaded from these later once all the table definitions | 85 | // // keep track of extension data so the libraries can be loaded from these later once all the table definitions |
105 | // are loaded; this will allow extensions to have cross table definition dependencies | 86 | // // are loaded; this will allow extensions to have cross table definition dependencies |
106 | this.extensionData.Add(extension); | 87 | // this.extensionData.Add(extension); |
107 | } | 88 | //} |
108 | 89 | ||
109 | /// <summary> | 90 | /// <summary> |
110 | /// Links a collection of sections into an output. | 91 | /// Links a collection of sections into an output. |
@@ -112,31 +93,39 @@ namespace WixToolset | |||
112 | /// <param name="inputs">The collection of sections to link together.</param> | 93 | /// <param name="inputs">The collection of sections to link together.</param> |
113 | /// <param name="expectedOutputType">Expected output type, based on output file extension provided to the linker.</param> | 94 | /// <param name="expectedOutputType">Expected output type, based on output file extension provided to the linker.</param> |
114 | /// <returns>Output object from the linking.</returns> | 95 | /// <returns>Output object from the linking.</returns> |
115 | public Output Link(IEnumerable<Section> inputs, OutputType expectedOutputType) | 96 | public Intermediate Link(ILinkContext context) |
116 | { | 97 | { |
117 | Output output = null; | 98 | this.Context = context ?? throw new ArgumentNullException(nameof(context)); |
118 | List<Section> sections = new List<Section>(inputs); | ||
119 | 99 | ||
120 | try | 100 | //IEnumerable<Section> inputs, OutputType expectedOutputType |
121 | { | 101 | |
102 | var sections = this.Context.Intermediates.SelectMany(i => i.Sections).ToList(); | ||
103 | |||
104 | #if MOVE_TO_BACKEND | ||
122 | bool containsModuleSubstitution = false; | 105 | bool containsModuleSubstitution = false; |
123 | bool containsModuleConfiguration = false; | 106 | bool containsModuleConfiguration = false; |
107 | #endif | ||
124 | 108 | ||
125 | this.activeOutput = null; | 109 | //this.activeOutput = null; |
126 | 110 | ||
127 | List<Row> actionRows = new List<Row>(); | 111 | #if MOVE_TO_BACKEND |
128 | List<Row> suppressActionRows = new List<Row>(); | 112 | var actionRows = new List<IntermediateTuple>(); |
113 | var suppressActionRows = new List<IntermediateTuple>(); | ||
114 | #endif | ||
129 | 115 | ||
130 | TableDefinitionCollection customTableDefinitions = new TableDefinitionCollection(); | 116 | //TableDefinitionCollection customTableDefinitions = new TableDefinitionCollection(); |
131 | List<Row> customRows = new List<Row>(); | 117 | //IntermediateTuple customRows = new List<IntermediateTuple>(); |
132 | 118 | ||
119 | #if MOVE_TO_BACKEND | ||
133 | StringCollection generatedShortFileNameIdentifiers = new StringCollection(); | 120 | StringCollection generatedShortFileNameIdentifiers = new StringCollection(); |
134 | Hashtable generatedShortFileNames = new Hashtable(); | 121 | Hashtable generatedShortFileNames = new Hashtable(); |
122 | #endif | ||
135 | 123 | ||
136 | Hashtable multipleFeatureComponents = new Hashtable(); | 124 | Hashtable multipleFeatureComponents = new Hashtable(); |
137 | 125 | ||
138 | Hashtable wixVariables = new Hashtable(); | 126 | var wixVariables = new Dictionary<string, WixVariableTuple>(); |
139 | 127 | ||
128 | #if MOVE_TO_BACKEND | ||
140 | // verify that modularization types match for foreign key relationships | 129 | // verify that modularization types match for foreign key relationships |
141 | foreach (TableDefinition tableDefinition in this.tableDefinitions) | 130 | foreach (TableDefinition tableDefinition in this.tableDefinitions) |
142 | { | 131 | { |
@@ -164,7 +153,9 @@ namespace WixToolset | |||
164 | } | 153 | } |
165 | } | 154 | } |
166 | } | 155 | } |
156 | #endif | ||
167 | 157 | ||
158 | #if TODO | ||
168 | // Add sections from the extensions with data. | 159 | // Add sections from the extensions with data. |
169 | foreach (IExtensionData data in this.extensionData) | 160 | foreach (IExtensionData data in this.extensionData) |
170 | { | 161 | { |
@@ -175,123 +166,118 @@ namespace WixToolset | |||
175 | sections.AddRange(library.Sections); | 166 | sections.AddRange(library.Sections); |
176 | } | 167 | } |
177 | } | 168 | } |
169 | #endif | ||
178 | 170 | ||
179 | // First find the entry section and while processing all sections load all the symbols from all of the sections. | 171 | // First find the entry section and while processing all sections load all the symbols from all of the sections. |
180 | // sections.FindEntrySectionAndLoadSymbols(false, this, expectedOutputType, out entrySection, out allSymbols); | 172 | // sections.FindEntrySectionAndLoadSymbols(false, this, expectedOutputType, out entrySection, out allSymbols); |
181 | FindEntrySectionAndLoadSymbolsCommand find = new FindEntrySectionAndLoadSymbolsCommand(sections); | 173 | var find = new FindEntrySectionAndLoadSymbolsCommand(sections); |
182 | find.ExpectedOutputType = expectedOutputType; | 174 | find.ExpectedOutputType = this.Context.ExpectedOutputType; |
175 | find.Execute(); | ||
183 | 176 | ||
184 | find.Execute(); | 177 | // Must have found the entry section by now. |
178 | if (null == find.EntrySection) | ||
179 | { | ||
180 | throw new WixException(WixErrors.MissingEntrySection(this.Context.ExpectedOutputType.ToString())); | ||
181 | } | ||
185 | 182 | ||
186 | // Must have found the entry section by now. | 183 | // Now that we know where we're starting from, create the section to hold the linked content. |
187 | if (null == find.EntrySection) | 184 | var resolvedSection = new IntermediateSection(find.EntrySection.Id, find.EntrySection.Type, find.EntrySection.Codepage); |
188 | { | 185 | var allSymbols = find.Symbols; |
189 | throw new WixException(WixErrors.MissingEntrySection(expectedOutputType.ToString())); | ||
190 | } | ||
191 | 186 | ||
192 | IDictionary<string, Symbol> allSymbols = find.Symbols; | 187 | // Add the missing standard action symbols. |
188 | this.LoadStandardActionSymbols(resolvedSection, allSymbols); | ||
193 | 189 | ||
194 | // Add the missing standard action symbols. | 190 | // Resolve the symbol references to find the set of sections we care about for linking. |
195 | this.LoadStandardActionSymbols(allSymbols); | 191 | // Of course, we start with the entry section (that's how it got its name after all). |
192 | var resolve = new ResolveReferencesCommand(find.EntrySection, allSymbols); | ||
193 | resolve.BuildingMergeModule = (SectionType.Module == find.EntrySection.Type); | ||
196 | 194 | ||
197 | // now that we know where we're starting from, create the output object | 195 | resolve.Execute(); |
198 | output = new Output(null); | ||
199 | output.EntrySection = find.EntrySection; // Note: this entry section will get added to the Output.Sections collection later | ||
200 | if (null != this.Localizer && -1 != this.Localizer.Codepage) | ||
201 | { | ||
202 | output.Codepage = this.Localizer.Codepage; | ||
203 | } | ||
204 | this.activeOutput = output; | ||
205 | 196 | ||
206 | // Resolve the symbol references to find the set of sections we care about for linking. | 197 | if (Messaging.Instance.EncounteredError) |
207 | // Of course, we start with the entry section (that's how it got its name after all). | 198 | { |
208 | ResolveReferencesCommand resolve = new ResolveReferencesCommand(output.EntrySection, allSymbols); | 199 | return null; |
209 | resolve.BuildingMergeModule = (OutputType.Module == output.Type); | 200 | } |
210 | 201 | ||
211 | resolve.Execute(); | 202 | // Reset the sections to only those that were resolved then flatten the complex |
203 | // references that particpate in groups. | ||
204 | sections = resolve.ResolvedSections.ToList(); | ||
212 | 205 | ||
213 | if (Messaging.Instance.EncounteredError) | 206 | this.FlattenSectionsComplexReferences(sections); |
214 | { | ||
215 | return null; | ||
216 | } | ||
217 | 207 | ||
218 | // Add the resolved sections to the output then flatten the complex | 208 | if (Messaging.Instance.EncounteredError) |
219 | // references that particpate in groups. | 209 | { |
220 | foreach (Section section in resolve.ResolvedSections) | 210 | return null; |
221 | { | 211 | } |
222 | output.Sections.Add(section); | ||
223 | } | ||
224 | 212 | ||
225 | this.FlattenSectionsComplexReferences(output.Sections); | 213 | // The hard part in linking is processing the complex references. |
214 | var referencedComponents = new HashSet<string>(); | ||
215 | var componentsToFeatures = new ConnectToFeatureCollection(); | ||
216 | var featuresToFeatures = new ConnectToFeatureCollection(); | ||
217 | var modulesToFeatures = new ConnectToFeatureCollection(); | ||
218 | this.ProcessComplexReferences(resolvedSection, sections, referencedComponents, componentsToFeatures, featuresToFeatures, modulesToFeatures); | ||
226 | 219 | ||
227 | if (Messaging.Instance.EncounteredError) | 220 | if (Messaging.Instance.EncounteredError) |
221 | { | ||
222 | return null; | ||
223 | } | ||
224 | |||
225 | // Display an error message for Components that were not referenced by a Feature. | ||
226 | foreach (var symbol in resolve.ReferencedSymbols.Where(s => s.Row.Definition.Type == TupleDefinitionType.Component)) | ||
227 | { | ||
228 | if (!referencedComponents.Contains(symbol.Name)) | ||
228 | { | 229 | { |
229 | return null; | 230 | this.OnMessage(WixErrors.OrphanedComponent(symbol.Row.SourceLineNumbers, symbol.Row.Id.Id)); |
230 | } | 231 | } |
232 | } | ||
231 | 233 | ||
232 | // The hard part in linking is processing the complex references. | 234 | // Report duplicates that would ultimately end up being primary key collisions. |
233 | HashSet<string> referencedComponents = new HashSet<string>(); | 235 | ReportConflictingSymbolsCommand reportDupes = new ReportConflictingSymbolsCommand(find.PossiblyConflictingSymbols, resolve.ResolvedSections); |
234 | ConnectToFeatureCollection componentsToFeatures = new ConnectToFeatureCollection(); | 236 | reportDupes.Execute(); |
235 | ConnectToFeatureCollection featuresToFeatures = new ConnectToFeatureCollection(); | ||
236 | ConnectToFeatureCollection modulesToFeatures = new ConnectToFeatureCollection(); | ||
237 | this.ProcessComplexReferences(output, output.Sections, referencedComponents, componentsToFeatures, featuresToFeatures, modulesToFeatures); | ||
238 | 237 | ||
239 | if (Messaging.Instance.EncounteredError) | 238 | if (Messaging.Instance.EncounteredError) |
240 | { | 239 | { |
241 | return null; | 240 | return null; |
242 | } | 241 | } |
243 | 242 | ||
244 | // Display an error message for Components that were not referenced by a Feature. | 243 | // resolve the feature to feature connects |
245 | foreach (Symbol symbol in resolve.ReferencedSymbols.Where(s => "Component".Equals(s.Row.TableDefinition.Name, StringComparison.Ordinal))) | 244 | this.ResolveFeatureToFeatureConnects(featuresToFeatures, allSymbols); |
246 | { | ||
247 | if (!referencedComponents.Contains(symbol.Name)) | ||
248 | { | ||
249 | this.OnMessage(WixErrors.OrphanedComponent(symbol.Row.SourceLineNumbers, (string)symbol.Row[0])); | ||
250 | } | ||
251 | } | ||
252 | 245 | ||
253 | // Report duplicates that would ultimately end up being primary key collisions. | 246 | // start generating OutputTables and OutputRows for all the sections in the output |
254 | ReportConflictingSymbolsCommand reportDupes = new ReportConflictingSymbolsCommand(find.PossiblyConflictingSymbols, resolve.ResolvedSections); | 247 | var ensureTableRows = new List<IntermediateTuple>(); |
255 | reportDupes.Execute(); | ||
256 | 248 | ||
257 | if (Messaging.Instance.EncounteredError) | 249 | int sectionCount = 0; |
250 | foreach (var section in sections) | ||
251 | { | ||
252 | sectionCount++; | ||
253 | |||
254 | string sectionId = section.Id; | ||
255 | if (null == sectionId && this.sectionIdOnRows) | ||
258 | { | 256 | { |
259 | return null; | 257 | sectionId = "wix.section." + sectionCount.ToString(CultureInfo.InvariantCulture); |
260 | } | 258 | } |
261 | 259 | ||
262 | // resolve the feature to feature connects | 260 | foreach (var tuple in section.Tuples) |
263 | this.ResolveFeatureToFeatureConnects(featuresToFeatures, allSymbols); | ||
264 | |||
265 | // start generating OutputTables and OutputRows for all the sections in the output | ||
266 | List<Row> ensureTableRows = new List<Row>(); | ||
267 | int sectionCount = 0; | ||
268 | foreach (Section section in output.Sections) | ||
269 | { | 261 | { |
270 | sectionCount++; | 262 | var copyTuple = true; // by default, copy tuples. |
271 | string sectionId = section.Id; | ||
272 | if (null == sectionId && this.sectionIdOnRows) | ||
273 | { | ||
274 | sectionId = "wix.section." + sectionCount.ToString(CultureInfo.InvariantCulture); | ||
275 | } | ||
276 | 263 | ||
277 | foreach (Table table in section.Tables) | 264 | // handle special tables |
265 | switch (tuple.Definition.Type) | ||
278 | { | 266 | { |
279 | bool copyRows = true; // by default, copy rows. | 267 | #if MOVE_TO_BACKEND |
280 | |||
281 | // handle special tables | ||
282 | switch (table.Name) | ||
283 | { | ||
284 | case "AppSearch": | 268 | case "AppSearch": |
285 | this.activeOutput.EnsureTable(this.tableDefinitions["Signature"]); | 269 | this.activeOutput.EnsureTable(this.tableDefinitions["Signature"]); |
286 | break; | 270 | break; |
271 | #endif | ||
287 | 272 | ||
288 | case "Class": | 273 | case TupleDefinitionType.Class: |
289 | if (OutputType.Product == output.Type) | 274 | if (SectionType.Product == resolvedSection.Type) |
290 | { | 275 | { |
291 | this.ResolveFeatures(table.Rows, 2, 11, componentsToFeatures, multipleFeatureComponents); | 276 | this.ResolveFeatures(tuple, 2, 11, componentsToFeatures, multipleFeatureComponents); |
292 | } | 277 | } |
293 | break; | 278 | break; |
294 | 279 | ||
280 | #if MOVE_TO_BACKEND | ||
295 | case "CustomAction": | 281 | case "CustomAction": |
296 | if (OutputType.Module == this.activeOutput.Type) | 282 | if (OutputType.Module == this.activeOutput.Type) |
297 | { | 283 | { |
@@ -342,29 +328,32 @@ namespace WixToolset | |||
342 | } | 328 | } |
343 | } | 329 | } |
344 | break; | 330 | break; |
331 | #endif | ||
332 | case TupleDefinitionType.Extension: | ||
333 | if (SectionType.Product == resolvedSection.Type) | ||
334 | { | ||
335 | this.ResolveFeatures(tuple, 1, 4, componentsToFeatures, multipleFeatureComponents); | ||
336 | } | ||
337 | break; | ||
345 | 338 | ||
346 | case "Extension": | 339 | #if MOVE_TO_BACKEND |
347 | if (OutputType.Product == output.Type) | 340 | case TupleDefinitionType.ModuleSubstitution: |
348 | { | ||
349 | this.ResolveFeatures(table.Rows, 1, 4, componentsToFeatures, multipleFeatureComponents); | ||
350 | } | ||
351 | break; | ||
352 | |||
353 | case "ModuleSubstitution": | ||
354 | containsModuleSubstitution = true; | 341 | containsModuleSubstitution = true; |
355 | break; | 342 | break; |
356 | 343 | ||
357 | case "ModuleConfiguration": | 344 | case TupleDefinitionType.ModuleConfiguration: |
358 | containsModuleConfiguration = true; | 345 | containsModuleConfiguration = true; |
359 | break; | 346 | break; |
347 | #endif | ||
360 | 348 | ||
361 | case "MsiAssembly": | 349 | case TupleDefinitionType.MsiAssembly: |
362 | if (OutputType.Product == output.Type) | 350 | if (SectionType.Product == resolvedSection.Type) |
363 | { | 351 | { |
364 | this.ResolveFeatures(table.Rows, 0, 1, componentsToFeatures, multipleFeatureComponents); | 352 | this.ResolveFeatures(tuple, 0, 1, componentsToFeatures, multipleFeatureComponents); |
365 | } | 353 | } |
366 | break; | 354 | break; |
367 | 355 | ||
356 | #if MOVE_TO_BACKEND | ||
368 | case "ProgId": | 357 | case "ProgId": |
369 | // the Extension table is required with a ProgId table | 358 | // the Extension table is required with a ProgId table |
370 | this.activeOutput.EnsureTable(this.tableDefinitions["Extension"]); | 359 | this.activeOutput.EnsureTable(this.tableDefinitions["Extension"]); |
@@ -382,42 +371,46 @@ namespace WixToolset | |||
382 | } | 371 | } |
383 | } | 372 | } |
384 | break; | 373 | break; |
374 | #endif | ||
385 | 375 | ||
386 | case "PublishComponent": | 376 | case TupleDefinitionType.PublishComponent: |
387 | if (OutputType.Product == output.Type) | 377 | if (SectionType.Product == resolvedSection.Type) |
388 | { | 378 | { |
389 | this.ResolveFeatures(table.Rows, 2, 4, componentsToFeatures, multipleFeatureComponents); | 379 | this.ResolveFeatures(tuple, 2, 4, componentsToFeatures, multipleFeatureComponents); |
390 | } | 380 | } |
391 | break; | 381 | break; |
392 | |||
393 | case "Shortcut": | ||
394 | if (OutputType.Product == output.Type) | ||
395 | { | ||
396 | this.ResolveFeatures(table.Rows, 3, 4, componentsToFeatures, multipleFeatureComponents); | ||
397 | } | ||
398 | break; | ||
399 | 382 | ||
400 | case "TypeLib": | 383 | case TupleDefinitionType.Shortcut: |
401 | if (OutputType.Product == output.Type) | 384 | if (SectionType.Product == resolvedSection.Type) |
402 | { | 385 | { |
403 | this.ResolveFeatures(table.Rows, 2, 6, componentsToFeatures, multipleFeatureComponents); | 386 | this.ResolveFeatures(tuple, 3, 4, componentsToFeatures, multipleFeatureComponents); |
404 | } | 387 | } |
405 | break; | 388 | break; |
406 | 389 | ||
407 | case "WixAction": | 390 | case TupleDefinitionType.TypeLib: |
408 | if (this.sectionIdOnRows) | 391 | if (SectionType.Product == resolvedSection.Type) |
409 | { | 392 | { |
410 | foreach (Row row in table.Rows) | 393 | this.ResolveFeatures(tuple, 2, 6, componentsToFeatures, multipleFeatureComponents); |
411 | { | 394 | } |
412 | row.SectionId = sectionId; | 395 | break; |
413 | } | 396 | |
414 | } | 397 | #if MOVE_TO_BACKEND |
415 | actionRows.AddRange(table.Rows); | 398 | case TupleDefinitionType.WixAction: |
399 | //if (this.sectionIdOnRows) | ||
400 | //{ | ||
401 | // foreach (Row row in table.Rows) | ||
402 | // { | ||
403 | // row.SectionId = sectionId; | ||
404 | // } | ||
405 | //} | ||
406 | actionRows.Add(tuple); | ||
416 | break; | 407 | break; |
408 | #endif | ||
417 | 409 | ||
410 | #if SOLVE_CUSTOM_TABLE | ||
418 | case "WixCustomTable": | 411 | case "WixCustomTable": |
419 | this.LinkCustomTable(table, customTableDefinitions); | 412 | this.LinkCustomTable(table, customTableDefinitions); |
420 | copyRows = false; // we've created table definitions from these rows, no need to process them any longer | 413 | copyTuple = false; // we've created table definitions from these rows, no need to process them any longer |
421 | break; | 414 | break; |
422 | 415 | ||
423 | case "WixCustomRow": | 416 | case "WixCustomRow": |
@@ -426,19 +419,22 @@ namespace WixToolset | |||
426 | row.SectionId = (this.sectionIdOnRows ? sectionId : null); | 419 | row.SectionId = (this.sectionIdOnRows ? sectionId : null); |
427 | customRows.Add(row); | 420 | customRows.Add(row); |
428 | } | 421 | } |
429 | copyRows = false; | 422 | copyTuple = false; |
430 | break; | 423 | break; |
424 | #endif | ||
425 | |||
426 | case TupleDefinitionType.WixEnsureTable: | ||
427 | ensureTableRows.Add(tuple); | ||
428 | break; | ||
431 | 429 | ||
432 | case "WixEnsureTable": | ||
433 | ensureTableRows.AddRange(table.Rows); | ||
434 | break; | ||
435 | 430 | ||
431 | #if MOVE_TO_BACKEND | ||
436 | case "WixFile": | 432 | case "WixFile": |
437 | foreach (Row row in table.Rows) | 433 | foreach (Row row in table.Rows) |
438 | { | 434 | { |
439 | // DiskId is not valid when creating a module, so set it to | 435 | // DiskId is not valid when creating a module, so set it to |
440 | // 0 for all files to ensure proper sorting in the binder | 436 | // 0 for all files to ensure proper sorting in the binder |
441 | if (OutputType.Module == this.activeOutput.Type) | 437 | if (SectionType.Module == entrySection.Type) |
442 | { | 438 | { |
443 | row[5] = 0; | 439 | row[5] = 0; |
444 | } | 440 | } |
@@ -450,61 +446,76 @@ namespace WixToolset | |||
450 | } | 446 | } |
451 | } | 447 | } |
452 | break; | 448 | break; |
449 | #endif | ||
453 | 450 | ||
454 | case "WixMerge": | 451 | case TupleDefinitionType.WixMerge: |
455 | if (OutputType.Product == output.Type) | 452 | if (SectionType.Product == resolvedSection.Type) |
456 | { | 453 | { |
457 | this.ResolveFeatures(table.Rows, 0, 7, modulesToFeatures, null); | 454 | this.ResolveFeatures(tuple, 0, 7, modulesToFeatures, null); |
458 | } | 455 | } |
459 | break; | 456 | break; |
460 | 457 | ||
461 | case "WixSuppressAction": | 458 | #if MOVE_TO_BACKEND |
462 | suppressActionRows.AddRange(table.Rows); | 459 | case TupleDefinitionType.WixSuppressAction: |
460 | suppressActionRows.Add(tuple); | ||
463 | break; | 461 | break; |
462 | #endif | ||
464 | 463 | ||
465 | case "WixVariable": | 464 | case TupleDefinitionType.WixComplexReference: |
466 | // check for colliding values and collect the wix variable rows | 465 | copyTuple = false; |
467 | foreach (WixVariableRow row in table.Rows) | 466 | break; |
468 | { | 467 | |
469 | WixVariableRow collidingRow = (WixVariableRow)wixVariables[row.Id]; | 468 | case TupleDefinitionType.WixSimpleReference: |
469 | copyTuple = false; | ||
470 | break; | ||
470 | 471 | ||
471 | if (null == collidingRow || (collidingRow.Overridable && !row.Overridable)) | 472 | case TupleDefinitionType.WixVariable: |
473 | // check for colliding values and collect the wix variable rows | ||
474 | { | ||
475 | var row = (WixVariableTuple)tuple; | ||
476 | |||
477 | if (wixVariables.TryGetValue(row.WixVariable, out var collidingRow)) | ||
478 | { | ||
479 | if (collidingRow.Overridable && !row.Overridable) | ||
472 | { | 480 | { |
473 | wixVariables[row.Id] = row; | 481 | wixVariables[row.WixVariable] = row; |
474 | } | 482 | } |
475 | else if (!row.Overridable || (collidingRow.Overridable && row.Overridable)) | 483 | else if (!row.Overridable || (collidingRow.Overridable && row.Overridable)) |
476 | { | 484 | { |
477 | this.OnMessage(WixErrors.WixVariableCollision(row.SourceLineNumbers, row.Id)); | 485 | this.OnMessage(WixErrors.WixVariableCollision(row.SourceLineNumbers, row.WixVariable)); |
478 | } | 486 | } |
479 | } | 487 | } |
480 | copyRows = false; | 488 | else |
481 | break; | 489 | { |
482 | } | 490 | wixVariables.Add(row.WixVariable, row); |
491 | } | ||
492 | } | ||
483 | 493 | ||
484 | if (copyRows) | 494 | copyTuple = false; |
485 | { | 495 | break; |
486 | Table outputTable = this.activeOutput.EnsureTable(this.tableDefinitions[table.Name]); | 496 | } |
487 | this.CopyTableRowsToOutputTable(table, outputTable, sectionId); | 497 | |
488 | } | 498 | if (copyTuple) |
499 | { | ||
500 | resolvedSection.Tuples.Add(tuple); | ||
489 | } | 501 | } |
490 | } | 502 | } |
503 | } | ||
491 | 504 | ||
492 | // copy the module to feature connections into the output | 505 | // copy the module to feature connections into the output |
493 | if (0 < modulesToFeatures.Count) | 506 | foreach (ConnectToFeature connectToFeature in modulesToFeatures) |
507 | { | ||
508 | foreach (var feature in connectToFeature.ConnectFeatures) | ||
494 | { | 509 | { |
495 | Table wixFeatureModulesTable = this.activeOutput.EnsureTable(this.tableDefinitions["WixFeatureModules"]); | 510 | var row = new WixFeatureModulesTuple(); |
511 | row.Feature_ = feature; | ||
512 | row.WixMerge_ = connectToFeature.ChildId; | ||
496 | 513 | ||
497 | foreach (ConnectToFeature connectToFeature in modulesToFeatures) | 514 | resolvedSection.Tuples.Add(row); |
498 | { | ||
499 | foreach (string feature in connectToFeature.ConnectFeatures) | ||
500 | { | ||
501 | Row row = wixFeatureModulesTable.CreateRow(null); | ||
502 | row[0] = feature; | ||
503 | row[1] = connectToFeature.ChildId; | ||
504 | } | ||
505 | } | ||
506 | } | 515 | } |
516 | } | ||
507 | 517 | ||
518 | #if MOVE_TO_BACKEND | ||
508 | // ensure the creation of tables that need to exist | 519 | // ensure the creation of tables that need to exist |
509 | if (0 < ensureTableRows.Count) | 520 | if (0 < ensureTableRows.Count) |
510 | { | 521 | { |
@@ -525,17 +536,14 @@ namespace WixToolset | |||
525 | this.activeOutput.EnsureTable(tableDef); | 536 | this.activeOutput.EnsureTable(tableDef); |
526 | } | 537 | } |
527 | } | 538 | } |
539 | #endif | ||
528 | 540 | ||
529 | // copy all the suppress action rows to the output to suppress actions from merge modules | 541 | #if MOVE_TO_BACKEND |
530 | if (0 < suppressActionRows.Count) | ||
531 | { | ||
532 | Table suppressActionTable = this.activeOutput.EnsureTable(this.tableDefinitions["WixSuppressAction"]); | ||
533 | suppressActionRows.ForEach(r => suppressActionTable.Rows.Add(r)); | ||
534 | } | ||
535 | |||
536 | // sequence all the actions | 542 | // sequence all the actions |
537 | this.SequenceActions(actionRows, suppressActionRows); | 543 | this.SequenceActions(actionRows, suppressActionRows); |
544 | #endif | ||
538 | 545 | ||
546 | #if MOVE_TO_BACKEND | ||
539 | // check for missing table and add them or display an error as appropriate | 547 | // check for missing table and add them or display an error as appropriate |
540 | switch (this.activeOutput.Type) | 548 | switch (this.activeOutput.Type) |
541 | { | 549 | { |
@@ -576,7 +584,9 @@ namespace WixToolset | |||
576 | } | 584 | } |
577 | 585 | ||
578 | this.CheckForIllegalTables(this.activeOutput); | 586 | this.CheckForIllegalTables(this.activeOutput); |
587 | #endif | ||
579 | 588 | ||
589 | #if SOLVE_CUSTOM_TABLE | ||
580 | // add the custom row data | 590 | // add the custom row data |
581 | foreach (Row row in customRows) | 591 | foreach (Row row in customRows) |
582 | { | 592 | { |
@@ -649,35 +659,28 @@ namespace WixToolset | |||
649 | } | 659 | } |
650 | } | 660 | } |
651 | } | 661 | } |
662 | #endif | ||
652 | 663 | ||
653 | //correct the section Id in FeatureComponents table | 664 | //correct the section Id in FeatureComponents table |
654 | if (this.sectionIdOnRows) | 665 | if (this.sectionIdOnRows) |
655 | { | 666 | { |
656 | Hashtable componentSectionIds = new Hashtable(); | 667 | //var componentSectionIds = new Dictionary<string, string>(); |
657 | Table componentTable = output.Tables["Component"]; | 668 | |
658 | 669 | //foreach (var componentTuple in entrySection.Tuples.OfType<ComponentTuple>()) | |
659 | if (null != componentTable) | 670 | //{ |
660 | { | 671 | // componentSectionIds.Add(componentTuple.Id.Id, componentTuple.SectionId); |
661 | foreach (Row componentRow in componentTable.Rows) | 672 | //} |
662 | { | 673 | |
663 | componentSectionIds.Add(componentRow.Fields[0].Data.ToString(), componentRow.SectionId); | 674 | //foreach (var featureComponentTuple in entrySection.Tuples.OfType<FeatureComponentsTuple>()) |
664 | } | 675 | //{ |
665 | } | 676 | // if (componentSectionIds.TryGetValue(featureComponentTuple.Component_, out var componentSectionId)) |
666 | 677 | // { | |
667 | Table featureComponentsTable = output.Tables["FeatureComponents"]; | 678 | // featureComponentTuple.SectionId = componentSectionId; |
668 | 679 | // } | |
669 | if (null != featureComponentsTable) | 680 | //} |
670 | { | 681 | } |
671 | foreach (Row featureComponentsRow in featureComponentsTable.Rows) | ||
672 | { | ||
673 | if (componentSectionIds.Contains(featureComponentsRow.Fields[1].Data.ToString())) | ||
674 | { | ||
675 | featureComponentsRow.SectionId = (string)componentSectionIds[featureComponentsRow.Fields[1].Data.ToString()]; | ||
676 | } | ||
677 | } | ||
678 | } | ||
679 | } | ||
680 | 682 | ||
683 | #if MOVE_TO_BACKEND | ||
681 | // add the ModuleSubstitution table to the ModuleIgnoreTable | 684 | // add the ModuleSubstitution table to the ModuleIgnoreTable |
682 | if (containsModuleSubstitution) | 685 | if (containsModuleSubstitution) |
683 | { | 686 | { |
@@ -695,7 +698,9 @@ namespace WixToolset | |||
695 | Row moduleIgnoreTableRow = moduleIgnoreTableTable.CreateRow(null); | 698 | Row moduleIgnoreTableRow = moduleIgnoreTableTable.CreateRow(null); |
696 | moduleIgnoreTableRow[0] = "ModuleConfiguration"; | 699 | moduleIgnoreTableRow[0] = "ModuleConfiguration"; |
697 | } | 700 | } |
701 | #endif | ||
698 | 702 | ||
703 | #if MOVE_TO_BACKEND | ||
699 | // index all the file rows | 704 | // index all the file rows |
700 | Table fileTable = this.activeOutput.Tables["File"]; | 705 | Table fileTable = this.activeOutput.Tables["File"]; |
701 | RowDictionary<FileRow> indexedFileRows = (null == fileTable) ? new RowDictionary<FileRow>() : new RowDictionary<FileRow>(fileTable); | 706 | RowDictionary<FileRow> indexedFileRows = (null == fileTable) ? new RowDictionary<FileRow>() : new RowDictionary<FileRow>(fileTable); |
@@ -740,47 +745,32 @@ namespace WixToolset | |||
740 | } | 745 | } |
741 | } | 746 | } |
742 | } | 747 | } |
748 | #endif | ||
743 | 749 | ||
744 | // copy the wix variable rows to the output after all overriding has been accounted for. | 750 | // copy the wix variable rows to the output after all overriding has been accounted for. |
745 | if (0 < wixVariables.Count) | 751 | foreach (var row in wixVariables.Values) |
746 | { | 752 | { |
747 | Table wixVariableTable = output.EnsureTable(this.tableDefinitions["WixVariable"]); | 753 | resolvedSection.Tuples.Add(row); |
754 | } | ||
748 | 755 | ||
749 | foreach (WixVariableRow row in wixVariables.Values) | 756 | // Bundles have groups of data that must be flattened in a way different from other types. |
750 | { | 757 | this.FlattenBundleTables(resolvedSection); |
751 | wixVariableTable.Rows.Add(row); | ||
752 | } | ||
753 | } | ||
754 | 758 | ||
755 | // Bundles have groups of data that must be flattened in a way different from other types. | 759 | if (Messaging.Instance.EncounteredError) |
756 | this.FlattenBundleTables(output); | 760 | { |
761 | return null; | ||
762 | } | ||
757 | 763 | ||
758 | if (Messaging.Instance.EncounteredError) | 764 | var output = new Intermediate(resolvedSection.Id, new[] { resolvedSection }, null, null); |
759 | { | ||
760 | return null; | ||
761 | } | ||
762 | 765 | ||
766 | #if MOVE_TO_BACKEND | ||
763 | this.CheckOutputConsistency(output); | 767 | this.CheckOutputConsistency(output); |
764 | 768 | #endif | |
765 | // inspect the output | ||
766 | InspectorCore inspectorCore = new InspectorCore(); | ||
767 | foreach (InspectorExtension inspectorExtension in this.inspectorExtensions) | ||
768 | { | ||
769 | inspectorExtension.Core = inspectorCore; | ||
770 | inspectorExtension.InspectOutput(output); | ||
771 | |||
772 | // reset | ||
773 | inspectorExtension.Core = null; | ||
774 | } | ||
775 | } | ||
776 | finally | ||
777 | { | ||
778 | this.activeOutput = null; | ||
779 | } | ||
780 | 769 | ||
781 | return Messaging.Instance.EncounteredError ? null : output; | 770 | return Messaging.Instance.EncounteredError ? null : output; |
782 | } | 771 | } |
783 | 772 | ||
773 | #if SOLVE_CUSTOM_TABLE | ||
784 | /// <summary> | 774 | /// <summary> |
785 | /// Links the definition of a custom table. | 775 | /// Links the definition of a custom table. |
786 | /// </summary> | 776 | /// </summary> |
@@ -995,7 +985,9 @@ namespace WixToolset | |||
995 | customTableDefinitions.Add(customTable); | 985 | customTableDefinitions.Add(customTable); |
996 | } | 986 | } |
997 | } | 987 | } |
988 | #endif | ||
998 | 989 | ||
990 | #if MOVE_TO_BACKEND | ||
999 | /// <summary> | 991 | /// <summary> |
1000 | /// Checks for any tables in the output which are not allowed in the output type. | 992 | /// Checks for any tables in the output which are not allowed in the output type. |
1001 | /// </summary> | 993 | /// </summary> |
@@ -1088,7 +1080,9 @@ namespace WixToolset | |||
1088 | } | 1080 | } |
1089 | } | 1081 | } |
1090 | } | 1082 | } |
1083 | #endif | ||
1091 | 1084 | ||
1085 | #if MOVE_TO_BACKEND | ||
1092 | /// <summary> | 1086 | /// <summary> |
1093 | /// Performs various consistency checks on the output. | 1087 | /// Performs various consistency checks on the output. |
1094 | /// </summary> | 1088 | /// </summary> |
@@ -1145,30 +1139,30 @@ namespace WixToolset | |||
1145 | } | 1139 | } |
1146 | } | 1140 | } |
1147 | } | 1141 | } |
1148 | 1142 | #endif | |
1149 | /// <summary> | 1143 | /// <summary> |
1150 | /// Sends a message to the message delegate if there is one. | 1144 | /// Sends a message to the message delegate if there is one. |
1151 | /// </summary> | 1145 | /// </summary> |
1152 | /// <param name="mea">Message event arguments.</param> | 1146 | /// <param name="mea">Message event arguments.</param> |
1153 | public void OnMessage(MessageEventArgs e) | 1147 | public void OnMessage(MessageEventArgs e) |
1154 | { | 1148 | { |
1155 | Messaging.Instance.OnMessage(e); | 1149 | this.Context.Messaging.OnMessage(e); |
1156 | } | 1150 | } |
1157 | 1151 | ||
1158 | /// <summary> | 1152 | /// <summary> |
1159 | /// Load the standard action symbols. | 1153 | /// Load the standard action symbols. |
1160 | /// </summary> | 1154 | /// </summary> |
1161 | /// <param name="allSymbols">Collection of symbols.</param> | 1155 | /// <param name="symbols">Collection of symbols.</param> |
1162 | private void LoadStandardActionSymbols(IDictionary<string, Symbol> allSymbols) | 1156 | private void LoadStandardActionSymbols(IntermediateSection section, IDictionary<string, Symbol> symbols) |
1163 | { | 1157 | { |
1164 | foreach (WixActionRow actionRow in this.standardActions) | 1158 | foreach (var actionRow in WindowsInstallerStandard.StandardActions()) |
1165 | { | 1159 | { |
1166 | Symbol actionSymbol = new Symbol(actionRow); | 1160 | var symbol = new Symbol(section, actionRow); |
1167 | 1161 | ||
1168 | // If the action's symbol has not already been defined (i.e. overriden by the user), add it now. | 1162 | // If the action's symbol has not already been defined (i.e. overriden by the user), add it now. |
1169 | if (!allSymbols.ContainsKey(actionSymbol.Name)) | 1163 | if (!symbols.ContainsKey(symbol.Name)) |
1170 | { | 1164 | { |
1171 | allSymbols.Add(actionSymbol.Name, actionSymbol); | 1165 | symbols.Add(symbol.Name, symbol); |
1172 | } | 1166 | } |
1173 | } | 1167 | } |
1174 | } | 1168 | } |
@@ -1176,186 +1170,180 @@ namespace WixToolset | |||
1176 | /// <summary> | 1170 | /// <summary> |
1177 | /// Process the complex references. | 1171 | /// Process the complex references. |
1178 | /// </summary> | 1172 | /// </summary> |
1179 | /// <param name="output">Active output to add sections to.</param> | 1173 | /// <param name="resolvedSection">Active section to add tuples to.</param> |
1180 | /// <param name="sections">Sections that are referenced during the link process.</param> | 1174 | /// <param name="sections">Sections that are referenced during the link process.</param> |
1181 | /// <param name="referencedComponents">Collection of all components referenced by complex reference.</param> | 1175 | /// <param name="referencedComponents">Collection of all components referenced by complex reference.</param> |
1182 | /// <param name="componentsToFeatures">Component to feature complex references.</param> | 1176 | /// <param name="componentsToFeatures">Component to feature complex references.</param> |
1183 | /// <param name="featuresToFeatures">Feature to feature complex references.</param> | 1177 | /// <param name="featuresToFeatures">Feature to feature complex references.</param> |
1184 | /// <param name="modulesToFeatures">Module to feature complex references.</param> | 1178 | /// <param name="modulesToFeatures">Module to feature complex references.</param> |
1185 | private void ProcessComplexReferences(Output output, IEnumerable<Section> sections, ISet<string> referencedComponents, ConnectToFeatureCollection componentsToFeatures, ConnectToFeatureCollection featuresToFeatures, ConnectToFeatureCollection modulesToFeatures) | 1179 | private void ProcessComplexReferences(IntermediateSection resolvedSection, IEnumerable<IntermediateSection> sections, ISet<string> referencedComponents, ConnectToFeatureCollection componentsToFeatures, ConnectToFeatureCollection featuresToFeatures, ConnectToFeatureCollection modulesToFeatures) |
1186 | { | 1180 | { |
1187 | Hashtable componentsToModules = new Hashtable(); | 1181 | Hashtable componentsToModules = new Hashtable(); |
1188 | 1182 | ||
1189 | foreach (Section section in sections) | 1183 | foreach (var section in sections) |
1190 | { | 1184 | { |
1191 | Table wixComplexReferenceTable = section.Tables["WixComplexReference"]; | 1185 | var featureComponents = new List<FeatureComponentsTuple>(); |
1192 | 1186 | ||
1193 | if (null != wixComplexReferenceTable) | 1187 | foreach (var wixComplexReferenceRow in section.Tuples.OfType<WixComplexReferenceTuple>()) |
1194 | { | 1188 | { |
1195 | foreach (WixComplexReferenceRow wixComplexReferenceRow in wixComplexReferenceTable.Rows) | 1189 | ConnectToFeature connection; |
1190 | switch (wixComplexReferenceRow.ParentType) | ||
1196 | { | 1191 | { |
1197 | ConnectToFeature connection; | 1192 | case ComplexReferenceParentType.Feature: |
1198 | switch (wixComplexReferenceRow.ParentType) | 1193 | switch (wixComplexReferenceRow.ChildType) |
1199 | { | 1194 | { |
1200 | case ComplexReferenceParentType.Feature: | 1195 | case ComplexReferenceChildType.Component: |
1201 | switch (wixComplexReferenceRow.ChildType) | 1196 | connection = componentsToFeatures[wixComplexReferenceRow.Child]; |
1202 | { | 1197 | if (null == connection) |
1203 | case ComplexReferenceChildType.Component: | 1198 | { |
1204 | connection = componentsToFeatures[wixComplexReferenceRow.ChildId]; | 1199 | componentsToFeatures.Add(new ConnectToFeature(section, wixComplexReferenceRow.Child, wixComplexReferenceRow.Parent, wixComplexReferenceRow.IsPrimary)); |
1205 | if (null == connection) | 1200 | } |
1206 | { | 1201 | else if (wixComplexReferenceRow.IsPrimary) |
1207 | componentsToFeatures.Add(new ConnectToFeature(section, wixComplexReferenceRow.ChildId, wixComplexReferenceRow.ParentId, wixComplexReferenceRow.IsPrimary)); | 1202 | { |
1208 | } | 1203 | if (connection.IsExplicitPrimaryFeature) |
1209 | else if (wixComplexReferenceRow.IsPrimary) | ||
1210 | { | 1204 | { |
1211 | if (connection.IsExplicitPrimaryFeature) | 1205 | this.OnMessage(WixErrors.MultiplePrimaryReferences(wixComplexReferenceRow.SourceLineNumbers, wixComplexReferenceRow.ChildType.ToString(), wixComplexReferenceRow.Child, wixComplexReferenceRow.ParentType.ToString(), wixComplexReferenceRow.Parent, (null != connection.PrimaryFeature ? "Feature" : "Product"), connection.PrimaryFeature ?? resolvedSection.Id)); |
1212 | { | 1206 | continue; |
1213 | this.OnMessage(WixErrors.MultiplePrimaryReferences(section.SourceLineNumbers, wixComplexReferenceRow.ChildType.ToString(), wixComplexReferenceRow.ChildId, wixComplexReferenceRow.ParentType.ToString(), wixComplexReferenceRow.ParentId, (null != connection.PrimaryFeature ? "Feature" : "Product"), (null != connection.PrimaryFeature ? connection.PrimaryFeature : this.activeOutput.EntrySection.Id))); | ||
1214 | continue; | ||
1215 | } | ||
1216 | else | ||
1217 | { | ||
1218 | connection.ConnectFeatures.Add(connection.PrimaryFeature); // move the guessed primary feature to the list of connects | ||
1219 | connection.PrimaryFeature = wixComplexReferenceRow.ParentId; // set the new primary feature | ||
1220 | connection.IsExplicitPrimaryFeature = true; // and make sure we remember that we set it so we can fail if we try to set it again | ||
1221 | } | ||
1222 | } | 1207 | } |
1223 | else | 1208 | else |
1224 | { | 1209 | { |
1225 | connection.ConnectFeatures.Add(wixComplexReferenceRow.ParentId); | 1210 | connection.ConnectFeatures.Add(connection.PrimaryFeature); // move the guessed primary feature to the list of connects |
1211 | connection.PrimaryFeature = wixComplexReferenceRow.Parent; // set the new primary feature | ||
1212 | connection.IsExplicitPrimaryFeature = true; // and make sure we remember that we set it so we can fail if we try to set it again | ||
1226 | } | 1213 | } |
1214 | } | ||
1215 | else | ||
1216 | { | ||
1217 | connection.ConnectFeatures.Add(wixComplexReferenceRow.Parent); | ||
1218 | } | ||
1227 | 1219 | ||
1228 | // add a row to the FeatureComponents table | 1220 | // add a row to the FeatureComponents table |
1229 | Table featureComponentsTable = output.EnsureTable(this.tableDefinitions["FeatureComponents"]); | 1221 | var featureComponent = new FeatureComponentsTuple(); |
1230 | Row row = featureComponentsTable.CreateRow(null); | 1222 | featureComponent.Feature_ = wixComplexReferenceRow.Parent; |
1231 | if (this.sectionIdOnRows) | 1223 | featureComponent.Component_ = wixComplexReferenceRow.Child; |
1232 | { | ||
1233 | row.SectionId = section.Id; | ||
1234 | } | ||
1235 | row[0] = wixComplexReferenceRow.ParentId; | ||
1236 | row[1] = wixComplexReferenceRow.ChildId; | ||
1237 | 1224 | ||
1238 | // index the component for finding orphaned records | 1225 | featureComponents.Add(featureComponent); |
1239 | string symbolName = String.Concat("Component:", wixComplexReferenceRow.ChildId); | ||
1240 | referencedComponents.Add(symbolName); | ||
1241 | 1226 | ||
1242 | break; | 1227 | // index the component for finding orphaned records |
1228 | var symbolName = String.Concat("Component:", wixComplexReferenceRow.Child); | ||
1229 | referencedComponents.Add(symbolName); | ||
1243 | 1230 | ||
1244 | case ComplexReferenceChildType.Feature: | 1231 | break; |
1245 | connection = featuresToFeatures[wixComplexReferenceRow.ChildId]; | ||
1246 | if (null != connection) | ||
1247 | { | ||
1248 | this.OnMessage(WixErrors.MultiplePrimaryReferences(section.SourceLineNumbers, wixComplexReferenceRow.ChildType.ToString(), wixComplexReferenceRow.ChildId, wixComplexReferenceRow.ParentType.ToString(), wixComplexReferenceRow.ParentId, (null != connection.PrimaryFeature ? "Feature" : "Product"), (null != connection.PrimaryFeature ? connection.PrimaryFeature : this.activeOutput.EntrySection.Id))); | ||
1249 | continue; | ||
1250 | } | ||
1251 | 1232 | ||
1252 | featuresToFeatures.Add(new ConnectToFeature(section, wixComplexReferenceRow.ChildId, wixComplexReferenceRow.ParentId, wixComplexReferenceRow.IsPrimary)); | 1233 | case ComplexReferenceChildType.Feature: |
1253 | break; | 1234 | connection = featuresToFeatures[wixComplexReferenceRow.Child]; |
1235 | if (null != connection) | ||
1236 | { | ||
1237 | this.OnMessage(WixErrors.MultiplePrimaryReferences(wixComplexReferenceRow.SourceLineNumbers, wixComplexReferenceRow.ChildType.ToString(), wixComplexReferenceRow.Child, wixComplexReferenceRow.ParentType.ToString(), wixComplexReferenceRow.Parent, (null != connection.PrimaryFeature ? "Feature" : "Product"), (null != connection.PrimaryFeature ? connection.PrimaryFeature : resolvedSection.Id))); | ||
1238 | continue; | ||
1239 | } | ||
1254 | 1240 | ||
1255 | case ComplexReferenceChildType.Module: | 1241 | featuresToFeatures.Add(new ConnectToFeature(section, wixComplexReferenceRow.Child, wixComplexReferenceRow.Parent, wixComplexReferenceRow.IsPrimary)); |
1256 | connection = modulesToFeatures[wixComplexReferenceRow.ChildId]; | 1242 | break; |
1257 | if (null == connection) | 1243 | |
1258 | { | 1244 | case ComplexReferenceChildType.Module: |
1259 | modulesToFeatures.Add(new ConnectToFeature(section, wixComplexReferenceRow.ChildId, wixComplexReferenceRow.ParentId, wixComplexReferenceRow.IsPrimary)); | 1245 | connection = modulesToFeatures[wixComplexReferenceRow.Child]; |
1260 | } | 1246 | if (null == connection) |
1261 | else if (wixComplexReferenceRow.IsPrimary) | 1247 | { |
1248 | modulesToFeatures.Add(new ConnectToFeature(section, wixComplexReferenceRow.Child, wixComplexReferenceRow.Parent, wixComplexReferenceRow.IsPrimary)); | ||
1249 | } | ||
1250 | else if (wixComplexReferenceRow.IsPrimary) | ||
1251 | { | ||
1252 | if (connection.IsExplicitPrimaryFeature) | ||
1262 | { | 1253 | { |
1263 | if (connection.IsExplicitPrimaryFeature) | 1254 | this.OnMessage(WixErrors.MultiplePrimaryReferences(wixComplexReferenceRow.SourceLineNumbers, wixComplexReferenceRow.ChildType.ToString(), wixComplexReferenceRow.Child, wixComplexReferenceRow.ParentType.ToString(), wixComplexReferenceRow.Parent, (null != connection.PrimaryFeature ? "Feature" : "Product"), (null != connection.PrimaryFeature ? connection.PrimaryFeature : resolvedSection.Id))); |
1264 | { | 1255 | continue; |
1265 | this.OnMessage(WixErrors.MultiplePrimaryReferences(section.SourceLineNumbers, wixComplexReferenceRow.ChildType.ToString(), wixComplexReferenceRow.ChildId, wixComplexReferenceRow.ParentType.ToString(), wixComplexReferenceRow.ParentId, (null != connection.PrimaryFeature ? "Feature" : "Product"), (null != connection.PrimaryFeature ? connection.PrimaryFeature : this.activeOutput.EntrySection.Id))); | ||
1266 | continue; | ||
1267 | } | ||
1268 | else | ||
1269 | { | ||
1270 | connection.ConnectFeatures.Add(connection.PrimaryFeature); // move the guessed primary feature to the list of connects | ||
1271 | connection.PrimaryFeature = wixComplexReferenceRow.ParentId; // set the new primary feature | ||
1272 | connection.IsExplicitPrimaryFeature = true; // and make sure we remember that we set it so we can fail if we try to set it again | ||
1273 | } | ||
1274 | } | 1256 | } |
1275 | else | 1257 | else |
1276 | { | 1258 | { |
1277 | connection.ConnectFeatures.Add(wixComplexReferenceRow.ParentId); | 1259 | connection.ConnectFeatures.Add(connection.PrimaryFeature); // move the guessed primary feature to the list of connects |
1260 | connection.PrimaryFeature = wixComplexReferenceRow.Parent; // set the new primary feature | ||
1261 | connection.IsExplicitPrimaryFeature = true; // and make sure we remember that we set it so we can fail if we try to set it again | ||
1278 | } | 1262 | } |
1279 | break; | 1263 | } |
1264 | else | ||
1265 | { | ||
1266 | connection.ConnectFeatures.Add(wixComplexReferenceRow.Parent); | ||
1267 | } | ||
1268 | break; | ||
1280 | 1269 | ||
1281 | default: | 1270 | default: |
1282 | throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceChildType), wixComplexReferenceRow.ChildType))); | 1271 | throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceChildType), wixComplexReferenceRow.ChildType))); |
1283 | } | 1272 | } |
1284 | break; | 1273 | break; |
1285 | 1274 | ||
1286 | case ComplexReferenceParentType.Module: | 1275 | case ComplexReferenceParentType.Module: |
1287 | switch (wixComplexReferenceRow.ChildType) | 1276 | switch (wixComplexReferenceRow.ChildType) |
1288 | { | 1277 | { |
1289 | case ComplexReferenceChildType.Component: | 1278 | case ComplexReferenceChildType.Component: |
1290 | if (componentsToModules.ContainsKey(wixComplexReferenceRow.ChildId)) | 1279 | if (componentsToModules.ContainsKey(wixComplexReferenceRow.Child)) |
1291 | { | 1280 | { |
1292 | this.OnMessage(WixErrors.ComponentReferencedTwice(section.SourceLineNumbers, wixComplexReferenceRow.ChildId)); | 1281 | this.OnMessage(WixErrors.ComponentReferencedTwice(wixComplexReferenceRow.SourceLineNumbers, wixComplexReferenceRow.Child)); |
1293 | continue; | 1282 | continue; |
1294 | } | 1283 | } |
1295 | else | 1284 | else |
1296 | { | 1285 | { |
1297 | componentsToModules.Add(wixComplexReferenceRow.ChildId, wixComplexReferenceRow); // should always be new | 1286 | componentsToModules.Add(wixComplexReferenceRow.Child, wixComplexReferenceRow); // should always be new |
1298 | 1287 | ||
1299 | // add a row to the ModuleComponents table | 1288 | // add a row to the ModuleComponents table |
1300 | Table moduleComponentsTable = output.EnsureTable(this.tableDefinitions["ModuleComponents"]); | 1289 | var moduleComponent = new ModuleComponentsTuple(); |
1301 | Row row = moduleComponentsTable.CreateRow(null); | 1290 | moduleComponent.Component = wixComplexReferenceRow.Child; |
1302 | if (this.sectionIdOnRows) | 1291 | moduleComponent.ModuleID = wixComplexReferenceRow.Parent; |
1303 | { | 1292 | moduleComponent.Language = Convert.ToInt32(wixComplexReferenceRow.ParentLanguage); |
1304 | row.SectionId = section.Id; | 1293 | } |
1305 | } | ||
1306 | row[0] = wixComplexReferenceRow.ChildId; | ||
1307 | row[1] = wixComplexReferenceRow.ParentId; | ||
1308 | row[2] = wixComplexReferenceRow.ParentLanguage; | ||
1309 | } | ||
1310 | 1294 | ||
1311 | // index the component for finding orphaned records | 1295 | // index the component for finding orphaned records |
1312 | string componentSymbolName = String.Concat("Component:", wixComplexReferenceRow.ChildId); | 1296 | string componentSymbolName = String.Concat("Component:", wixComplexReferenceRow.Child); |
1313 | referencedComponents.Add(componentSymbolName); | 1297 | referencedComponents.Add(componentSymbolName); |
1314 | 1298 | ||
1315 | break; | 1299 | break; |
1316 | 1300 | ||
1317 | default: | 1301 | default: |
1318 | throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceChildType), wixComplexReferenceRow.ChildType))); | 1302 | throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceChildType), wixComplexReferenceRow.ChildType))); |
1319 | } | 1303 | } |
1320 | break; | 1304 | break; |
1321 | 1305 | ||
1322 | case ComplexReferenceParentType.Patch: | 1306 | case ComplexReferenceParentType.Patch: |
1323 | switch (wixComplexReferenceRow.ChildType) | 1307 | switch (wixComplexReferenceRow.ChildType) |
1324 | { | 1308 | { |
1325 | case ComplexReferenceChildType.PatchFamily: | 1309 | case ComplexReferenceChildType.PatchFamily: |
1326 | case ComplexReferenceChildType.PatchFamilyGroup: | 1310 | case ComplexReferenceChildType.PatchFamilyGroup: |
1327 | break; | 1311 | break; |
1328 | 1312 | ||
1329 | default: | 1313 | default: |
1330 | throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceChildType), wixComplexReferenceRow.ChildType))); | 1314 | throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceChildType), wixComplexReferenceRow.ChildType))); |
1331 | } | 1315 | } |
1332 | break; | 1316 | break; |
1333 | 1317 | ||
1334 | case ComplexReferenceParentType.Product: | 1318 | case ComplexReferenceParentType.Product: |
1335 | switch (wixComplexReferenceRow.ChildType) | 1319 | switch (wixComplexReferenceRow.ChildType) |
1336 | { | 1320 | { |
1337 | case ComplexReferenceChildType.Feature: | 1321 | case ComplexReferenceChildType.Feature: |
1338 | connection = featuresToFeatures[wixComplexReferenceRow.ChildId]; | 1322 | connection = featuresToFeatures[wixComplexReferenceRow.Child]; |
1339 | if (null != connection) | 1323 | if (null != connection) |
1340 | { | 1324 | { |
1341 | this.OnMessage(WixErrors.MultiplePrimaryReferences(section.SourceLineNumbers, wixComplexReferenceRow.ChildType.ToString(), wixComplexReferenceRow.ChildId, wixComplexReferenceRow.ParentType.ToString(), wixComplexReferenceRow.ParentId, (null != connection.PrimaryFeature ? "Feature" : "Product"), (null != connection.PrimaryFeature ? connection.PrimaryFeature : this.activeOutput.EntrySection.Id))); | 1325 | this.OnMessage(WixErrors.MultiplePrimaryReferences(wixComplexReferenceRow.SourceLineNumbers, wixComplexReferenceRow.ChildType.ToString(), wixComplexReferenceRow.Child, wixComplexReferenceRow.ParentType.ToString(), wixComplexReferenceRow.Parent, (null != connection.PrimaryFeature ? "Feature" : "Product"), (null != connection.PrimaryFeature ? connection.PrimaryFeature : resolvedSection.Id))); |
1342 | continue; | 1326 | continue; |
1343 | } | 1327 | } |
1344 | 1328 | ||
1345 | featuresToFeatures.Add(new ConnectToFeature(section, wixComplexReferenceRow.ChildId, null, wixComplexReferenceRow.IsPrimary)); | 1329 | featuresToFeatures.Add(new ConnectToFeature(section, wixComplexReferenceRow.Child, null, wixComplexReferenceRow.IsPrimary)); |
1346 | break; | 1330 | break; |
1347 | 1331 | ||
1348 | default: | 1332 | default: |
1349 | throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceChildType), wixComplexReferenceRow.ChildType))); | 1333 | throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceChildType), wixComplexReferenceRow.ChildType))); |
1350 | } | 1334 | } |
1351 | break; | 1335 | break; |
1352 | 1336 | ||
1353 | default: | 1337 | default: |
1354 | // Note: Groups have been processed before getting here so they are not handled by any case above. | 1338 | // Note: Groups have been processed before getting here so they are not handled by any case above. |
1355 | throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceParentType), wixComplexReferenceRow.ParentType))); | 1339 | throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceParentType), wixComplexReferenceRow.ParentType))); |
1356 | } | ||
1357 | } | 1340 | } |
1358 | } | 1341 | } |
1342 | |||
1343 | foreach (var featureComponent in featureComponents) | ||
1344 | { | ||
1345 | section.Tuples.Add(featureComponent); | ||
1346 | } | ||
1359 | } | 1347 | } |
1360 | } | 1348 | } |
1361 | 1349 | ||
@@ -1363,11 +1351,11 @@ namespace WixToolset | |||
1363 | /// Flattens all complex references in all sections in the collection. | 1351 | /// Flattens all complex references in all sections in the collection. |
1364 | /// </summary> | 1352 | /// </summary> |
1365 | /// <param name="sections">Sections that are referenced during the link process.</param> | 1353 | /// <param name="sections">Sections that are referenced during the link process.</param> |
1366 | private void FlattenSectionsComplexReferences(IEnumerable<Section> sections) | 1354 | private void FlattenSectionsComplexReferences(IEnumerable<IntermediateSection> sections) |
1367 | { | 1355 | { |
1368 | Hashtable parentGroups = new Hashtable(); | 1356 | var parentGroups = new Dictionary<string, List<WixComplexReferenceTuple>>(); |
1369 | Hashtable parentGroupsSections = new Hashtable(); | 1357 | var parentGroupsSections = new Dictionary<string, IntermediateSection>(); |
1370 | Hashtable parentGroupsNeedingProcessing = new Hashtable(); | 1358 | var parentGroupsNeedingProcessing = new Dictionary<string, IntermediateSection>(); |
1371 | 1359 | ||
1372 | // DisplaySectionComplexReferences("--- section's complex references before flattening ---", sections); | 1360 | // DisplaySectionComplexReferences("--- section's complex references before flattening ---", sections); |
1373 | 1361 | ||
@@ -1376,69 +1364,60 @@ namespace WixToolset | |||
1376 | // parents" of Features, Modules, and, of course, Groups. These references | 1364 | // parents" of Features, Modules, and, of course, Groups. These references |
1377 | // that participate in a "grouping parent" will be removed from their section | 1365 | // that participate in a "grouping parent" will be removed from their section |
1378 | // now and after processing added back in Step 3 below. | 1366 | // now and after processing added back in Step 3 below. |
1379 | foreach (Section section in sections) | 1367 | foreach (var section in sections) |
1380 | { | 1368 | { |
1381 | Table wixComplexReferenceTable = section.Tables["WixComplexReference"]; | 1369 | // Count down because we'll sometimes remove items from the list. |
1382 | 1370 | for (int i = section.Tuples.Count - 1; i >= 0; --i) | |
1383 | if (null != wixComplexReferenceTable) | ||
1384 | { | 1371 | { |
1385 | // Count down because we'll sometimes remove items from the list. | 1372 | // Only process the "grouping parents" such as FeatureGroup, ComponentGroup, Feature, |
1386 | for (int i = wixComplexReferenceTable.Rows.Count - 1; i >= 0; --i) | 1373 | // and Module. Non-grouping complex references are simple and |
1374 | // resolved during normal complex reference resolutions. | ||
1375 | if (section.Tuples[i] is WixComplexReferenceTuple wixComplexReferenceRow && | ||
1376 | (ComplexReferenceParentType.FeatureGroup == wixComplexReferenceRow.ParentType || | ||
1377 | ComplexReferenceParentType.ComponentGroup == wixComplexReferenceRow.ParentType || | ||
1378 | ComplexReferenceParentType.Feature == wixComplexReferenceRow.ParentType || | ||
1379 | ComplexReferenceParentType.Module == wixComplexReferenceRow.ParentType || | ||
1380 | ComplexReferenceParentType.PatchFamilyGroup == wixComplexReferenceRow.ParentType || | ||
1381 | ComplexReferenceParentType.Product == wixComplexReferenceRow.ParentType)) | ||
1387 | { | 1382 | { |
1388 | WixComplexReferenceRow wixComplexReferenceRow = (WixComplexReferenceRow)wixComplexReferenceTable.Rows[i]; | 1383 | var parentTypeAndId = CombineTypeAndId(wixComplexReferenceRow.ParentType, wixComplexReferenceRow.Parent); |
1389 | 1384 | ||
1390 | // Only process the "grouping parents" such as FeatureGroup, ComponentGroup, Feature, | 1385 | // Group all complex references with a common parent |
1391 | // and Module. Non-grouping complex references are simple and | 1386 | // together so we can find them quickly while processing in |
1392 | // resolved during normal complex reference resolutions. | 1387 | // Step 2. |
1393 | if (ComplexReferenceParentType.FeatureGroup == wixComplexReferenceRow.ParentType || | 1388 | if (!parentGroups.TryGetValue(parentTypeAndId, out var childrenComplexRefs)) |
1394 | ComplexReferenceParentType.ComponentGroup == wixComplexReferenceRow.ParentType || | ||
1395 | ComplexReferenceParentType.Feature == wixComplexReferenceRow.ParentType || | ||
1396 | ComplexReferenceParentType.Module == wixComplexReferenceRow.ParentType || | ||
1397 | ComplexReferenceParentType.PatchFamilyGroup == wixComplexReferenceRow.ParentType || | ||
1398 | ComplexReferenceParentType.Product == wixComplexReferenceRow.ParentType) | ||
1399 | { | 1389 | { |
1400 | string parentTypeAndId = CombineTypeAndId(wixComplexReferenceRow.ParentType, wixComplexReferenceRow.ParentId); | 1390 | childrenComplexRefs = new List<WixComplexReferenceTuple>(); |
1391 | parentGroups.Add(parentTypeAndId, childrenComplexRefs); | ||
1392 | } | ||
1401 | 1393 | ||
1402 | // Group all complex references with a common parent | 1394 | childrenComplexRefs.Add(wixComplexReferenceRow); |
1403 | // together so we can find them quickly while processing in | 1395 | section.Tuples.RemoveAt(i); |
1404 | // Step 2. | ||
1405 | ArrayList childrenComplexRefs = parentGroups[parentTypeAndId] as ArrayList; | ||
1406 | if (null == childrenComplexRefs) | ||
1407 | { | ||
1408 | childrenComplexRefs = new ArrayList(); | ||
1409 | parentGroups.Add(parentTypeAndId, childrenComplexRefs); | ||
1410 | } | ||
1411 | 1396 | ||
1412 | childrenComplexRefs.Add(wixComplexReferenceRow); | 1397 | // Remember the mapping from set of complex references with a common |
1413 | wixComplexReferenceTable.Rows.RemoveAt(i); | 1398 | // parent to their section. We'll need this to add them back to the |
1399 | // correct section in Step 3. | ||
1400 | if (!parentGroupsSections.TryGetValue(parentTypeAndId, out var parentSection)) | ||
1401 | { | ||
1402 | parentGroupsSections.Add(parentTypeAndId, section); | ||
1403 | } | ||
1414 | 1404 | ||
1415 | // Remember the mapping from set of complex references with a common | 1405 | // If the child of the complex reference is another group, then in Step 2 |
1416 | // parent to their section. We'll need this to add them back to the | 1406 | // we're going to have to process this complex reference again to copy |
1417 | // correct section in Step 3. | 1407 | // the child group's references into the parent group. |
1418 | Section parentSection = parentGroupsSections[parentTypeAndId] as Section; | 1408 | if ((ComplexReferenceChildType.ComponentGroup == wixComplexReferenceRow.ChildType) || |
1419 | if (null == parentSection) | 1409 | (ComplexReferenceChildType.FeatureGroup == wixComplexReferenceRow.ChildType) || |
1420 | { | 1410 | (ComplexReferenceChildType.PatchFamilyGroup == wixComplexReferenceRow.ChildType)) |
1421 | parentGroupsSections.Add(parentTypeAndId, section); | 1411 | { |
1422 | } | 1412 | if (!parentGroupsNeedingProcessing.ContainsKey(parentTypeAndId)) |
1423 | // Debug.Assert(section == (Section)parentGroupsSections[parentTypeAndId]); | ||
1424 | |||
1425 | // If the child of the complex reference is another group, then in Step 2 | ||
1426 | // we're going to have to process this complex reference again to copy | ||
1427 | // the child group's references into the parent group. | ||
1428 | if ((ComplexReferenceChildType.ComponentGroup == wixComplexReferenceRow.ChildType) || | ||
1429 | (ComplexReferenceChildType.FeatureGroup == wixComplexReferenceRow.ChildType) || | ||
1430 | (ComplexReferenceChildType.PatchFamilyGroup == wixComplexReferenceRow.ChildType)) | ||
1431 | { | 1413 | { |
1432 | if (!parentGroupsNeedingProcessing.ContainsKey(parentTypeAndId)) | 1414 | parentGroupsNeedingProcessing.Add(parentTypeAndId, section); |
1433 | { | ||
1434 | parentGroupsNeedingProcessing.Add(parentTypeAndId, section); | ||
1435 | } | ||
1436 | // Debug.Assert(section == (Section)parentGroupsNeedingProcessing[parentTypeAndId]); | ||
1437 | } | 1415 | } |
1438 | } | 1416 | } |
1439 | } | 1417 | } |
1440 | } | 1418 | } |
1441 | } | 1419 | } |
1420 | |||
1442 | Debug.Assert(parentGroups.Count == parentGroupsSections.Count); | 1421 | Debug.Assert(parentGroups.Count == parentGroupsSections.Count); |
1443 | Debug.Assert(parentGroupsNeedingProcessing.Count <= parentGroups.Count); | 1422 | Debug.Assert(parentGroupsNeedingProcessing.Count <= parentGroups.Count); |
1444 | 1423 | ||
@@ -1447,14 +1426,13 @@ namespace WixToolset | |||
1447 | // Step 2: Loop through the parent groups that have nested groups removing | 1426 | // Step 2: Loop through the parent groups that have nested groups removing |
1448 | // them from the hash table as they are processed. At the end of this the | 1427 | // them from the hash table as they are processed. At the end of this the |
1449 | // complex references should all be flattened. | 1428 | // complex references should all be flattened. |
1450 | string[] keys = new string[parentGroupsNeedingProcessing.Keys.Count]; | 1429 | var keys = parentGroupsNeedingProcessing.Keys.ToList(); |
1451 | parentGroupsNeedingProcessing.Keys.CopyTo(keys, 0); | ||
1452 | 1430 | ||
1453 | foreach (string key in keys) | 1431 | foreach (string key in keys) |
1454 | { | 1432 | { |
1455 | if (parentGroupsNeedingProcessing.Contains(key)) | 1433 | if (parentGroupsNeedingProcessing.ContainsKey(key)) |
1456 | { | 1434 | { |
1457 | Stack loopDetector = new Stack(); | 1435 | var loopDetector = new Stack<string>(); |
1458 | this.FlattenGroup(key, loopDetector, parentGroups, parentGroupsNeedingProcessing); | 1436 | this.FlattenGroup(key, loopDetector, parentGroups, parentGroupsNeedingProcessing); |
1459 | } | 1437 | } |
1460 | else | 1438 | else |
@@ -1468,18 +1446,17 @@ namespace WixToolset | |||
1468 | // in Step 1 and flattened in Step 2 are added to their appropriate | 1446 | // in Step 1 and flattened in Step 2 are added to their appropriate |
1469 | // section. This is where we will toss out the final no-longer-needed | 1447 | // section. This is where we will toss out the final no-longer-needed |
1470 | // groups. | 1448 | // groups. |
1471 | foreach (string parentGroup in parentGroups.Keys) | 1449 | foreach (var parentGroup in parentGroups.Keys) |
1472 | { | 1450 | { |
1473 | Section section = (Section)parentGroupsSections[parentGroup]; | 1451 | var section = parentGroupsSections[parentGroup]; |
1474 | Table wixComplexReferenceTable = section.Tables["WixComplexReference"]; | ||
1475 | 1452 | ||
1476 | foreach (WixComplexReferenceRow wixComplexReferenceRow in (ArrayList)parentGroups[parentGroup]) | 1453 | foreach (var wixComplexReferenceRow in parentGroups[parentGroup]) |
1477 | { | 1454 | { |
1478 | if ((ComplexReferenceParentType.FeatureGroup != wixComplexReferenceRow.ParentType) && | 1455 | if ((ComplexReferenceParentType.FeatureGroup != wixComplexReferenceRow.ParentType) && |
1479 | (ComplexReferenceParentType.ComponentGroup != wixComplexReferenceRow.ParentType) && | 1456 | (ComplexReferenceParentType.ComponentGroup != wixComplexReferenceRow.ParentType) && |
1480 | (ComplexReferenceParentType.PatchFamilyGroup != wixComplexReferenceRow.ParentType)) | 1457 | (ComplexReferenceParentType.PatchFamilyGroup != wixComplexReferenceRow.ParentType)) |
1481 | { | 1458 | { |
1482 | wixComplexReferenceTable.Rows.Add(wixComplexReferenceRow); | 1459 | section.Tuples.Add(wixComplexReferenceRow); |
1483 | } | 1460 | } |
1484 | } | 1461 | } |
1485 | } | 1462 | } |
@@ -1504,46 +1481,39 @@ namespace WixToolset | |||
1504 | /// <param name="loopDetector">Stack of groups processed thus far. Used to detect loops.</param> | 1481 | /// <param name="loopDetector">Stack of groups processed thus far. Used to detect loops.</param> |
1505 | /// <param name="parentGroups">Hash table of complex references grouped by parent id.</param> | 1482 | /// <param name="parentGroups">Hash table of complex references grouped by parent id.</param> |
1506 | /// <param name="parentGroupsNeedingProcessing">Hash table of parent groups that still have nested groups that need to be flattened.</param> | 1483 | /// <param name="parentGroupsNeedingProcessing">Hash table of parent groups that still have nested groups that need to be flattened.</param> |
1507 | private void FlattenGroup(string parentTypeAndId, Stack loopDetector, Hashtable parentGroups, Hashtable parentGroupsNeedingProcessing) | 1484 | private void FlattenGroup(string parentTypeAndId, Stack<string> loopDetector, Dictionary<string, List<WixComplexReferenceTuple>> parentGroups, Dictionary<string, IntermediateSection> parentGroupsNeedingProcessing) |
1508 | { | 1485 | { |
1509 | Debug.Assert(parentGroupsNeedingProcessing.Contains(parentTypeAndId)); | 1486 | Debug.Assert(parentGroupsNeedingProcessing.ContainsKey(parentTypeAndId)); |
1510 | loopDetector.Push(parentTypeAndId); // push this complex reference parent identfier into the stack for loop verifying | 1487 | loopDetector.Push(parentTypeAndId); // push this complex reference parent identfier into the stack for loop verifying |
1511 | 1488 | ||
1512 | ArrayList allNewChildComplexReferences = new ArrayList(); | 1489 | var allNewChildComplexReferences = new List<WixComplexReferenceTuple>(); |
1513 | ArrayList referencesToParent = (ArrayList)parentGroups[parentTypeAndId]; | 1490 | |
1514 | foreach (WixComplexReferenceRow wixComplexReferenceRow in referencesToParent) | 1491 | var referencesToParent = parentGroups[parentTypeAndId]; |
1492 | foreach (var wixComplexReferenceRow in referencesToParent) | ||
1515 | { | 1493 | { |
1516 | Debug.Assert(ComplexReferenceParentType.ComponentGroup == wixComplexReferenceRow.ParentType || ComplexReferenceParentType.FeatureGroup == wixComplexReferenceRow.ParentType || ComplexReferenceParentType.Feature == wixComplexReferenceRow.ParentType || ComplexReferenceParentType.Module == wixComplexReferenceRow.ParentType || ComplexReferenceParentType.Product == wixComplexReferenceRow.ParentType || ComplexReferenceParentType.PatchFamilyGroup == wixComplexReferenceRow.ParentType || ComplexReferenceParentType.Patch == wixComplexReferenceRow.ParentType); | 1494 | Debug.Assert(ComplexReferenceParentType.ComponentGroup == wixComplexReferenceRow.ParentType || ComplexReferenceParentType.FeatureGroup == wixComplexReferenceRow.ParentType || ComplexReferenceParentType.Feature == wixComplexReferenceRow.ParentType || ComplexReferenceParentType.Module == wixComplexReferenceRow.ParentType || ComplexReferenceParentType.Product == wixComplexReferenceRow.ParentType || ComplexReferenceParentType.PatchFamilyGroup == wixComplexReferenceRow.ParentType || ComplexReferenceParentType.Patch == wixComplexReferenceRow.ParentType); |
1517 | Debug.Assert(parentTypeAndId == CombineTypeAndId(wixComplexReferenceRow.ParentType, wixComplexReferenceRow.ParentId)); | 1495 | Debug.Assert(parentTypeAndId == CombineTypeAndId(wixComplexReferenceRow.ParentType, wixComplexReferenceRow.Parent)); |
1518 | 1496 | ||
1519 | // We are only interested processing when the child is a group. | 1497 | // We are only interested processing when the child is a group. |
1520 | if ((ComplexReferenceChildType.ComponentGroup == wixComplexReferenceRow.ChildType) || | 1498 | if ((ComplexReferenceChildType.ComponentGroup == wixComplexReferenceRow.ChildType) || |
1521 | (ComplexReferenceChildType.FeatureGroup == wixComplexReferenceRow.ChildType) || | 1499 | (ComplexReferenceChildType.FeatureGroup == wixComplexReferenceRow.ChildType) || |
1522 | (ComplexReferenceChildType.PatchFamilyGroup == wixComplexReferenceRow.ChildType)) | 1500 | (ComplexReferenceChildType.PatchFamilyGroup == wixComplexReferenceRow.ChildType)) |
1523 | { | 1501 | { |
1524 | string childTypeAndId = CombineTypeAndId(wixComplexReferenceRow.ChildType, wixComplexReferenceRow.ChildId); | 1502 | string childTypeAndId = CombineTypeAndId(wixComplexReferenceRow.ChildType, wixComplexReferenceRow.Child); |
1525 | if (loopDetector.Contains(childTypeAndId)) | 1503 | if (loopDetector.Contains(childTypeAndId)) |
1526 | { | 1504 | { |
1527 | // Create a comma delimited list of the references that participate in the | 1505 | // Create a comma delimited list of the references that participate in the |
1528 | // loop for the error message. Start at the bottom of the stack and work the | 1506 | // loop for the error message. Start at the bottom of the stack and work the |
1529 | // way up to present the loop as a directed graph. | 1507 | // way up to present the loop as a directed graph. |
1530 | object[] stack = loopDetector.ToArray(); | 1508 | var loop = String.Join(" -> ", loopDetector); |
1531 | StringBuilder loop = new StringBuilder(); | ||
1532 | for (int i = stack.Length - 1; i >= 0; --i) | ||
1533 | { | ||
1534 | loop.Append((string)stack[i]); | ||
1535 | if (0 < i) | ||
1536 | { | ||
1537 | loop.Append(" -> "); | ||
1538 | } | ||
1539 | } | ||
1540 | 1509 | ||
1541 | this.OnMessage(WixErrors.ReferenceLoopDetected(wixComplexReferenceRow.Table.Section == null ? null : wixComplexReferenceRow.Table.Section.SourceLineNumbers, loop.ToString())); | 1510 | this.OnMessage(WixErrors.ReferenceLoopDetected(wixComplexReferenceRow?.SourceLineNumbers, loop)); |
1542 | 1511 | ||
1543 | // Cleanup the parentGroupsNeedingProcessing and the loopDetector just like the | 1512 | // Cleanup the parentGroupsNeedingProcessing and the loopDetector just like the |
1544 | // exit of this method does at the end because we are exiting early. | 1513 | // exit of this method does at the end because we are exiting early. |
1545 | loopDetector.Pop(); | 1514 | loopDetector.Pop(); |
1546 | parentGroupsNeedingProcessing.Remove(parentTypeAndId); | 1515 | parentGroupsNeedingProcessing.Remove(parentTypeAndId); |
1516 | |||
1547 | return; // bail | 1517 | return; // bail |
1548 | } | 1518 | } |
1549 | 1519 | ||
@@ -1560,10 +1530,9 @@ namespace WixToolset | |||
1560 | // complex reference (because we're moving references up the tree), and finally | 1530 | // complex reference (because we're moving references up the tree), and finally |
1561 | // add the cloned child's complex reference to the list of complex references | 1531 | // add the cloned child's complex reference to the list of complex references |
1562 | // that we'll eventually add to the parent group. | 1532 | // that we'll eventually add to the parent group. |
1563 | ArrayList referencesToChild = (ArrayList)parentGroups[childTypeAndId]; | 1533 | if (parentGroups.TryGetValue(childTypeAndId, out var referencesToChild)) |
1564 | if (null != referencesToChild) | ||
1565 | { | 1534 | { |
1566 | foreach (WixComplexReferenceRow crefChild in referencesToChild) | 1535 | foreach (var crefChild in referencesToChild) |
1567 | { | 1536 | { |
1568 | // Only merge up the non-group items since groups are purged | 1537 | // Only merge up the non-group items since groups are purged |
1569 | // after this part of the processing anyway (cloning them would | 1538 | // after this part of the processing anyway (cloning them would |
@@ -1572,8 +1541,8 @@ namespace WixToolset | |||
1572 | (ComplexReferenceChildType.ComponentGroup != crefChild.ChildType) || | 1541 | (ComplexReferenceChildType.ComponentGroup != crefChild.ChildType) || |
1573 | (ComplexReferenceChildType.PatchFamilyGroup != crefChild.ChildType)) | 1542 | (ComplexReferenceChildType.PatchFamilyGroup != crefChild.ChildType)) |
1574 | { | 1543 | { |
1575 | WixComplexReferenceRow crefChildClone = crefChild.Clone(); | 1544 | var crefChildClone = crefChild.Clone(); |
1576 | Debug.Assert(crefChildClone.ParentId == wixComplexReferenceRow.ChildId); | 1545 | Debug.Assert(crefChildClone.Parent == wixComplexReferenceRow.Child); |
1577 | 1546 | ||
1578 | crefChildClone.Reparent(wixComplexReferenceRow); | 1547 | crefChildClone.Reparent(wixComplexReferenceRow); |
1579 | allNewChildComplexReferences.Add(crefChildClone); | 1548 | allNewChildComplexReferences.Add(crefChildClone); |
@@ -1587,10 +1556,11 @@ namespace WixToolset | |||
1587 | // group. Clean out any left over groups and quietly remove any | 1556 | // group. Clean out any left over groups and quietly remove any |
1588 | // duplicate complex references that occurred during the merge. | 1557 | // duplicate complex references that occurred during the merge. |
1589 | referencesToParent.AddRange(allNewChildComplexReferences); | 1558 | referencesToParent.AddRange(allNewChildComplexReferences); |
1590 | referencesToParent.Sort(); | 1559 | referencesToParent.Sort(ComplexReferenceComparision); |
1591 | for (int i = referencesToParent.Count - 1; i >= 0; --i) | 1560 | for (int i = referencesToParent.Count - 1; i >= 0; --i) |
1592 | { | 1561 | { |
1593 | WixComplexReferenceRow wixComplexReferenceRow = (WixComplexReferenceRow)referencesToParent[i]; | 1562 | var wixComplexReferenceRow = referencesToParent[i]; |
1563 | |||
1594 | if ((ComplexReferenceChildType.FeatureGroup == wixComplexReferenceRow.ChildType) || | 1564 | if ((ComplexReferenceChildType.FeatureGroup == wixComplexReferenceRow.ChildType) || |
1595 | (ComplexReferenceChildType.ComponentGroup == wixComplexReferenceRow.ChildType) || | 1565 | (ComplexReferenceChildType.ComponentGroup == wixComplexReferenceRow.ChildType) || |
1596 | (ComplexReferenceChildType.PatchFamilyGroup == wixComplexReferenceRow.ChildType)) | 1566 | (ComplexReferenceChildType.PatchFamilyGroup == wixComplexReferenceRow.ChildType)) |
@@ -1602,7 +1572,7 @@ namespace WixToolset | |||
1602 | // Since the list is already sorted, we can find duplicates by simply | 1572 | // Since the list is already sorted, we can find duplicates by simply |
1603 | // looking at the next sibling in the list and tossing out one if they | 1573 | // looking at the next sibling in the list and tossing out one if they |
1604 | // match. | 1574 | // match. |
1605 | WixComplexReferenceRow crefCompare = (WixComplexReferenceRow)referencesToParent[i - 1]; | 1575 | var crefCompare = referencesToParent[i - 1]; |
1606 | if (0 == wixComplexReferenceRow.CompareToWithoutConsideringPrimary(crefCompare)) | 1576 | if (0 == wixComplexReferenceRow.CompareToWithoutConsideringPrimary(crefCompare)) |
1607 | { | 1577 | { |
1608 | referencesToParent.RemoveAt(i); | 1578 | referencesToParent.RemoveAt(i); |
@@ -1610,6 +1580,29 @@ namespace WixToolset | |||
1610 | } | 1580 | } |
1611 | } | 1581 | } |
1612 | 1582 | ||
1583 | int ComplexReferenceComparision(WixComplexReferenceTuple x, WixComplexReferenceTuple y) | ||
1584 | { | ||
1585 | var comparison = x.ChildType - y.ChildType; | ||
1586 | if (0 == comparison) | ||
1587 | { | ||
1588 | comparison = String.Compare(x.Child, y.Child, StringComparison.Ordinal); | ||
1589 | if (0 == comparison) | ||
1590 | { | ||
1591 | comparison = x.ParentType - y.ParentType; | ||
1592 | if (0 == comparison) | ||
1593 | { | ||
1594 | comparison = String.Compare(x.ParentLanguage ?? String.Empty, y.ParentLanguage ?? String.Empty, StringComparison.Ordinal); | ||
1595 | if (0 == comparison) | ||
1596 | { | ||
1597 | comparison = String.Compare(x.Parent, y.Parent, StringComparison.Ordinal); | ||
1598 | } | ||
1599 | } | ||
1600 | } | ||
1601 | } | ||
1602 | |||
1603 | return comparison; | ||
1604 | } | ||
1605 | |||
1613 | loopDetector.Pop(); // pop this complex reference off the stack since we're done verify the loop here | 1606 | loopDetector.Pop(); // pop this complex reference off the stack since we're done verify the loop here |
1614 | parentGroupsNeedingProcessing.Remove(parentTypeAndId); // remove the newly processed complex reference | 1607 | parentGroupsNeedingProcessing.Remove(parentTypeAndId); // remove the newly processed complex reference |
1615 | } | 1608 | } |
@@ -1639,9 +1632,9 @@ namespace WixToolset | |||
1639 | /// Flattens the tables used in a Bundle. | 1632 | /// Flattens the tables used in a Bundle. |
1640 | /// </summary> | 1633 | /// </summary> |
1641 | /// <param name="output">Output containing the tables to process.</param> | 1634 | /// <param name="output">Output containing the tables to process.</param> |
1642 | private void FlattenBundleTables(Output output) | 1635 | private void FlattenBundleTables(IntermediateSection entrySection) |
1643 | { | 1636 | { |
1644 | if (OutputType.Bundle != output.Type) | 1637 | if (SectionType.Bundle != entrySection.Type) |
1645 | { | 1638 | { |
1646 | return; | 1639 | return; |
1647 | } | 1640 | } |
@@ -1651,7 +1644,7 @@ namespace WixToolset | |||
1651 | // will hold Payloads under UX, ChainPackages (references?) under Chain, | 1644 | // will hold Payloads under UX, ChainPackages (references?) under Chain, |
1652 | // and ChainPackages/Payloads under the attached and any detatched | 1645 | // and ChainPackages/Payloads under the attached and any detatched |
1653 | // Containers. | 1646 | // Containers. |
1654 | WixGroupingOrdering groups = new WixGroupingOrdering(output, this); | 1647 | var groups = new WixGroupingOrdering(entrySection, this); |
1655 | 1648 | ||
1656 | // Create UX payloads and Package payloads | 1649 | // Create UX payloads and Package payloads |
1657 | groups.UseTypes(new string[] { "Container", "Layout", "PackageGroup", "PayloadGroup", "Package" }, new string[] { "PackageGroup", "Package", "PayloadGroup", "Payload" }); | 1650 | groups.UseTypes(new string[] { "Container", "Layout", "PackageGroup", "PayloadGroup", "Package" }, new string[] { "PackageGroup", "Package", "PayloadGroup", "Payload" }); |
@@ -1675,21 +1668,21 @@ namespace WixToolset | |||
1675 | { | 1668 | { |
1676 | foreach (ConnectToFeature connection in featuresToFeatures) | 1669 | foreach (ConnectToFeature connection in featuresToFeatures) |
1677 | { | 1670 | { |
1678 | WixSimpleReferenceRow wixSimpleReferenceRow = new WixSimpleReferenceRow(null, this.tableDefinitions["WixSimpleReference"]); | 1671 | var wixSimpleReferenceRow = new WixSimpleReferenceTuple(); |
1679 | wixSimpleReferenceRow.TableName = "Feature"; | 1672 | wixSimpleReferenceRow.Table = "Feature"; |
1680 | wixSimpleReferenceRow.PrimaryKeys = connection.ChildId; | 1673 | wixSimpleReferenceRow.PrimaryKeys = connection.ChildId; |
1681 | 1674 | ||
1682 | Symbol symbol; | 1675 | if (!allSymbols.TryGetValue(wixSimpleReferenceRow.SymbolicName, out var symbol)) |
1683 | if (!allSymbols.TryGetValue(wixSimpleReferenceRow.SymbolicName, out symbol)) | ||
1684 | { | 1676 | { |
1685 | continue; | 1677 | continue; |
1686 | } | 1678 | } |
1687 | 1679 | ||
1688 | Row row = symbol.Row; | 1680 | var row = symbol.Row; |
1689 | row[1] = connection.PrimaryFeature; | 1681 | row.Set(1, connection.PrimaryFeature); |
1690 | } | 1682 | } |
1691 | } | 1683 | } |
1692 | 1684 | ||
1685 | #if DEAD_CODE | ||
1693 | /// <summary> | 1686 | /// <summary> |
1694 | /// Copies a table's rows to an output table. | 1687 | /// Copies a table's rows to an output table. |
1695 | /// </summary> | 1688 | /// </summary> |
@@ -1731,16 +1724,18 @@ namespace WixToolset | |||
1731 | outputTable.Rows.Add(row); | 1724 | outputTable.Rows.Add(row); |
1732 | } | 1725 | } |
1733 | } | 1726 | } |
1727 | #endif | ||
1734 | 1728 | ||
1729 | #if MOVE_TO_BACKEND | ||
1735 | /// <summary> | 1730 | /// <summary> |
1736 | /// Set sequence numbers for all the actions and create rows in the output object. | 1731 | /// Set sequence numbers for all the actions and create rows in the output object. |
1737 | /// </summary> | 1732 | /// </summary> |
1738 | /// <param name="actionRows">Collection of actions to schedule.</param> | 1733 | /// <param name="actionRows">Collection of actions to schedule.</param> |
1739 | /// <param name="suppressActionRows">Collection of actions to suppress.</param> | 1734 | /// <param name="suppressActionRows">Collection of actions to suppress.</param> |
1740 | private void SequenceActions(List<Row> actionRows, List<Row> suppressActionRows) | 1735 | private void SequenceActions(List<IntermediateTuple> actionRows, List<IntermediateTuple> suppressActionRows) |
1741 | { | 1736 | { |
1742 | WixActionRowCollection overridableActionRows = new WixActionRowCollection(); | 1737 | var overridableActionRows = new WixActionRowCollection(); |
1743 | WixActionRowCollection requiredActionRows = new WixActionRowCollection(); | 1738 | var requiredActionRows = new WixActionRowCollection(); |
1744 | ArrayList scheduledActionRows = new ArrayList(); | 1739 | ArrayList scheduledActionRows = new ArrayList(); |
1745 | 1740 | ||
1746 | // gather the required actions for the output type | 1741 | // gather the required actions for the output type |
@@ -2362,6 +2357,7 @@ namespace WixToolset | |||
2362 | WixActionRowCollection relatedRows = (after ? parentActionRow.NextActionRows : parentActionRow.PreviousActionRows); | 2357 | WixActionRowCollection relatedRows = (after ? parentActionRow.NextActionRows : parentActionRow.PreviousActionRows); |
2363 | relatedRows.Add(actionRow); | 2358 | relatedRows.Add(actionRow); |
2364 | } | 2359 | } |
2360 | #endif | ||
2365 | 2361 | ||
2366 | /// <summary> | 2362 | /// <summary> |
2367 | /// Resolve features for columns that have null guid placeholders. | 2363 | /// Resolve features for columns that have null guid placeholders. |
@@ -2371,59 +2367,55 @@ namespace WixToolset | |||
2371 | /// <param name="featureColumn">Number of the column containing the feature.</param> | 2367 | /// <param name="featureColumn">Number of the column containing the feature.</param> |
2372 | /// <param name="connectToFeatures">Connect to feature complex references.</param> | 2368 | /// <param name="connectToFeatures">Connect to feature complex references.</param> |
2373 | /// <param name="multipleFeatureComponents">Hashtable of known components under multiple features.</param> | 2369 | /// <param name="multipleFeatureComponents">Hashtable of known components under multiple features.</param> |
2374 | private void ResolveFeatures(IEnumerable<Row> rows, int connectionColumn, int featureColumn, ConnectToFeatureCollection connectToFeatures, Hashtable multipleFeatureComponents) | 2370 | private void ResolveFeatures(IntermediateTuple row, int connectionColumn, int featureColumn, ConnectToFeatureCollection connectToFeatures, Hashtable multipleFeatureComponents) |
2375 | { | 2371 | { |
2376 | foreach (Row row in rows) | 2372 | var connectionId = row.AsString(connectionColumn); |
2373 | var featureId = row.AsString(featureColumn); | ||
2374 | |||
2375 | if (emptyGuid == featureId) | ||
2377 | { | 2376 | { |
2378 | string connectionId = (string)row[connectionColumn]; | 2377 | ConnectToFeature connection = connectToFeatures[connectionId]; |
2379 | string featureId = (string)row[featureColumn]; | ||
2380 | 2378 | ||
2381 | if (emptyGuid == featureId) | 2379 | if (null == connection) |
2382 | { | 2380 | { |
2383 | ConnectToFeature connection = connectToFeatures[connectionId]; | 2381 | // display an error for the component or merge module as approrpriate |
2384 | 2382 | if (null != multipleFeatureComponents) | |
2385 | if (null == connection) | ||
2386 | { | 2383 | { |
2387 | // display an error for the component or merge module as approrpriate | 2384 | this.OnMessage(WixErrors.ComponentExpectedFeature(row.SourceLineNumbers, connectionId, row.Definition.Name, row.Id.Id)); |
2388 | if (null != multipleFeatureComponents) | ||
2389 | { | ||
2390 | this.OnMessage(WixErrors.ComponentExpectedFeature(row.SourceLineNumbers, connectionId, row.Table.Name, row.GetPrimaryKey('/'))); | ||
2391 | } | ||
2392 | else | ||
2393 | { | ||
2394 | this.OnMessage(WixErrors.MergeModuleExpectedFeature(row.SourceLineNumbers, connectionId)); | ||
2395 | } | ||
2396 | } | 2385 | } |
2397 | else | 2386 | else |
2398 | { | 2387 | { |
2399 | // check for unique, implicit, primary feature parents with multiple possible parent features | 2388 | this.OnMessage(WixErrors.MergeModuleExpectedFeature(row.SourceLineNumbers, connectionId)); |
2400 | if (this.ShowPedanticMessages && | 2389 | } |
2401 | !connection.IsExplicitPrimaryFeature && | 2390 | } |
2402 | 0 < connection.ConnectFeatures.Count) | 2391 | else |
2392 | { | ||
2393 | // check for unique, implicit, primary feature parents with multiple possible parent features | ||
2394 | if (this.ShowPedanticMessages && | ||
2395 | !connection.IsExplicitPrimaryFeature && | ||
2396 | 0 < connection.ConnectFeatures.Count) | ||
2397 | { | ||
2398 | // display a warning for the component or merge module as approrpriate | ||
2399 | if (null != multipleFeatureComponents) | ||
2403 | { | 2400 | { |
2404 | // display a warning for the component or merge module as approrpriate | 2401 | if (!multipleFeatureComponents.Contains(connectionId)) |
2405 | if (null != multipleFeatureComponents) | ||
2406 | { | 2402 | { |
2407 | if (!multipleFeatureComponents.Contains(connectionId)) | 2403 | this.OnMessage(WixWarnings.ImplicitComponentPrimaryFeature(connectionId)); |
2408 | { | ||
2409 | this.OnMessage(WixWarnings.ImplicitComponentPrimaryFeature(connectionId)); | ||
2410 | 2404 | ||
2411 | // remember this component so only one warning is generated for it | 2405 | // remember this component so only one warning is generated for it |
2412 | multipleFeatureComponents[connectionId] = null; | 2406 | multipleFeatureComponents[connectionId] = null; |
2413 | } | ||
2414 | } | ||
2415 | else | ||
2416 | { | ||
2417 | this.OnMessage(WixWarnings.ImplicitMergeModulePrimaryFeature(connectionId)); | ||
2418 | } | 2407 | } |
2419 | } | 2408 | } |
2420 | 2409 | else | |
2421 | // set the feature | 2410 | { |
2422 | row[featureColumn] = connection.PrimaryFeature; | 2411 | this.OnMessage(WixWarnings.ImplicitMergeModulePrimaryFeature(connectionId)); |
2412 | } | ||
2423 | } | 2413 | } |
2414 | |||
2415 | // set the feature | ||
2416 | row.Set(featureColumn, connection.PrimaryFeature); | ||
2424 | } | 2417 | } |
2425 | } | 2418 | } |
2426 | } | 2419 | } |
2427 | |||
2428 | } | 2420 | } |
2429 | } | 2421 | } |