public void Build(Project model) { LogMessage($"Scanning project {model.ProjectFilePath} for eventsource definitions"); model.ProjectBasePath = System.IO.Path.GetDirectoryName(model.ProjectFilePath); var projectItems = new List <ProjectItem>(); if (model.ProjectFilePath == null) { LogMessage($"Could not find basePath of {model.ProjectFilePath}"); } if (model.ProjectBasePath != null) { var projectName = System.IO.Path.GetFileNameWithoutExtension(model.ProjectFilePath); var configuration = "Debug"; var projectTool = new FG.Utils.BuildTools.ProjectTool(model.ProjectFilePath, null); var projectFiles = projectTool.ScanFilesInProjectFolder(); var projectReferences = projectTool.GetProjectReferences(); var projectProperties = projectTool.GetProjectProperties(configuration, model.Platform); LogMessage($"Loaded project {model.ProjectFilePath} from XML with {projectFiles.Count()} items"); var rootNamespace = projectProperties.ContainsKey("RootNamespace") ? projectProperties["RootNamespace"] : projectName; var assemblyName = projectProperties.ContainsKey("AssemblyName") ? projectProperties["AssemblyName"] : projectName; model.RootNamespace = rootNamespace; model.AssemblyName = assemblyName; var hasEventSource = false; foreach (var projectItem in projectFiles.Where(item => item.Name.EndsWith(@".eventsource.json", StringComparison.InvariantCultureIgnoreCase))) { projectItems.Add(new ProjectItem <EventSourceModel>(ProjectItemType.EventSourceDefinition, projectItem.Path) { Include = projectItem.Name, RootNamespace = rootNamespace, AssemblyName = assemblyName, }); hasEventSource = true; } foreach (var projectItem in projectFiles.Where(item => item.Name.Matches(@"*.eventsource.output.json", StringComparison.InvariantCultureIgnoreCase, useWildcards: true) && item.IncludeType == "Content")) { var projectItemFilePath = projectItem.Path; projectItems.Add(new ProjectItem <ProjectSummary>(ProjectItemType.ProjectSummary, projectItemFilePath) { Include = projectItem.Name, }); } var autogeneratedMetadataTypes = new[] { ProjectItemType.ProjectSummary, ProjectItemType.DefaultGeneratedEventSourceDefinition, ProjectItemType.EventSource, ProjectItemType.EventSourceLoggerPartial, ProjectItemType.LoggerImplementation } .Select(metadata => Enum.GetName(typeof(ProjectItemType), metadata)) .ToArray(); foreach (var projectItem in projectFiles.Where(item => item.Name.Matches(@"(^|\\)I[^\\]*Logger.cs", StringComparison.InvariantCultureIgnoreCase, useWildcards: false) && item.IncludeType == "Compile" && !autogeneratedMetadataTypes.Contains((item.Properties.ContainsKey("AutoGenerated") ? item.Properties["AutoGenerated"] : "") ?? ""))) { var projectItemFilePath = projectItem.Path; projectItems.Add(new ProjectItem <LoggerTemplateModel>(ProjectItemType.LoggerInterface, projectItemFilePath) { Include = projectItem.Name }); } foreach (var projectItem in projectFiles.Where(item => item.Name.Matches(@"(^|\\)[^\\]*Extension.cs", StringComparison.InvariantCultureIgnoreCase, useWildcards: false) && item.IncludeType == "Compile" && !autogeneratedMetadataTypes.Contains((item.Properties.ContainsKey("AutoGenerated") ? item.Properties["AutoGenerated"] : "") ?? ""))) { var projectItemFilePath = projectItem.Path; projectItems.Add(new ProjectItem(ProjectItemType.BuilderExtension, projectItemFilePath) { Include = projectItem.Name }); } var outputPath = projectTool.GetProjectOutputPath(configuration, null); var buildOutputPath = PathExtensions.GetAbsolutePath(model.ProjectBasePath, outputPath); var outputPathExists = System.IO.Directory.Exists(buildOutputPath); if (!outputPathExists) { outputPath = projectTool.GetProjectOutputPath(configuration, "x64"); buildOutputPath = PathExtensions.GetAbsolutePath(model.ProjectBasePath, outputPath); outputPathExists = System.IO.Directory.Exists(buildOutputPath); } if (outputPathExists) { var outputFiles = System.IO.Directory.GetFiles(buildOutputPath, "*.*", SearchOption.AllDirectories); foreach (var outputFile in outputFiles) { var outputFileType = System.IO.Path.GetExtension(outputFile); if (outputFileType == ".dll" || outputFileType == ".exe") { var referenceFilePath = outputFile; var referenceName = System.IO.Path.GetFileNameWithoutExtension(outputFile); projectItems.Add( new ProjectItem(ProjectItemType.Reference, referenceFilePath) { Include = referenceName }); } } } if (!hasEventSource) { var defaultEventSourceName = $"{assemblyName}EventSource"; defaultEventSourceName = defaultEventSourceName.RemoveNonWordCharacters(); var include = $"{defaultEventSourceName}.eventsource.json"; var projectItemFilePath = System.IO.Path.Combine(model.ProjectBasePath, include); projectItems.Add(new ProjectItem <EventSourceModel>(ProjectItemType.DefaultGeneratedEventSourceDefinition, projectItemFilePath) { Include = include, RootNamespace = rootNamespace, AssemblyName = assemblyName, }); } } model.ProjectItems = projectItems.ToArray(); }
private void AddGeneratedOutputsToProject(Project model, bool saveChanges = true) { var projectFilePath = model.ProjectFilePath; var includes = model.ProjectItems.Where(p => p.ItemType != ProjectItemType.Reference && p.ItemType != ProjectItemType.ProjectReference && p.ItemType != ProjectItemType.Unknown); LogMessage($"Loading projectfile {projectFilePath} to include new files"); var updatedProjectFile = false; var loadedFromProjectCollection = false; var project = new FG.Utils.BuildTools.ProjectTool(projectFilePath, null); LogMessage($"Loaded project {projectFilePath} from XML to {project.Name}, {(project.IsCpsDocument ? "as CPS project" : "as classic project")}"); var projectFiles = project.ScanFilesInProjectFolder(); var existingItems = new List <FG.Utils.BuildTools.FileReference>(); existingItems.AddRange(projectFiles.Where(item => item.Properties.ContainsKey("AutoGenerated"))); // Add or check that it already exists foreach (var include in includes) { var includeName = model.GetIncludeName(include); var filePath = include.Name; var isAutogeneratedType = include.ItemType.IsAutogeneratedType(); try { var matchingItem = projectFiles.FirstOrDefault(item => item.Name.Matches($"{includeName}", StringComparison.InvariantCultureIgnoreCase)); var metadata = include.ItemType.Name(); IDictionary <string, string> properties = new Dictionary <string, string>(); if (include.ItemType == ProjectItemType.DefaultGeneratedEventSourceDefinition) { var hash = include.Output.ToMD5().ToHex(); properties = new Dictionary <string, string> { { "AutoGenerated", metadata }, { "Hash", hash } }; } else if (isAutogeneratedType) { properties = new Dictionary <string, string> { { "AutoGen", "true" }, { "AutoGenerated", metadata }, { "DependentUpon", include.DependentUpon.Include.RemoveCommonPrefix(includeName, System.IO.Path.DirectorySeparatorChar) }, }; } var fileType = System.IO.Path.GetExtension(include.Include); var includeType = (include.ItemType == ProjectItemType.DefaultGeneratedEventSourceDefinition || include.ItemType == ProjectItemType.ProjectSummary) ? "None" : fileType == ".cs" ? "Compile" : "Content"; if (matchingItem == null || !FG.Utils.BuildTools.DictionaryExtensions.AreEquivalent(matchingItem.Properties, properties)) { //var metadata = Enum.GetName(typeof(ProjectItemType), include.ItemType); updatedProjectFile = true; var addedItems = new List <string>(); project.AddFileToProject(filePath, includeType, properties); addedItems.Add(includeName); foreach (var addedItem in addedItems) { LogMessage($"Including project item {addedItem}"); existingItems.RemoveAll(fr => fr.Name == addedItem); } } else { LogMessage($"Matched existing project item {matchingItem.Name}"); existingItems.Remove(matchingItem); } } catch (Exception ex) { LogError($"Failed to include/add {includeName} - {ex.Message}\n{ex}"); } } // Check if we should remove the AutoGenerated DefaultEventSource.eventsource var autoGeneratedDefaultEventSource = existingItems.FirstOrDefault( existingItem => existingItem.Properties.ContainsKey("AutoGenerated") && existingItem.Properties["AutoGenerated"] == "DefaultEventSource"); if (autoGeneratedDefaultEventSource != null) { if (autoGeneratedDefaultEventSource.Name != "DefaultEventSource.cs") { updatedProjectFile = true; LogMessage($"Updating Project Metadata for {autoGeneratedDefaultEventSource.Name} as it has been changed from it's original state"); var properties = autoGeneratedDefaultEventSource.Properties; if (properties.ContainsKey("AutoGenerated")) { properties.Remove("AutoGenerated"); } project.AddFileToProject(autoGeneratedDefaultEventSource.Name, autoGeneratedDefaultEventSource.IncludeType, properties); existingItems.Remove(autoGeneratedDefaultEventSource); } else { var hash = autoGeneratedDefaultEventSource.Properties.ContainsKey("Hash") ? autoGeneratedDefaultEventSource.Properties["Hash"] : ""; var filePath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(projectFilePath), autoGeneratedDefaultEventSource.Name); var fileContent = System.IO.File.ReadAllText(filePath); var hashCheck = StringMatchExtensions.ToHex(StringMatchExtensions.ToMD5(fileContent)); if (hash != hashCheck) { updatedProjectFile = true; LogMessage($"Updating Project Metadata for {autoGeneratedDefaultEventSource.Name} as it's content been changed from it's original state"); var properties = autoGeneratedDefaultEventSource.Properties; if (properties.ContainsKey("AutoGenerated")) { properties.Remove("AutoGenerated"); } project.AddFileToProject(autoGeneratedDefaultEventSource.Name, autoGeneratedDefaultEventSource.IncludeType, properties); existingItems.Remove(autoGeneratedDefaultEventSource); } } } // Remove old items that are no longer referenced foreach (var existingItem in existingItems) { LogMessage($"Removing existing project item {existingItem.Name}"); } if (existingItems.Count > 0) { updatedProjectFile = true; foreach (var fileReference in existingItems) { project.RemoveFileFromProject(fileReference.Path); } } if (!updatedProjectFile) { LogMessage($"Igoring to save project file {projectFilePath} - no changes performed"); } else { if (saveChanges) { LogMessage($"Saving project file {projectFilePath}"); project.Save(); } else { LogMessage($"Project file {projectFilePath} changed"); var rawXml = System.IO.File.ReadAllText(project.FilePath); LogMessage(rawXml); } } }