From 1d6ff8af3c423ee4622185edc986ae5caad6b122 Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Tue, 26 Dec 2017 15:11:40 -0800 Subject: Standardize creation of public objects in move towards interfaces --- src/WixToolset.BuildTasks/DoIt.cs | 1 - .../Bundles/ProcessPayloadsCommand.cs | 3 - src/WixToolset.Core/Binder.cs | 14 +-- src/WixToolset.Core/CommandLine/BuildCommand.cs | 89 ++++++-------- .../CommandLine/CommandLineParser.cs | 4 +- src/WixToolset.Core/CommandLine/CompileCommand.cs | 42 ++----- src/WixToolset.Core/Compiler.cs | 37 ++++-- .../ExtensibilityServices/PreprocessHelper.cs | 6 +- src/WixToolset.Core/Librarian.cs | 32 +++-- src/WixToolset.Core/LibraryContext.cs | 5 + src/WixToolset.Core/Linker.cs | 36 ++++-- src/WixToolset.Core/Preprocessor.cs | 136 ++++++++++++++------- src/WixToolset.Core/WixToolsetServiceProvider.cs | 128 ++++++++----------- 13 files changed, 293 insertions(+), 240 deletions(-) (limited to 'src') diff --git a/src/WixToolset.BuildTasks/DoIt.cs b/src/WixToolset.BuildTasks/DoIt.cs index aabd92b5..aa01f6ec 100644 --- a/src/WixToolset.BuildTasks/DoIt.cs +++ b/src/WixToolset.BuildTasks/DoIt.cs @@ -157,7 +157,6 @@ namespace WixToolset.BuildTasks commandLineBuilder.AppendSwitchIfNotNull("-contentsfile ", this.BindContentsFile); commandLineBuilder.AppendSwitchIfNotNull("-outputsfile ", this.BindOutputsFile); commandLineBuilder.AppendSwitchIfNotNull("-builtoutputsfile ", this.BindBuiltOutputsFile); - commandLineBuilder.AppendSwitchIfNotNull("-wixprojectfile ", this.WixProjectFile); commandLineBuilder.AppendIfTrue("-bindFiles", this.BindFiles); commandLineBuilder.AppendArrayIfNotNull("-bindPath ", this.CalculateBindPathStrings()); diff --git a/src/WixToolset.Core.Burn/Bundles/ProcessPayloadsCommand.cs b/src/WixToolset.Core.Burn/Bundles/ProcessPayloadsCommand.cs index 1d91ddf2..80f3add3 100644 --- a/src/WixToolset.Core.Burn/Bundles/ProcessPayloadsCommand.cs +++ b/src/WixToolset.Core.Burn/Bundles/ProcessPayloadsCommand.cs @@ -9,9 +9,6 @@ namespace WixToolset.Core.Burn.Bundles using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Text; - using WixToolset.Data; - using WixToolset.Data.Bind; - using WixToolset.Data.Rows; internal class ProcessPayloadsCommand { diff --git a/src/WixToolset.Core/Binder.cs b/src/WixToolset.Core/Binder.cs index c442c94d..f112a214 100644 --- a/src/WixToolset.Core/Binder.cs +++ b/src/WixToolset.Core/Binder.cs @@ -125,19 +125,19 @@ namespace WixToolset.Core { var entrySection = output.Sections.First(s => s.Type != SectionType.Fragment); - Assembly executingAssembly = Assembly.GetExecutingAssembly(); - FileVersionInfo fileVersion = FileVersionInfo.GetVersionInfo(executingAssembly.Location); + var executingAssembly = Assembly.GetExecutingAssembly(); + var fileVersion = FileVersionInfo.GetVersionInfo(executingAssembly.Location); - var buildInfoRow = new WixBuildInfoTuple(); - buildInfoRow.WixVersion = fileVersion.FileVersion; - buildInfoRow.WixOutputFile = outputFile; + var buildInfoTuple = new WixBuildInfoTuple(); + buildInfoTuple.WixVersion = fileVersion.FileVersion; + buildInfoTuple.WixOutputFile = outputFile; if (!String.IsNullOrEmpty(outputPdbPath)) { - buildInfoRow.WixPdbFile = outputPdbPath; + buildInfoTuple.WixPdbFile = outputPdbPath; } - entrySection.Tuples.Add(buildInfoRow); + entrySection.Tuples.Add(buildInfoTuple); } } } diff --git a/src/WixToolset.Core/CommandLine/BuildCommand.cs b/src/WixToolset.Core/CommandLine/BuildCommand.cs index 5653afca..b5ad0b0e 100644 --- a/src/WixToolset.Core/CommandLine/BuildCommand.cs +++ b/src/WixToolset.Core/CommandLine/BuildCommand.cs @@ -13,11 +13,11 @@ namespace WixToolset.Core.CommandLine internal class BuildCommand : ICommandLineCommand { - public BuildCommand(IServiceProvider serviceProvider, IMessaging messaging, IExtensionManager extensions, IEnumerable sources, IDictionary preprocessorVariables, IEnumerable locFiles, IEnumerable libraryFiles, string outputPath, OutputType outputType, string cabCachePath, IEnumerable cultures, bool bindFiles, IEnumerable bindPaths, string intermediateFolder, string contentsFile, string outputsFile, string builtOutputsFile) + public BuildCommand(IServiceProvider serviceProvider, IEnumerable sources, IDictionary preprocessorVariables, IEnumerable locFiles, IEnumerable libraryFiles, string outputPath, OutputType outputType, string cabCachePath, IEnumerable cultures, bool bindFiles, IEnumerable bindPaths, string intermediateFolder, string contentsFile, string outputsFile, string builtOutputsFile) { this.ServiceProvider = serviceProvider; - this.Messaging = messaging; - this.ExtensionManager = extensions; + this.Messaging = serviceProvider.GetService(); + this.ExtensionManager = serviceProvider.GetService(); this.LocFiles = locFiles; this.LibraryFiles = libraryFiles; this.PreprocessorVariables = preprocessorVariables; @@ -76,6 +76,11 @@ namespace WixToolset.Core.CommandLine { var intermediates = this.CompilePhase(); + if (this.Messaging.EncounteredError) + { + return this.Messaging.LastErrorNumber; + } + if (!intermediates.Any()) { return 1; @@ -112,35 +117,30 @@ namespace WixToolset.Core.CommandLine foreach (var sourceFile in this.SourceFiles) { - var preprocessContext = this.ServiceProvider.GetService(); - preprocessContext.Messaging = this.Messaging; - preprocessContext.Extensions = this.ExtensionManager.Create(); - preprocessContext.Platform = Platform.X86; // TODO: set this correctly - preprocessContext.IncludeSearchPaths = this.IncludeSearchPaths?.ToList() ?? new List(); - preprocessContext.SourceFile = sourceFile.SourcePath; - preprocessContext.Variables = new Dictionary(this.PreprocessorVariables); + var preprocessor = new Preprocessor(this.ServiceProvider); + preprocessor.IncludeSearchPaths = this.IncludeSearchPaths; + preprocessor.Platform = Platform.X86; // TODO: set this correctly + preprocessor.SourcePath = sourceFile.SourcePath; + preprocessor.Variables = this.PreprocessorVariables; + var document = preprocessor.Execute(); + + if (this.Messaging.EncounteredError) + { + continue; + } - var preprocessor = new Preprocessor(); - var document = preprocessor.Process(preprocessContext); + var compiler = new Compiler(this.ServiceProvider); + compiler.OutputPath = sourceFile.OutputPath; + compiler.Platform = Platform.X86; // TODO: set this correctly + compiler.SourceDocument = document; + var intermediate = compiler.Execute(); - if (!this.Messaging.EncounteredError) + if (this.Messaging.EncounteredError) { - var compileContext = this.ServiceProvider.GetService(); - compileContext.Messaging = this.Messaging; - compileContext.CompilationId = Guid.NewGuid().ToString("N"); - compileContext.Extensions = this.ExtensionManager.Create(); - compileContext.OutputPath = sourceFile.OutputPath; - compileContext.Platform = Platform.X86; // TODO: set this correctly - compileContext.Source = document; - - var compiler = new Compiler(); - var intermediate = compiler.Compile(compileContext); - - if (!this.Messaging.EncounteredError) - { - intermediates.Add(intermediate); - } + continue; } + + intermediates.Add(intermediate); } return intermediates; @@ -156,17 +156,12 @@ namespace WixToolset.Core.CommandLine return null; } - var context = new LibraryContext(); - context.Messaging = this.Messaging; - context.BindFiles = this.BindFiles; - context.BindPaths = this.BindPaths; - context.Extensions = this.ExtensionManager.Create(); - context.Localizations = localizations; - context.LibraryId = Guid.NewGuid().ToString("N"); - context.Intermediates = intermediates; - - var librarian = new Librarian(); - return librarian.Combine(context); + var librarian = new Librarian(this.ServiceProvider); + librarian.BindFiles = this.BindFiles; + librarian.BindPaths = this.BindPaths; + librarian.Intermediates = intermediates; + librarian.Localizations = localizations; + return librarian.Execute(); } private Intermediate LinkPhase(IEnumerable intermediates) @@ -180,16 +175,12 @@ namespace WixToolset.Core.CommandLine return null; } - var context = this.ServiceProvider.GetService(); - context.Messaging = this.Messaging; - context.Extensions = this.ExtensionManager.Create(); - context.ExtensionData = this.ExtensionManager.Create(); - context.ExpectedOutputType = this.OutputType; - context.Intermediates = intermediates.Union(libraries).ToList(); - context.TupleDefinitionCreator = creator; - - var linker = new Linker(); - return linker.Link(context); + var linker = new Linker(this.ServiceProvider); + linker.OutputType = this.OutputType; + linker.Intermediates = intermediates; + linker.Libraries = libraries; + linker.TupleDefinitionCreator = creator; + return linker.Execute(); } private void BindPhase(Intermediate output) diff --git a/src/WixToolset.Core/CommandLine/CommandLineParser.cs b/src/WixToolset.Core/CommandLine/CommandLineParser.cs index 0e7da42a..c5d3c03b 100644 --- a/src/WixToolset.Core/CommandLine/CommandLineParser.cs +++ b/src/WixToolset.Core/CommandLine/CommandLineParser.cs @@ -207,14 +207,14 @@ namespace WixToolset.Core.CommandLine var variables = this.GatherPreprocessorVariables(defines); var bindPathList = this.GatherBindPaths(bindPaths); var type = CalculateOutputType(outputType, outputFile); - return new BuildCommand(this.ServiceProvider, this.Messaging, this.ExtensionManager, sourceFiles, variables, locFiles, libraryFiles, outputFile, type, cabCachePath, cultures, bindFiles, bindPathList, intermediateFolder, contentsFile, outputsFile, builtOutputsFile); + return new BuildCommand(this.ServiceProvider, sourceFiles, variables, locFiles, libraryFiles, outputFile, type, cabCachePath, cultures, bindFiles, bindPathList, intermediateFolder, contentsFile, outputsFile, builtOutputsFile); } case Commands.Compile: { var sourceFiles = GatherSourceFiles(files, outputFolder); var variables = GatherPreprocessorVariables(defines); - return new CompileCommand(this.ServiceProvider, this.Messaging, this.ExtensionManager, sourceFiles, variables); + return new CompileCommand(this.ServiceProvider, sourceFiles, variables); } } diff --git a/src/WixToolset.Core/CommandLine/CompileCommand.cs b/src/WixToolset.Core/CommandLine/CompileCommand.cs index f0ff5b1a..123318f5 100644 --- a/src/WixToolset.Core/CommandLine/CompileCommand.cs +++ b/src/WixToolset.Core/CommandLine/CompileCommand.cs @@ -4,28 +4,21 @@ namespace WixToolset.Core.CommandLine { using System; using System.Collections.Generic; - using System.Linq; using WixToolset.Data; using WixToolset.Extensibility; using WixToolset.Extensibility.Services; internal class CompileCommand : ICommandLineCommand { - public CompileCommand(IServiceProvider serviceProvider, IMessaging messaging, IExtensionManager extensions, IEnumerable sources, IDictionary preprocessorVariables) + public CompileCommand(IServiceProvider serviceProvider, IEnumerable sources, IDictionary preprocessorVariables) { this.PreprocessorVariables = preprocessorVariables; this.ServiceProvider = serviceProvider; - this.Messaging = messaging; - this.ExtensionManager = extensions; this.SourceFiles = sources; } private IServiceProvider ServiceProvider { get; } - private IMessaging Messaging { get; } - - private IExtensionManager ExtensionManager { get; } - public IEnumerable IncludeSearchPaths { get; } private IEnumerable SourceFiles { get; } @@ -36,27 +29,18 @@ namespace WixToolset.Core.CommandLine { foreach (var sourceFile in this.SourceFiles) { - var preprocessContext = this.ServiceProvider.GetService(); - preprocessContext.Messaging = this.Messaging; - preprocessContext.Extensions = this.ExtensionManager.Create(); - preprocessContext.Platform = Platform.X86; // TODO: set this correctly - preprocessContext.IncludeSearchPaths = this.IncludeSearchPaths?.ToList() ?? new List(); - preprocessContext.SourceFile = sourceFile.SourcePath; - preprocessContext.Variables = new Dictionary(this.PreprocessorVariables); - - var preprocessor = new Preprocessor(); - var document = preprocessor.Process(preprocessContext); - - var compileContext = this.ServiceProvider.GetService(); - compileContext.Messaging = this.Messaging; - compileContext.CompilationId = Guid.NewGuid().ToString("N"); - compileContext.Extensions = this.ExtensionManager.Create(); - compileContext.OutputPath = sourceFile.OutputPath; - compileContext.Platform = Platform.X86; // TODO: set this correctly - compileContext.Source = document; - - var compiler = new Compiler(); - var intermediate = compiler.Compile(compileContext); + var preprocessor = new Preprocessor(this.ServiceProvider); + preprocessor.IncludeSearchPaths = this.IncludeSearchPaths; + preprocessor.Platform = Platform.X86; // TODO: set this correctly + preprocessor.SourcePath = sourceFile.SourcePath; + preprocessor.Variables = new Dictionary(this.PreprocessorVariables); + var document = preprocessor.Execute(); + + var compiler = new Compiler(this.ServiceProvider); + compiler.OutputPath = sourceFile.OutputPath; + compiler.Platform = Platform.X86; // TODO: set this correctly + compiler.SourceDocument = document; + var intermediate = compiler.Execute(); intermediate.Save(sourceFile.OutputPath); } diff --git a/src/WixToolset.Core/Compiler.cs b/src/WixToolset.Core/Compiler.cs index 2dd7da4d..587c24fe 100644 --- a/src/WixToolset.Core/Compiler.cs +++ b/src/WixToolset.Core/Compiler.cs @@ -68,10 +68,25 @@ namespace WixToolset.Core Icon, } + public Compiler(IServiceProvider serviceProvider) + { + this.ServiceProvider = serviceProvider; + } + + private IServiceProvider ServiceProvider { get; } + private ICompileContext Context { get; set; } private CompilerCore Core { get; set; } + public string CompliationId { get; set; } + + public string OutputPath { get; set; } + + public Platform Platform { get; set; } + + public XDocument SourceDocument { get; set; } + /// /// Gets or sets the platform which the compiler will use when defaulting 64-bit attributes and elements. /// @@ -87,17 +102,21 @@ namespace WixToolset.Core /// /// Compiles the provided Xml document into an intermediate object /// - /// Context for the compile. The BaseURI property - /// should be properly set to get messages containing source line information. /// Intermediate object representing compiled source document. /// This method is not thread-safe. - public Intermediate Compile(ICompileContext context) + public Intermediate Execute() { - this.Context = context ?? throw new ArgumentNullException(nameof(context)); + this.Context = this.ServiceProvider.GetService(); + this.Context.Messaging = this.ServiceProvider.GetService(); + this.Context.Extensions = this.ServiceProvider.GetService().Create(); + this.Context.CompilationId = this.CompliationId; + this.Context.OutputPath = this.OutputPath; + this.Context.Platform = this.Platform; + this.Context.Source = this.SourceDocument; var target = new Intermediate(); - if (String.IsNullOrEmpty(context.CompilationId)) + if (String.IsNullOrEmpty(this.Context.CompilationId)) { this.Context.CompilationId = target.Id; } @@ -115,20 +134,20 @@ namespace WixToolset.Core this.Context.Messaging.Write(ErrorMessages.DuplicateExtensionXmlSchemaNamespace(extension.GetType().ToString(), extension.Namespace.NamespaceName, collidingExtension.GetType().ToString())); } - extension.PreCompile(context); + extension.PreCompile(this.Context); } // Try to compile it. try { - var parseHelper = context.ServiceProvider.GetService(); + var parseHelper = this.Context.ServiceProvider.GetService(); this.Core = new CompilerCore(target, this.Context.Messaging, parseHelper, extensionsByNamespace); this.Core.ShowPedanticMessages = this.ShowPedanticMessages; this.componentIdPlaceholdersResolver = new WixVariableResolver(this.Context.Messaging); // parse the document - var source = context.Source; + var source = this.Context.Source; var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(source.Root); if ("Wix" == source.Root.Name.LocalName) { @@ -158,7 +177,7 @@ namespace WixToolset.Core } finally { - foreach (var extension in context.Extensions) + foreach (var extension in this.Context.Extensions) { extension.PostCompile(target); } diff --git a/src/WixToolset.Core/ExtensibilityServices/PreprocessHelper.cs b/src/WixToolset.Core/ExtensibilityServices/PreprocessHelper.cs index 0e3e0bfd..0331c815 100644 --- a/src/WixToolset.Core/ExtensibilityServices/PreprocessHelper.cs +++ b/src/WixToolset.Core/ExtensibilityServices/PreprocessHelper.cs @@ -458,7 +458,11 @@ namespace WixToolset.Core.ExtensibilityServices { this.ExtensionsByPrefix = new Dictionary(); - foreach (var extension in context.Extensions) + var extensionManager = this.ServiceProvider.GetService(); + + var extensions = extensionManager.Create(); + + foreach (var extension in extensions) { if (null != extension.Prefixes) { diff --git a/src/WixToolset.Core/Librarian.cs b/src/WixToolset.Core/Librarian.cs index 2efb0f9b..3e843070 100644 --- a/src/WixToolset.Core/Librarian.cs +++ b/src/WixToolset.Core/Librarian.cs @@ -9,27 +9,45 @@ namespace WixToolset.Core using WixToolset.Core.Link; using WixToolset.Data; using WixToolset.Extensibility; + using WixToolset.Extensibility.Services; /// /// Core librarian tool. /// public sealed class Librarian { + public Librarian(IServiceProvider serviceProvider) + { + this.ServiceProvider = serviceProvider; + } + + private IServiceProvider ServiceProvider { get; } + private ILibraryContext Context { get; set; } + public bool BindFiles { get; set; } + + public IEnumerable BindPaths { get; set; } + + public IEnumerable Localizations { get; set; } + + public IEnumerable Intermediates { get; set; } + /// /// Create a library by combining several intermediates (objects). /// /// The sections to combine into a library. /// Returns the new library. - public Intermediate Combine(ILibraryContext context) + public Intermediate Execute() { - this.Context = context ?? throw new ArgumentNullException(nameof(context)); - - if (String.IsNullOrEmpty(this.Context.LibraryId)) - { - this.Context.LibraryId = Convert.ToBase64String(Guid.NewGuid().ToByteArray()).TrimEnd('=').Replace('+', '.').Replace('/', '_'); - } + this.Context = new LibraryContext(this.ServiceProvider); + this.Context.Messaging = this.ServiceProvider.GetService(); + this.Context.BindFiles = this.BindFiles; + this.Context.BindPaths = this.BindPaths; + this.Context.Extensions = this.ServiceProvider.GetService().Create(); + this.Context.Localizations = this.Localizations; + this.Context.LibraryId = Convert.ToBase64String(Guid.NewGuid().ToByteArray()).TrimEnd('=').Replace('+', '.').Replace('/', '_'); + this.Context.Intermediates = this.Intermediates; foreach (var extension in this.Context.Extensions) { diff --git a/src/WixToolset.Core/LibraryContext.cs b/src/WixToolset.Core/LibraryContext.cs index c1aec5ce..56a9389f 100644 --- a/src/WixToolset.Core/LibraryContext.cs +++ b/src/WixToolset.Core/LibraryContext.cs @@ -10,6 +10,11 @@ namespace WixToolset.Core public class LibraryContext : ILibraryContext { + public LibraryContext(IServiceProvider serviceProvider) + { + this.ServiceProvider = serviceProvider; + } + public IServiceProvider ServiceProvider { get; } public IMessaging Messaging { get; set; } diff --git a/src/WixToolset.Core/Linker.cs b/src/WixToolset.Core/Linker.cs index 93f50efa..79ddd30a 100644 --- a/src/WixToolset.Core/Linker.cs +++ b/src/WixToolset.Core/Linker.cs @@ -12,6 +12,7 @@ namespace WixToolset.Core using WixToolset.Data; using WixToolset.Data.Tuples; using WixToolset.Extensibility; + using WixToolset.Extensibility.Services; using WixToolset.Link; /// @@ -27,14 +28,17 @@ namespace WixToolset.Core /// /// Creates a linker. /// - public Linker() + public Linker(IServiceProvider serviceProvider) { + this.ServiceProvider = serviceProvider; this.sectionIdOnRows = true; // TODO: what is the correct value for this? //this.extensionData = new List(); //this.inspectorExtensions = new List(); } + private IServiceProvider ServiceProvider { get; } + private ILinkContext Context { get; set; } /// @@ -49,11 +53,13 @@ namespace WixToolset.Core /// The option to show pedantic messages. public bool ShowPedanticMessages { get; set; } - /// - /// Gets or sets the Wix variable resolver. - /// - /// The Wix variable resolver. - //internal IBindVariableResolver WixVariableResolver { get; set; } + public OutputType OutputType { get; set; } + + public IEnumerable Intermediates { get; set; } + + public IEnumerable Libraries { get; set; } + + public ITupleDefinitionCreator TupleDefinitionCreator { get; set; } /// /// Links a collection of sections into an output. @@ -61,16 +67,26 @@ namespace WixToolset.Core /// The collection of sections to link together. /// Expected output type, based on output file extension provided to the linker. /// Output object from the linking. - public Intermediate Link(ILinkContext context) + public Intermediate Execute() { - this.Context = context ?? throw new ArgumentNullException(nameof(context)); + var extensionManager = this.ServiceProvider.GetService(); + + var creator = this.TupleDefinitionCreator ?? this.ServiceProvider.GetService(); + + this.Context = this.ServiceProvider.GetService(); + this.Context.Messaging = this.ServiceProvider.GetService(); + this.Context.Extensions = extensionManager.Create(); + this.Context.ExtensionData = extensionManager.Create(); + this.Context.ExpectedOutputType = this.OutputType; + this.Context.Intermediates = this.Intermediates.Union(this.Libraries).ToList(); + this.Context.TupleDefinitionCreator = creator; var sections = this.Context.Intermediates.SelectMany(i => i.Sections).ToList(); // Add sections from the extensions with data. - foreach (var data in context.ExtensionData) + foreach (var data in this.Context.ExtensionData) { - var library = data.GetLibrary(context.TupleDefinitionCreator); + var library = data.GetLibrary(this.Context.TupleDefinitionCreator); if (library != null) { diff --git a/src/WixToolset.Core/Preprocessor.cs b/src/WixToolset.Core/Preprocessor.cs index 53d60c87..6733f493 100644 --- a/src/WixToolset.Core/Preprocessor.cs +++ b/src/WixToolset.Core/Preprocessor.cs @@ -14,6 +14,7 @@ namespace WixToolset.Core using WixToolset.Extensibility; using WixToolset.Core.Preprocess; using WixToolset.Extensibility.Services; + using System.Linq; /// /// Preprocessor object @@ -35,6 +36,21 @@ namespace WixToolset.Core XmlResolver = null, }; + public Preprocessor(IServiceProvider serviceProvider) + { + this.ServiceProvider = serviceProvider; + } + + public IEnumerable IncludeSearchPaths { get; set; } + + public Platform Platform { get; set; } + + public string SourcePath { get; set; } + + public IDictionary Variables { get; set; } + + private IServiceProvider ServiceProvider { get; } + private IPreprocessContext Context { get; set; } private Stack CurrentFileStack { get; } = new Stack(); @@ -87,14 +103,19 @@ namespace WixToolset.Core /// /// The preprocessing context. /// XDocument with the postprocessed data. - public XDocument Process(IPreprocessContext context) + public XDocument Execute() { - this.Context = context ?? throw new ArgumentNullException(nameof(context)); + this.Context = this.CreateContext(); + + this.PreProcess(); - using (XmlReader reader = XmlReader.Create(context.SourceFile, DocumentXmlReaderSettings)) + XDocument document; + using (XmlReader reader = XmlReader.Create(this.Context.SourceFile, DocumentXmlReaderSettings)) { - return Process(context, reader); + document = this.Process(reader); } + + return PostProcess(document); } /// @@ -103,46 +124,32 @@ namespace WixToolset.Core /// The preprocessing context. /// XmlReader to processing the context. /// XDocument with the postprocessed data. - public XDocument Process(IPreprocessContext context, XmlReader reader) + public XDocument Execute(XmlReader reader) { - if (this.Context == null) - { - this.Context = context ?? throw new ArgumentNullException(nameof(context)); - } - else if (this.Context != context) - { - throw new ArgumentException(nameof(context)); - } - - if (String.IsNullOrEmpty(this.Context.SourceFile) && !String.IsNullOrEmpty(reader.BaseURI)) + if (String.IsNullOrEmpty(this.SourcePath) && !String.IsNullOrEmpty(reader.BaseURI)) { var uri = new Uri(reader.BaseURI); - this.Context.SourceFile = uri.AbsolutePath; + this.SourcePath = uri.AbsolutePath; } - this.Context.CurrentSourceLineNumber = new SourceLineNumber(this.Context.SourceFile); + this.Context = this.CreateContext(); - this.Helper = this.Context.ServiceProvider.GetService(); + this.PreProcess(); - foreach (var extension in this.Context.Extensions) - { - if (null != extension.Prefixes) - { - foreach (string prefix in extension.Prefixes) - { - if (!this.ExtensionsByPrefix.TryGetValue(prefix, out var collidingExtension)) - { - this.ExtensionsByPrefix.Add(prefix, extension); - } - else - { - this.Context.Messaging.Write(ErrorMessages.DuplicateExtensionPreprocessorType(extension.GetType().ToString(), prefix, collidingExtension.GetType().ToString())); - } - } - } + var document = this.Process(reader); - extension.PrePreprocess(context); - } + return PostProcess(document); + } + + /// + /// Preprocesses a file. + /// + /// The preprocessing context. + /// XmlReader to processing the context. + /// XDocument with the postprocessed data. + private XDocument Process(XmlReader reader) + { + this.Helper = this.ServiceProvider.GetService(); this.CurrentFileStack.Clear(); this.CurrentFileStack.Push(this.Helper.GetVariableValue(this.Context, "sys", "SOURCEFILEDIR")); @@ -161,14 +168,6 @@ namespace WixToolset.Core this.UpdateCurrentLineNumber(reader, 0); throw new WixException(ErrorMessages.InvalidXml(this.Context.CurrentSourceLineNumber, "source", e.Message)); } - finally - { - // Finalize the preprocessing. - foreach (var extension in this.Context.Extensions) - { - extension.PostPreprocess(output); - } - } return this.Context.Messaging.EncounteredError ? null : output; } @@ -1404,7 +1403,7 @@ namespace WixToolset.Core { // build a string to test the directory containing the source file first var currentFolder = this.CurrentFileStack.Peek(); - var includeTestPath = Path.Combine(Path.GetDirectoryName(currentFolder) , includePath); + var includeTestPath = Path.Combine(Path.GetDirectoryName(currentFolder), includePath); // test the source file directory if (File.Exists(includeTestPath)) @@ -1428,5 +1427,52 @@ namespace WixToolset.Core return finalIncludePath; } + + private IPreprocessContext CreateContext() + { + var context = this.ServiceProvider.GetService(); + context.Messaging = this.ServiceProvider.GetService(); + context.Extensions = this.ServiceProvider.GetService().Create(); + context.CurrentSourceLineNumber = new SourceLineNumber(this.SourcePath); + context.Platform = this.Platform; + context.IncludeSearchPaths = this.IncludeSearchPaths?.ToList() ?? new List(); + context.SourceFile = this.SourcePath; + context.Variables = new Dictionary(this.Variables); + + return context; + } + + private void PreProcess() + { + foreach (var extension in this.Context.Extensions) + { + if (extension.Prefixes != null) + { + foreach (var prefix in extension.Prefixes) + { + if (!this.ExtensionsByPrefix.TryGetValue(prefix, out var collidingExtension)) + { + this.ExtensionsByPrefix.Add(prefix, extension); + } + else + { + this.Context.Messaging.Write(ErrorMessages.DuplicateExtensionPreprocessorType(extension.GetType().ToString(), prefix, collidingExtension.GetType().ToString())); + } + } + } + + extension.PrePreprocess(this.Context); + } + } + + private XDocument PostProcess(XDocument document) + { + foreach (var extension in this.Context.Extensions) + { + extension.PostPreprocess(document); + } + + return document; + } } } diff --git a/src/WixToolset.Core/WixToolsetServiceProvider.cs b/src/WixToolset.Core/WixToolsetServiceProvider.cs index a018b8dc..0c40c56d 100644 --- a/src/WixToolset.Core/WixToolsetServiceProvider.cs +++ b/src/WixToolset.Core/WixToolsetServiceProvider.cs @@ -3,6 +3,7 @@ namespace WixToolset.Core { using System; + using System.Collections.Generic; using WixToolset.Core.CommandLine; using WixToolset.Core.ExtensibilityServices; using WixToolset.Data; @@ -11,95 +12,68 @@ namespace WixToolset.Core public class WixToolsetServiceProvider : IServiceProvider { - private ExtensionManager extensionManager; - private Messaging messaging; - private ParseHelper parseHelper; - private PreprocessHelper preprocessHelper; - private TupleDefinitionCreator tupleDefinitionCreator; - private WindowsInstallerBackendHelper windowsInstallerBackendHelper; - - public object GetService(Type serviceType) + public WixToolsetServiceProvider() { - if (serviceType == null) throw new ArgumentNullException(nameof(serviceType)); - - // Transients. - if (serviceType == typeof(IPreprocessContext)) - { - return new PreprocessContext(this); - } - - if (serviceType == typeof(ICompileContext)) - { - return new CompileContext(this); - } - - if (serviceType == typeof(ILinkContext)) - { - return new LinkContext(this); - } - - if (serviceType == typeof(IBindContext)) - { - return new BindContext(this); - } - - if (serviceType == typeof(ILayoutContext)) - { - return new LayoutContext(this); - } - - if (serviceType == typeof(IResolveContext)) - { - return new ResolveContext(this); - } - - if (serviceType == typeof(IInscribeContext)) - { - return new InscribeContext(this); - } - - if (serviceType == typeof(ICommandLineContext)) + this.CreationFunctions = new Dictionary, object>> { - return new CommandLineContext(this); - } + // Singletons. + { typeof(IExtensionManager), (provider, singletons) => AddSingleton(singletons, typeof(IExtensionManager), new ExtensionManager()) }, + { typeof(IMessaging), (provider, singletons) => AddSingleton(singletons, typeof(IMessaging), new Messaging()) }, + { typeof(ITupleDefinitionCreator), (provider, singletons) => AddSingleton(singletons, typeof(ITupleDefinitionCreator), new TupleDefinitionCreator(provider)) }, + { typeof(IParseHelper), (provider, singletons) => AddSingleton(singletons, typeof(IParseHelper), new ParseHelper(provider)) }, + { typeof(IPreprocessHelper), (provider, singletons) => AddSingleton(singletons, typeof(IPreprocessHelper), new PreprocessHelper(provider)) }, + { typeof(IWindowsInstallerBackendHelper), (provider, singletons) => AddSingleton(singletons, typeof(IWindowsInstallerBackendHelper), new WindowsInstallerBackendHelper(provider)) }, - if (serviceType == typeof(ICommandLine)) - { - return new CommandLineParser(); - } + // Transients. + { typeof(ICommandLineContext), (provider, singletons) => new CommandLineContext(provider) }, + { typeof(ICommandLine), (provider, singletons) => new CommandLineParser() }, + { typeof(IPreprocessContext), (provider, singletons) => new PreprocessContext(provider) }, + { typeof(ICompileContext), (provider, singletons) => new CompileContext(provider) }, + { typeof(ILinkContext), (provider, singletons) => new LinkContext(provider) }, + { typeof(IResolveContext), (provider, singletons) => new ResolveContext(provider) }, + { typeof(IBindContext), (provider, singletons) => new BindContext(provider) }, + { typeof(ILayoutContext), (provider, singletons) => new LayoutContext(provider) }, + { typeof(IInscribeContext), (provider, singletons) => new InscribeContext(provider) }, + }; + + this.Singletons = new Dictionary(); + } - // Singletons. - if (serviceType == typeof(IExtensionManager)) - { - return this.extensionManager = this.extensionManager ?? new ExtensionManager(); - } + private Dictionary, object>> CreationFunctions { get; } - if (serviceType == typeof(IMessaging)) - { - return this.messaging = this.messaging ?? new Messaging(); - } + private Dictionary Singletons { get; } - if (serviceType == typeof(ITupleDefinitionCreator)) - { - return this.tupleDefinitionCreator = this.tupleDefinitionCreator ?? new TupleDefinitionCreator(this); - } + public object GetService(Type serviceType) + { + if (serviceType == null) throw new ArgumentNullException(nameof(serviceType)); - if (serviceType == typeof(IParseHelper)) + if (!this.Singletons.TryGetValue(serviceType, out var service)) { - return this.parseHelper = this.parseHelper ?? new ParseHelper(this); + if (this.CreationFunctions.TryGetValue(serviceType, out var creationFunction)) + { + service = creationFunction(this, this.Singletons); + +#if DEBUG + if (!serviceType.IsAssignableFrom(service?.GetType())) + { + throw new InvalidOperationException($"Creation function for service type: {serviceType.Name} created incompatible service with type: {service?.GetType()}"); + } +#endif + } } - if (serviceType == typeof(IPreprocessHelper)) - { - return this.preprocessHelper = this.preprocessHelper ?? new PreprocessHelper(this); - } + return service ?? throw new ArgumentException($"Unknown service type: {serviceType.Name}", nameof(serviceType)); + } - if (serviceType == typeof(IWindowsInstallerBackendHelper)) - { - return this.windowsInstallerBackendHelper = this.windowsInstallerBackendHelper ?? new WindowsInstallerBackendHelper(this); - } + public void AddService(Type serviceType, Func, object> creationFunction) + { + this.CreationFunctions[serviceType] = creationFunction; + } - throw new ArgumentException($"Unknown service type: {serviceType.Name}", nameof(serviceType)); + private static object AddSingleton(Dictionary singletons, Type type, object service) + { + singletons.Add(type, service); + return service; } } } -- cgit v1.2.3-55-g6feb