aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core/Linker.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/WixToolset.Core/Linker.cs')
-rw-r--r--src/WixToolset.Core/Linker.cs441
1 files changed, 214 insertions, 227 deletions
diff --git a/src/WixToolset.Core/Linker.cs b/src/WixToolset.Core/Linker.cs
index 04188e53..80d57fa7 100644
--- a/src/WixToolset.Core/Linker.cs
+++ b/src/WixToolset.Core/Linker.cs
@@ -11,19 +11,18 @@ namespace WixToolset.Core
11 using WixToolset.Core.Link; 11 using WixToolset.Core.Link;
12 using WixToolset.Data; 12 using WixToolset.Data;
13 using WixToolset.Data.Tuples; 13 using WixToolset.Data.Tuples;
14 using WixToolset.Extensibility;
15 using WixToolset.Extensibility.Data; 14 using WixToolset.Extensibility.Data;
16 using WixToolset.Extensibility.Services; 15 using WixToolset.Extensibility.Services;
17 16
18 /// <summary> 17 /// <summary>
19 /// Linker core of the WiX toolset. 18 /// Linker core of the WiX toolset.
20 /// </summary> 19 /// </summary>
21 internal class Linker 20 internal class Linker : ILinker
22 { 21 {
23 private static readonly char[] colonCharacter = ":".ToCharArray(); 22 private static readonly char[] colonCharacter = ":".ToCharArray();
24 private static readonly string emptyGuid = Guid.Empty.ToString("B"); 23 private static readonly string emptyGuid = Guid.Empty.ToString("B");
25 24
26 private bool sectionIdOnRows; 25 private readonly bool sectionIdOnRows;
27 26
28 /// <summary> 27 /// <summary>
29 /// Creates a linker. 28 /// Creates a linker.
@@ -53,32 +52,20 @@ namespace WixToolset.Core
53 /// <value>The option to show pedantic messages.</value> 52 /// <value>The option to show pedantic messages.</value>
54 public bool ShowPedanticMessages { get; set; } 53 public bool ShowPedanticMessages { get; set; }
55 54
56 public OutputType OutputType { get; set; }
57
58 public IEnumerable<Intermediate> Intermediates { get; set; }
59
60 public IEnumerable<Intermediate> Libraries { get; set; }
61
62 public ITupleDefinitionCreator TupleDefinitionCreator { get; set; }
63
64 /// <summary> 55 /// <summary>
65 /// Links a collection of sections into an output. 56 /// Links a collection of sections into an output.
66 /// </summary> 57 /// </summary>
67 /// <param name="inputs">The collection of sections to link together.</param> 58 /// <param name="inputs">The collection of sections to link together.</param>
68 /// <param name="expectedOutputType">Expected output type, based on output file extension provided to the linker.</param> 59 /// <param name="expectedOutputType">Expected output type, based on output file extension provided to the linker.</param>
69 /// <returns>Output object from the linking.</returns> 60 /// <returns>Output object from the linking.</returns>
70 public Intermediate Execute() 61 public Intermediate Link(ILinkContext context)
71 { 62 {
72 var extensionManager = this.ServiceProvider.GetService<IExtensionManager>(); 63 this.Context = context;
73
74 var creator = this.TupleDefinitionCreator ?? this.ServiceProvider.GetService<ITupleDefinitionCreator>();
75 64
76 this.Context = this.ServiceProvider.GetService<ILinkContext>(); 65 if (this.Context.TupleDefinitionCreator == null)
77 this.Context.Extensions = extensionManager.Create<ILinkerExtension>(); 66 {
78 this.Context.ExtensionData = extensionManager.Create<IExtensionData>(); 67 this.Context.TupleDefinitionCreator = this.ServiceProvider.GetService<ITupleDefinitionCreator>();
79 this.Context.ExpectedOutputType = this.OutputType; 68 }
80 this.Context.Intermediates = this.Intermediates.Concat(this.Libraries).ToList();
81 this.Context.TupleDefinitionCreator = creator;
82 69
83 foreach (var extension in this.Context.Extensions) 70 foreach (var extension in this.Context.Extensions)
84 { 71 {
@@ -117,7 +104,7 @@ namespace WixToolset.Core
117 Hashtable generatedShortFileNames = new Hashtable(); 104 Hashtable generatedShortFileNames = new Hashtable();
118#endif 105#endif
119 106
120 Hashtable multipleFeatureComponents = new Hashtable(); 107 var multipleFeatureComponents = new Hashtable();
121 108
122 var wixVariables = new Dictionary<string, WixVariableTuple>(); 109 var wixVariables = new Dictionary<string, WixVariableTuple>();
123 110
@@ -238,7 +225,7 @@ namespace WixToolset.Core
238 sectionCount++; 225 sectionCount++;
239 226
240 var sectionId = section.Id; 227 var sectionId = section.Id;
241 if (null == sectionId && this.sectionIdOnRows) 228 if (null == sectionId && sectionIdOnRows)
242 { 229 {
243 sectionId = "wix.section." + sectionCount.ToString(CultureInfo.InvariantCulture); 230 sectionId = "wix.section." + sectionCount.ToString(CultureInfo.InvariantCulture);
244 } 231 }
@@ -256,12 +243,12 @@ namespace WixToolset.Core
256 break; 243 break;
257#endif 244#endif
258 245
259 case TupleDefinitionType.Class: 246 case TupleDefinitionType.Class:
260 if (SectionType.Product == resolvedSection.Type) 247 if (SectionType.Product == resolvedSection.Type)
261 { 248 {
262 this.ResolveFeatures(tuple, 2, 11, componentsToFeatures, multipleFeatureComponents); 249 this.ResolveFeatures(tuple, 2, 11, componentsToFeatures, multipleFeatureComponents);
263 } 250 }
264 break; 251 break;
265 252
266#if MOVE_TO_BACKEND 253#if MOVE_TO_BACKEND
267 case "CustomAction": 254 case "CustomAction":
@@ -315,12 +302,12 @@ namespace WixToolset.Core
315 } 302 }
316 break; 303 break;
317#endif 304#endif
318 case TupleDefinitionType.Extension: 305 case TupleDefinitionType.Extension:
319 if (SectionType.Product == resolvedSection.Type) 306 if (SectionType.Product == resolvedSection.Type)
320 { 307 {
321 this.ResolveFeatures(tuple, 1, 4, componentsToFeatures, multipleFeatureComponents); 308 this.ResolveFeatures(tuple, 1, 4, componentsToFeatures, multipleFeatureComponents);
322 } 309 }
323 break; 310 break;
324 311
325#if MOVE_TO_BACKEND 312#if MOVE_TO_BACKEND
326 case TupleDefinitionType.ModuleSubstitution: 313 case TupleDefinitionType.ModuleSubstitution:
@@ -332,12 +319,12 @@ namespace WixToolset.Core
332 break; 319 break;
333#endif 320#endif
334 321
335 case TupleDefinitionType.MsiAssembly: 322 case TupleDefinitionType.MsiAssembly:
336 if (SectionType.Product == resolvedSection.Type) 323 if (SectionType.Product == resolvedSection.Type)
337 { 324 {
338 this.ResolveFeatures(tuple, 0, 1, componentsToFeatures, multipleFeatureComponents); 325 this.ResolveFeatures(tuple, 0, 1, componentsToFeatures, multipleFeatureComponents);
339 } 326 }
340 break; 327 break;
341 328
342#if MOVE_TO_BACKEND 329#if MOVE_TO_BACKEND
343 case "ProgId": 330 case "ProgId":
@@ -359,26 +346,26 @@ namespace WixToolset.Core
359 break; 346 break;
360#endif 347#endif
361 348
362 case TupleDefinitionType.PublishComponent: 349 case TupleDefinitionType.PublishComponent:
363 if (SectionType.Product == resolvedSection.Type) 350 if (SectionType.Product == resolvedSection.Type)
364 { 351 {
365 this.ResolveFeatures(tuple, 2, 4, componentsToFeatures, multipleFeatureComponents); 352 this.ResolveFeatures(tuple, 2, 4, componentsToFeatures, multipleFeatureComponents);
366 } 353 }
367 break; 354 break;
368 355
369 case TupleDefinitionType.Shortcut: 356 case TupleDefinitionType.Shortcut:
370 if (SectionType.Product == resolvedSection.Type) 357 if (SectionType.Product == resolvedSection.Type)
371 { 358 {
372 this.ResolveFeatures(tuple, 3, 4, componentsToFeatures, multipleFeatureComponents); 359 this.ResolveFeatures(tuple, 3, 4, componentsToFeatures, multipleFeatureComponents);
373 } 360 }
374 break; 361 break;
375 362
376 case TupleDefinitionType.TypeLib: 363 case TupleDefinitionType.TypeLib:
377 if (SectionType.Product == resolvedSection.Type) 364 if (SectionType.Product == resolvedSection.Type)
378 { 365 {
379 this.ResolveFeatures(tuple, 2, 6, componentsToFeatures, multipleFeatureComponents); 366 this.ResolveFeatures(tuple, 2, 6, componentsToFeatures, multipleFeatureComponents);
380 } 367 }
381 break; 368 break;
382 369
383#if SOLVE_CUSTOM_TABLE 370#if SOLVE_CUSTOM_TABLE
384 case "WixCustomTable": 371 case "WixCustomTable":
@@ -396,9 +383,9 @@ namespace WixToolset.Core
396 break; 383 break;
397#endif 384#endif
398 385
399 case TupleDefinitionType.WixEnsureTable: 386 case TupleDefinitionType.WixEnsureTable:
400 ensureTableRows.Add(tuple); 387 ensureTableRows.Add(tuple);
401 break; 388 break;
402 389
403 390
404#if MOVE_TO_BACKEND 391#if MOVE_TO_BACKEND
@@ -421,45 +408,45 @@ namespace WixToolset.Core
421 break; 408 break;
422#endif 409#endif
423 410
424 case TupleDefinitionType.WixMerge: 411 case TupleDefinitionType.WixMerge:
425 if (SectionType.Product == resolvedSection.Type) 412 if (SectionType.Product == resolvedSection.Type)
426 { 413 {
427 this.ResolveFeatures(tuple, 0, 7, modulesToFeatures, null); 414 this.ResolveFeatures(tuple, 0, 7, modulesToFeatures, null);
428 } 415 }
429 break; 416 break;
430 417
431 case TupleDefinitionType.WixComplexReference: 418 case TupleDefinitionType.WixComplexReference:
432 copyTuple = false; 419 copyTuple = false;
433 break; 420 break;
434 421
435 case TupleDefinitionType.WixSimpleReference: 422 case TupleDefinitionType.WixSimpleReference:
436 copyTuple = false; 423 copyTuple = false;
437 break; 424 break;
438 425
439 case TupleDefinitionType.WixVariable: 426 case TupleDefinitionType.WixVariable:
440 // check for colliding values and collect the wix variable rows 427 // check for colliding values and collect the wix variable rows
441 { 428 {
442 var row = (WixVariableTuple)tuple; 429 var row = (WixVariableTuple)tuple;
443 430
444 if (wixVariables.TryGetValue(row.WixVariable, out var collidingRow)) 431 if (wixVariables.TryGetValue(row.WixVariable, out var collidingRow))
445 { 432 {
446 if (collidingRow.Overridable && !row.Overridable) 433 if (collidingRow.Overridable && !row.Overridable)
447 { 434 {
448 wixVariables[row.WixVariable] = row; 435 wixVariables[row.WixVariable] = row;
449 } 436 }
450 else if (!row.Overridable || (collidingRow.Overridable && row.Overridable)) 437 else if (!row.Overridable || (collidingRow.Overridable && row.Overridable))
451 { 438 {
452 this.OnMessage(ErrorMessages.WixVariableCollision(row.SourceLineNumbers, row.WixVariable)); 439 this.OnMessage(ErrorMessages.WixVariableCollision(row.SourceLineNumbers, row.WixVariable));
453 }
454 }
455 else
456 {
457 wixVariables.Add(row.WixVariable, row);
458 }
459 } 440 }
441 }
442 else
443 {
444 wixVariables.Add(row.WixVariable, row);
445 }
446 }
460 447
461 copyTuple = false; 448 copyTuple = false;
462 break; 449 break;
463 } 450 }
464 451
465 if (copyTuple) 452 if (copyTuple)
@@ -624,7 +611,7 @@ namespace WixToolset.Core
624#endif 611#endif
625 612
626 //correct the section Id in FeatureComponents table 613 //correct the section Id in FeatureComponents table
627 if (this.sectionIdOnRows) 614 if (sectionIdOnRows)
628 { 615 {
629 //var componentSectionIds = new Dictionary<string, string>(); 616 //var componentSectionIds = new Dictionary<string, string>();
630 617
@@ -1152,7 +1139,7 @@ namespace WixToolset.Core
1152 /// <param name="modulesToFeatures">Module to feature complex references.</param> 1139 /// <param name="modulesToFeatures">Module to feature complex references.</param>
1153 private void ProcessComplexReferences(IntermediateSection resolvedSection, IEnumerable<IntermediateSection> sections, ISet<string> referencedComponents, ConnectToFeatureCollection componentsToFeatures, ConnectToFeatureCollection featuresToFeatures, ConnectToFeatureCollection modulesToFeatures) 1140 private void ProcessComplexReferences(IntermediateSection resolvedSection, IEnumerable<IntermediateSection> sections, ISet<string> referencedComponents, ConnectToFeatureCollection componentsToFeatures, ConnectToFeatureCollection featuresToFeatures, ConnectToFeatureCollection modulesToFeatures)
1154 { 1141 {
1155 Hashtable componentsToModules = new Hashtable(); 1142 var componentsToModules = new Hashtable();
1156 1143
1157 foreach (var section in sections) 1144 foreach (var section in sections)
1158 { 1145 {
@@ -1163,154 +1150,154 @@ namespace WixToolset.Core
1163 ConnectToFeature connection; 1150 ConnectToFeature connection;
1164 switch (wixComplexReferenceRow.ParentType) 1151 switch (wixComplexReferenceRow.ParentType)
1165 { 1152 {
1166 case ComplexReferenceParentType.Feature: 1153 case ComplexReferenceParentType.Feature:
1167 switch (wixComplexReferenceRow.ChildType) 1154 switch (wixComplexReferenceRow.ChildType)
1155 {
1156 case ComplexReferenceChildType.Component:
1157 connection = componentsToFeatures[wixComplexReferenceRow.Child];
1158 if (null == connection)
1168 { 1159 {
1169 case ComplexReferenceChildType.Component: 1160 componentsToFeatures.Add(new ConnectToFeature(section, wixComplexReferenceRow.Child, wixComplexReferenceRow.Parent, wixComplexReferenceRow.IsPrimary));
1170 connection = componentsToFeatures[wixComplexReferenceRow.Child]; 1161 }
1171 if (null == connection) 1162 else if (wixComplexReferenceRow.IsPrimary)
1172 { 1163 {
1173 componentsToFeatures.Add(new ConnectToFeature(section, wixComplexReferenceRow.Child, wixComplexReferenceRow.Parent, wixComplexReferenceRow.IsPrimary)); 1164 if (connection.IsExplicitPrimaryFeature)
1174 } 1165 {
1175 else if (wixComplexReferenceRow.IsPrimary) 1166 this.OnMessage(ErrorMessages.MultiplePrimaryReferences(wixComplexReferenceRow.SourceLineNumbers, wixComplexReferenceRow.ChildType.ToString(), wixComplexReferenceRow.Child, wixComplexReferenceRow.ParentType.ToString(), wixComplexReferenceRow.Parent, (null != connection.PrimaryFeature ? "Feature" : "Product"), connection.PrimaryFeature ?? resolvedSection.Id));
1176 { 1167 continue;
1177 if (connection.IsExplicitPrimaryFeature) 1168 }
1178 { 1169 else
1179 this.OnMessage(ErrorMessages.MultiplePrimaryReferences(wixComplexReferenceRow.SourceLineNumbers, wixComplexReferenceRow.ChildType.ToString(), wixComplexReferenceRow.Child, wixComplexReferenceRow.ParentType.ToString(), wixComplexReferenceRow.Parent, (null != connection.PrimaryFeature ? "Feature" : "Product"), connection.PrimaryFeature ?? resolvedSection.Id)); 1170 {
1180 continue; 1171 connection.ConnectFeatures.Add(connection.PrimaryFeature); // move the guessed primary feature to the list of connects
1181 } 1172 connection.PrimaryFeature = wixComplexReferenceRow.Parent; // set the new primary feature
1182 else 1173 connection.IsExplicitPrimaryFeature = true; // and make sure we remember that we set it so we can fail if we try to set it again
1183 { 1174 }
1184 connection.ConnectFeatures.Add(connection.PrimaryFeature); // move the guessed primary feature to the list of connects 1175 }
1185 connection.PrimaryFeature = wixComplexReferenceRow.Parent; // set the new primary feature 1176 else
1186 connection.IsExplicitPrimaryFeature = true; // and make sure we remember that we set it so we can fail if we try to set it again 1177 {
1187 } 1178 connection.ConnectFeatures.Add(wixComplexReferenceRow.Parent);
1188 } 1179 }
1189 else
1190 {
1191 connection.ConnectFeatures.Add(wixComplexReferenceRow.Parent);
1192 }
1193
1194 // add a row to the FeatureComponents table
1195 var featureComponent = new FeatureComponentsTuple();
1196 featureComponent.Feature_ = wixComplexReferenceRow.Parent;
1197 featureComponent.Component_ = wixComplexReferenceRow.Child;
1198 1180
1199 featureComponents.Add(featureComponent); 1181 // add a row to the FeatureComponents table
1182 var featureComponent = new FeatureComponentsTuple();
1183 featureComponent.Feature_ = wixComplexReferenceRow.Parent;
1184 featureComponent.Component_ = wixComplexReferenceRow.Child;
1200 1185
1201 // index the component for finding orphaned records 1186 featureComponents.Add(featureComponent);
1202 var symbolName = String.Concat("Component:", wixComplexReferenceRow.Child);
1203 referencedComponents.Add(symbolName);
1204 1187
1205 break; 1188 // index the component for finding orphaned records
1189 var symbolName = String.Concat("Component:", wixComplexReferenceRow.Child);
1190 referencedComponents.Add(symbolName);
1206 1191
1207 case ComplexReferenceChildType.Feature: 1192 break;
1208 connection = featuresToFeatures[wixComplexReferenceRow.Child];
1209 if (null != connection)
1210 {
1211 this.OnMessage(ErrorMessages.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)));
1212 continue;
1213 }
1214 1193
1215 featuresToFeatures.Add(new ConnectToFeature(section, wixComplexReferenceRow.Child, wixComplexReferenceRow.Parent, wixComplexReferenceRow.IsPrimary)); 1194 case ComplexReferenceChildType.Feature:
1216 break; 1195 connection = featuresToFeatures[wixComplexReferenceRow.Child];
1196 if (null != connection)
1197 {
1198 this.OnMessage(ErrorMessages.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)));
1199 continue;
1200 }
1217 1201
1218 case ComplexReferenceChildType.Module: 1202 featuresToFeatures.Add(new ConnectToFeature(section, wixComplexReferenceRow.Child, wixComplexReferenceRow.Parent, wixComplexReferenceRow.IsPrimary));
1219 connection = modulesToFeatures[wixComplexReferenceRow.Child]; 1203 break;
1220 if (null == connection)
1221 {
1222 modulesToFeatures.Add(new ConnectToFeature(section, wixComplexReferenceRow.Child, wixComplexReferenceRow.Parent, wixComplexReferenceRow.IsPrimary));
1223 }
1224 else if (wixComplexReferenceRow.IsPrimary)
1225 {
1226 if (connection.IsExplicitPrimaryFeature)
1227 {
1228 this.OnMessage(ErrorMessages.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)));
1229 continue;
1230 }
1231 else
1232 {
1233 connection.ConnectFeatures.Add(connection.PrimaryFeature); // move the guessed primary feature to the list of connects
1234 connection.PrimaryFeature = wixComplexReferenceRow.Parent; // set the new primary feature
1235 connection.IsExplicitPrimaryFeature = true; // and make sure we remember that we set it so we can fail if we try to set it again
1236 }
1237 }
1238 else
1239 {
1240 connection.ConnectFeatures.Add(wixComplexReferenceRow.Parent);
1241 }
1242 break;
1243 1204
1244 default: 1205 case ComplexReferenceChildType.Module:
1245 throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceChildType), wixComplexReferenceRow.ChildType))); 1206 connection = modulesToFeatures[wixComplexReferenceRow.Child];
1207 if (null == connection)
1208 {
1209 modulesToFeatures.Add(new ConnectToFeature(section, wixComplexReferenceRow.Child, wixComplexReferenceRow.Parent, wixComplexReferenceRow.IsPrimary));
1210 }
1211 else if (wixComplexReferenceRow.IsPrimary)
1212 {
1213 if (connection.IsExplicitPrimaryFeature)
1214 {
1215 this.OnMessage(ErrorMessages.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)));
1216 continue;
1217 }
1218 else
1219 {
1220 connection.ConnectFeatures.Add(connection.PrimaryFeature); // move the guessed primary feature to the list of connects
1221 connection.PrimaryFeature = wixComplexReferenceRow.Parent; // set the new primary feature
1222 connection.IsExplicitPrimaryFeature = true; // and make sure we remember that we set it so we can fail if we try to set it again
1223 }
1224 }
1225 else
1226 {
1227 connection.ConnectFeatures.Add(wixComplexReferenceRow.Parent);
1246 } 1228 }
1247 break; 1229 break;
1248 1230
1249 case ComplexReferenceParentType.Module: 1231 default:
1250 switch (wixComplexReferenceRow.ChildType) 1232 throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceChildType), wixComplexReferenceRow.ChildType)));
1251 { 1233 }
1252 case ComplexReferenceChildType.Component: 1234 break;
1253 if (componentsToModules.ContainsKey(wixComplexReferenceRow.Child))
1254 {
1255 this.OnMessage(ErrorMessages.ComponentReferencedTwice(wixComplexReferenceRow.SourceLineNumbers, wixComplexReferenceRow.Child));
1256 continue;
1257 }
1258 else
1259 {
1260 componentsToModules.Add(wixComplexReferenceRow.Child, wixComplexReferenceRow); // should always be new
1261 1235
1262 // add a row to the ModuleComponents table 1236 case ComplexReferenceParentType.Module:
1263 var moduleComponent = new ModuleComponentsTuple(); 1237 switch (wixComplexReferenceRow.ChildType)
1264 moduleComponent.Component = wixComplexReferenceRow.Child; 1238 {
1265 moduleComponent.ModuleID = wixComplexReferenceRow.Parent; 1239 case ComplexReferenceChildType.Component:
1266 moduleComponent.Language = Convert.ToInt32(wixComplexReferenceRow.ParentLanguage); 1240 if (componentsToModules.ContainsKey(wixComplexReferenceRow.Child))
1267 } 1241 {
1242 this.OnMessage(ErrorMessages.ComponentReferencedTwice(wixComplexReferenceRow.SourceLineNumbers, wixComplexReferenceRow.Child));
1243 continue;
1244 }
1245 else
1246 {
1247 componentsToModules.Add(wixComplexReferenceRow.Child, wixComplexReferenceRow); // should always be new
1268 1248
1269 // index the component for finding orphaned records 1249 // add a row to the ModuleComponents table
1270 string componentSymbolName = String.Concat("Component:", wixComplexReferenceRow.Child); 1250 var moduleComponent = new ModuleComponentsTuple();
1271 referencedComponents.Add(componentSymbolName); 1251 moduleComponent.Component = wixComplexReferenceRow.Child;
1252 moduleComponent.ModuleID = wixComplexReferenceRow.Parent;
1253 moduleComponent.Language = Convert.ToInt32(wixComplexReferenceRow.ParentLanguage);
1254 }
1272 1255
1273 break; 1256 // index the component for finding orphaned records
1257 var componentSymbolName = String.Concat("Component:", wixComplexReferenceRow.Child);
1258 referencedComponents.Add(componentSymbolName);
1274 1259
1275 default:
1276 throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceChildType), wixComplexReferenceRow.ChildType)));
1277 }
1278 break; 1260 break;
1279 1261
1280 case ComplexReferenceParentType.Patch: 1262 default:
1281 switch (wixComplexReferenceRow.ChildType) 1263 throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceChildType), wixComplexReferenceRow.ChildType)));
1282 { 1264 }
1283 case ComplexReferenceChildType.PatchFamily: 1265 break;
1284 case ComplexReferenceChildType.PatchFamilyGroup:
1285 break;
1286 1266
1287 default: 1267 case ComplexReferenceParentType.Patch:
1288 throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceChildType), wixComplexReferenceRow.ChildType))); 1268 switch (wixComplexReferenceRow.ChildType)
1289 } 1269 {
1270 case ComplexReferenceChildType.PatchFamily:
1271 case ComplexReferenceChildType.PatchFamilyGroup:
1290 break; 1272 break;
1291 1273
1292 case ComplexReferenceParentType.Product: 1274 default:
1293 switch (wixComplexReferenceRow.ChildType) 1275 throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceChildType), wixComplexReferenceRow.ChildType)));
1294 { 1276 }
1295 case ComplexReferenceChildType.Feature: 1277 break;
1296 connection = featuresToFeatures[wixComplexReferenceRow.Child];
1297 if (null != connection)
1298 {
1299 this.OnMessage(ErrorMessages.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)));
1300 continue;
1301 }
1302
1303 featuresToFeatures.Add(new ConnectToFeature(section, wixComplexReferenceRow.Child, null, wixComplexReferenceRow.IsPrimary));
1304 break;
1305 1278
1306 default: 1279 case ComplexReferenceParentType.Product:
1307 throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceChildType), wixComplexReferenceRow.ChildType))); 1280 switch (wixComplexReferenceRow.ChildType)
1281 {
1282 case ComplexReferenceChildType.Feature:
1283 connection = featuresToFeatures[wixComplexReferenceRow.Child];
1284 if (null != connection)
1285 {
1286 this.OnMessage(ErrorMessages.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)));
1287 continue;
1308 } 1288 }
1289
1290 featuresToFeatures.Add(new ConnectToFeature(section, wixComplexReferenceRow.Child, null, wixComplexReferenceRow.IsPrimary));
1309 break; 1291 break;
1310 1292
1311 default: 1293 default:
1312 // Note: Groups have been processed before getting here so they are not handled by any case above. 1294 throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceChildType), wixComplexReferenceRow.ChildType)));
1313 throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceParentType), wixComplexReferenceRow.ParentType))); 1295 }
1296 break;
1297
1298 default:
1299 // Note: Groups have been processed before getting here so they are not handled by any case above.
1300 throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceParentType), wixComplexReferenceRow.ParentType)));
1314 } 1301 }
1315 } 1302 }
1316 1303
@@ -1341,7 +1328,7 @@ namespace WixToolset.Core
1341 foreach (var section in sections) 1328 foreach (var section in sections)
1342 { 1329 {
1343 // Count down because we'll sometimes remove items from the list. 1330 // Count down because we'll sometimes remove items from the list.
1344 for (int i = section.Tuples.Count - 1; i >= 0; --i) 1331 for (var i = section.Tuples.Count - 1; i >= 0; --i)
1345 { 1332 {
1346 // Only process the "grouping parents" such as FeatureGroup, ComponentGroup, Feature, 1333 // Only process the "grouping parents" such as FeatureGroup, ComponentGroup, Feature,
1347 // and Module. Non-grouping complex references are simple and 1334 // and Module. Non-grouping complex references are simple and
@@ -1354,7 +1341,7 @@ namespace WixToolset.Core
1354 ComplexReferenceParentType.PatchFamilyGroup == wixComplexReferenceRow.ParentType || 1341 ComplexReferenceParentType.PatchFamilyGroup == wixComplexReferenceRow.ParentType ||
1355 ComplexReferenceParentType.Product == wixComplexReferenceRow.ParentType)) 1342 ComplexReferenceParentType.Product == wixComplexReferenceRow.ParentType))
1356 { 1343 {
1357 var parentTypeAndId = CombineTypeAndId(wixComplexReferenceRow.ParentType, wixComplexReferenceRow.Parent); 1344 var parentTypeAndId = this.CombineTypeAndId(wixComplexReferenceRow.ParentType, wixComplexReferenceRow.Parent);
1358 1345
1359 // Group all complex references with a common parent 1346 // Group all complex references with a common parent
1360 // together so we can find them quickly while processing in 1347 // together so we can find them quickly while processing in
@@ -1402,7 +1389,7 @@ namespace WixToolset.Core
1402 // complex references should all be flattened. 1389 // complex references should all be flattened.
1403 var keys = parentGroupsNeedingProcessing.Keys.ToList(); 1390 var keys = parentGroupsNeedingProcessing.Keys.ToList();
1404 1391
1405 foreach (string key in keys) 1392 foreach (var key in keys)
1406 { 1393 {
1407 if (parentGroupsNeedingProcessing.ContainsKey(key)) 1394 if (parentGroupsNeedingProcessing.ContainsKey(key))
1408 { 1395 {
@@ -1466,14 +1453,14 @@ namespace WixToolset.Core
1466 foreach (var wixComplexReferenceRow in referencesToParent) 1453 foreach (var wixComplexReferenceRow in referencesToParent)
1467 { 1454 {
1468 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); 1455 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);
1469 Debug.Assert(parentTypeAndId == CombineTypeAndId(wixComplexReferenceRow.ParentType, wixComplexReferenceRow.Parent)); 1456 Debug.Assert(parentTypeAndId == this.CombineTypeAndId(wixComplexReferenceRow.ParentType, wixComplexReferenceRow.Parent));
1470 1457
1471 // We are only interested processing when the child is a group. 1458 // We are only interested processing when the child is a group.
1472 if ((ComplexReferenceChildType.ComponentGroup == wixComplexReferenceRow.ChildType) || 1459 if ((ComplexReferenceChildType.ComponentGroup == wixComplexReferenceRow.ChildType) ||
1473 (ComplexReferenceChildType.FeatureGroup == wixComplexReferenceRow.ChildType) || 1460 (ComplexReferenceChildType.FeatureGroup == wixComplexReferenceRow.ChildType) ||
1474 (ComplexReferenceChildType.PatchFamilyGroup == wixComplexReferenceRow.ChildType)) 1461 (ComplexReferenceChildType.PatchFamilyGroup == wixComplexReferenceRow.ChildType))
1475 { 1462 {
1476 string childTypeAndId = CombineTypeAndId(wixComplexReferenceRow.ChildType, wixComplexReferenceRow.Child); 1463 var childTypeAndId = this.CombineTypeAndId(wixComplexReferenceRow.ChildType, wixComplexReferenceRow.Child);
1477 if (loopDetector.Contains(childTypeAndId)) 1464 if (loopDetector.Contains(childTypeAndId))
1478 { 1465 {
1479 // Create a comma delimited list of the references that participate in the 1466 // Create a comma delimited list of the references that participate in the
@@ -1531,7 +1518,7 @@ namespace WixToolset.Core
1531 // duplicate complex references that occurred during the merge. 1518 // duplicate complex references that occurred during the merge.
1532 referencesToParent.AddRange(allNewChildComplexReferences); 1519 referencesToParent.AddRange(allNewChildComplexReferences);
1533 referencesToParent.Sort(ComplexReferenceComparision); 1520 referencesToParent.Sort(ComplexReferenceComparision);
1534 for (int i = referencesToParent.Count - 1; i >= 0; --i) 1521 for (var i = referencesToParent.Count - 1; i >= 0; --i)
1535 { 1522 {
1536 var wixComplexReferenceRow = referencesToParent[i]; 1523 var wixComplexReferenceRow = referencesToParent[i];
1537 1524
@@ -1716,7 +1703,7 @@ namespace WixToolset.Core
1716 1703
1717 if (emptyGuid == featureId) 1704 if (emptyGuid == featureId)
1718 { 1705 {
1719 ConnectToFeature connection = connectToFeatures[connectionId]; 1706 var connection = connectToFeatures[connectionId];
1720 1707
1721 if (null == connection) 1708 if (null == connection)
1722 { 1709 {