From 005d506c2dc9e60cfbca89bbfaedee7d98511890 Mon Sep 17 00:00:00 2001 From: Pedro Debevere Date: Mon, 30 Oct 2023 13:41:57 +0100 Subject: [PATCH 1/3] project.assets.json processing --- Assemblers.Common/ProjectAssetsProcessor.cs | 263 ++++++++++++++++++ Assemblers.Protocol/ProtocolBuilder.cs | 106 +++++-- .../ProtocolBuilderTests.cs | 81 +++--- Skyline.DataMiner.CICD.Assemblers.sln | 12 +- 4 files changed, 397 insertions(+), 65 deletions(-) create mode 100644 Assemblers.Common/ProjectAssetsProcessor.cs diff --git a/Assemblers.Common/ProjectAssetsProcessor.cs b/Assemblers.Common/ProjectAssetsProcessor.cs new file mode 100644 index 0000000..c70a12b --- /dev/null +++ b/Assemblers.Common/ProjectAssetsProcessor.cs @@ -0,0 +1,263 @@ +namespace Skyline.DataMiner.CICD.Assemblers.Common +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Linq; + using System.Threading; + using System.Threading.Tasks; + + using NuGet.Common; + using NuGet.Configuration; + using NuGet.Frameworks; + using NuGet.Packaging; + using NuGet.Packaging.Core; + using NuGet.Packaging.Signing; + using NuGet.ProjectModel; + using NuGet.Protocol; + using NuGet.Protocol.Core.Types; + using NuGet.Versioning; + + using Skyline.DataMiner.CICD.Common.NuGet; + using Skyline.DataMiner.CICD.FileSystem; + using Skyline.DataMiner.CICD.Loggers; + using Skyline.DataMiner.CICD.Parsers.Common.VisualStudio.Projects; + + /// + /// Processes the assemblies of the NuGet packages referenced in a project. + /// + /// This class uses the project.assets.json file to determine the unified NuGet packages that should be referenced. + /// The project references are not processed using this file. They are processed via the protocol solution object. + /// + public class ProjectAssetsProcessor + { + private readonly ILogCollector logCollector; + private readonly ISettings settings; + private readonly ILogger nuGetLogger; + private readonly ICollection repositories; + + // V3 package path resolver + //private readonly VersionFolderPathResolver versionFolderPathResolver; + + //private readonly FrameworkReducer frameworkReducer; + + //private readonly SourceRepositoryProvider sourceRepositoryProvider; + + private readonly IFileSystem _fileSystem = FileSystem.Instance; + + + /// + /// Initializes a new instance of the class. + /// + /// Directory path of the solution. + public ProjectAssetsProcessor(string solutionDirectoryPath) + { + nuGetLogger = NullLogger.Instance; + + // Start with the lowest settings. It will automatically look at the other NuGet.config files it can find on the default locations + settings = Settings.LoadDefaultSettings(root: solutionDirectoryPath); + + //var provider = new PackageSourceProvider(settings); + //sourceRepositoryProvider = new SourceRepositoryProvider(provider, Repository.Provider.GetCoreV3()); + + NuGetRootPath = SettingsUtility.GetGlobalPackagesFolder(settings); + + //// Add global packages to be the first repository as it speeds up everything when reading from disk then via internet. + //var repos = sourceRepositoryProvider.GetRepositories().ToList(); + //repos.Insert(0, new SourceRepository(new PackageSource(NuGetRootPath), Repository.Provider.GetCoreV3())); + //repositories = repos; + + //// https://docs.microsoft.com/en-us/nuget/consume-packages/managing-the-global-packages-and-cache-folders + //versionFolderPathResolver = new VersionFolderPathResolver(NuGetRootPath); + + //frameworkReducer = new FrameworkReducer(); + } + + /// + /// Initializes a new instance of the class. + /// + /// The log collector. + /// Directory path of the solution (to find the NuGet.config) + /// is . + public ProjectAssetsProcessor(ILogCollector logCollector, string solutionDirectoryPath) : this(solutionDirectoryPath) + { + this.logCollector = logCollector ?? throw new ArgumentNullException(nameof(logCollector)); + + foreach (SourceRepository sourceRepository in repositories) + { + LogDebug($"Source: [{sourceRepository.PackageSource?.Name}] {sourceRepository.PackageSource?.Source}"); + } + + LogDebug($"NuGet Root Path: {NuGetRootPath}"); + } + + /// + /// Gets the NuGet root path. + /// + /// The NuGet root path. + public string NuGetRootPath { get; } + + /// + /// Processes the NuGet packages. + /// + /// The project to process. + /// The target framework moniker. + /// The assembly info of the processed packages. + /// Cannot find the package with the identity. + public NuGetPackageAssemblyData ProcessAsync(Project project, string targetFrameworkMoniker) + { + return Process(project, targetFrameworkMoniker, new List()); + } + + /// + /// Processes the NuGet packages. + /// + /// The project to process. + /// The target framework moniker. + /// Specifies the NuGet package IDs that are included by default. + /// The assembly info of the processed packages. + /// Cannot find the package with the identity. + public NuGetPackageAssemblyData Process(Project project, string targetFrameworkMoniker, IReadOnlyCollection defaultIncludedFilesNuGetPackages) + { + var nugetPackageAssemblyData = new NuGetPackageAssemblyData(); + + var projectAssetsFilePath = Path.Combine(Path.GetDirectoryName(project.Path), "obj\\project.assets.json"); + + if(!File.Exists(projectAssetsFilePath)) + { + throw new InvalidOperationException("project.assets.json file not found. Make sure to perform a restore of the project."); + } + + var lockFileFormat = new LockFileFormat(); + var assetsFileContent = File.ReadAllText(projectAssetsFilePath); + var assetsFile = lockFileFormat.Parse(assetsFileContent, "In Memory"); + + var targetCount = assetsFile.Targets.Count; + + var target = assetsFile.Targets.FirstOrDefault(t => t.Name == targetFrameworkMoniker); + + if(target == null) + { + throw new InvalidOperationException($"Could not find target '{targetFrameworkMoniker}' in project.assets.json file '{projectAssetsFilePath}'."); + } + + foreach (var library in target.Libraries) + { + if (String.Equals(library.Type, "package", StringComparison.OrdinalIgnoreCase)) + { + ProcessPackage(library, defaultIncludedFilesNuGetPackages, nugetPackageAssemblyData); + } + + // Do not process items of type "project", project references are processed in builder already. + } + + return nugetPackageAssemblyData; + } + + private void ProcessPackage(LockFileTargetLibrary library, IReadOnlyCollection defaultIncludedFilesNuGetPackages, NuGetPackageAssemblyData nugetPackageAssemblyData) + { + // This is a NuGet package. + if (!defaultIncludedFilesNuGetPackages.Contains(library.Name) && + !String.Equals(library.Name, "StyleCop.Analyzers", StringComparison.OrdinalIgnoreCase) && + !library.Name.StartsWith("Skyline.DataMiner.Dev")) + { + if (ShouldSkipPackage(library)) return; + + Console.WriteLine(library.Name); + ProcessLibItemsOfPackage(library, nugetPackageAssemblyData); + ProcessFrameworkItemsOfPackage(library, nugetPackageAssemblyData); + } + } + + /// + /// Checks whether packages that are part of dev packs were overridden by another package + /// + /// + /// + /// + private bool ShouldSkipPackage(LockFileTargetLibrary library) + { + // In dev packs, the Newtonsoft.Json and SharpZipLib packages were added as dependencies but only for runtime.. + if(String.Equals(library.Name, "Newtonsoft.Json", StringComparison.OrdinalIgnoreCase)) + { + var assemblyFound = library.CompileTimeAssemblies.FirstOrDefault(a => a.Path.EndsWith(".dll")); + + if (assemblyFound == null) + return true; + } + else if(String.Equals(library.Name, "SharpZipLib", StringComparison.OrdinalIgnoreCase)) + { + var assemblyFound = library.CompileTimeAssemblies.FirstOrDefault(a => a.Path.EndsWith(".dll")); + + if (assemblyFound == null) + return true; + } + + return false; + } + + private void ProcessLibItemsOfPackage(LockFileTargetLibrary library, NuGetPackageAssemblyData nugetPackageAssemblyData) + { + string packageKey = library.Name.ToLower() + "\\" + library.Version.ToString().ToLower(); + + foreach (var runtimeAssembly in library.RuntimeAssemblies) + { + // Currently, only lib items are supported. + if(runtimeAssembly.Path.StartsWith("lib/")) + { + string assemblyName = runtimeAssembly.Path.Substring(runtimeAssembly.Path.LastIndexOf('/') + 1); + string dllImportEntry = packageKey + "\\" + runtimeAssembly.Path.Replace("/", "\\"); + + nugetPackageAssemblyData.ProcessedAssemblies.Add(assemblyName); + + string fullPath = null; + string dllImportValue; + bool isFilePackage = false; + + if (library.Name.StartsWith(DevPackHelper.FilesPrefix)) + { + // Full path is not set as it should not be included. + dllImportValue = assemblyName; + isFilePackage = true; + } + else + { + fullPath = _fileSystem.Path.GetFullPath(_fileSystem.Path.Combine(NuGetRootPath, library.Name.ToLower(), library.Version.ToString().ToLower(), runtimeAssembly.Path)); + dllImportValue = _fileSystem.Path.Combine(dllImportEntry); // fileInfo.Name + } + + var packageAssemblyReference = new PackageAssemblyReference(dllImportValue, fullPath, isFilePackage); + + // Needs to be added as a reference in the dllImport attribute/script references. + nugetPackageAssemblyData.DllImportNugetAssemblyReferences.Add(packageAssemblyReference); + + if (!library.Name.StartsWith(DevPackHelper.FilesPrefix)) + { + // Needs to be provided in the package to install. + nugetPackageAssemblyData.NugetAssemblies.Add(packageAssemblyReference); + } + } + } + } + + private void ProcessFrameworkItemsOfPackage(LockFileTargetLibrary library, NuGetPackageAssemblyData nugetPackageAssemblyData) + { + // Framework references are items that are that are part of the targeted .NET framework. These are specified in the nuspec file. + // See: https://docs.microsoft.com/en-us/nuget/reference/nuspec#framework-assembly-references + var frameworkItems = library.FrameworkReferences; + + nugetPackageAssemblyData.ProcessedAssemblies.AddRange(frameworkItems); + nugetPackageAssemblyData.DllImportFrameworkAssemblyReferences.AddRange(frameworkItems); + } + + private static bool IsDevPackNuGetPackage(string packageId) + { + return DevPackHelper.DevPackNuGetPackages.Contains(packageId) || packageId.StartsWith(DevPackHelper.FilesPrefix); + } + + private void LogDebug(string message) + { + logCollector?.ReportDebug($"PackageReferenceProcessor|{message}"); + } + } +} \ No newline at end of file diff --git a/Assemblers.Protocol/ProtocolBuilder.cs b/Assemblers.Protocol/ProtocolBuilder.cs index 217d08c..710b3eb 100644 --- a/Assemblers.Protocol/ProtocolBuilder.cs +++ b/Assemblers.Protocol/ProtocolBuilder.cs @@ -7,9 +7,8 @@ using System.Reflection; using System.Text; using System.Threading.Tasks; - - using NuGet.Packaging.Core; - using NuGet.Versioning; + using NuGet.Packaging.Core; + using NuGet.Versioning; using Skyline.DataMiner.CICD.Assemblers.Common; using Skyline.DataMiner.CICD.Loggers; @@ -43,6 +42,8 @@ public ProtocolBuilder(ProtocolSolution solution) throw new ArgumentNullException(nameof(solution)); } + SolutionFilePath = solution.SolutionPath; + Document = solution.ProtocolDocument; Model = new ProtocolModel(Document); @@ -80,10 +81,16 @@ internal ProtocolBuilder(XmlDocument document, IDictionary proj } /// - /// Gets the XML document of the protocol. + /// Gets the solution file path. /// - /// The protocol model. - public XmlDocument Document { get; } + /// The solution file path. + public string SolutionFilePath { get; } + + /// + /// Gets the XML document of the protocol. + /// + /// The protocol model. + public XmlDocument Document { get; } /// /// Gets the protocol model/ @@ -105,10 +112,10 @@ internal ProtocolBuilder(XmlDocument document, IDictionary proj /// No code files found for QAction -or- /// File could not be found in project -or- /// Cannot replace QAction, because the target XML node is not empty. - public async Task BuildAsync() + public BuildResultItems Build() { var protocolEdit = new ProtocolDocumentEdit(Document, Model); - return await BuildResultsAsync(protocolEdit).ConfigureAwait(false); + return BuildResults(protocolEdit); } /// @@ -152,36 +159,36 @@ public static IList GetRelevantCodeFilesSorted(Project project) return files; } - private async Task BuildResultsAsync(ProtocolDocumentEdit protocolEdit) + private BuildResultItems BuildResults(ProtocolDocumentEdit protocolEdit) { BuildResultItems buildResultItems = new BuildResultItems(); - await BuildQActions(protocolEdit, buildResultItems, Model?.Protocol?.Compliancies).ConfigureAwait(false); + BuildQActions(protocolEdit, buildResultItems, Model?.Protocol?.Compliancies); BuildVersionHistoryComment(protocolEdit, Model); buildResultItems.Document = protocolEdit.Document.GetXml(); return buildResultItems; } - private async Task BuildQActions(ProtocolDocumentEdit protocolEdit, BuildResultItems buildResultItems, ICompliancies compliancies) + private void BuildQActions(ProtocolDocumentEdit protocolEdit, BuildResultItems buildResultItems, ICompliancies compliancies) { - var packageReferenceProcessor = new PackageReferenceProcessor(); + ProjectAssetsProcessor projectAssetProcessor = new ProjectAssetsProcessor(SolutionFilePath); - var qactions = protocolEdit.Protocol?.QActions; + var qactions = protocolEdit.Protocol?.QActions; if (qactions != null) { foreach (var qa in qactions) { - await BuildQAction(qa, qactions.Read, packageReferenceProcessor, buildResultItems, compliancies).ConfigureAwait(false); + BuildQAction(qa, qactions.Read, projectAssetProcessor, buildResultItems, compliancies); } } } - private async Task BuildQAction(QActionsQAction qa, IQActions allQActions, PackageReferenceProcessor packageReferenceProcessor, BuildResultItems buildResultItems, ICompliancies compliancies) + private void BuildQAction(QActionsQAction qa, IQActions allQActions, ProjectAssetsProcessor projectAssetProcessor, BuildResultItems buildResultItems, ICompliancies compliancies) { if (qa.Encoding?.Value != EnumQActionEncoding.Csharp) { - // skip JScript etc.. + // Skip non C# QActions (e.g. JScript). return; } @@ -196,8 +203,8 @@ private async Task BuildQAction(QActionsQAction qa, IQActions allQActions, Packa // replace code var hasQActionCodeChanges = BuildQActionCode(qa, project, qaId); - // DLL imports - var hasDllImportChanges = await BuildQActionDllImports(qa, project, allQActions, packageReferenceProcessor, buildResultItems, compliancies).ConfigureAwait(false); + // build DLL imports + var hasDllImportChanges = BuildQActionDllImports(qa, project, projectAssetProcessor, allQActions, buildResultItems, compliancies); // format if (hasQActionCodeChanges || hasDllImportChanges) @@ -225,7 +232,37 @@ private static bool BuildQActionCode(QActionsQAction qa, Project project, uint? return hasChanges; } - private static async Task BuildQActionDllImports(QActionsQAction qa, Project project, IQActions allQActions, PackageReferenceProcessor packageReferenceProcessor, BuildResultItems buildResultItems, ICompliancies compliancies) + + private static bool BuildQActionDllImports(QActionsQAction qa, Project project, ProjectAssetsProcessor projectAssetProcessor, IQActions allQActions, BuildResultItems buildResultItems, ICompliancies compliancies) + { + bool hasChanges = false; + + var dllImports = new HashSet(StringComparer.OrdinalIgnoreCase); + + string dllsFolder = null; + if (project.Path != null) + { + dllsFolder = Path.Combine(Directory.GetParent(Path.GetDirectoryName(project.Path)).FullName, @"Dlls\"); + } + + // project.assets.json contains both package and project references. + NuGetPackageAssemblyData nugetAssemblyData = ProcessPackageReferencesViaAssets(project, projectAssetProcessor, buildResultItems, dllImports); + + // Process regular references (if not yet added). + ProcessReferences(project, projectAssetProcessor.NuGetRootPath, compliancies, nugetAssemblyData, dllsFolder, dllImports); + ProcessProjectReferences(project, allQActions, dllImports); + + // Edit QAction@dllImport + if (dllImports.Count > 0) + { + qa.DllImport = String.Join(";", dllImports); + hasChanges = true; + } + + return hasChanges; + } + + private static async Task BuildQActionDllImportsOld(QActionsQAction qa, Project project, IQActions allQActions, PackageReferenceProcessor packageReferenceProcessor, BuildResultItems buildResultItems, ICompliancies compliancies) { bool hasChanges = false; @@ -238,7 +275,7 @@ private static async Task BuildQActionDllImports(QActionsQAction qa, Proje } NuGetPackageAssemblyData nugetAssemblyData = await ProcessPackageReferences(project, packageReferenceProcessor, buildResultItems, dllImports); - ProcessReferences(project, packageReferenceProcessor, compliancies, nugetAssemblyData, dllsFolder, dllImports); + ProcessReferences(project, packageReferenceProcessor.NuGetRootPath, compliancies, nugetAssemblyData, dllsFolder, dllImports); ProcessProjectReferences(project, allQActions, dllImports); // Edit QAction@dllImport @@ -275,7 +312,30 @@ private static async Task ProcessPackageReferences(Pro return nugetAssemblyData; } - private static void ProcessLibAssemblies(BuildResultItems buildResultItems, HashSet dllImports, NuGetPackageAssemblyData nugetAssemblyData) + private static NuGetPackageAssemblyData ProcessPackageReferencesViaAssets(Project project, ProjectAssetsProcessor projectAssetProcessor, BuildResultItems buildResultItems, HashSet dllImports) + { + if (project.PackageReferences == null) + { + return null; + } + + List packageIdentities = GetPackageIdentities(project); + + if (packageIdentities.Count <= 0) + { + return null; + } + + NuGetPackageAssemblyData nugetAssemblyData = projectAssetProcessor.Process(project, project.TargetFrameworkMoniker, + Skyline.DataMiner.CICD.Common.NuGet.DevPackHelper.ProtocolDevPackNuGetDependenciesIncludingTransitive); + + ProcessFrameworkAssemblies(dllImports, nugetAssemblyData); + ProcessLibAssemblies(buildResultItems, dllImports, nugetAssemblyData); + + return nugetAssemblyData; + } + + private static void ProcessLibAssemblies(BuildResultItems buildResultItems, HashSet dllImports, NuGetPackageAssemblyData nugetAssemblyData) { ProcessDllImportNuGetAssemblyReferences(dllImports, nugetAssemblyData); @@ -449,7 +509,7 @@ private static void ProcessProjectReferences(Project project, IQActions allQActi } } - private static void ProcessReferences(Project project, PackageReferenceProcessor packageReferenceProcessor, ICompliancies compliancies, + private static void ProcessReferences(Project project, string nugetRootPath, ICompliancies compliancies, NuGetPackageAssemblyData nugetAssemblyData, string dllsFolder, HashSet dllImports) { if (project.References != null) @@ -464,7 +524,7 @@ private static void ProcessReferences(Project project, PackageReferenceProcessor continue; } - if (r.HintPath?.Contains(packageReferenceProcessor.NuGetRootPath) == true) + if (r.HintPath?.Contains(nugetRootPath) == true) { // DLL is from a NuGet but is transitive from precompile or other project reference. // These can be ignored. diff --git a/Assemblers.ProtocolTests/ProtocolBuilderTests.cs b/Assemblers.ProtocolTests/ProtocolBuilderTests.cs index 43b3382..7161e38 100644 --- a/Assemblers.ProtocolTests/ProtocolBuilderTests.cs +++ b/Assemblers.ProtocolTests/ProtocolBuilderTests.cs @@ -21,7 +21,20 @@ public class ProtocolBuilderTests { [TestMethod] - public async Task ProtocolCompiler_ProtocolBuilder_BasicAsync() + public void TestProtocol() + { + var solutionFilePath = @"D:\TESTING\ConnectorSDKStyle\ConnectorSDKStyle.sln"; + ProtocolSolution solution = ProtocolSolution.Load(solutionFilePath); + ProtocolBuilder builder = new ProtocolBuilder(solution); + + var buildResultItems = builder.Build(); + + File.WriteAllText(@"D:\TESTING\resultProtocol.xml", buildResultItems.Document); + } + + + [TestMethod] + public void ProtocolCompiler_ProtocolBuilder_Basic() { string originalProtocol = @" @@ -44,7 +57,7 @@ public async Task ProtocolCompiler_ProtocolBuilder_BasicAsync() ProtocolBuilder builder = new ProtocolBuilder(XmlDocument.Parse(originalProtocol), projects); - string result = (await builder.BuildAsync().ConfigureAwait(false)).Document; + string result = builder.Build().Document; Diff d = DiffBuilder.Compare(Input.FromString(expected)) .WithTest(Input.FromString(result)).Build(); @@ -53,7 +66,7 @@ public async Task ProtocolCompiler_ProtocolBuilder_BasicAsync() } [TestMethod] - public async Task ProtocolCompiler_ProtocolBuilder_MultipleQActionsAsync() + public void ProtocolCompiler_ProtocolBuilder_MultipleQActions() { string originalProtocol = @" @@ -82,7 +95,7 @@ public async Task ProtocolCompiler_ProtocolBuilder_MultipleQActionsAsync() ProtocolBuilder builder = new ProtocolBuilder(XmlDocument.Parse(originalProtocol), projects); - string result = (await builder.BuildAsync().ConfigureAwait(false)).Document; + string result = builder.Build().Document; Diff d = DiffBuilder.Compare(Input.FromString(expected)) .WithTest(Input.FromString(result)).Build(); @@ -91,7 +104,7 @@ public async Task ProtocolCompiler_ProtocolBuilder_MultipleQActionsAsync() } [TestMethod] - public async Task ProtocolCompiler_ProtocolBuilder_VersionHistoryAsync() + public void ProtocolCompiler_ProtocolBuilder_VersionHistory() { string originalProtocol = @" @@ -209,7 +222,7 @@ DATE VERSION AUTHOR COMMENTS ProtocolBuilder builder = new ProtocolBuilder(XmlDocument.Parse(originalProtocol), projects); - string result = (await builder.BuildAsync().ConfigureAwait(false)).Document; + string result = builder.Build().Document; Diff d = DiffBuilder.Compare(Input.FromString(expected)) .WithTest(Input.FromString(result)).Build(); @@ -218,7 +231,7 @@ DATE VERSION AUTHOR COMMENTS } [TestMethod] - public async Task ProtocolCompiler_ProtocolBuilder_MultipleFilesAsync() + public void ProtocolCompiler_ProtocolBuilder_MultipleFiles() { string originalProtocol = @" @@ -252,7 +265,7 @@ class Class1 {}]]> ProtocolBuilder builder = new ProtocolBuilder(XmlDocument.Parse(originalProtocol), projects); - string result = (await builder.BuildAsync().ConfigureAwait(false)).Document; + string result = builder.Build().Document; Diff d = DiffBuilder.Compare(Input.FromString(expected)) .WithTest(Input.FromString(result)).Build(); @@ -278,15 +291,13 @@ public void ProtocolCompiler_ProtocolBuilder_TargetNotEmpty() ProtocolBuilder builder = new ProtocolBuilder(XmlDocument.Parse(originalProtocol), projects); - var exception = Assert.ThrowsException(() => builder.BuildAsync().Result); + var exception = Assert.ThrowsException(() => builder.Build()); - Assert.IsNotNull(exception.InnerException); - Assert.IsInstanceOfType(exception.InnerException, typeof(AssemblerException)); - Assert.AreEqual("Cannot replace QAction 1, because the target XML node is not empty!", exception.InnerException.Message); + Assert.AreEqual("Cannot replace QAction 1, because the target XML node is not empty!", exception.Message); } [TestMethod] - public async Task ProtocolCompiler_ProtocolBuilder_DllImportsAsync() + public void ProtocolCompiler_ProtocolBuilder_DllImports() { string originalProtocol = @" @@ -313,7 +324,7 @@ public async Task ProtocolCompiler_ProtocolBuilder_DllImportsAsync() ProtocolBuilder builder = new ProtocolBuilder(XmlDocument.Parse(originalProtocol), projects); - string result = (await builder.BuildAsync().ConfigureAwait(false)).Document; + string result = builder.Build().Document; Diff d = DiffBuilder.Compare(Input.FromString(expected)) .WithTest(Input.FromString(result)).Build(); @@ -322,7 +333,7 @@ public async Task ProtocolCompiler_ProtocolBuilder_DllImportsAsync() } [TestMethod] - public async Task ProtocolCompiler_ProtocolBuilder_DllImports_NoDuplicateAsync() + public void ProtocolCompiler_ProtocolBuilder_DllImports_NoDuplicate() { string originalProtocol = @" @@ -349,7 +360,7 @@ public async Task ProtocolCompiler_ProtocolBuilder_DllImports_NoDuplicateAsync() ProtocolBuilder builder = new ProtocolBuilder(XmlDocument.Parse(originalProtocol), projects); - string result = (await builder.BuildAsync().ConfigureAwait(false)).Document; + string result = builder.Build().Document; Diff d = DiffBuilder.Compare(Input.FromString(expected)) .WithTest(Input.FromString(result)).Build(); @@ -358,7 +369,7 @@ public async Task ProtocolCompiler_ProtocolBuilder_DllImports_NoDuplicateAsync() } [TestMethod] - public async Task ProtocolCompiler_ProtocolBuilder_DllImports_ProjectReference() + public void ProtocolCompiler_ProtocolBuilder_DllImports_ProjectReference() { string originalProtocol = @" @@ -385,7 +396,7 @@ public async Task ProtocolCompiler_ProtocolBuilder_DllImports_ProjectReference() ProtocolBuilder builder = new ProtocolBuilder(XmlDocument.Parse(originalProtocol), projects); - string result = (await builder.BuildAsync().ConfigureAwait(false)).Document; + string result = builder.Build().Document; Diff d = DiffBuilder.Compare(Input.FromString(expected)) .WithTest(Input.FromString(result)).Build(); @@ -394,7 +405,7 @@ public async Task ProtocolCompiler_ProtocolBuilder_DllImports_ProjectReference() } [TestMethod] - public async Task ProtocolCompiler_ProtocolBuilder_ClassLibraryAsync() + public void ProtocolCompiler_ProtocolBuilder_ClassLibrary() { string originalProtocol = @" @@ -429,7 +440,7 @@ public async Task ProtocolCompiler_ProtocolBuilder_ClassLibraryAsync() ProtocolBuilder builder = new ProtocolBuilder(XmlDocument.Parse(originalProtocol), projects); - string result = (await builder.BuildAsync().ConfigureAwait(false)).Document; + string result = builder.Build().Document; Diff d = DiffBuilder.Compare(Input.FromString(expected)) .WithTest(Input.FromString(result)).Build(); @@ -438,7 +449,7 @@ public async Task ProtocolCompiler_ProtocolBuilder_ClassLibraryAsync() } [TestMethod] - public async Task ProtocolCompiler_ProtocolBuilder_ReferencedQActionAsync() + public void ProtocolCompiler_ProtocolBuilder_ReferencedQAction() { string originalProtocol = @" @@ -471,7 +482,7 @@ public async Task ProtocolCompiler_ProtocolBuilder_ReferencedQActionAsync() ProtocolBuilder builder = new ProtocolBuilder(XmlDocument.Parse(originalProtocol), projects); - string result = (await builder.BuildAsync().ConfigureAwait(false)).Document; + string result = builder.Build().Document; Diff d = DiffBuilder.Compare(Input.FromString(expected)) .WithTest(Input.FromString(result)).Build(); @@ -480,7 +491,7 @@ public async Task ProtocolCompiler_ProtocolBuilder_ReferencedQActionAsync() } [TestMethod] - public async Task ProtocolCompiler_ProtocolBuilder_ReferencedQActionWithCustomNameAsync() + public void ProtocolCompiler_ProtocolBuilder_ReferencedQActionWithCustomName() { string originalProtocol = @" @@ -513,7 +524,7 @@ public async Task ProtocolCompiler_ProtocolBuilder_ReferencedQActionWithCustomNa ProtocolBuilder builder = new ProtocolBuilder(XmlDocument.Parse(originalProtocol), projects); - string result = (await builder.BuildAsync().ConfigureAwait(false)).Document; + string result = builder.Build().Document; Diff d = DiffBuilder.Compare(Input.FromString(expected)) .WithTest(Input.FromString(result)).Build(); @@ -532,15 +543,13 @@ public void ProtocolCompiler_ProtocolBuilder_MissingQAction() var projects = new Dictionary(); ProtocolBuilder builder = new ProtocolBuilder(XmlDocument.Parse(originalProtocol), projects); - var exception = Assert.ThrowsException(() => builder.BuildAsync().Result); + var exception = Assert.ThrowsException(() => builder.Build()); - Assert.IsNotNull(exception.InnerException); - Assert.IsInstanceOfType(exception.InnerException, typeof(AssemblerException)); - Assert.AreEqual("Project with name 'QAction_1' could not be found!", exception.InnerException.Message); + Assert.AreEqual("Project with name 'QAction_1' could not be found!", exception.Message); } [TestMethod] - public async Task ProtocolCompiler_ProtocolBuilder_MissingNameAsync() + public void ProtocolCompiler_ProtocolBuilder_MissingName() { string originalProtocol = @" @@ -563,7 +572,7 @@ public async Task ProtocolCompiler_ProtocolBuilder_MissingNameAsync() ProtocolBuilder builder = new ProtocolBuilder(XmlDocument.Parse(originalProtocol), projects); - string result = (await builder.BuildAsync().ConfigureAwait(false)).Document; + string result = builder.Build().Document; Diff d = DiffBuilder.Compare(Input.FromString(expected)) .WithTest(Input.FromString(result)).Build(); @@ -572,7 +581,7 @@ public async Task ProtocolCompiler_ProtocolBuilder_MissingNameAsync() } [TestMethod] - public async Task ProtocolCompiler_ProtocolBuilder_JScriptQActionAsync() + public void ProtocolCompiler_ProtocolBuilder_JScriptQAction() { string originalProtocol = @" @@ -598,7 +607,7 @@ public async Task ProtocolCompiler_ProtocolBuilder_JScriptQActionAsync() ProtocolBuilder builder = new ProtocolBuilder(XmlDocument.Parse(originalProtocol), projects); - string result = (await builder.BuildAsync().ConfigureAwait(false)).Document; + string result = builder.Build().Document; Diff d = DiffBuilder.Compare(Input.FromString(expected)) .WithTest(Input.FromString(result)).Build(); @@ -607,7 +616,7 @@ public async Task ProtocolCompiler_ProtocolBuilder_JScriptQActionAsync() } [TestMethod] - public async Task ProtocolCompiler_ProtocolBuilder_SpecialCharactersAsync() + public void ProtocolCompiler_ProtocolBuilder_SpecialCharacters() { string originalProtocol = @" @@ -630,7 +639,7 @@ public async Task ProtocolCompiler_ProtocolBuilder_SpecialCharactersAsync() ProtocolBuilder builder = new ProtocolBuilder(XmlDocument.Parse(originalProtocol), projects); - string result = (await builder.BuildAsync().ConfigureAwait(false)).Document; + string result = builder.Build().Document; Diff d = DiffBuilder.Compare(Input.FromString(expected)) .WithTest(Input.FromString(result)).Build(); @@ -639,7 +648,7 @@ public async Task ProtocolCompiler_ProtocolBuilder_SpecialCharactersAsync() } [TestMethod] - public async Task ProtocolCompiler_Solution_Build() + public void ProtocolCompiler_Solution_Build() { // arrange var baseDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); @@ -650,7 +659,7 @@ public async Task ProtocolCompiler_Solution_Build() // act ProtocolBuilder builder = new ProtocolBuilder(solution); - var buildResultItems = await builder.BuildAsync().ConfigureAwait(false); + var buildResultItems = builder.Build(); string result = buildResultItems.Document; diff --git a/Skyline.DataMiner.CICD.Assemblers.sln b/Skyline.DataMiner.CICD.Assemblers.sln index 6e7cc9b..1d09144 100644 --- a/Skyline.DataMiner.CICD.Assemblers.sln +++ b/Skyline.DataMiner.CICD.Assemblers.sln @@ -11,10 +11,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Assemblers.Automation", "As EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Assemblers.AutomationTests", "Assemblers.AutomationTests\Assemblers.AutomationTests.csproj", "{BEB3AC6D-F2CB-4889-85CB-CFDBF13E87E2}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Assemblers.ProtocolTests", "Assemblers.ProtocolTests\Assemblers.ProtocolTests.csproj", "{856FF1A4-C580-4CFB-AB80-3380CCA6CDDA}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Assemblers.Protocol", "Assemblers.Protocol\Assemblers.Protocol.csproj", "{1B83E0DA-9665-4362-8173-20E375C41E0B}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Assemblers.ProtocolTests", "Assemblers.ProtocolTests\Assemblers.ProtocolTests.csproj", "{5404F875-2C5B-40E6-A440-720E0D6376C0}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -37,14 +37,14 @@ Global {BEB3AC6D-F2CB-4889-85CB-CFDBF13E87E2}.Debug|Any CPU.Build.0 = Debug|Any CPU {BEB3AC6D-F2CB-4889-85CB-CFDBF13E87E2}.Release|Any CPU.ActiveCfg = Release|Any CPU {BEB3AC6D-F2CB-4889-85CB-CFDBF13E87E2}.Release|Any CPU.Build.0 = Release|Any CPU - {856FF1A4-C580-4CFB-AB80-3380CCA6CDDA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {856FF1A4-C580-4CFB-AB80-3380CCA6CDDA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {856FF1A4-C580-4CFB-AB80-3380CCA6CDDA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {856FF1A4-C580-4CFB-AB80-3380CCA6CDDA}.Release|Any CPU.Build.0 = Release|Any CPU {1B83E0DA-9665-4362-8173-20E375C41E0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1B83E0DA-9665-4362-8173-20E375C41E0B}.Debug|Any CPU.Build.0 = Debug|Any CPU {1B83E0DA-9665-4362-8173-20E375C41E0B}.Release|Any CPU.ActiveCfg = Release|Any CPU {1B83E0DA-9665-4362-8173-20E375C41E0B}.Release|Any CPU.Build.0 = Release|Any CPU + {5404F875-2C5B-40E6-A440-720E0D6376C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5404F875-2C5B-40E6-A440-720E0D6376C0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5404F875-2C5B-40E6-A440-720E0D6376C0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5404F875-2C5B-40E6-A440-720E0D6376C0}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 1be2117c9540c1bcc3824592d521cf0a7e7ad5ef Mon Sep 17 00:00:00 2001 From: Pedro Debevere Date: Thu, 2 Nov 2023 08:51:10 +0100 Subject: [PATCH 2/3] remove test --- Assemblers.ProtocolTests/ProtocolBuilderTests.cs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/Assemblers.ProtocolTests/ProtocolBuilderTests.cs b/Assemblers.ProtocolTests/ProtocolBuilderTests.cs index 7161e38..4931590 100644 --- a/Assemblers.ProtocolTests/ProtocolBuilderTests.cs +++ b/Assemblers.ProtocolTests/ProtocolBuilderTests.cs @@ -20,19 +20,6 @@ [TestClass] public class ProtocolBuilderTests { - [TestMethod] - public void TestProtocol() - { - var solutionFilePath = @"D:\TESTING\ConnectorSDKStyle\ConnectorSDKStyle.sln"; - ProtocolSolution solution = ProtocolSolution.Load(solutionFilePath); - ProtocolBuilder builder = new ProtocolBuilder(solution); - - var buildResultItems = builder.Build(); - - File.WriteAllText(@"D:\TESTING\resultProtocol.xml", buildResultItems.Document); - } - - [TestMethod] public void ProtocolCompiler_ProtocolBuilder_Basic() { From 3aa35c5eb859572b3c57ff527a58d17445b563da Mon Sep 17 00:00:00 2001 From: Pedro Debevere Date: Mon, 6 Nov 2023 10:07:40 +0100 Subject: [PATCH 3/3] CR remarks implementation --- Assemblers.Common/ProjectAssetsProcessor.cs | 53 ++------------------- 1 file changed, 4 insertions(+), 49 deletions(-) diff --git a/Assemblers.Common/ProjectAssetsProcessor.cs b/Assemblers.Common/ProjectAssetsProcessor.cs index c70a12b..f87f690 100644 --- a/Assemblers.Common/ProjectAssetsProcessor.cs +++ b/Assemblers.Common/ProjectAssetsProcessor.cs @@ -4,19 +4,12 @@ using System.Collections.Generic; using System.IO; using System.Linq; - using System.Threading; - using System.Threading.Tasks; using NuGet.Common; using NuGet.Configuration; - using NuGet.Frameworks; using NuGet.Packaging; - using NuGet.Packaging.Core; - using NuGet.Packaging.Signing; using NuGet.ProjectModel; - using NuGet.Protocol; using NuGet.Protocol.Core.Types; - using NuGet.Versioning; using Skyline.DataMiner.CICD.Common.NuGet; using Skyline.DataMiner.CICD.FileSystem; @@ -36,13 +29,6 @@ public class ProjectAssetsProcessor private readonly ILogger nuGetLogger; private readonly ICollection repositories; - // V3 package path resolver - //private readonly VersionFolderPathResolver versionFolderPathResolver; - - //private readonly FrameworkReducer frameworkReducer; - - //private readonly SourceRepositoryProvider sourceRepositoryProvider; - private readonly IFileSystem _fileSystem = FileSystem.Instance; @@ -57,20 +43,7 @@ public ProjectAssetsProcessor(string solutionDirectoryPath) // Start with the lowest settings. It will automatically look at the other NuGet.config files it can find on the default locations settings = Settings.LoadDefaultSettings(root: solutionDirectoryPath); - //var provider = new PackageSourceProvider(settings); - //sourceRepositoryProvider = new SourceRepositoryProvider(provider, Repository.Provider.GetCoreV3()); - NuGetRootPath = SettingsUtility.GetGlobalPackagesFolder(settings); - - //// Add global packages to be the first repository as it speeds up everything when reading from disk then via internet. - //var repos = sourceRepositoryProvider.GetRepositories().ToList(); - //repos.Insert(0, new SourceRepository(new PackageSource(NuGetRootPath), Repository.Provider.GetCoreV3())); - //repositories = repos; - - //// https://docs.microsoft.com/en-us/nuget/consume-packages/managing-the-global-packages-and-cache-folders - //versionFolderPathResolver = new VersionFolderPathResolver(NuGetRootPath); - - //frameworkReducer = new FrameworkReducer(); } /// @@ -97,18 +70,6 @@ public ProjectAssetsProcessor(ILogCollector logCollector, string solutionDirecto /// The NuGet root path. public string NuGetRootPath { get; } - /// - /// Processes the NuGet packages. - /// - /// The project to process. - /// The target framework moniker. - /// The assembly info of the processed packages. - /// Cannot find the package with the identity. - public NuGetPackageAssemblyData ProcessAsync(Project project, string targetFrameworkMoniker) - { - return Process(project, targetFrameworkMoniker, new List()); - } - /// /// Processes the NuGet packages. /// @@ -121,19 +82,18 @@ public NuGetPackageAssemblyData Process(Project project, string targetFrameworkM { var nugetPackageAssemblyData = new NuGetPackageAssemblyData(); - var projectAssetsFilePath = Path.Combine(Path.GetDirectoryName(project.Path), "obj\\project.assets.json"); + var projectAssetsFilePath = Path.Combine(Path.GetDirectoryName(project.Path), "obj", "project.assets.json"); if(!File.Exists(projectAssetsFilePath)) { - throw new InvalidOperationException("project.assets.json file not found. Make sure to perform a restore of the project."); + // Projects that do not use any NuGet packages and do not reference any project that uses NuGet packages will not have a project.assets.json file. + return nugetPackageAssemblyData; } var lockFileFormat = new LockFileFormat(); var assetsFileContent = File.ReadAllText(projectAssetsFilePath); var assetsFile = lockFileFormat.Parse(assetsFileContent, "In Memory"); - var targetCount = assetsFile.Targets.Count; - var target = assetsFile.Targets.FirstOrDefault(t => t.Name == targetFrameworkMoniker); if(target == null) @@ -250,14 +210,9 @@ private void ProcessFrameworkItemsOfPackage(LockFileTargetLibrary library, NuGet nugetPackageAssemblyData.DllImportFrameworkAssemblyReferences.AddRange(frameworkItems); } - private static bool IsDevPackNuGetPackage(string packageId) - { - return DevPackHelper.DevPackNuGetPackages.Contains(packageId) || packageId.StartsWith(DevPackHelper.FilesPrefix); - } - private void LogDebug(string message) { - logCollector?.ReportDebug($"PackageReferenceProcessor|{message}"); + logCollector?.ReportDebug($"ProjectAssetsProcessor|{message}"); } } } \ No newline at end of file