Extract interfaces for Preprocess/Compile/Link/Bind/etc
Rob Mensching committed
Oct 18, 2018 at 13:42 UTC
13eedbfcf97e402ade06f2be29f98723ef7ff286
30 files changed
+928
-790
src/WixToolset.Core.Burn/BundleBackend.cs
+5
@@ -27,6 +27,11 @@ namespace WixToolset.Core.Burn
27
return new BindResult { FileTransfers = command.FileTransfers, TrackedFiles = command.TrackedFiles };
28
}
29
30
+ public BindResult Decompile(IDecompileContext context)
31
+ {
32
+ throw new NotImplementedException();
33
+ }
34
+
35
public bool Inscribe(IInscribeContext context)
36
{
37
if (String.IsNullOrEmpty(context.SignedEngineFile))
src/WixToolset.Core.Burn/BurnBackendFactory.cs
+1
-1
@@ -9,7 +9,7 @@ namespace WixToolset.Core.Burn
9
10
internal class BurnBackendFactory : IBackendFactory
11
{
12
- public bool TryCreateBackend(string outputType, string outputFile, IBindContext context, out IBackend backend)
12
+ public bool TryCreateBackend(string outputType, string outputFile, out IBackend backend)
13
{
14
if (String.IsNullOrEmpty(outputType))
15
{
src/WixToolset.Core.WindowsInstaller/MsiBackend.cs
+5
@@ -38,6 +38,11 @@ namespace WixToolset.Core.WindowsInstaller
38
return result;
39
}
40
41
+ public BindResult Decompile(IDecompileContext context)
42
+ {
43
+ throw new NotImplementedException();
44
+ }
45
+
46
public bool Inscribe(IInscribeContext context)
47
{
48
var command = new InscribeMsiPackageCommand(context);
src/WixToolset.Core.WindowsInstaller/MsmBackend.cs
+5
@@ -43,6 +43,11 @@ namespace WixToolset.Core.WindowsInstaller
43
return result;
44
}
45
46
+ public BindResult Decompile(IDecompileContext context)
47
+ {
48
+ throw new NotImplementedException();
49
+ }
50
+
51
public bool Inscribe(IInscribeContext context)
52
{
53
return false;
src/WixToolset.Core.WindowsInstaller/MspBackend.cs
+5
@@ -21,6 +21,11 @@ namespace WixToolset.Core.WindowsInstaller
21
throw new NotImplementedException();
22
}
23
24
+ public BindResult Decompile(IDecompileContext context)
25
+ {
26
+ throw new NotImplementedException();
27
+ }
28
+
29
public bool Inscribe(IInscribeContext context)
30
{
31
throw new NotImplementedException();
src/WixToolset.Core.WindowsInstaller/MstBackend.cs
+5
@@ -25,6 +25,11 @@ namespace WixToolset.Core.WindowsInstaller
25
throw new NotImplementedException();
26
}
27
28
+ public BindResult Decompile(IDecompileContext context)
29
+ {
30
+ throw new NotImplementedException();
31
+ }
32
+
33
public bool Inscribe(IInscribeContext context)
34
{
35
throw new NotImplementedException();
src/WixToolset.Core.WindowsInstaller/Unbinder.cs
+1
-1
@@ -74,7 +74,7 @@ namespace WixToolset.Core
74
75
foreach (var factory in this.BackendFactories)
76
{
77
- if (factory.TryCreateBackend(outputType.ToString(), file, null, out var backend))
77
+ if (factory.TryCreateBackend(outputType.ToString(), file, out var backend))
78
{
79
return backend.Unbind(context);
80
}
src/WixToolset.Core.WindowsInstaller/WindowsInstallerBackendFactory.cs
+1
-1
@@ -9,7 +9,7 @@ namespace WixToolset.Core.WindowsInstaller
9
10
internal class WindowsInstallerBackendFactory : IBackendFactory
11
{
12
- public bool TryCreateBackend(string outputType, string outputFile, IBindContext context, out IBackend backend)
12
+ public bool TryCreateBackend(string outputType, string outputFile, out IBackend backend)
13
{
14
if (String.IsNullOrEmpty(outputType))
15
{
src/WixToolset.Core/Binder.cs
+6
-51
@@ -3,7 +3,6 @@
3
namespace WixToolset.Core
4
{
5
using System;
6
- using System.Collections.Generic;
6
using System.Diagnostics;
7
using System.Linq;
8
using System.Reflection;
@@ -16,61 +15,17 @@ namespace WixToolset.Core
15
/// <summary>
16
/// Binder of the WiX toolset.
17
/// </summary>
19
- internal class Binder
18
+ internal class Binder : IBinder
19
{
20
internal Binder(IServiceProvider serviceProvider)
21
{
22
this.ServiceProvider = serviceProvider;
23
}
24
26
- public int CabbingThreadCount { get; set; }
27
-
28
- public string CabCachePath { get; set; }
29
-
30
- public int Codepage { get; set; }
31
-
32
- public CompressionLevel? DefaultCompressionLevel { get; set; }
33
-
34
- public IEnumerable<IDelayedField> DelayedFields { get; set; }
35
-
36
- public IEnumerable<IExpectedExtractFile> ExpectedEmbeddedFiles { get; set; }
37
-
38
- public IEnumerable<string> Ices { get; set; }
39
-
40
- public string IntermediateFolder { get; set; }
41
-
42
- public Intermediate IntermediateRepresentation { get; set; }
43
-
44
- public string OutputPath { get; set; }
45
-
46
- public string OutputPdbPath { get; set; }
47
-
48
- public IEnumerable<string> SuppressIces { get; set; }
49
-
50
- public bool SuppressValidation { get; set; }
51
-
52
- public bool DeltaBinaryPatch { get; set; }
53
-
25
public IServiceProvider ServiceProvider { get; }
26
56
- public BindResult Execute()
27
+ public BindResult Bind(IBindContext context)
28
{
58
- var context = this.ServiceProvider.GetService<IBindContext>();
59
- context.CabbingThreadCount = this.CabbingThreadCount;
60
- context.CabCachePath = this.CabCachePath;
61
- context.Codepage = this.Codepage;
62
- context.DefaultCompressionLevel = this.DefaultCompressionLevel;
63
- context.DelayedFields = this.DelayedFields;
64
- context.ExpectedEmbeddedFiles = this.ExpectedEmbeddedFiles;
65
- context.Extensions = this.ServiceProvider.GetService<IExtensionManager>().Create<IBinderExtension>();
66
- context.Ices = this.Ices;
67
- context.IntermediateFolder = this.IntermediateFolder;
68
- context.IntermediateRepresentation = this.IntermediateRepresentation;
69
- context.OutputPath = this.OutputPath;
70
- context.OutputPdbPath = this.OutputPdbPath;
71
- context.SuppressIces = this.SuppressIces;
72
- context.SuppressValidation = this.SuppressValidation;
73
-
29
// Prebind.
30
//
31
foreach (var extension in context.Extensions)
@@ -80,7 +35,7 @@ namespace WixToolset.Core
35
36
// Bind.
37
//
83
- this.WriteBuildInfoTable(context.IntermediateRepresentation, context.OutputPath, context.OutputPdbPath);
38
+ this.WriteBuildInfoTuple(context.IntermediateRepresentation, context.OutputPath, context.OutputPdbPath);
39
40
var bindResult = this.BackendBind(context);
41
@@ -107,7 +62,7 @@ namespace WixToolset.Core
62
63
foreach (var factory in backendFactories)
64
{
110
- if (factory.TryCreateBackend(entrySection.Type.ToString(), context.OutputPath, null, out var backend))
65
+ if (factory.TryCreateBackend(entrySection.Type.ToString(), context.OutputPath, out var backend))
66
{
67
var result = backend.Bind(context);
68
return result;
@@ -118,8 +73,8 @@ namespace WixToolset.Core
73
74
return null;
75
}
121
-
122
- private void WriteBuildInfoTable(Intermediate output, string outputFile, string outputPdbPath)
76
+
77
+ private void WriteBuildInfoTuple(Intermediate output, string outputFile, string outputPdbPath)
78
{
79
var entrySection = output.Sections.First(s => s.Type != SectionType.Fragment);
80
src/WixToolset.Core/CommandLine/BuildCommand.cs
+117
-77
@@ -8,6 +8,7 @@ namespace WixToolset.Core.CommandLine
8
using System.Linq;
9
using System.Xml.Linq;
10
using WixToolset.Data;
11
+ using WixToolset.Extensibility;
12
using WixToolset.Extensibility.Data;
13
using WixToolset.Extensibility.Services;
14
@@ -172,16 +173,24 @@ namespace WixToolset.Core.CommandLine
173
174
foreach (var sourceFile in sourceFiles)
175
{
175
- var preprocessor = new Preprocessor(this.ServiceProvider);
176
- preprocessor.IncludeSearchPaths = this.IncludeSearchPaths;
177
- preprocessor.Platform = this.Platform;
178
- preprocessor.SourcePath = sourceFile.SourcePath;
179
- preprocessor.Variables = this.PreprocessorVariables;
176
+ var document = this.Preprocess(sourceFile.SourcePath);
177
181
- XDocument document = null;
178
+ if (this.Messaging.EncounteredError)
179
+ {
180
+ continue;
181
+ }
182
+
183
+ var context = this.ServiceProvider.GetService<ICompileContext>();
184
+ context.Extensions = this.ExtensionManager.Create<ICompilerExtension>();
185
+ context.OutputPath = sourceFile.OutputPath;
186
+ context.Platform = this.Platform;
187
+ context.Source = document;
188
+
189
+ Intermediate intermediate = null;
190
try
191
{
184
- document = preprocessor.Execute();
192
+ var compiler = this.ServiceProvider.GetService<ICompiler>();
193
+ intermediate = compiler.Compile(context);
194
}
195
catch (WixException e)
196
{
@@ -193,17 +202,6 @@ namespace WixToolset.Core.CommandLine
202
continue;
203
}
204
196
- var compiler = new Compiler(this.ServiceProvider);
197
- compiler.OutputPath = sourceFile.OutputPath;
198
- compiler.Platform = this.Platform;
199
- compiler.SourceDocument = document;
200
- var intermediate = compiler.Execute();
201
-
202
- if (this.Messaging.EncounteredError)
203
- {
204
- continue;
205
- }
206
-
205
intermediates.Add(intermediate);
206
}
207
@@ -212,14 +210,27 @@ namespace WixToolset.Core.CommandLine
210
211
private Intermediate LibraryPhase(IEnumerable<Intermediate> intermediates, IEnumerable<Localization> localizations)
212
{
215
- var librarian = new Librarian(this.ServiceProvider);
216
- librarian.BindFiles = this.BindFiles;
217
- librarian.BindPaths = this.BindPaths;
218
- librarian.Intermediates = intermediates;
219
- librarian.Localizations = localizations;
220
- return librarian.Execute();
221
- }
213
+ var context = this.ServiceProvider.GetService<ILibraryContext>();
214
+ context.BindFiles = this.BindFiles;
215
+ context.BindPaths = this.BindPaths;
216
+ context.Extensions = this.ExtensionManager.Create<ILibrarianExtension>();
217
+ context.Localizations = localizations;
218
+ context.Intermediates = intermediates;
219
+
220
+ Intermediate library = null;
221
+ try
222
+ {
223
+ var librarian = this.ServiceProvider.GetService<ILibrarian>();
224
+ library = librarian.Combine(context);
225
+ }
226
+ catch (WixException e)
227
+ {
228
+ this.Messaging.Write(e.Error);
229
+ }
230
231
+ return library;
232
+ }
233
+
234
private Intermediate LinkPhase(IEnumerable<Intermediate> intermediates, ITupleDefinitionCreator creator)
235
{
236
var libraries = this.LoadLibraries(creator);
@@ -229,26 +240,39 @@ namespace WixToolset.Core.CommandLine
240
return null;
241
}
242
232
- var linker = new Linker(this.ServiceProvider);
233
- linker.OutputType = this.OutputType;
234
- linker.Intermediates = intermediates;
235
- linker.Libraries = libraries;
236
- linker.TupleDefinitionCreator = creator;
237
- return linker.Execute();
243
+ var context = this.ServiceProvider.GetService<ILinkContext>();
244
+ context.Extensions = this.ExtensionManager.Create<ILinkerExtension>();
245
+ context.ExtensionData = this.ExtensionManager.Create<IExtensionData>();
246
+ context.ExpectedOutputType = this.OutputType;
247
+ context.Intermediates = intermediates.Concat(libraries).ToList();
248
+ context.TupleDefinitionCreator = creator;
249
+
250
+ var linker = this.ServiceProvider.GetService<ILinker>();
251
+ return linker.Link(context);
252
}
253
254
private void BindPhase(Intermediate output, IEnumerable<Localization> localizations)
255
{
256
+ var intermediateFolder = this.IntermediateFolder;
257
+ if (String.IsNullOrEmpty(intermediateFolder))
258
+ {
259
+ intermediateFolder = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
260
+ }
261
+
262
ResolveResult resolveResult;
263
{
244
- var resolver = new Resolver(this.ServiceProvider);
245
- resolver.BindPaths = this.BindPaths;
246
- resolver.FilterCultures = this.FilterCultures;
247
- resolver.IntermediateFolder = this.IntermediateFolder;
248
- resolver.IntermediateRepresentation = output;
249
- resolver.Localizations = localizations;
250
-
251
- resolveResult = resolver.Execute();
264
+ var context = this.ServiceProvider.GetService<IResolveContext>();
265
+ context.BindPaths = this.BindPaths;
266
+ context.Extensions = this.ExtensionManager.Create<IResolverExtension>();
267
+ context.ExtensionData = this.ExtensionManager.Create<IExtensionData>();
268
+ context.FilterCultures = this.FilterCultures;
269
+ context.IntermediateFolder = intermediateFolder;
270
+ context.IntermediateRepresentation = output;
271
+ context.Localizations = localizations;
272
+ context.VariableResolver = new WixVariableResolver(this.Messaging);
273
+
274
+ var resolver = this.ServiceProvider.GetService<IResolver>();
275
+ resolveResult = resolver.Resolve(context);
276
}
277
278
if (this.Messaging.EncounteredError)
@@ -258,28 +282,24 @@ namespace WixToolset.Core.CommandLine
282
283
BindResult bindResult;
284
{
261
- var intermediateFolder = this.IntermediateFolder;
262
- if (String.IsNullOrEmpty(intermediateFolder))
263
- {
264
- intermediateFolder = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
265
- }
266
-
267
- var binder = new Binder(this.ServiceProvider);
268
- //binder.CabbingThreadCount = this.CabbingThreadCount;
269
- binder.CabCachePath = this.CabCachePath;
270
- binder.Codepage = resolveResult.Codepage;
271
- //binder.DefaultCompressionLevel = this.DefaultCompressionLevel;
272
- binder.DelayedFields = resolveResult.DelayedFields;
273
- binder.ExpectedEmbeddedFiles = resolveResult.ExpectedEmbeddedFiles;
274
- binder.Ices = Array.Empty<string>(); // TODO: set this correctly
275
- binder.IntermediateFolder = intermediateFolder;
276
- binder.IntermediateRepresentation = resolveResult.IntermediateRepresentation;
277
- binder.OutputPath = this.OutputPath;
278
- binder.OutputPdbPath = Path.ChangeExtension(this.OutputPath, ".wixpdb");
279
- binder.SuppressIces = Array.Empty<string>(); // TODO: set this correctly
280
- binder.SuppressValidation = true; // TODO: set this correctly
281
-
282
- bindResult = binder.Execute();
285
+ var context = this.ServiceProvider.GetService<IBindContext>();
286
+ //context.CabbingThreadCount = this.CabbingThreadCount;
287
+ context.CabCachePath = this.CabCachePath;
288
+ context.Codepage = resolveResult.Codepage;
289
+ //context.DefaultCompressionLevel = this.DefaultCompressionLevel;
290
+ context.DelayedFields = resolveResult.DelayedFields;
291
+ context.ExpectedEmbeddedFiles = resolveResult.ExpectedEmbeddedFiles;
292
+ context.Extensions = this.ExtensionManager.Create<IBinderExtension>();
293
+ context.Ices = Array.Empty<string>(); // TODO: set this correctly
294
+ context.IntermediateFolder = intermediateFolder;
295
+ context.IntermediateRepresentation = resolveResult.IntermediateRepresentation;
296
+ context.OutputPath = this.OutputPath;
297
+ context.OutputPdbPath = Path.ChangeExtension(this.OutputPath, ".wixpdb");
298
+ context.SuppressIces = Array.Empty<string>(); // TODO: set this correctly
299
+ context.SuppressValidation = true; // TODO: set this correctly
300
+
301
+ var binder = this.ServiceProvider.GetService<IBinder>();
302
+ bindResult = binder.Bind(context);
303
}
304
305
if (this.Messaging.EncounteredError)
@@ -288,16 +308,18 @@ namespace WixToolset.Core.CommandLine
308
}
309
310
{
291
- var layout = new Layout(this.ServiceProvider);
292
- layout.TrackedFiles = bindResult.TrackedFiles;
293
- layout.FileTransfers = bindResult.FileTransfers;
294
- layout.IntermediateFolder = this.IntermediateFolder;
295
- layout.ContentsFile = this.ContentsFile;
296
- layout.OutputsFile = this.OutputsFile;
297
- layout.BuiltOutputsFile = this.BuiltOutputsFile;
298
- layout.SuppressAclReset = false; // TODO: correctly set SuppressAclReset
299
-
300
- layout.Execute();
311
+ var context = this.ServiceProvider.GetService<ILayoutContext>();
312
+ context.Extensions = this.ExtensionManager.Create<ILayoutExtension>();
313
+ context.TrackedFiles = bindResult.TrackedFiles;
314
+ context.FileTransfers = bindResult.FileTransfers;
315
+ context.IntermediateFolder = intermediateFolder;
316
+ context.ContentsFile = this.ContentsFile;
317
+ context.OutputsFile = this.OutputsFile;
318
+ context.BuiltOutputsFile = this.BuiltOutputsFile;
319
+ context.SuppressAclReset = false; // TODO: correctly set SuppressAclReset
320
+
321
+ var layout = this.ServiceProvider.GetService<ILayoutCreator>();
322
+ layout.Layout(context);
323
}
324
}
325
@@ -335,12 +357,7 @@ namespace WixToolset.Core.CommandLine
357
358
foreach (var loc in this.LocFiles)
359
{
338
- var preprocessor = new Preprocessor(this.ServiceProvider);
339
- preprocessor.IncludeSearchPaths = this.IncludeSearchPaths;
340
- preprocessor.Platform = Platform.X86; // TODO: set this correctly
341
- preprocessor.SourcePath = loc;
342
- preprocessor.Variables = this.PreprocessorVariables;
343
- var document = preprocessor.Execute();
360
+ var document = this.Preprocess(loc);
361
362
if (this.Messaging.EncounteredError)
363
{
@@ -351,5 +368,28 @@ namespace WixToolset.Core.CommandLine
368
yield return localization;
369
}
370
}
371
+
372
+ private XDocument Preprocess(string sourcePath)
373
+ {
374
+ var context = this.ServiceProvider.GetService<IPreprocessContext>();
375
+ context.Extensions = this.ExtensionManager.Create<IPreprocessorExtension>();
376
+ context.Platform = this.Platform;
377
+ context.IncludeSearchPaths = this.IncludeSearchPaths;
378
+ context.SourcePath = sourcePath;
379
+ context.Variables = this.PreprocessorVariables;
380
+
381
+ XDocument document = null;
382
+ try
383
+ {
384
+ var preprocessor = this.ServiceProvider.GetService<IPreprocessor>();
385
+ document = preprocessor.Preprocess(context);
386
+ }
387
+ catch (WixException e)
388
+ {
389
+ this.Messaging.Write(e.Error);
390
+ }
391
+
392
+ return document;
393
+ }
394
}
395
}
src/WixToolset.Core/CommandLine/CompileCommand.cs
+20
-11
@@ -6,6 +6,7 @@ namespace WixToolset.Core.CommandLine
6
using System.Collections.Generic;
7
using System.Xml.Linq;
8
using WixToolset.Data;
9
+ using WixToolset.Extensibility;
10
using WixToolset.Extensibility.Data;
11
using WixToolset.Extensibility.Services;
12
@@ -15,6 +16,7 @@ namespace WixToolset.Core.CommandLine
16
{
17
this.ServiceProvider = serviceProvider;
18
this.Messaging = serviceProvider.GetService<IMessaging>();
19
+ this.ExtensionManager = serviceProvider.GetService<IExtensionManager>();
20
this.SourceFiles = sources;
21
this.PreprocessorVariables = preprocessorVariables;
22
this.Platform = platform;
@@ -24,6 +26,8 @@ namespace WixToolset.Core.CommandLine
26
27
public IMessaging Messaging { get; }
28
29
+ public IExtensionManager ExtensionManager { get; }
30
+
31
private IEnumerable<SourceFile> SourceFiles { get; }
32
33
private IDictionary<string, string> PreprocessorVariables { get; }
@@ -36,16 +40,18 @@ namespace WixToolset.Core.CommandLine
40
{
41
foreach (var sourceFile in this.SourceFiles)
42
{
39
- var preprocessor = new Preprocessor(this.ServiceProvider);
40
- preprocessor.IncludeSearchPaths = this.IncludeSearchPaths;
41
- preprocessor.Platform = Platform.X86; // TODO: set this correctly
42
- preprocessor.SourcePath = sourceFile.SourcePath;
43
- preprocessor.Variables = new Dictionary<string, string>(this.PreprocessorVariables);
43
+ var context = this.ServiceProvider.GetService<IPreprocessContext>();
44
+ context.Extensions = this.ExtensionManager.Create<IPreprocessorExtension>();
45
+ context.Platform = this.Platform;
46
+ context.IncludeSearchPaths = this.IncludeSearchPaths;
47
+ context.SourcePath = sourceFile.SourcePath;
48
+ context.Variables = this.PreprocessorVariables;
49
50
XDocument document = null;
51
try
52
{
48
- document = preprocessor.Execute();
53
+ var preprocessor = this.ServiceProvider.GetService<IPreprocessor>();
54
+ document = preprocessor.Preprocess(context);
55
}
56
catch (WixException e)
57
{
@@ -57,11 +63,14 @@ namespace WixToolset.Core.CommandLine
63
continue;
64
}
65
60
- var compiler = new Compiler(this.ServiceProvider);
61
- compiler.OutputPath = sourceFile.OutputPath;
62
- compiler.Platform = this.Platform;
63
- compiler.SourceDocument = document;
64
- var intermediate = compiler.Execute();
66
+ var compileContext = this.ServiceProvider.GetService<ICompileContext>();
67
+ compileContext.Extensions = this.ExtensionManager.Create<ICompilerExtension>();
68
+ compileContext.OutputPath = sourceFile.OutputPath;
69
+ compileContext.Platform = this.Platform;
70
+ compileContext.Source = document;
71
+
72
+ var compiler = this.ServiceProvider.GetService<ICompiler>();
73
+ var intermediate = compiler.Compile(compileContext);
74
75
intermediate.Save(sourceFile.OutputPath);
76
}
src/WixToolset.Core/Compiler.cs
+6
-19
@@ -22,7 +22,7 @@ namespace WixToolset.Core
22
/// <summary>
23
/// Compiler of the WiX toolset.
24
/// </summary>
25
- internal class Compiler
25
+ internal class Compiler : ICompiler
26
{
27
public const string UpgradeDetectedProperty = "WIX_UPGRADE_DETECTED";
28
public const string UpgradePreventedCondition = "NOT WIX_UPGRADE_DETECTED";
@@ -84,14 +84,6 @@ namespace WixToolset.Core
84
85
private CompilerCore Core { get; set; }
86
87
- public string CompliationId { get; set; }
88
-
89
- public string OutputPath { get; set; }
90
-
91
- public Platform Platform { get; set; }
92
-
93
- public XDocument SourceDocument { get; set; }
94
-
87
/// <summary>
88
/// Gets or sets the platform which the compiler will use when defaulting 64-bit attributes and elements.
89
/// </summary>
@@ -109,22 +101,17 @@ namespace WixToolset.Core
101
/// </summary>
102
/// <returns>Intermediate object representing compiled source document.</returns>
103
/// <remarks>This method is not thread-safe.</remarks>
112
- public Intermediate Execute()
104
+ public Intermediate Compile(ICompileContext context)
105
{
114
- this.Context = this.ServiceProvider.GetService<ICompileContext>();
115
- this.Context.Extensions = this.ServiceProvider.GetService<IExtensionManager>().Create<ICompilerExtension>();
116
- this.Context.CompilationId = this.CompliationId;
117
- this.Context.OutputPath = this.OutputPath;
118
- this.Context.Platform = this.Platform;
119
- this.Context.Source = this.SourceDocument;
120
-
106
var target = new Intermediate();
107
123
- if (String.IsNullOrEmpty(this.Context.CompilationId))
108
+ if (String.IsNullOrEmpty(context.CompilationId))
109
{
125
- this.Context.CompilationId = target.Id;
110
+ context.CompilationId = target.Id;
111
}
112
113
+ this.Context = context;
114
+
115
var extensionsByNamespace = new Dictionary<XNamespace, ICompilerExtension>();
116
117
foreach (var extension in this.Context.Extensions)
src/WixToolset.Core/DecompileContext.cs
new
+28
@@ -0,0 +1,28 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+namespace WixToolset.Core
4
+{
5
+ using System;
6
+ using System.Collections.Generic;
7
+ using WixToolset.Data;
8
+ using WixToolset.Extensibility;
9
+ using WixToolset.Extensibility.Data;
10
+
11
+ internal class DecompileContext : IDecompileContext
12
+ {
13
+ internal DecompileContext(IServiceProvider serviceProvider)
14
+ {
15
+ this.ServiceProvider = serviceProvider;
16
+ }
17
+
18
+ public IServiceProvider ServiceProvider { get; }
19
+
20
+ public OutputType DecompileType { get; set; }
21
+
22
+ public IEnumerable<IDecompilerExtension> Extensions { get; set; }
23
+
24
+ public string IntermediateFolder { get; set; }
25
+
26
+ public string OutputPath { get; set; }
27
+ }
28
+}
src/WixToolset.Core/Decompiler.cs
new
+75
@@ -0,0 +1,75 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+namespace WixToolset.Core
4
+{
5
+ using System;
6
+ using WixToolset.Data;
7
+ using WixToolset.Extensibility;
8
+ using WixToolset.Extensibility.Data;
9
+ using WixToolset.Extensibility.Services;
10
+
11
+ /// <summary>
12
+ /// Decompiler of the WiX toolset.
13
+ /// </summary>
14
+ internal class Decompiler : IDecompiler
15
+ {
16
+ internal Decompiler(IServiceProvider serviceProvider)
17
+ {
18
+ this.ServiceProvider = serviceProvider;
19
+ }
20
+
21
+ public OutputType DecompileType { get; set; }
22
+
23
+ public string IntermediateFolder { get; set; }
24
+
25
+ public string OutputPath { get; set; }
26
+
27
+ public IServiceProvider ServiceProvider { get; }
28
+
29
+ public BindResult Decompile(IDecompileContext context)
30
+ {
31
+ // Pre-decompile.
32
+ //
33
+ foreach (var extension in context.Extensions)
34
+ {
35
+ extension.PreDecompile(context);
36
+ }
37
+
38
+ // Decompile.
39
+ //
40
+ var bindResult = this.BackendDecompile(context);
41
+
42
+ if (bindResult != null)
43
+ {
44
+ // Post-decompile.
45
+ //
46
+ foreach (var extension in context.Extensions)
47
+ {
48
+ extension.PostDecompile(bindResult);
49
+ }
50
+ }
51
+
52
+ return bindResult;
53
+ }
54
+
55
+ private BindResult BackendDecompile(IDecompileContext context)
56
+ {
57
+ var extensionManager = context.ServiceProvider.GetService<IExtensionManager>();
58
+
59
+ var backendFactories = extensionManager.Create<IBackendFactory>();
60
+
61
+ foreach (var factory in backendFactories)
62
+ {
63
+ if (factory.TryCreateBackend(context.DecompileType.ToString(), context.OutputPath, out var backend))
64
+ {
65
+ var result = backend.Decompile(context);
66
+ return result;
67
+ }
68
+ }
69
+
70
+ // TODO: messaging that a backend could not be found to decompile the decompile type?
71
+
72
+ return null;
73
+ }
74
+ }
75
+}
src/WixToolset.Core/IBinder.cs
new
+11
@@ -0,0 +1,11 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+namespace WixToolset.Core
4
+{
5
+ using WixToolset.Extensibility.Data;
6
+
7
+ public interface IBinder
8
+ {
9
+ BindResult Bind(IBindContext context);
10
+ }
11
+}
src/WixToolset.Core/ICompiler.cs
new
+12
@@ -0,0 +1,12 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+namespace WixToolset.Core
4
+{
5
+ using WixToolset.Data;
6
+ using WixToolset.Extensibility.Data;
7
+
8
+ public interface ICompiler
9
+ {
10
+ Intermediate Compile(ICompileContext context);
11
+ }
12
+}
src/WixToolset.Core/IDecompiler.cs
new
+11
@@ -0,0 +1,11 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+namespace WixToolset.Core
4
+{
5
+ using WixToolset.Extensibility.Data;
6
+
7
+ public interface IDecompiler
8
+ {
9
+ BindResult Decompile(IDecompileContext context);
10
+ }
11
+}
src/WixToolset.Core/ILayoutCreator.cs
new
+11
@@ -0,0 +1,11 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+namespace WixToolset.Core
4
+{
5
+ using WixToolset.Extensibility.Data;
6
+
7
+ public interface ILayoutCreator
8
+ {
9
+ void Layout(ILayoutContext context);
10
+ }
11
+}
src/WixToolset.Core/ILibrarian.cs
new
+12
@@ -0,0 +1,12 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+namespace WixToolset.Core
4
+{
5
+ using WixToolset.Data;
6
+ using WixToolset.Extensibility.Data;
7
+
8
+ public interface ILibrarian
9
+ {
10
+ Intermediate Combine(ILibraryContext context);
11
+ }
12
+}
src/WixToolset.Core/ILinker.cs
new
+12
@@ -0,0 +1,12 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+namespace WixToolset.Core
4
+{
5
+ using WixToolset.Data;
6
+ using WixToolset.Extensibility.Data;
7
+
8
+ public interface ILinker
9
+ {
10
+ Intermediate Link(ILinkContext context);
11
+ }
12
+}
src/WixToolset.Core/IPreprocessor.cs
new
+15
@@ -0,0 +1,15 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+namespace WixToolset.Core
4
+{
5
+ using System.Xml;
6
+ using System.Xml.Linq;
7
+ using WixToolset.Extensibility.Data;
8
+
9
+ internal interface IPreprocessor
10
+ {
11
+ XDocument Preprocess(IPreprocessContext context);
12
+
13
+ XDocument Preprocess(IPreprocessContext context, XmlReader reader);
14
+ }
15
+}
src/WixToolset.Core/IResolver.cs
new
+11
@@ -0,0 +1,11 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+namespace WixToolset.Core
4
+{
5
+ using WixToolset.Extensibility.Data;
6
+
7
+ public interface IResolver
8
+ {
9
+ ResolveResult Resolve(IResolveContext context);
10
+ }
11
+}
src/WixToolset.Core/LayoutContext.cs
+1
-1
@@ -24,7 +24,7 @@ namespace WixToolset.Core
24
25
public IEnumerable<ITrackedFile> TrackedFiles { get; set; }
26
27
- public string OutputPdbPath { get; set; }
27
+ public string IntermediateFolder { get; set; }
28
29
public string ContentsFile { get; set; }
30
src/WixToolset.Core/LayoutCreator.cs
renamed
+12
-38
@@ -8,16 +8,15 @@ namespace WixToolset.Core
8
using System.Linq;
9
using WixToolset.Core.Bind;
10
using WixToolset.Data;
11
- using WixToolset.Extensibility;
11
using WixToolset.Extensibility.Data;
12
using WixToolset.Extensibility.Services;
13
14
/// <summary>
15
/// Layout for the WiX toolset.
16
/// </summary>
18
- internal class Layout
17
+ internal class LayoutCreator : ILayoutCreator
18
{
20
- internal Layout(IServiceProvider serviceProvider)
19
+ internal LayoutCreator(IServiceProvider serviceProvider)
20
{
21
this.ServiceProvider = serviceProvider;
22
@@ -28,33 +27,8 @@ namespace WixToolset.Core
27
28
private IMessaging Messaging { get; }
29
31
- public IEnumerable<ITrackedFile> TrackedFiles { get; set; }
32
-
33
- public IEnumerable<IFileTransfer> FileTransfers { get; set; }
34
-
35
- public string IntermediateFolder { get; set; }
36
-
37
- public string ContentsFile { get; set; }
38
-
39
- public string OutputsFile { get; set; }
40
-
41
- public string BuiltOutputsFile { get; set; }
42
-
43
- public bool SuppressAclReset { get; set; }
44
-
45
- public void Execute()
30
+ public void Layout(ILayoutContext context)
31
{
47
- var extensionManager = this.ServiceProvider.GetService<IExtensionManager>();
48
-
49
- var context = this.ServiceProvider.GetService<ILayoutContext>();
50
- context.Extensions = extensionManager.Create<ILayoutExtension>();
51
- context.TrackedFiles = this.TrackedFiles;
52
- context.FileTransfers = this.FileTransfers;
53
- context.ContentsFile = this.ContentsFile;
54
- context.OutputsFile = this.OutputsFile;
55
- context.BuiltOutputsFile = this.BuiltOutputsFile;
56
- context.SuppressAclReset = this.SuppressAclReset;
57
-
32
// Pre-layout.
33
//
34
foreach (var extension in context.Extensions)
@@ -76,7 +50,7 @@ namespace WixToolset.Core
50
51
if (context.TrackedFiles != null)
52
{
79
- this.CleanTempFiles(context.TrackedFiles);
53
+ this.CleanTempFiles(context.IntermediateFolder, context.TrackedFiles);
54
}
55
}
56
finally
@@ -126,7 +100,7 @@ namespace WixToolset.Core
100
101
using (var contents = new StreamWriter(path, false))
102
{
129
- foreach (string inputPath in uniqueInputFilePaths)
103
+ foreach (var inputPath in uniqueInputFilePaths)
104
{
105
contents.WriteLine(inputPath);
106
}
@@ -190,7 +164,7 @@ namespace WixToolset.Core
164
}
165
}
166
193
- private void CleanTempFiles(IEnumerable<ITrackedFile> trackedFiles)
167
+ private void CleanTempFiles(string intermediateFolder, IEnumerable<ITrackedFile> trackedFiles)
168
{
169
var uniqueTempPaths = new SortedSet<string>(trackedFiles.Where(t => t.Type == TrackedFileType.Temporary).Select(t => t.Path), StringComparer.OrdinalIgnoreCase);
170
@@ -201,7 +175,7 @@ namespace WixToolset.Core
175
176
var uniqueFolders = new SortedSet<string>(StringComparer.OrdinalIgnoreCase)
177
{
204
- this.IntermediateFolder
178
+ intermediateFolder
179
};
180
181
// Clean up temp files.
@@ -209,7 +183,7 @@ namespace WixToolset.Core
183
{
184
try
185
{
212
- this.SplitUniqueFolders(tempPath, uniqueFolders);
186
+ this.SplitUniqueFolders(intermediateFolder, tempPath, uniqueFolders);
187
188
File.Delete(tempPath);
189
}
@@ -231,15 +205,15 @@ namespace WixToolset.Core
205
}
206
}
207
234
- private void SplitUniqueFolders(string tempPath, SortedSet<string> uniqueFolders)
208
+ private void SplitUniqueFolders(string intermediateFolder, string tempPath, SortedSet<string> uniqueFolders)
209
{
236
- if (tempPath.StartsWith(this.IntermediateFolder, StringComparison.OrdinalIgnoreCase))
210
+ if (tempPath.StartsWith(intermediateFolder, StringComparison.OrdinalIgnoreCase))
211
{
238
- var folder = Path.GetDirectoryName(tempPath).Substring(this.IntermediateFolder.Length);
212
+ var folder = Path.GetDirectoryName(tempPath).Substring(intermediateFolder.Length);
213
214
var parts = folder.Split(new[] { '\\', '/' }, StringSplitOptions.RemoveEmptyEntries);
215
242
- folder = this.IntermediateFolder;
216
+ folder = intermediateFolder;
217
218
foreach (var part in parts)
219
{
src/WixToolset.Core/Librarian.cs
+19
-33
@@ -8,14 +8,13 @@ namespace WixToolset.Core
8
using WixToolset.Core.Bind;
9
using WixToolset.Core.Link;
10
using WixToolset.Data;
11
- using WixToolset.Extensibility;
11
using WixToolset.Extensibility.Data;
12
using WixToolset.Extensibility.Services;
13
14
/// <summary>
15
/// Core librarian tool.
16
/// </summary>
18
- internal class Librarian
17
+ internal class Librarian : ILibrarian
18
{
19
internal Librarian(IServiceProvider serviceProvider)
20
{
@@ -28,42 +27,29 @@ namespace WixToolset.Core
27
28
private IMessaging Messaging { get; }
29
31
- private ILibraryContext Context { get; set; }
32
-
33
- public bool BindFiles { get; set; }
34
-
35
- public IEnumerable<BindPath> BindPaths { get; set; }
36
-
37
- public IEnumerable<Localization> Localizations { get; set; }
38
-
39
- public IEnumerable<Intermediate> Intermediates { get; set; }
40
-
30
/// <summary>
31
/// Create a library by combining several intermediates (objects).
32
/// </summary>
33
/// <param name="sections">The sections to combine into a library.</param>
34
/// <returns>Returns the new library.</returns>
46
- public Intermediate Execute()
35
+ public Intermediate Combine(ILibraryContext context)
36
{
48
- this.Context = new LibraryContext(this.ServiceProvider);
49
- this.Context.BindFiles = this.BindFiles;
50
- this.Context.BindPaths = this.BindPaths;
51
- this.Context.Extensions = this.ServiceProvider.GetService<IExtensionManager>().Create<ILibrarianExtension>();
52
- this.Context.Localizations = this.Localizations;
53
- this.Context.LibraryId = Convert.ToBase64String(Guid.NewGuid().ToByteArray()).TrimEnd('=').Replace('+', '.').Replace('/', '_');
54
- this.Context.Intermediates = this.Intermediates;
55
-
56
- foreach (var extension in this.Context.Extensions)
37
+ if (String.IsNullOrEmpty(context.LibraryId))
38
+ {
39
+ context.LibraryId = Convert.ToBase64String(Guid.NewGuid().ToByteArray()).TrimEnd('=').Replace('+', '.').Replace('/', '_');
40
+ }
41
+
42
+ foreach (var extension in context.Extensions)
43
{
58
- extension.PreCombine(this.Context);
44
+ extension.PreCombine(context);
45
}
46
47
Intermediate library = null;
48
try
49
{
64
- var sections = this.Context.Intermediates.SelectMany(i => i.Sections).ToList();
50
+ var sections = context.Intermediates.SelectMany(i => i.Sections).ToList();
51
66
- var collate = new CollateLocalizationsCommand(this.Messaging, this.Context.Localizations);
52
+ var collate = new CollateLocalizationsCommand(this.Messaging, context.Localizations);
53
var localizationsByCulture = collate.Execute();
54
55
if (this.Messaging.EncounteredError)
@@ -71,20 +57,20 @@ namespace WixToolset.Core
57
return null;
58
}
59
74
- var embedFilePaths = this.ResolveFilePathsToEmbed(sections);
60
+ var embedFilePaths = this.ResolveFilePathsToEmbed(context, sections);
61
62
foreach (var section in sections)
63
{
78
- section.LibraryId = this.Context.LibraryId;
64
+ section.LibraryId = context.LibraryId;
65
}
66
81
- library = new Intermediate(this.Context.LibraryId, sections, localizationsByCulture, embedFilePaths);
67
+ library = new Intermediate(context.LibraryId, sections, localizationsByCulture, embedFilePaths);
68
69
this.Validate(library);
70
}
71
finally
72
{
87
- foreach (var extension in this.Context.Extensions)
73
+ foreach (var extension in context.Extensions)
74
{
75
extension.PostCombine(library);
76
}
@@ -99,7 +85,7 @@ namespace WixToolset.Core
85
/// <param name="library">Library to validate.</param>
86
private void Validate(Intermediate library)
87
{
102
- FindEntrySectionAndLoadSymbolsCommand find = new FindEntrySectionAndLoadSymbolsCommand(this.Messaging, library.Sections);
88
+ var find = new FindEntrySectionAndLoadSymbolsCommand(this.Messaging, library.Sections);
89
find.Execute();
90
91
// TODO: Consider bringing this sort of verification back.
@@ -113,16 +99,16 @@ namespace WixToolset.Core
99
// }
100
}
101
116
- private List<string> ResolveFilePathsToEmbed(IEnumerable<IntermediateSection> sections)
102
+ private List<string> ResolveFilePathsToEmbed(ILibraryContext context, IEnumerable<IntermediateSection> sections)
103
{
104
var embedFilePaths = new List<string>();
105
106
// Resolve paths to files that are to be embedded in the library.
121
- if (this.Context.BindFiles)
107
+ if (context.BindFiles)
108
{
109
var variableResolver = new WixVariableResolver(this.Messaging);
110
125
- var fileResolver = new FileResolver(this.Context.BindPaths, this.Context.Extensions);
111
+ var fileResolver = new FileResolver(context.BindPaths, context.Extensions);
112
113
foreach (var tuple in sections.SelectMany(s => s.Tuples))
114
{
src/WixToolset.Core/Linker.cs
+214
-227
@@ -11,19 +11,18 @@ namespace WixToolset.Core
11
using WixToolset.Core.Link;
12
using WixToolset.Data;
13
using WixToolset.Data.Tuples;
14
- using WixToolset.Extensibility;
14
using WixToolset.Extensibility.Data;
15
using WixToolset.Extensibility.Services;
16
17
/// <summary>
18
/// Linker core of the WiX toolset.
19
/// </summary>
21
- internal class Linker
20
+ internal class Linker : ILinker
21
{
22
private static readonly char[] colonCharacter = ":".ToCharArray();
23
private static readonly string emptyGuid = Guid.Empty.ToString("B");
24
26
- private bool sectionIdOnRows;
25
+ private readonly bool sectionIdOnRows;
26
27
/// <summary>
28
/// Creates a linker.
@@ -53,32 +52,20 @@ namespace WixToolset.Core
52
/// <value>The option to show pedantic messages.</value>
53
public bool ShowPedanticMessages { get; set; }
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
-
55
/// <summary>
56
/// Links a collection of sections into an output.
57
/// </summary>
58
/// <param name="inputs">The collection of sections to link together.</param>
59
/// <param name="expectedOutputType">Expected output type, based on output file extension provided to the linker.</param>
60
/// <returns>Output object from the linking.</returns>
70
- public Intermediate Execute()
61
+ public Intermediate Link(ILinkContext context)
62
{
72
- var extensionManager = this.ServiceProvider.GetService<IExtensionManager>();
73
-
74
- var creator = this.TupleDefinitionCreator ?? this.ServiceProvider.GetService<ITupleDefinitionCreator>();
63
+ this.Context = context;
64
76
- this.Context = this.ServiceProvider.GetService<ILinkContext>();
77
- this.Context.Extensions = extensionManager.Create<ILinkerExtension>();
78
- this.Context.ExtensionData = extensionManager.Create<IExtensionData>();
79
- this.Context.ExpectedOutputType = this.OutputType;
80
- this.Context.Intermediates = this.Intermediates.Concat(this.Libraries).ToList();
81
- this.Context.TupleDefinitionCreator = creator;
65
+ if (this.Context.TupleDefinitionCreator == null)
66
+ {
67
+ this.Context.TupleDefinitionCreator = this.ServiceProvider.GetService<ITupleDefinitionCreator>();
68
+ }
69
70
foreach (var extension in this.Context.Extensions)
71
{
@@ -117,7 +104,7 @@ namespace WixToolset.Core
104
Hashtable generatedShortFileNames = new Hashtable();
105
#endif
106
120
- Hashtable multipleFeatureComponents = new Hashtable();
107
+ var multipleFeatureComponents = new Hashtable();
108
109
var wixVariables = new Dictionary<string, WixVariableTuple>();
110
@@ -238,7 +225,7 @@ namespace WixToolset.Core
225
sectionCount++;
226
227
var sectionId = section.Id;
241
- if (null == sectionId && this.sectionIdOnRows)
228
+ if (null == sectionId && sectionIdOnRows)
229
{
230
sectionId = "wix.section." + sectionCount.ToString(CultureInfo.InvariantCulture);
231
}
@@ -256,12 +243,12 @@ namespace WixToolset.Core
243
break;
244
#endif
245
259
- case TupleDefinitionType.Class:
260
- if (SectionType.Product == resolvedSection.Type)
261
- {
262
- this.ResolveFeatures(tuple, 2, 11, componentsToFeatures, multipleFeatureComponents);
263
- }
264
- break;
246
+ case TupleDefinitionType.Class:
247
+ if (SectionType.Product == resolvedSection.Type)
248
+ {
249
+ this.ResolveFeatures(tuple, 2, 11, componentsToFeatures, multipleFeatureComponents);
250
+ }
251
+ break;
252
253
#if MOVE_TO_BACKEND
254
case "CustomAction":
@@ -315,12 +302,12 @@ namespace WixToolset.Core
302
}
303
break;
304
#endif
318
- case TupleDefinitionType.Extension:
319
- if (SectionType.Product == resolvedSection.Type)
320
- {
321
- this.ResolveFeatures(tuple, 1, 4, componentsToFeatures, multipleFeatureComponents);
322
- }
323
- break;
305
+ case TupleDefinitionType.Extension:
306
+ if (SectionType.Product == resolvedSection.Type)
307
+ {
308
+ this.ResolveFeatures(tuple, 1, 4, componentsToFeatures, multipleFeatureComponents);
309
+ }
310
+ break;
311
312
#if MOVE_TO_BACKEND
313
case TupleDefinitionType.ModuleSubstitution:
@@ -332,12 +319,12 @@ namespace WixToolset.Core
319
break;
320
#endif
321
335
- case TupleDefinitionType.MsiAssembly:
336
- if (SectionType.Product == resolvedSection.Type)
337
- {
338
- this.ResolveFeatures(tuple, 0, 1, componentsToFeatures, multipleFeatureComponents);
339
- }
340
- break;
322
+ case TupleDefinitionType.MsiAssembly:
323
+ if (SectionType.Product == resolvedSection.Type)
324
+ {
325
+ this.ResolveFeatures(tuple, 0, 1, componentsToFeatures, multipleFeatureComponents);
326
+ }
327
+ break;
328
329
#if MOVE_TO_BACKEND
330
case "ProgId":
@@ -359,26 +346,26 @@ namespace WixToolset.Core
346
break;
347
#endif
348
362
- case TupleDefinitionType.PublishComponent:
363
- if (SectionType.Product == resolvedSection.Type)
364
- {
365
- this.ResolveFeatures(tuple, 2, 4, componentsToFeatures, multipleFeatureComponents);
366
- }
367
- break;
349
+ case TupleDefinitionType.PublishComponent:
350
+ if (SectionType.Product == resolvedSection.Type)
351
+ {
352
+ this.ResolveFeatures(tuple, 2, 4, componentsToFeatures, multipleFeatureComponents);
353
+ }
354
+ break;
355
369
- case TupleDefinitionType.Shortcut:
370
- if (SectionType.Product == resolvedSection.Type)
371
- {
372
- this.ResolveFeatures(tuple, 3, 4, componentsToFeatures, multipleFeatureComponents);
373
- }
374
- break;
356
+ case TupleDefinitionType.Shortcut:
357
+ if (SectionType.Product == resolvedSection.Type)
358
+ {
359
+ this.ResolveFeatures(tuple, 3, 4, componentsToFeatures, multipleFeatureComponents);
360
+ }
361
+ break;
362
376
- case TupleDefinitionType.TypeLib:
377
- if (SectionType.Product == resolvedSection.Type)
378
- {
379
- this.ResolveFeatures(tuple, 2, 6, componentsToFeatures, multipleFeatureComponents);
380
- }
381
- break;
363
+ case TupleDefinitionType.TypeLib:
364
+ if (SectionType.Product == resolvedSection.Type)
365
+ {
366
+ this.ResolveFeatures(tuple, 2, 6, componentsToFeatures, multipleFeatureComponents);
367
+ }
368
+ break;
369
370
#if SOLVE_CUSTOM_TABLE
371
case "WixCustomTable":
@@ -396,9 +383,9 @@ namespace WixToolset.Core
383
break;
384
#endif
385
399
- case TupleDefinitionType.WixEnsureTable:
400
- ensureTableRows.Add(tuple);
401
- break;
386
+ case TupleDefinitionType.WixEnsureTable:
387
+ ensureTableRows.Add(tuple);
388
+ break;
389
390
391
#if MOVE_TO_BACKEND
@@ -421,45 +408,45 @@ namespace WixToolset.Core
408
break;
409
#endif
410
424
- case TupleDefinitionType.WixMerge:
425
- if (SectionType.Product == resolvedSection.Type)
426
- {
427
- this.ResolveFeatures(tuple, 0, 7, modulesToFeatures, null);
428
- }
429
- break;
411
+ case TupleDefinitionType.WixMerge:
412
+ if (SectionType.Product == resolvedSection.Type)
413
+ {
414
+ this.ResolveFeatures(tuple, 0, 7, modulesToFeatures, null);
415
+ }
416
+ break;
417
431
- case TupleDefinitionType.WixComplexReference:
432
- copyTuple = false;
433
- break;
418
+ case TupleDefinitionType.WixComplexReference:
419
+ copyTuple = false;
420
+ break;
421
435
- case TupleDefinitionType.WixSimpleReference:
436
- copyTuple = false;
437
- break;
422
+ case TupleDefinitionType.WixSimpleReference:
423
+ copyTuple = false;
424
+ break;
425
439
- case TupleDefinitionType.WixVariable:
440
- // check for colliding values and collect the wix variable rows
441
- {
442
- var row = (WixVariableTuple)tuple;
426
+ case TupleDefinitionType.WixVariable:
427
+ // check for colliding values and collect the wix variable rows
428
+ {
429
+ var row = (WixVariableTuple)tuple;
430
444
- if (wixVariables.TryGetValue(row.WixVariable, out var collidingRow))
445
- {
446
- if (collidingRow.Overridable && !row.Overridable)
447
- {
448
- wixVariables[row.WixVariable] = row;
449
- }
450
- else if (!row.Overridable || (collidingRow.Overridable && row.Overridable))
451
- {
452
- this.OnMessage(ErrorMessages.WixVariableCollision(row.SourceLineNumbers, row.WixVariable));
453
- }
454
- }
455
- else
456
- {
457
- wixVariables.Add(row.WixVariable, row);
458
- }
431
+ if (wixVariables.TryGetValue(row.WixVariable, out var collidingRow))
432
+ {
433
+ if (collidingRow.Overridable && !row.Overridable)
434
+ {
435
+ wixVariables[row.WixVariable] = row;
436
+ }
437
+ else if (!row.Overridable || (collidingRow.Overridable && row.Overridable))
438
+ {
439
+ this.OnMessage(ErrorMessages.WixVariableCollision(row.SourceLineNumbers, row.WixVariable));
440
}
441
+ }
442
+ else
443
+ {
444
+ wixVariables.Add(row.WixVariable, row);
445
+ }
446
+ }
447
461
- copyTuple = false;
462
- break;
448
+ copyTuple = false;
449
+ break;
450
}
451
452
if (copyTuple)
@@ -624,7 +611,7 @@ namespace WixToolset.Core
611
#endif
612
613
//correct the section Id in FeatureComponents table
627
- if (this.sectionIdOnRows)
614
+ if (sectionIdOnRows)
615
{
616
//var componentSectionIds = new Dictionary<string, string>();
617
@@ -1152,7 +1139,7 @@ namespace WixToolset.Core
1139
/// <param name="modulesToFeatures">Module to feature complex references.</param>
1140
private void ProcessComplexReferences(IntermediateSection resolvedSection, IEnumerable<IntermediateSection> sections, ISet<string> referencedComponents, ConnectToFeatureCollection componentsToFeatures, ConnectToFeatureCollection featuresToFeatures, ConnectToFeatureCollection modulesToFeatures)
1141
{
1155
- Hashtable componentsToModules = new Hashtable();
1142
+ var componentsToModules = new Hashtable();
1143
1144
foreach (var section in sections)
1145
{
@@ -1163,154 +1150,154 @@ namespace WixToolset.Core
1150
ConnectToFeature connection;
1151
switch (wixComplexReferenceRow.ParentType)
1152
{
1166
- case ComplexReferenceParentType.Feature:
1167
- switch (wixComplexReferenceRow.ChildType)
1153
+ case ComplexReferenceParentType.Feature:
1154
+ switch (wixComplexReferenceRow.ChildType)
1155
+ {
1156
+ case ComplexReferenceChildType.Component:
1157
+ connection = componentsToFeatures[wixComplexReferenceRow.Child];
1158
+ if (null == connection)
1159
{
1169
- case ComplexReferenceChildType.Component:
1170
- connection = componentsToFeatures[wixComplexReferenceRow.Child];
1171
- if (null == connection)
1172
- {
1173
- componentsToFeatures.Add(new ConnectToFeature(section, wixComplexReferenceRow.Child, wixComplexReferenceRow.Parent, wixComplexReferenceRow.IsPrimary));
1174
- }
1175
- else if (wixComplexReferenceRow.IsPrimary)
1176
- {
1177
- if (connection.IsExplicitPrimaryFeature)
1178
- {
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));
1180
- continue;
1181
- }
1182
- else
1183
- {
1184
- connection.ConnectFeatures.Add(connection.PrimaryFeature); // move the guessed primary feature to the list of connects
1185
- connection.PrimaryFeature = wixComplexReferenceRow.Parent; // set the new primary feature
1186
- connection.IsExplicitPrimaryFeature = true; // and make sure we remember that we set it so we can fail if we try to set it again
1187
- }
1188
- }
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;
1160
+ componentsToFeatures.Add(new ConnectToFeature(section, wixComplexReferenceRow.Child, wixComplexReferenceRow.Parent, wixComplexReferenceRow.IsPrimary));
1161
+ }
1162
+ else if (wixComplexReferenceRow.IsPrimary)
1163
+ {
1164
+ if (connection.IsExplicitPrimaryFeature)
1165
+ {
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));
1167
+ continue;
1168
+ }
1169
+ else
1170
+ {
1171
+ connection.ConnectFeatures.Add(connection.PrimaryFeature); // move the guessed primary feature to the list of connects
1172
+ connection.PrimaryFeature = wixComplexReferenceRow.Parent; // set the new primary feature
1173
+ connection.IsExplicitPrimaryFeature = true; // and make sure we remember that we set it so we can fail if we try to set it again
1174
+ }
1175
+ }
1176
+ else
1177
+ {
1178
+ connection.ConnectFeatures.Add(wixComplexReferenceRow.Parent);
1179
+ }
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;
1185
1201
- // index the component for finding orphaned records
1202
- var symbolName = String.Concat("Component:", wixComplexReferenceRow.Child);
1203
- referencedComponents.Add(symbolName);
1186
+ featureComponents.Add(featureComponent);
1187
1205
- break;
1188
+ // index the component for finding orphaned records
1189
+ var symbolName = String.Concat("Component:", wixComplexReferenceRow.Child);
1190
+ referencedComponents.Add(symbolName);
1191
1207
- case ComplexReferenceChildType.Feature:
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
- }
1192
+ break;
1193
1215
- featuresToFeatures.Add(new ConnectToFeature(section, wixComplexReferenceRow.Child, wixComplexReferenceRow.Parent, wixComplexReferenceRow.IsPrimary));
1216
- break;
1194
+ case ComplexReferenceChildType.Feature:
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
+ }
1201
1218
- case ComplexReferenceChildType.Module:
1219
- connection = modulesToFeatures[wixComplexReferenceRow.Child];
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;
1202
+ featuresToFeatures.Add(new ConnectToFeature(section, wixComplexReferenceRow.Child, wixComplexReferenceRow.Parent, wixComplexReferenceRow.IsPrimary));
1203
+ break;
1204
1244
- default:
1245
- throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceChildType), wixComplexReferenceRow.ChildType)));
1205
+ case ComplexReferenceChildType.Module:
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);
1228
}
1229
break;
1230
1249
- case ComplexReferenceParentType.Module:
1250
- switch (wixComplexReferenceRow.ChildType)
1251
- {
1252
- case ComplexReferenceChildType.Component:
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
1231
+ default:
1232
+ throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceChildType), wixComplexReferenceRow.ChildType)));
1233
+ }
1234
+ break;
1235
1262
- // add a row to the ModuleComponents table
1263
- var moduleComponent = new ModuleComponentsTuple();
1264
- moduleComponent.Component = wixComplexReferenceRow.Child;
1265
- moduleComponent.ModuleID = wixComplexReferenceRow.Parent;
1266
- moduleComponent.Language = Convert.ToInt32(wixComplexReferenceRow.ParentLanguage);
1267
- }
1236
+ case ComplexReferenceParentType.Module:
1237
+ switch (wixComplexReferenceRow.ChildType)
1238
+ {
1239
+ case ComplexReferenceChildType.Component:
1240
+ if (componentsToModules.ContainsKey(wixComplexReferenceRow.Child))
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
1248
1269
- // index the component for finding orphaned records
1270
- string componentSymbolName = String.Concat("Component:", wixComplexReferenceRow.Child);
1271
- referencedComponents.Add(componentSymbolName);
1249
+ // add a row to the ModuleComponents table
1250
+ var moduleComponent = new ModuleComponentsTuple();
1251
+ moduleComponent.Component = wixComplexReferenceRow.Child;
1252
+ moduleComponent.ModuleID = wixComplexReferenceRow.Parent;
1253
+ moduleComponent.Language = Convert.ToInt32(wixComplexReferenceRow.ParentLanguage);
1254
+ }
1255
1273
- break;
1256
+ // index the component for finding orphaned records
1257
+ var componentSymbolName = String.Concat("Component:", wixComplexReferenceRow.Child);
1258
+ referencedComponents.Add(componentSymbolName);
1259
1275
- default:
1276
- throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceChildType), wixComplexReferenceRow.ChildType)));
1277
- }
1260
break;
1261
1280
- case ComplexReferenceParentType.Patch:
1281
- switch (wixComplexReferenceRow.ChildType)
1282
- {
1283
- case ComplexReferenceChildType.PatchFamily:
1284
- case ComplexReferenceChildType.PatchFamilyGroup:
1285
- break;
1262
+ default:
1263
+ throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceChildType), wixComplexReferenceRow.ChildType)));
1264
+ }
1265
+ break;
1266
1287
- default:
1288
- throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceChildType), wixComplexReferenceRow.ChildType)));
1289
- }
1267
+ case ComplexReferenceParentType.Patch:
1268
+ switch (wixComplexReferenceRow.ChildType)
1269
+ {
1270
+ case ComplexReferenceChildType.PatchFamily:
1271
+ case ComplexReferenceChildType.PatchFamilyGroup:
1272
break;
1273
1292
- case ComplexReferenceParentType.Product:
1293
- switch (wixComplexReferenceRow.ChildType)
1294
- {
1295
- case ComplexReferenceChildType.Feature:
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;
1274
+ default:
1275
+ throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceChildType), wixComplexReferenceRow.ChildType)));
1276
+ }
1277
+ break;
1278
1306
- default:
1307
- throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceChildType), wixComplexReferenceRow.ChildType)));
1279
+ case ComplexReferenceParentType.Product:
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;
1288
}
1289
+
1290
+ featuresToFeatures.Add(new ConnectToFeature(section, wixComplexReferenceRow.Child, null, wixComplexReferenceRow.IsPrimary));
1291
break;
1292
1293
default:
1312
- // Note: Groups have been processed before getting here so they are not handled by any case above.
1313
- throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceParentType), wixComplexReferenceRow.ParentType)));
1294
+ throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_UnexpectedComplexReferenceChildType, Enum.GetName(typeof(ComplexReferenceChildType), wixComplexReferenceRow.ChildType)));
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)));
1301
}
1302
}
1303
@@ -1341,7 +1328,7 @@ namespace WixToolset.Core
1328
foreach (var section in sections)
1329
{
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)
1332
{
1333
// Only process the "grouping parents" such as FeatureGroup, ComponentGroup, Feature,
1334
// and Module. Non-grouping complex references are simple and
@@ -1354,7 +1341,7 @@ namespace WixToolset.Core
1341
ComplexReferenceParentType.PatchFamilyGroup == wixComplexReferenceRow.ParentType ||
1342
ComplexReferenceParentType.Product == wixComplexReferenceRow.ParentType))
1343
{
1357
- var parentTypeAndId = CombineTypeAndId(wixComplexReferenceRow.ParentType, wixComplexReferenceRow.Parent);
1344
+ var parentTypeAndId = this.CombineTypeAndId(wixComplexReferenceRow.ParentType, wixComplexReferenceRow.Parent);
1345
1346
// Group all complex references with a common parent
1347
// together so we can find them quickly while processing in
@@ -1402,7 +1389,7 @@ namespace WixToolset.Core
1389
// complex references should all be flattened.
1390
var keys = parentGroupsNeedingProcessing.Keys.ToList();
1391
1405
- foreach (string key in keys)
1392
+ foreach (var key in keys)
1393
{
1394
if (parentGroupsNeedingProcessing.ContainsKey(key))
1395
{
@@ -1466,14 +1453,14 @@ namespace WixToolset.Core
1453
foreach (var wixComplexReferenceRow in referencesToParent)
1454
{
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));
1457
1458
// We are only interested processing when the child is a group.
1459
if ((ComplexReferenceChildType.ComponentGroup == wixComplexReferenceRow.ChildType) ||
1460
(ComplexReferenceChildType.FeatureGroup == wixComplexReferenceRow.ChildType) ||
1461
(ComplexReferenceChildType.PatchFamilyGroup == wixComplexReferenceRow.ChildType))
1462
{
1476
- string childTypeAndId = CombineTypeAndId(wixComplexReferenceRow.ChildType, wixComplexReferenceRow.Child);
1463
+ var childTypeAndId = this.CombineTypeAndId(wixComplexReferenceRow.ChildType, wixComplexReferenceRow.Child);
1464
if (loopDetector.Contains(childTypeAndId))
1465
{
1466
// Create a comma delimited list of the references that participate in the
@@ -1531,7 +1518,7 @@ namespace WixToolset.Core
1518
// duplicate complex references that occurred during the merge.
1519
referencesToParent.AddRange(allNewChildComplexReferences);
1520
referencesToParent.Sort(ComplexReferenceComparision);
1534
- for (int i = referencesToParent.Count - 1; i >= 0; --i)
1521
+ for (var i = referencesToParent.Count - 1; i >= 0; --i)
1522
{
1523
var wixComplexReferenceRow = referencesToParent[i];
1524
@@ -1716,7 +1703,7 @@ namespace WixToolset.Core
1703
1704
if (emptyGuid == featureId)
1705
{
1719
- ConnectToFeature connection = connectToFeatures[connectionId];
1706
+ var connection = connectToFeatures[connectionId];
1707
1708
if (null == connection)
1709
{
src/WixToolset.Core/PreprocessContext.cs
+2
-2
@@ -21,9 +21,9 @@ namespace WixToolset.Core
21
22
public Platform Platform { get; set; }
23
24
- public IList<string> IncludeSearchPaths { get; set; }
24
+ public IEnumerable<string> IncludeSearchPaths { get; set; }
25
26
- public string SourceFile { get; set; }
26
+ public string SourcePath { get; set; }
27
28
public IDictionary<string, string> Variables { get; set; }
29
src/WixToolset.Core/Preprocessor.cs
+287
-310
@@ -6,7 +6,6 @@ namespace WixToolset.Core
6
using System.Collections.Generic;
7
using System.Globalization;
8
using System.IO;
9
- using System.Linq;
9
using System.Text;
10
using System.Text.RegularExpressions;
11
using System.Xml;
@@ -20,7 +19,7 @@ namespace WixToolset.Core
19
/// <summary>
20
/// Preprocessor object
21
/// </summary>
23
- internal class Preprocessor
22
+ internal class Preprocessor : IPreprocessor
23
{
24
private static readonly Regex DefineRegex = new Regex(@"^\s*(?<varName>.+?)\s*(=\s*(?<varValue>.+?)\s*)?$", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.ExplicitCapture);
25
private static readonly Regex PragmaRegex = new Regex(@"^\s*(?<pragmaName>.+?)(?<pragmaValue>[\s\(].+?)?$", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.ExplicitCapture);
@@ -30,6 +29,7 @@ namespace WixToolset.Core
29
ValidationFlags = System.Xml.Schema.XmlSchemaValidationFlags.None,
30
XmlResolver = null,
31
};
32
+
33
private static readonly XmlReaderSettings FragmentXmlReaderSettings = new XmlReaderSettings()
34
{
35
ConformanceLevel = ConformanceLevel.Fragment,
@@ -44,14 +44,6 @@ namespace WixToolset.Core
44
this.Messaging = this.ServiceProvider.GetService<IMessaging>();
45
}
46
47
- public IEnumerable<string> IncludeSearchPaths { get; set; }
48
-
49
- public Platform Platform { get; set; }
50
-
51
- public string SourcePath { get; set; }
52
-
53
- public IDictionary<string, string> Variables { get; set; }
54
-
47
private IServiceProvider ServiceProvider { get; }
48
49
private IMessaging Messaging { get; }
@@ -108,19 +100,21 @@ namespace WixToolset.Core
100
/// </summary>
101
/// <param name="context">The preprocessing context.</param>
102
/// <returns>XDocument with the postprocessed data.</returns>
111
- public XDocument Execute()
103
+ public XDocument Preprocess(IPreprocessContext context)
104
{
113
- this.Context = this.CreateContext();
105
+ this.Context = context;
106
+ this.Context.CurrentSourceLineNumber = new SourceLineNumber(context.SourcePath);
107
+ this.Context.Variables = this.Context.Variables == null ? new Dictionary<string, string>() : new Dictionary<string, string>(this.Context.Variables);
108
109
this.PreProcess();
110
111
XDocument document;
118
- using (XmlReader reader = XmlReader.Create(this.Context.SourceFile, DocumentXmlReaderSettings))
112
+ using (var reader = XmlReader.Create(this.Context.SourcePath, DocumentXmlReaderSettings))
113
{
114
document = this.Process(reader);
115
}
116
123
- return PostProcess(document);
117
+ return this.PostProcess(document);
118
}
119
120
/// <summary>
@@ -129,21 +123,23 @@ namespace WixToolset.Core
123
/// <param name="context">The preprocessing context.</param>
124
/// <param name="reader">XmlReader to processing the context.</param>
125
/// <returns>XDocument with the postprocessed data.</returns>
132
- public XDocument Execute(XmlReader reader)
126
+ public XDocument Preprocess(IPreprocessContext context, XmlReader reader)
127
{
134
- if (String.IsNullOrEmpty(this.SourcePath) && !String.IsNullOrEmpty(reader.BaseURI))
128
+ if (String.IsNullOrEmpty(context.SourcePath) && !String.IsNullOrEmpty(reader.BaseURI))
129
{
130
var uri = new Uri(reader.BaseURI);
137
- this.SourcePath = uri.AbsolutePath;
131
+ context.SourcePath = uri.AbsolutePath;
132
}
133
140
- this.Context = this.CreateContext();
134
+ this.Context = context;
135
+ this.Context.CurrentSourceLineNumber = new SourceLineNumber(context.SourcePath);
136
+ this.Context.Variables = this.Context.Variables == null ? new Dictionary<string, string>() : new Dictionary<string, string>(this.Context.Variables);
137
138
this.PreProcess();
139
140
var document = this.Process(reader);
141
146
- return PostProcess(document);
142
+ return this.PostProcess(document);
143
}
144
145
/// <summary>
@@ -160,13 +156,13 @@ namespace WixToolset.Core
156
this.CurrentFileStack.Push(this.Helper.GetVariableValue(this.Context, "sys", "SOURCEFILEDIR"));
157
158
// Process the reader into the output.
163
- XDocument output = new XDocument();
159
+ var output = new XDocument();
160
try
161
{
162
this.PreprocessReader(false, reader, output, 0);
163
164
// Fire event with post-processed document.
169
- this.ProcessedStream?.Invoke(this, new ProcessedStreamEventArgs(this.Context.SourceFile, output));
165
+ this.ProcessedStream?.Invoke(this, new ProcessedStreamEventArgs(this.Context.SourcePath, output));
166
}
167
catch (XmlException e)
168
{
@@ -221,8 +217,8 @@ namespace WixToolset.Core
217
return false;
218
}
219
224
- int numQuotes = 0;
225
- int tmpIndex = 0;
220
+ var numQuotes = 0;
221
+ var tmpIndex = 0;
222
while (-1 != (tmpIndex = expression.IndexOf('\"', tmpIndex, index - tmpIndex)))
223
{
224
numQuotes++;
@@ -250,26 +246,26 @@ namespace WixToolset.Core
246
expression = expression.ToUpperInvariant();
247
switch (operation)
248
{
253
- case PreprocessorOperation.Not:
254
- if (expression.StartsWith("NOT ", StringComparison.Ordinal) || expression.StartsWith("NOT(", StringComparison.Ordinal))
255
- {
256
- return true;
257
- }
258
- break;
259
- case PreprocessorOperation.And:
260
- if (expression.StartsWith("AND ", StringComparison.Ordinal) || expression.StartsWith("AND(", StringComparison.Ordinal))
261
- {
262
- return true;
263
- }
264
- break;
265
- case PreprocessorOperation.Or:
266
- if (expression.StartsWith("OR ", StringComparison.Ordinal) || expression.StartsWith("OR(", StringComparison.Ordinal))
267
- {
268
- return true;
269
- }
270
- break;
271
- default:
272
- break;
249
+ case PreprocessorOperation.Not:
250
+ if (expression.StartsWith("NOT ", StringComparison.Ordinal) || expression.StartsWith("NOT(", StringComparison.Ordinal))
251
+ {
252
+ return true;
253
+ }
254
+ break;
255
+ case PreprocessorOperation.And:
256
+ if (expression.StartsWith("AND ", StringComparison.Ordinal) || expression.StartsWith("AND(", StringComparison.Ordinal))
257
+ {
258
+ return true;
259
+ }
260
+ break;
261
+ case PreprocessorOperation.Or:
262
+ if (expression.StartsWith("OR ", StringComparison.Ordinal) || expression.StartsWith("OR(", StringComparison.Ordinal))
263
+ {
264
+ return true;
265
+ }
266
+ break;
267
+ default:
268
+ break;
269
}
270
return false;
271
}
@@ -283,11 +279,11 @@ namespace WixToolset.Core
279
/// <param name="offset">Original offset for the line numbers being processed.</param>
280
private void PreprocessReader(bool include, XmlReader reader, XContainer container, int offset)
281
{
286
- XContainer currentContainer = container;
287
- Stack<XContainer> containerStack = new Stack<XContainer>();
282
+ var currentContainer = container;
283
+ var containerStack = new Stack<XContainer>();
284
289
- IfContext ifContext = new IfContext(true, true, IfState.Unknown); // start by assuming we want to keep the nodes in the source code
290
- Stack<IfContext> ifStack = new Stack<IfContext>();
285
+ var ifContext = new IfContext(true, true, IfState.Unknown); // start by assuming we want to keep the nodes in the source code
286
+ var ifStack = new Stack<IfContext>();
287
288
// process the reader into the writer
289
while (reader.Read())
@@ -300,102 +296,102 @@ namespace WixToolset.Core
296
// check for changes in conditional processing
297
if (XmlNodeType.ProcessingInstruction == reader.NodeType)
298
{
303
- bool ignore = false;
299
+ var ignore = false;
300
string name = null;
301
302
switch (reader.LocalName)
303
{
308
- case "if":
309
- ifStack.Push(ifContext);
310
- if (ifContext.IsTrue)
311
- {
312
- ifContext = new IfContext(ifContext.IsTrue & ifContext.Active, this.EvaluateExpression(reader.Value), IfState.If);
313
- }
314
- else // Use a default IfContext object so we don't try to evaluate the expression if the context isn't true
315
- {
316
- ifContext = new IfContext();
317
- }
318
- ignore = true;
319
- break;
304
+ case "if":
305
+ ifStack.Push(ifContext);
306
+ if (ifContext.IsTrue)
307
+ {
308
+ ifContext = new IfContext(ifContext.IsTrue & ifContext.Active, this.EvaluateExpression(reader.Value), IfState.If);
309
+ }
310
+ else // Use a default IfContext object so we don't try to evaluate the expression if the context isn't true
311
+ {
312
+ ifContext = new IfContext();
313
+ }
314
+ ignore = true;
315
+ break;
316
321
- case "ifdef":
322
- ifStack.Push(ifContext);
323
- name = reader.Value.Trim();
324
- if (ifContext.IsTrue)
325
- {
326
- ifContext = new IfContext(ifContext.IsTrue & ifContext.Active, (null != this.Helper.GetVariableValue(this.Context, name, true)), IfState.If);
327
- }
328
- else // Use a default IfContext object so we don't try to evaluate the expression if the context isn't true
329
- {
330
- ifContext = new IfContext();
331
- }
332
- ignore = true;
333
- this.IfDef?.Invoke(this, new IfDefEventArgs(sourceLineNumbers, true, ifContext.IsTrue, name));
334
- break;
317
+ case "ifdef":
318
+ ifStack.Push(ifContext);
319
+ name = reader.Value.Trim();
320
+ if (ifContext.IsTrue)
321
+ {
322
+ ifContext = new IfContext(ifContext.IsTrue & ifContext.Active, (null != this.Helper.GetVariableValue(this.Context, name, true)), IfState.If);
323
+ }
324
+ else // Use a default IfContext object so we don't try to evaluate the expression if the context isn't true
325
+ {
326
+ ifContext = new IfContext();
327
+ }
328
+ ignore = true;
329
+ this.IfDef?.Invoke(this, new IfDefEventArgs(sourceLineNumbers, true, ifContext.IsTrue, name));
330
+ break;
331
336
- case "ifndef":
337
- ifStack.Push(ifContext);
338
- name = reader.Value.Trim();
339
- if (ifContext.IsTrue)
340
- {
341
- ifContext = new IfContext(ifContext.IsTrue & ifContext.Active, (null == this.Helper.GetVariableValue(this.Context, name, true)), IfState.If);
342
- }
343
- else // Use a default IfContext object so we don't try to evaluate the expression if the context isn't true
344
- {
345
- ifContext = new IfContext();
346
- }
347
- ignore = true;
348
- this.IfDef?.Invoke(this, new IfDefEventArgs(sourceLineNumbers, false, !ifContext.IsTrue, name));
349
- break;
332
+ case "ifndef":
333
+ ifStack.Push(ifContext);
334
+ name = reader.Value.Trim();
335
+ if (ifContext.IsTrue)
336
+ {
337
+ ifContext = new IfContext(ifContext.IsTrue & ifContext.Active, (null == this.Helper.GetVariableValue(this.Context, name, true)), IfState.If);
338
+ }
339
+ else // Use a default IfContext object so we don't try to evaluate the expression if the context isn't true
340
+ {
341
+ ifContext = new IfContext();
342
+ }
343
+ ignore = true;
344
+ this.IfDef?.Invoke(this, new IfDefEventArgs(sourceLineNumbers, false, !ifContext.IsTrue, name));
345
+ break;
346
351
- case "elseif":
352
- if (0 == ifStack.Count)
353
- {
354
- throw new WixException(ErrorMessages.UnmatchedPreprocessorInstruction(sourceLineNumbers, "if", "elseif"));
355
- }
347
+ case "elseif":
348
+ if (0 == ifStack.Count)
349
+ {
350
+ throw new WixException(ErrorMessages.UnmatchedPreprocessorInstruction(sourceLineNumbers, "if", "elseif"));
351
+ }
352
357
- if (IfState.If != ifContext.IfState && IfState.ElseIf != ifContext.IfState)
358
- {
359
- throw new WixException(ErrorMessages.UnmatchedPreprocessorInstruction(sourceLineNumbers, "if", "elseif"));
360
- }
353
+ if (IfState.If != ifContext.IfState && IfState.ElseIf != ifContext.IfState)
354
+ {
355
+ throw new WixException(ErrorMessages.UnmatchedPreprocessorInstruction(sourceLineNumbers, "if", "elseif"));
356
+ }
357
362
- ifContext.IfState = IfState.ElseIf; // we're now in an elseif
363
- if (!ifContext.WasEverTrue) // if we've never evaluated the if context to true, then we can try this test
364
- {
365
- ifContext.IsTrue = this.EvaluateExpression(reader.Value);
366
- }
367
- else if (ifContext.IsTrue)
368
- {
369
- ifContext.IsTrue = false;
370
- }
371
- ignore = true;
372
- break;
358
+ ifContext.IfState = IfState.ElseIf; // we're now in an elseif
359
+ if (!ifContext.WasEverTrue) // if we've never evaluated the if context to true, then we can try this test
360
+ {
361
+ ifContext.IsTrue = this.EvaluateExpression(reader.Value);
362
+ }
363
+ else if (ifContext.IsTrue)
364
+ {
365
+ ifContext.IsTrue = false;
366
+ }
367
+ ignore = true;
368
+ break;
369
374
- case "else":
375
- if (0 == ifStack.Count)
376
- {
377
- throw new WixException(ErrorMessages.UnmatchedPreprocessorInstruction(sourceLineNumbers, "if", "else"));
378
- }
370
+ case "else":
371
+ if (0 == ifStack.Count)
372
+ {
373
+ throw new WixException(ErrorMessages.UnmatchedPreprocessorInstruction(sourceLineNumbers, "if", "else"));
374
+ }
375
380
- if (IfState.If != ifContext.IfState && IfState.ElseIf != ifContext.IfState)
381
- {
382
- throw new WixException(ErrorMessages.UnmatchedPreprocessorInstruction(sourceLineNumbers, "if", "else"));
383
- }
376
+ if (IfState.If != ifContext.IfState && IfState.ElseIf != ifContext.IfState)
377
+ {
378
+ throw new WixException(ErrorMessages.UnmatchedPreprocessorInstruction(sourceLineNumbers, "if", "else"));
379
+ }
380
385
- ifContext.IfState = IfState.Else; // we're now in an else
386
- ifContext.IsTrue = !ifContext.WasEverTrue; // if we were never true, we can be true now
387
- ignore = true;
388
- break;
381
+ ifContext.IfState = IfState.Else; // we're now in an else
382
+ ifContext.IsTrue = !ifContext.WasEverTrue; // if we were never true, we can be true now
383
+ ignore = true;
384
+ break;
385
390
- case "endif":
391
- if (0 == ifStack.Count)
392
- {
393
- throw new WixException(ErrorMessages.UnmatchedPreprocessorInstruction(sourceLineNumbers, "if", "endif"));
394
- }
386
+ case "endif":
387
+ if (0 == ifStack.Count)
388
+ {
389
+ throw new WixException(ErrorMessages.UnmatchedPreprocessorInstruction(sourceLineNumbers, "if", "endif"));
390
+ }
391
396
- ifContext = (IfContext)ifStack.Pop();
397
- ignore = true;
398
- break;
392
+ ifContext = ifStack.Pop();
393
+ ignore = true;
394
+ break;
395
}
396
397
if (ignore) // ignore this node since we just handled it above
@@ -411,134 +407,134 @@ namespace WixToolset.Core
407
408
switch (reader.NodeType)
409
{
414
- case XmlNodeType.XmlDeclaration:
415
- XDocument document = currentContainer as XDocument;
416
- if (null != document)
410
+ case XmlNodeType.XmlDeclaration:
411
+ var document = currentContainer as XDocument;
412
+ if (null != document)
413
+ {
414
+ document.Declaration = new XDeclaration(null, null, null);
415
+ while (reader.MoveToNextAttribute())
416
{
418
- document.Declaration = new XDeclaration(null, null, null);
419
- while (reader.MoveToNextAttribute())
417
+ switch (reader.LocalName)
418
{
421
- switch (reader.LocalName)
422
- {
423
- case "version":
424
- document.Declaration.Version = reader.Value;
425
- break;
426
-
427
- case "encoding":
428
- document.Declaration.Encoding = reader.Value;
429
- break;
430
-
431
- case "standalone":
432
- document.Declaration.Standalone = reader.Value;
433
- break;
434
- }
435
- }
436
-
437
- }
438
- //else
439
- //{
440
- // display an error? Can this happen?
441
- //}
442
- break;
443
-
444
- case XmlNodeType.ProcessingInstruction:
445
- switch (reader.LocalName)
446
- {
447
- case "define":
448
- this.PreprocessDefine(reader.Value);
449
- break;
450
-
451
- case "error":
452
- this.PreprocessError(reader.Value);
453
- break;
454
-
455
- case "warning":
456
- this.PreprocessWarning(reader.Value);
419
+ case "version":
420
+ document.Declaration.Version = reader.Value;
421
break;
422
459
- case "undef":
460
- this.PreprocessUndef(reader.Value);
423
+ case "encoding":
424
+ document.Declaration.Encoding = reader.Value;
425
break;
426
463
- case "include":
464
- this.UpdateCurrentLineNumber(reader, offset);
465
- this.PreprocessInclude(reader.Value, currentContainer);
427
+ case "standalone":
428
+ document.Declaration.Standalone = reader.Value;
429
break;
430
+ }
431
+ }
432
468
- case "foreach":
469
- this.PreprocessForeach(reader, currentContainer, offset);
470
- break;
471
-
472
- case "endforeach": // endforeach is handled in PreprocessForeach, so seeing it here is an error
473
- throw new WixException(ErrorMessages.UnmatchedPreprocessorInstruction(sourceLineNumbers, "foreach", "endforeach"));
474
-
475
- case "pragma":
476
- this.PreprocessPragma(reader.Value, currentContainer);
477
- break;
433
+ }
434
+ //else
435
+ //{
436
+ // display an error? Can this happen?
437
+ //}
438
+ break;
439
479
- default:
480
- // unknown processing instructions are currently ignored
481
- break;
482
- }
440
+ case XmlNodeType.ProcessingInstruction:
441
+ switch (reader.LocalName)
442
+ {
443
+ case "define":
444
+ this.PreprocessDefine(reader.Value);
445
break;
446
485
- case XmlNodeType.Element:
486
- if (0 < this.IncludeNextStack.Count && this.IncludeNextStack.Peek())
487
- {
488
- if ("Include" != reader.LocalName)
489
- {
490
- this.Messaging.Write(ErrorMessages.InvalidDocumentElement(sourceLineNumbers, reader.Name, "include", "Include"));
491
- }
447
+ case "error":
448
+ this.PreprocessError(reader.Value);
449
+ break;
450
493
- this.IncludeNextStack.Pop();
494
- this.IncludeNextStack.Push(false);
495
- break;
496
- }
451
+ case "warning":
452
+ this.PreprocessWarning(reader.Value);
453
+ break;
454
498
- var empty = reader.IsEmptyElement;
499
- var ns = XNamespace.Get(reader.NamespaceURI);
500
- var element = new XElement(ns + reader.LocalName);
501
- currentContainer.Add(element);
455
+ case "undef":
456
+ this.PreprocessUndef(reader.Value);
457
+ break;
458
459
+ case "include":
460
this.UpdateCurrentLineNumber(reader, offset);
504
- element.AddAnnotation(sourceLineNumbers);
461
+ this.PreprocessInclude(reader.Value, currentContainer);
462
+ break;
463
506
- while (reader.MoveToNextAttribute())
507
- {
508
- var value = this.Helper.PreprocessString(this.Context, reader.Value);
464
+ case "foreach":
465
+ this.PreprocessForeach(reader, currentContainer, offset);
466
+ break;
467
510
- var attribNamespace = XNamespace.Get(reader.NamespaceURI);
511
- attribNamespace = XNamespace.Xmlns == attribNamespace && reader.LocalName.Equals("xmlns") ? XNamespace.None : attribNamespace;
468
+ case "endforeach": // endforeach is handled in PreprocessForeach, so seeing it here is an error
469
+ throw new WixException(ErrorMessages.UnmatchedPreprocessorInstruction(sourceLineNumbers, "foreach", "endforeach"));
470
513
- element.Add(new XAttribute(attribNamespace + reader.LocalName, value));
514
- }
471
+ case "pragma":
472
+ this.PreprocessPragma(reader.Value, currentContainer);
473
+ break;
474
516
- if (!empty)
517
- {
518
- containerStack.Push(currentContainer);
519
- currentContainer = element;
520
- }
475
+ default:
476
+ // unknown processing instructions are currently ignored
477
break;
478
+ }
479
+ break;
480
523
- case XmlNodeType.EndElement:
524
- if (0 < reader.Depth || !include)
481
+ case XmlNodeType.Element:
482
+ if (0 < this.IncludeNextStack.Count && this.IncludeNextStack.Peek())
483
+ {
484
+ if ("Include" != reader.LocalName)
485
{
526
- currentContainer = containerStack.Pop();
486
+ this.Messaging.Write(ErrorMessages.InvalidDocumentElement(sourceLineNumbers, reader.Name, "include", "Include"));
487
}
528
- break;
488
530
- case XmlNodeType.Text:
531
- string postprocessedText = this.Helper.PreprocessString(this.Context, reader.Value);
532
- currentContainer.Add(postprocessedText);
489
+ this.IncludeNextStack.Pop();
490
+ this.IncludeNextStack.Push(false);
491
break;
492
+ }
493
535
- case XmlNodeType.CDATA:
536
- string postprocessedValue = this.Helper.PreprocessString(this.Context, reader.Value);
537
- currentContainer.Add(new XCData(postprocessedValue));
538
- break;
494
+ var empty = reader.IsEmptyElement;
495
+ var ns = XNamespace.Get(reader.NamespaceURI);
496
+ var element = new XElement(ns + reader.LocalName);
497
+ currentContainer.Add(element);
498
540
- default:
541
- break;
499
+ this.UpdateCurrentLineNumber(reader, offset);
500
+ element.AddAnnotation(sourceLineNumbers);
501
+
502
+ while (reader.MoveToNextAttribute())
503
+ {
504
+ var value = this.Helper.PreprocessString(this.Context, reader.Value);
505
+
506
+ var attribNamespace = XNamespace.Get(reader.NamespaceURI);
507
+ attribNamespace = XNamespace.Xmlns == attribNamespace && reader.LocalName.Equals("xmlns") ? XNamespace.None : attribNamespace;
508
+
509
+ element.Add(new XAttribute(attribNamespace + reader.LocalName, value));
510
+ }
511
+
512
+ if (!empty)
513
+ {
514
+ containerStack.Push(currentContainer);
515
+ currentContainer = element;
516
+ }
517
+ break;
518
+
519
+ case XmlNodeType.EndElement:
520
+ if (0 < reader.Depth || !include)
521
+ {
522
+ currentContainer = containerStack.Pop();
523
+ }
524
+ break;
525
+
526
+ case XmlNodeType.Text:
527
+ var postprocessedText = this.Helper.PreprocessString(this.Context, reader.Value);
528
+ currentContainer.Add(postprocessedText);
529
+ break;
530
+
531
+ case XmlNodeType.CDATA:
532
+ var postprocessedValue = this.Helper.PreprocessString(this.Context, reader.Value);
533
+ currentContainer.Add(new XCData(postprocessedValue));
534
+ break;
535
+
536
+ default:
537
+ break;
538
}
539
}
540
@@ -652,7 +648,7 @@ namespace WixToolset.Core
648
throw new WixException(ErrorMessages.FileNotFound(sourceLineNumbers, includePath, "include"));
649
}
650
655
- using (XmlReader reader = XmlReader.Create(includeFile, DocumentXmlReaderSettings))
651
+ using (var reader = XmlReader.Create(includeFile, DocumentXmlReaderSettings))
652
{
653
this.PushInclude(includeFile);
654
@@ -689,13 +685,13 @@ namespace WixToolset.Core
685
}
686
687
// parse out the variable name
692
- string varName = reader.Value.Substring(0, indexOfInToken).Trim();
693
- string varValuesString = reader.Value.Substring(indexOfInToken + 4).Trim();
688
+ var varName = reader.Value.Substring(0, indexOfInToken).Trim();
689
+ var varValuesString = reader.Value.Substring(indexOfInToken + 4).Trim();
690
691
// preprocess the variable values string because it might be a variable itself
692
varValuesString = this.Helper.PreprocessString(this.Context, varValuesString);
693
698
- string[] varValues = varValuesString.Split(';');
694
+ var varValues = varValuesString.Split(';');
695
696
// go through all the empty strings
697
while (reader.Read() && XmlNodeType.Whitespace == reader.NodeType)
@@ -703,44 +699,44 @@ namespace WixToolset.Core
699
}
700
701
// get the offset of this xml fragment (for some reason its always off by 1)
706
- IXmlLineInfo lineInfoReader = reader as IXmlLineInfo;
702
+ var lineInfoReader = reader as IXmlLineInfo;
703
if (null != lineInfoReader)
704
{
705
offset += lineInfoReader.LineNumber - 1;
706
}
707
712
- XmlTextReader textReader = reader as XmlTextReader;
708
+ var textReader = reader as XmlTextReader;
709
// dump the xml to a string (maintaining whitespace if possible)
710
if (null != textReader)
711
{
712
textReader.WhitespaceHandling = WhitespaceHandling.All;
713
}
714
719
- StringBuilder fragmentBuilder = new StringBuilder();
720
- int nestedForeachCount = 1;
715
+ var fragmentBuilder = new StringBuilder();
716
+ var nestedForeachCount = 1;
717
while (nestedForeachCount != 0)
718
{
719
if (reader.NodeType == XmlNodeType.ProcessingInstruction)
720
{
721
switch (reader.LocalName)
722
{
727
- case "foreach":
728
- ++nestedForeachCount;
729
- // Output the foreach statement
730
- fragmentBuilder.AppendFormat("<?foreach {0}?>", reader.Value);
731
- break;
723
+ case "foreach":
724
+ ++nestedForeachCount;
725
+ // Output the foreach statement
726
+ fragmentBuilder.AppendFormat("<?foreach {0}?>", reader.Value);
727
+ break;
728
733
- case "endforeach":
734
- --nestedForeachCount;
735
- if (0 != nestedForeachCount)
736
- {
737
- fragmentBuilder.Append("<?endforeach ?>");
738
- }
739
- break;
729
+ case "endforeach":
730
+ --nestedForeachCount;
731
+ if (0 != nestedForeachCount)
732
+ {
733
+ fragmentBuilder.Append("<?endforeach ?>");
734
+ }
735
+ break;
736
741
- default:
742
- fragmentBuilder.AppendFormat("<?{0} {1}?>", reader.LocalName, reader.Value);
743
- break;
737
+ default:
738
+ fragmentBuilder.AppendFormat("<?{0} {1}?>", reader.LocalName, reader.Value);
739
+ break;
740
}
741
}
742
else if (reader.NodeType == XmlNodeType.Element)
@@ -764,7 +760,7 @@ namespace WixToolset.Core
760
using (var fragmentStream = new MemoryStream(Encoding.UTF8.GetBytes(fragmentBuilder.ToString())))
761
{
762
// process each iteration, updating the variable's value each time
767
- foreach (string varValue in varValues)
763
+ foreach (var varValue in varValues)
764
{
765
using (var loopReader = XmlReader.Create(fragmentStream, FragmentXmlReaderSettings))
766
{
@@ -801,7 +797,7 @@ namespace WixToolset.Core
797
}
798
799
// resolve other variables in the pragma argument(s)
804
- string pragmaArgs = this.Helper.PreprocessString(this.Context, match.Groups["pragmaValue"].Value).Trim();
800
+ var pragmaArgs = this.Helper.PreprocessString(this.Context, match.Groups["pragmaValue"].Value).Trim();
801
802
try
803
{
@@ -823,7 +819,7 @@ namespace WixToolset.Core
819
private string GetNextToken(string originalExpression, ref string expression, out bool stringLiteral)
820
{
821
stringLiteral = false;
826
- string token = String.Empty;
822
+ var token = String.Empty;
823
expression = expression.Trim();
824
if (0 == expression.Length)
825
{
@@ -833,7 +829,7 @@ namespace WixToolset.Core
829
if (expression.StartsWith("\"", StringComparison.Ordinal))
830
{
831
stringLiteral = true;
836
- int endingQuotes = expression.IndexOf('\"', 1);
832
+ var endingQuotes = expression.IndexOf('\"', 1);
833
if (-1 == endingQuotes)
834
{
835
throw new WixException(ErrorMessages.UnmatchedQuotesInExpression(this.Context.CurrentSourceLineNumber, originalExpression));
@@ -848,9 +844,9 @@ namespace WixToolset.Core
844
else if (expression.StartsWith("$(", StringComparison.Ordinal))
845
{
846
// Find the ending paren of the expression
851
- int endingParen = -1;
852
- int openedCount = 1;
853
- for (int i = 2; i < expression.Length; i++)
847
+ var endingParen = -1;
848
+ var openedCount = 1;
849
+ for (var i = 2; i < expression.Length; i++)
850
{
851
if ('(' == expression[i])
852
{
@@ -881,14 +877,14 @@ namespace WixToolset.Core
877
{
878
// Cut the token off at the next equal, space, inequality operator,
879
// or end of string, whichever comes first
884
- int space = expression.IndexOf(" ", StringComparison.Ordinal);
885
- int equals = expression.IndexOf("=", StringComparison.Ordinal);
886
- int lessThan = expression.IndexOf("<", StringComparison.Ordinal);
887
- int lessThanEquals = expression.IndexOf("<=", StringComparison.Ordinal);
888
- int greaterThan = expression.IndexOf(">", StringComparison.Ordinal);
889
- int greaterThanEquals = expression.IndexOf(">=", StringComparison.Ordinal);
890
- int notEquals = expression.IndexOf("!=", StringComparison.Ordinal);
891
- int equalsNoCase = expression.IndexOf("~=", StringComparison.Ordinal);
880
+ var space = expression.IndexOf(" ", StringComparison.Ordinal);
881
+ var equals = expression.IndexOf("=", StringComparison.Ordinal);
882
+ var lessThan = expression.IndexOf("<", StringComparison.Ordinal);
883
+ var lessThanEquals = expression.IndexOf("<=", StringComparison.Ordinal);
884
+ var greaterThan = expression.IndexOf(">", StringComparison.Ordinal);
885
+ var greaterThanEquals = expression.IndexOf(">=", StringComparison.Ordinal);
886
+ var notEquals = expression.IndexOf("!=", StringComparison.Ordinal);
887
+ var equalsNoCase = expression.IndexOf("~=", StringComparison.Ordinal);
888
int closingIndex;
889
890
if (space == -1)
@@ -970,7 +966,7 @@ namespace WixToolset.Core
966
{
967
// By default it's a literal and will only be evaluated if it
968
// matches the variable format
973
- string varValue = variable;
969
+ var varValue = variable;
970
971
if (variable.StartsWith("$(", StringComparison.Ordinal))
972
{
@@ -1008,8 +1004,7 @@ namespace WixToolset.Core
1004
/// <param name="rightValue">Right side value from expression.</param>
1005
private void GetNameValuePair(string originalExpression, ref string expression, out string leftValue, out string operation, out string rightValue)
1006
{
1011
- bool stringLiteral;
1012
- leftValue = this.GetNextToken(originalExpression, ref expression, out stringLiteral);
1007
+ leftValue = this.GetNextToken(originalExpression, ref expression, out var stringLiteral);
1008
1009
// If it wasn't a string literal, evaluate it
1010
if (!stringLiteral)
@@ -1060,14 +1055,10 @@ namespace WixToolset.Core
1055
private bool EvaluateAtomicExpression(string originalExpression, ref string expression)
1056
{
1057
// Quick test to see if the first token is a variable
1063
- bool startsWithVariable = expression.StartsWith("$(", StringComparison.Ordinal);
1064
-
1065
- string leftValue;
1066
- string rightValue;
1067
- string operation;
1068
- this.GetNameValuePair(originalExpression, ref expression, out leftValue, out operation, out rightValue);
1058
+ var startsWithVariable = expression.StartsWith("$(", StringComparison.Ordinal);
1059
+ this.GetNameValuePair(originalExpression, ref expression, out var leftValue, out var operation, out var rightValue);
1060
1070
- bool expressionValue = false;
1061
+ var expressionValue = false;
1062
1063
// If the variables don't exist, they were evaluated to null
1064
if (null == leftValue || null == rightValue)
@@ -1168,8 +1159,8 @@ namespace WixToolset.Core
1159
}
1160
1161
// search for the end of the expression with the matching paren
1171
- int openParenIndex = 0;
1172
- int closeParenIndex = 1;
1162
+ var openParenIndex = 0;
1163
+ var closeParenIndex = 1;
1164
while (openParenIndex != -1 && openParenIndex < closeParenIndex)
1165
{
1166
closeParenIndex = expression.IndexOf(')', closeParenIndex);
@@ -1214,17 +1205,17 @@ namespace WixToolset.Core
1205
{
1206
switch (operation)
1207
{
1217
- case PreprocessorOperation.And:
1218
- currentValue = currentValue && prevResult;
1219
- break;
1220
- case PreprocessorOperation.Or:
1221
- currentValue = currentValue || prevResult;
1222
- break;
1223
- case PreprocessorOperation.Not:
1224
- currentValue = !currentValue;
1225
- break;
1226
- default:
1227
- throw new WixException(ErrorMessages.UnexpectedPreprocessorOperator(this.Context.CurrentSourceLineNumber, operation.ToString()));
1208
+ case PreprocessorOperation.And:
1209
+ currentValue = currentValue && prevResult;
1210
+ break;
1211
+ case PreprocessorOperation.Or:
1212
+ currentValue = currentValue || prevResult;
1213
+ break;
1214
+ case PreprocessorOperation.Not:
1215
+ currentValue = !currentValue;
1216
+ break;
1217
+ default:
1218
+ throw new WixException(ErrorMessages.UnexpectedPreprocessorOperator(this.Context.CurrentSourceLineNumber, operation.ToString()));
1219
}
1220
}
1221
@@ -1235,7 +1226,7 @@ namespace WixToolset.Core
1226
/// <returns>Boolean result of expression.</returns>
1227
private bool EvaluateExpression(string expression)
1228
{
1238
- string tmpExpression = expression;
1229
+ var tmpExpression = expression;
1230
return this.EvaluateExpressionRecurse(expression, ref tmpExpression, PreprocessorOperation.And, true);
1231
}
1232
@@ -1269,7 +1260,7 @@ namespace WixToolset.Core
1260
/// <returns>Boolean to indicate if the expression is true or false</returns>
1261
private bool EvaluateExpressionRecurse(string originalExpression, ref string expression, PreprocessorOperation prevResultOperation, bool prevResult)
1262
{
1272
- bool expressionValue = false;
1263
+ var expressionValue = false;
1264
expression = expression.Trim();
1265
if (expression.Length == 0)
1266
{
@@ -1279,8 +1270,7 @@ namespace WixToolset.Core
1270
// If the expression starts with parenthesis, evaluate it
1271
if (expression.IndexOf('(') == 0)
1272
{
1282
- int endSubExpressionIndex;
1283
- string subExpression = this.GetParenthesisExpression(originalExpression, expression, out endSubExpressionIndex);
1273
+ var subExpression = this.GetParenthesisExpression(originalExpression, expression, out var endSubExpressionIndex);
1274
expressionValue = this.EvaluateExpressionRecurse(originalExpression, ref subExpression, PreprocessorOperation.And, true);
1275
1276
// Now get the rest of the expression that hasn't been evaluated
@@ -1337,10 +1327,10 @@ namespace WixToolset.Core
1327
/// <param name="offset">This is the artificial offset of the line numbers from the reader. Used for the foreach processing.</param>
1328
private void UpdateCurrentLineNumber(XmlReader reader, int offset)
1329
{
1340
- IXmlLineInfo lineInfoReader = reader as IXmlLineInfo;
1330
+ var lineInfoReader = reader as IXmlLineInfo;
1331
if (null != lineInfoReader)
1332
{
1343
- int newLine = lineInfoReader.LineNumber + offset;
1333
+ var newLine = lineInfoReader.LineNumber + offset;
1334
1335
if (this.Context.CurrentSourceLineNumber.LineNumber != newLine)
1336
{
@@ -1435,19 +1425,6 @@ namespace WixToolset.Core
1425
return finalIncludePath;
1426
}
1427
1438
- private IPreprocessContext CreateContext()
1439
- {
1440
- var context = this.ServiceProvider.GetService<IPreprocessContext>();
1441
- context.Extensions = this.ServiceProvider.GetService<IExtensionManager>().Create<IPreprocessorExtension>();
1442
- context.CurrentSourceLineNumber = new SourceLineNumber(this.SourcePath);
1443
- context.Platform = this.Platform;
1444
- context.IncludeSearchPaths = this.IncludeSearchPaths?.ToList() ?? new List<string>();
1445
- context.SourceFile = this.SourcePath;
1446
- context.Variables = new Dictionary<string, string>(this.Variables);
1447
-
1448
- return context;
1449
- }
1450
-
1428
private void PreProcess()
1429
{
1430
foreach (var extension in this.Context.Extensions)
src/WixToolset.Core/Resolver.cs
+7
-18
@@ -15,7 +15,7 @@ namespace WixToolset.Core
15
/// <summary>
16
/// Resolver for the WiX toolset.
17
/// </summary>
18
- internal class Resolver
18
+ internal class Resolver : IResolver
19
{
20
internal Resolver(IServiceProvider serviceProvider)
21
{
@@ -38,21 +38,10 @@ namespace WixToolset.Core
38
39
public IEnumerable<string> FilterCultures { get; set; }
40
41
- public ResolveResult Execute()
41
+ public ResolveResult Resolve(IResolveContext context)
42
{
43
- var extensionManager = this.ServiceProvider.GetService<IExtensionManager>();
44
-
45
- var context = this.ServiceProvider.GetService<IResolveContext>();
46
- context.BindPaths = this.BindPaths;
47
- context.Extensions = extensionManager.Create<IResolverExtension>();
48
- context.ExtensionData = extensionManager.Create<IExtensionData>();
49
- context.FilterCultures = this.FilterCultures;
50
- context.IntermediateFolder = this.IntermediateFolder;
51
- context.IntermediateRepresentation = this.IntermediateRepresentation;
52
- context.Localizations = this.Localizations;
53
- context.VariableResolver = new WixVariableResolver(this.Messaging);
54
-
55
- foreach (IResolverExtension extension in context.Extensions)
43
+
44
+ foreach (var extension in context.Extensions)
45
{
46
extension.PreResolve(context);
47
}
@@ -64,11 +53,11 @@ namespace WixToolset.Core
53
54
this.LocalizeUI(context);
55
67
- resolveResult = this.Resolve(context);
56
+ resolveResult = this.DoResolve(context);
57
}
58
finally
59
{
71
- foreach (IResolverExtension extension in context.Extensions)
60
+ foreach (var extension in context.Extensions)
61
{
62
extension.PostResolve(resolveResult);
63
}
@@ -77,7 +66,7 @@ namespace WixToolset.Core
66
return resolveResult;
67
}
68
80
- private ResolveResult Resolve(IResolveContext context)
69
+ private ResolveResult DoResolve(IResolveContext context)
70
{
71
var buildingPatch = context.IntermediateRepresentation.Sections.Any(s => s.Type == SectionType.Patch);
72
src/WixToolset.Core/WixToolsetServiceProvider.cs
+11
@@ -32,12 +32,23 @@ namespace WixToolset.Core
32
this.AddService<ICommandLineParser>((provider, singletons) => new CommandLineParser(provider));
33
this.AddService<IPreprocessContext>((provider, singletons) => new PreprocessContext(provider));
34
this.AddService<ICompileContext>((provider, singletons) => new CompileContext(provider));
35
+ this.AddService<ILibraryContext>((provider, singletons) => new LibraryContext(provider));
36
this.AddService<ILinkContext>((provider, singletons) => new LinkContext(provider));
37
this.AddService<IResolveContext>((provider, singletons) => new ResolveContext(provider));
38
this.AddService<IBindContext>((provider, singletons) => new BindContext(provider));
39
+ this.AddService<IDecompileContext>((provider, singletons) => new DecompileContext(provider));
40
this.AddService<ILayoutContext>((provider, singletons) => new LayoutContext(provider));
41
this.AddService<IInscribeContext>((provider, singletons) => new InscribeContext(provider));
42
43
+ this.AddService<IBinder>((provider, singletons) => new Binder(provider));
44
+ this.AddService<ICompiler>((provider, singletons) => new Compiler(provider));
45
+ this.AddService<IDecompiler>((provider, singletons) => new Decompiler(provider));
46
+ this.AddService<ILayoutCreator>((provider, singletons) => new LayoutCreator(provider));
47
+ this.AddService<IPreprocessor>((provider, singletons) => new Preprocessor(provider));
48
+ this.AddService<ILibrarian>((provider, singletons) => new Librarian(provider));
49
+ this.AddService<ILinker>((provider, singletons) => new Linker(provider));
50
+ this.AddService<IResolver>((provider, singletons) => new Resolver(provider));
51
+
52
// Internal implementations.
53
this.AddService<ILocalizer>((provider, singletons) => new Localizer(provider));
54
}