From 10f7fac599d9dadfd2e737bc88f5ecf2669009ff Mon Sep 17 00:00:00 2001 From: Alex S Date: Thu, 12 Feb 2026 12:03:45 -0800 Subject: [PATCH 1/6] Emit diagnostic messages --- src/Tasks/CollectDeclaredReferencesTask.cs | 69 ++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/src/Tasks/CollectDeclaredReferencesTask.cs b/src/Tasks/CollectDeclaredReferencesTask.cs index 061d725..1e9eeb9 100644 --- a/src/Tasks/CollectDeclaredReferencesTask.cs +++ b/src/Tasks/CollectDeclaredReferencesTask.cs @@ -61,16 +61,22 @@ public override bool Execute() AppDomain.CurrentDomain.AssemblyResolve += ResolveAssembly; try { + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Starting CollectDeclaredReferencesTask for project '{0}'", MSBuildProjectFile); + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: OutputFile='{0}', TargetFrameworkMoniker='{1}', TargetPlatformMoniker='{2}', RuntimeIdentifier='{3}'", + OutputFile, TargetFrameworkMoniker, TargetPlatformMoniker, RuntimeIdentifier); + List declaredReferences = new(); if (References != null) { + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Processing {0} Reference(s)", References.Length); HashSet targetFrameworkAssemblies = GetTargetFrameworkAssemblyNames(); foreach (ITaskItem reference in References) { // Ignore implicitly defined references (references which are SDK-provided) if (reference.GetMetadata("IsImplicitlyDefined").Equals("true", StringComparison.OrdinalIgnoreCase)) { + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Skipping Reference '{0}' because it is implicitly defined (SDK-provided)", reference.ItemSpec); continue; } @@ -79,18 +85,21 @@ public override bool Execute() // so the resulting reference would be unavoidable. if (targetFrameworkAssemblies.Contains(reference.ItemSpec)) { + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Skipping Reference '{0}' because it is a target framework assembly (resolved via package file conflicts)", reference.ItemSpec); continue; } // Ignore references from packages. Those as handled later. if (reference.GetMetadata("NuGetPackageId").Length != 0) { + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Skipping Reference '{0}' because it comes from NuGet package '{1}' (handled via PackageReferences)", reference.ItemSpec, reference.GetMetadata("NuGetPackageId")); continue; } // Ignore suppressions if (IsSuppressed(reference, "RT0001")) { + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Skipping Reference '{0}' because RT0001 is suppressed (via NoWarn or TreatAsUsed)", reference.ItemSpec); continue; } @@ -101,15 +110,25 @@ public override bool Execute() if (!string.IsNullOrEmpty(referenceHintPath) && File.Exists(referenceHintPath)) { referencePath = Path.GetFullPath(referenceHintPath); + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Reference '{0}' resolved via HintPath to '{1}'", referenceSpec, referencePath); } else if (File.Exists(referenceSpec)) { referencePath = Path.GetFullPath(referenceSpec); + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Reference '{0}' resolved via ItemSpec path to '{1}'", referenceSpec, referencePath); } else { var resolvedReference = ResolvedReferences.SingleOrDefault(rr => string.Equals(rr.GetMetadata("OriginalItemSpec"), referenceSpec, StringComparison.OrdinalIgnoreCase)); referencePath = resolvedReference is null ? null : resolvedReference.ItemSpec; + if (referencePath is not null) + { + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Reference '{0}' resolved via ResolvedReferences to '{1}'", referenceSpec, referencePath); + } + else + { + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Reference '{0}' could not be resolved to a file path", referenceSpec); + } } // If the reference is under the nuget package root, it's likely a Reference added in a package's props or targets. @@ -117,24 +136,32 @@ public override bool Execute() { if (referencePath.StartsWith(NuGetPackageRoot, StringComparison.OrdinalIgnoreCase)) { + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Skipping Reference '{0}' because its resolved path '{1}' is under the NuGet package root (likely added by a package's props/targets)", referenceSpec, referencePath); continue; } } if (referencePath is not null) { + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Including Reference '{0}' with resolved path '{1}'", referenceSpec, referencePath); declaredReferences.Add(new DeclaredReference(referencePath, DeclaredReferenceKind.Reference, referenceSpec)); } } } + else + { + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: No References to process"); + } if (ProjectReferences != null) { + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Processing {0} ProjectReference(s)", ProjectReferences.Length); foreach (ITaskItem projectReference in ProjectReferences) { // Ignore suppressions if (IsSuppressed(projectReference, "RT0002")) { + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Skipping ProjectReference '{0}' because RT0002 is suppressed (via NoWarn or TreatAsUsed)", projectReference.ItemSpec); continue; } @@ -145,48 +172,67 @@ public override bool Execute() if (isTransitiveDependency) { // Ignore transitive project references since the project doesn't have direct control over them. + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Skipping ProjectReference '{0}' because it is a transitive dependency (NuGetPackageId='{1}')", projectReference.ItemSpec, projectReference.GetMetadata("NuGetPackageId")); continue; } string projectReferenceAssemblyPath = Path.GetFullPath(projectReference.ItemSpec); string referenceProjectFile = projectReference.GetMetadata("OriginalProjectReferenceItemSpec"); + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Including ProjectReference '{0}' (project file: '{1}', assembly path: '{2}')", projectReference.ItemSpec, referenceProjectFile, projectReferenceAssemblyPath); declaredReferences.Add(new DeclaredReference(projectReferenceAssemblyPath, DeclaredReferenceKind.ProjectReference, referenceProjectFile)); } } + else + { + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: No ProjectReferences to process"); + } if (PackageReferences != null) { + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Processing {0} PackageReference(s)", PackageReferences.Length); Dictionary packageInfos = GetPackageInfos(); foreach (ITaskItem packageReference in PackageReferences) { // Ignore suppressions if (IsSuppressed(packageReference, "RT0003")) { + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Skipping PackageReference '{0}' because RT0003 is suppressed (via NoWarn or TreatAsUsed)", packageReference.ItemSpec); continue; } if (!packageInfos.TryGetValue(packageReference.ItemSpec, out PackageInfo packageInfo)) { // These are likely Analyzers, tools, etc. + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Skipping PackageReference '{0}' because it has no compile-time assemblies or build files (likely an Analyzer, tool, or content-only package)", packageReference.ItemSpec); continue; } if (packageInfo.BuildFiles.Count > 0) { + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Skipping PackageReference '{0}' because it has build file(s) (packages with build logic are considered used): {1} {2}", Environment.NewLine, packageReference.ItemSpec, string.Join(Environment.NewLine, packageInfo.BuildFiles)); continue; } + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Including PackageReference '{0}' with {1} compile-time assembly(ies)", packageReference.ItemSpec, packageInfo.CompileTimeAssemblies.Count); foreach (string assemblyPath in packageInfo.CompileTimeAssemblies) { + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Assembly: '{0}'", assemblyPath); declaredReferences.Add(new DeclaredReference(assemblyPath, DeclaredReferenceKind.PackageReference, packageReference.ItemSpec)); } } } + else + { + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: No PackageReferences to process"); + } + + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Collected {0} total declared reference(s)", declaredReferences.Count); if (OutputFile is not null) { new DeclaredReferences(declaredReferences).SaveToFile(OutputFile); + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Saved declared references to '{0}'", OutputFile); } } finally @@ -201,14 +247,17 @@ private Dictionary GetPackageInfos() { var packageInfoBuilders = new Dictionary(StringComparer.OrdinalIgnoreCase); + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Loading lock file from '{0}'", ProjectAssetsFile); var lockFile = LockFileUtilities.GetLockFile(ProjectAssetsFile, NullLogger.Instance); var packageFolders = lockFile.PackageFolders.Select(item => item.Path).ToList(); + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Package folders: {0}", string.Join("; ", packageFolders)); LockFileTarget? nugetTarget = null; if (!string.IsNullOrEmpty(TargetFrameworkMoniker)) { var nugetFramework = NuGetFramework.ParseComponents(TargetFrameworkMoniker!, TargetPlatformMoniker); nugetTarget = lockFile.GetTarget(nugetFramework, RuntimeIdentifier); + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Resolved NuGet target framework: '{0}'", nugetFramework); } List nugetLibraries; @@ -217,10 +266,12 @@ private Dictionary GetPackageInfos() nugetLibraries = nugetTarget.Libraries .Where(nugetLibrary => string.Equals(nugetLibrary.Type, "Package", StringComparison.OrdinalIgnoreCase)) .ToList(); + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Found {0} NuGet package library(ies) in lock file target", nugetLibraries.Count); } else { nugetLibraries = new List(); + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: No NuGet target libraries found in lock file"); } // Compute the hierarchy of packages. @@ -268,6 +319,7 @@ private Dictionary GetPackageInfos() { // This can happen if the project has a stale lock file. // Just ignore it as NuGet itself will likely error. + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Package '{0}' could not be found in any package folder (stale lock file?). Skipping.", nugetLibrary.Name); continue; } @@ -289,6 +341,14 @@ private Dictionary GetPackageInfos() .Select(path => Path.Combine(nugetLibraryAbsolutePath, path)) .ToList(); + if (packageToIgnoreBuildFiles.Contains(nugetLibrary.Name) && nugetLibrary.Build.Count > 0) + { + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Package '{0}' has {1} build file(s) but they are ignored via IgnorePackageBuildFiles", nugetLibrary.Name, nugetLibrary.Build.Count); + } + + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Package '{0}' v{1}: {2} compile-time assembly(ies), {3} build file(s)", + nugetLibrary.Name, nugetLibrary.Version, nugetLibraryAssemblies.Count, buildFiles.Count); + // Add this package's assets, if there are any if (nugetLibraryAssemblies.Count > 0 || buildFiles.Count > 0) { @@ -331,6 +391,7 @@ private Dictionary GetPackageInfos() packageInfos.Add(packageInfoBuilder.Key, packageInfoBuilder.Value.ToPackageInfo()); } + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Built package info for {0} package(s)", packageInfos.Count); return packageInfos; } @@ -344,11 +405,13 @@ private HashSet GetTargetFrameworkAssemblyNames() // See: https://github.com/dotnet/sdk/blob/main/src/Tasks/Common/ConflictResolution/FrameworkListReader.cs if (TargetFrameworkDirectories != null) { + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Scanning {0} TargetFrameworkDirectory(ies) for framework assemblies", TargetFrameworkDirectories.Length); foreach (ITaskItem targetFrameworkDirectory in TargetFrameworkDirectories) { string frameworkListPath = Path.Combine(targetFrameworkDirectory.ItemSpec, "RedistList", "FrameworkList.xml"); if (!File.Exists(frameworkListPath)) { + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: FrameworkList.xml not found at '{0}'", frameworkListPath); continue; } @@ -373,6 +436,7 @@ private HashSet GetTargetFrameworkAssemblyNames() } } + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Found {0} target framework assembly name(s)", targetFrameworkAssemblyNames.Count); return targetFrameworkAssemblyNames; } @@ -388,8 +452,13 @@ private HashSet GetTargetFrameworkAssemblyNames() string nugetProjectModelFile = Path.Combine(Path.GetDirectoryName(NuGetRestoreTargets)!, assemblyName.Name + ".dll"); if (File.Exists(nugetProjectModelFile)) { + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Resolved assembly '{0}' from '{1}'", assemblyName.Name, nugetProjectModelFile); return Assembly.LoadFrom(nugetProjectModelFile); } + else + { + Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Could not resolve assembly '{0}' - file not found at '{1}'", assemblyName.Name, nugetProjectModelFile); + } } return null; From 0cee7b0fa411f1874d0c6dd85d418f74c44a4b31 Mon Sep 17 00:00:00 2001 From: Alex S Date: Thu, 12 Feb 2026 12:34:39 -0800 Subject: [PATCH 2/6] update logs --- src/Tasks/CollectDeclaredReferencesTask.cs | 82 ++++++++++------------ 1 file changed, 39 insertions(+), 43 deletions(-) diff --git a/src/Tasks/CollectDeclaredReferencesTask.cs b/src/Tasks/CollectDeclaredReferencesTask.cs index 1e9eeb9..958b93d 100644 --- a/src/Tasks/CollectDeclaredReferencesTask.cs +++ b/src/Tasks/CollectDeclaredReferencesTask.cs @@ -61,22 +61,20 @@ public override bool Execute() AppDomain.CurrentDomain.AssemblyResolve += ResolveAssembly; try { - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Starting CollectDeclaredReferencesTask for project '{0}'", MSBuildProjectFile); - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: OutputFile='{0}', TargetFrameworkMoniker='{1}', TargetPlatformMoniker='{2}', RuntimeIdentifier='{3}'", + Log.LogMessage(MessageImportance.Low, "OutputFile='{0}', TargetFrameworkMoniker='{1}', TargetPlatformMoniker='{2}', RuntimeIdentifier='{3}'", OutputFile, TargetFrameworkMoniker, TargetPlatformMoniker, RuntimeIdentifier); List declaredReferences = new(); if (References != null) { - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Processing {0} Reference(s)", References.Length); HashSet targetFrameworkAssemblies = GetTargetFrameworkAssemblyNames(); foreach (ITaskItem reference in References) { // Ignore implicitly defined references (references which are SDK-provided) if (reference.GetMetadata("IsImplicitlyDefined").Equals("true", StringComparison.OrdinalIgnoreCase)) { - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Skipping Reference '{0}' because it is implicitly defined (SDK-provided)", reference.ItemSpec); + Log.LogMessage(MessageImportance.Low, "Skipping Reference '{0}' because it is implicitly defined (SDK-provided)", reference.ItemSpec); continue; } @@ -85,21 +83,21 @@ public override bool Execute() // so the resulting reference would be unavoidable. if (targetFrameworkAssemblies.Contains(reference.ItemSpec)) { - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Skipping Reference '{0}' because it is a target framework assembly (resolved via package file conflicts)", reference.ItemSpec); + Log.LogMessage(MessageImportance.Low, "Skipping Reference '{0}' because it is a target framework assembly", reference.ItemSpec); continue; } // Ignore references from packages. Those as handled later. if (reference.GetMetadata("NuGetPackageId").Length != 0) { - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Skipping Reference '{0}' because it comes from NuGet package '{1}' (handled via PackageReferences)", reference.ItemSpec, reference.GetMetadata("NuGetPackageId")); + Log.LogMessage(MessageImportance.Low, "Skipping Reference '{0}' because it comes from NuGet package '{1}' (handled via PackageReferences)", reference.ItemSpec, reference.GetMetadata("NuGetPackageId")); continue; } // Ignore suppressions if (IsSuppressed(reference, "RT0001")) { - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Skipping Reference '{0}' because RT0001 is suppressed (via NoWarn or TreatAsUsed)", reference.ItemSpec); + Log.LogMessage(MessageImportance.Low, "Skipping Reference '{0}' because it is suppressed via NoWarn=\"RT0001\" or ", reference.ItemSpec); continue; } @@ -110,12 +108,12 @@ public override bool Execute() if (!string.IsNullOrEmpty(referenceHintPath) && File.Exists(referenceHintPath)) { referencePath = Path.GetFullPath(referenceHintPath); - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Reference '{0}' resolved via HintPath to '{1}'", referenceSpec, referencePath); + Log.LogMessage(MessageImportance.Low, "Reference '{0}' resolved via HintPath to '{1}'", referenceSpec, referencePath); } else if (File.Exists(referenceSpec)) { referencePath = Path.GetFullPath(referenceSpec); - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Reference '{0}' resolved via ItemSpec path to '{1}'", referenceSpec, referencePath); + Log.LogMessage(MessageImportance.Low, "Reference '{0}' resolved via ItemSpec path to '{1}'", referenceSpec, referencePath); } else { @@ -123,11 +121,11 @@ public override bool Execute() referencePath = resolvedReference is null ? null : resolvedReference.ItemSpec; if (referencePath is not null) { - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Reference '{0}' resolved via ResolvedReferences to '{1}'", referenceSpec, referencePath); + Log.LogMessage(MessageImportance.Low, "Reference '{0}' resolved via ResolvedReferences to '{1}'", referenceSpec, referencePath); } else { - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Reference '{0}' could not be resolved to a file path", referenceSpec); + Log.LogMessage(MessageImportance.Low, "Reference '{0}' could not be resolved to a file path", referenceSpec); } } @@ -136,32 +134,31 @@ public override bool Execute() { if (referencePath.StartsWith(NuGetPackageRoot, StringComparison.OrdinalIgnoreCase)) { - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Skipping Reference '{0}' because its resolved path '{1}' is under the NuGet package root (likely added by a package's props/targets)", referenceSpec, referencePath); + Log.LogMessage(MessageImportance.Low, "Skipping Reference '{0}' because its resolved path '{1}' is under the NuGet package root (likely added by a package's props/targets)", referenceSpec, referencePath); continue; } } if (referencePath is not null) { - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Including Reference '{0}' with resolved path '{1}'", referenceSpec, referencePath); + Log.LogMessage(MessageImportance.Low, "Including Reference '{0}' with resolved path '{1}'", referenceSpec, referencePath); declaredReferences.Add(new DeclaredReference(referencePath, DeclaredReferenceKind.Reference, referenceSpec)); } } } else { - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: No References to process"); + Log.LogMessage(MessageImportance.Low, "No References to process"); } if (ProjectReferences != null) { - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Processing {0} ProjectReference(s)", ProjectReferences.Length); foreach (ITaskItem projectReference in ProjectReferences) { // Ignore suppressions if (IsSuppressed(projectReference, "RT0002")) { - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Skipping ProjectReference '{0}' because RT0002 is suppressed (via NoWarn or TreatAsUsed)", projectReference.ItemSpec); + Log.LogMessage(MessageImportance.Low, "Skipping ProjectReference '{0}' because it is suppressed via NoWarn=\"RT0002\" or ", projectReference.ItemSpec); continue; } @@ -172,67 +169,68 @@ public override bool Execute() if (isTransitiveDependency) { // Ignore transitive project references since the project doesn't have direct control over them. - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Skipping ProjectReference '{0}' because it is a transitive dependency (NuGetPackageId='{1}')", projectReference.ItemSpec, projectReference.GetMetadata("NuGetPackageId")); + Log.LogMessage(MessageImportance.Low, "Skipping ProjectReference '{0}' because it is a transitive dependency (NuGetPackageId='{1}')", projectReference.ItemSpec, projectReference.GetMetadata("NuGetPackageId")); continue; } string projectReferenceAssemblyPath = Path.GetFullPath(projectReference.ItemSpec); string referenceProjectFile = projectReference.GetMetadata("OriginalProjectReferenceItemSpec"); - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Including ProjectReference '{0}' (project file: '{1}', assembly path: '{2}')", projectReference.ItemSpec, referenceProjectFile, projectReferenceAssemblyPath); + Log.LogMessage(MessageImportance.Low, "Including ProjectReference '{0}' (project file: '{1}', assembly path: '{2}')", projectReference.ItemSpec, referenceProjectFile, projectReferenceAssemblyPath); declaredReferences.Add(new DeclaredReference(projectReferenceAssemblyPath, DeclaredReferenceKind.ProjectReference, referenceProjectFile)); } } else { - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: No ProjectReferences to process"); + Log.LogMessage(MessageImportance.Low, "No ProjectReferences to process"); } if (PackageReferences != null) { - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Processing {0} PackageReference(s)", PackageReferences.Length); + Log.LogMessage(MessageImportance.Low, "Processing {0} PackageReference(s)", PackageReferences.Length); Dictionary packageInfos = GetPackageInfos(); foreach (ITaskItem packageReference in PackageReferences) { // Ignore suppressions if (IsSuppressed(packageReference, "RT0003")) { - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Skipping PackageReference '{0}' because RT0003 is suppressed (via NoWarn or TreatAsUsed)", packageReference.ItemSpec); + Log.LogMessage(MessageImportance.Low, "Skipping PackageReference '{0}' because it is suppressed via NoWarn=\"RT0003\" or ", packageReference.ItemSpec); continue; } if (!packageInfos.TryGetValue(packageReference.ItemSpec, out PackageInfo packageInfo)) { // These are likely Analyzers, tools, etc. - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Skipping PackageReference '{0}' because it has no compile-time assemblies or build files (likely an Analyzer, tool, or content-only package)", packageReference.ItemSpec); + Log.LogMessage(MessageImportance.Low, "Skipping PackageReference '{0}' because it has no compile-time assemblies or build files (likely an Analyzer, tool, or content-only package)", packageReference.ItemSpec); continue; } if (packageInfo.BuildFiles.Count > 0) { - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Skipping PackageReference '{0}' because it has build file(s) (packages with build logic are considered used): {1} {2}", Environment.NewLine, packageReference.ItemSpec, string.Join(Environment.NewLine, packageInfo.BuildFiles)); + Log.LogMessage(MessageImportance.Low, "Skipping PackageReference '{0}' because it has build {1} file(s):", packageReference.ItemSpec, packageInfo.BuildFiles.Count); + foreach (string buildFile in packageInfo.BuildFiles) + { + Log.LogMessage(MessageImportance.Low, " Build file: '{0}'", buildFile); + } continue; } - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Including PackageReference '{0}' with {1} compile-time assembly(ies)", packageReference.ItemSpec, packageInfo.CompileTimeAssemblies.Count); + Log.LogMessage(MessageImportance.Low, "Including PackageReference '{0}' with {1} compile-time assembly(ies)", packageReference.ItemSpec, packageInfo.CompileTimeAssemblies.Count); foreach (string assemblyPath in packageInfo.CompileTimeAssemblies) { - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Assembly: '{0}'", assemblyPath); declaredReferences.Add(new DeclaredReference(assemblyPath, DeclaredReferenceKind.PackageReference, packageReference.ItemSpec)); } } } else { - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: No PackageReferences to process"); + Log.LogMessage(MessageImportance.Low, "No PackageReferences to process"); } - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Collected {0} total declared reference(s)", declaredReferences.Count); - if (OutputFile is not null) { new DeclaredReferences(declaredReferences).SaveToFile(OutputFile); - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Saved declared references to '{0}'", OutputFile); + Log.LogMessage(MessageImportance.Low, "Saved {0} declared references to '{1}'", declaredReferences.Count, OutputFile); } } finally @@ -247,17 +245,17 @@ private Dictionary GetPackageInfos() { var packageInfoBuilders = new Dictionary(StringComparer.OrdinalIgnoreCase); - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Loading lock file from '{0}'", ProjectAssetsFile); + Log.LogMessage(MessageImportance.Low, "Loading lock file from '{0}'", ProjectAssetsFile); var lockFile = LockFileUtilities.GetLockFile(ProjectAssetsFile, NullLogger.Instance); var packageFolders = lockFile.PackageFolders.Select(item => item.Path).ToList(); - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Package folders: {0}", string.Join("; ", packageFolders)); + Log.LogMessage(MessageImportance.Low, "Package folders: {0}", string.Join("; ", packageFolders)); LockFileTarget? nugetTarget = null; if (!string.IsNullOrEmpty(TargetFrameworkMoniker)) { var nugetFramework = NuGetFramework.ParseComponents(TargetFrameworkMoniker!, TargetPlatformMoniker); nugetTarget = lockFile.GetTarget(nugetFramework, RuntimeIdentifier); - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Resolved NuGet target framework: '{0}'", nugetFramework); + Log.LogMessage(MessageImportance.Low, "Resolved NuGet target framework: '{0}'", nugetFramework); } List nugetLibraries; @@ -266,12 +264,12 @@ private Dictionary GetPackageInfos() nugetLibraries = nugetTarget.Libraries .Where(nugetLibrary => string.Equals(nugetLibrary.Type, "Package", StringComparison.OrdinalIgnoreCase)) .ToList(); - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Found {0} NuGet package library(ies) in lock file target", nugetLibraries.Count); + Log.LogMessage(MessageImportance.Low, "Found {0} NuGet package library(ies) in lock file target", nugetLibraries.Count); } else { nugetLibraries = new List(); - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: No NuGet target libraries found in lock file"); + Log.LogMessage(MessageImportance.Low, "No NuGet target libraries found in lock file"); } // Compute the hierarchy of packages. @@ -319,7 +317,7 @@ private Dictionary GetPackageInfos() { // This can happen if the project has a stale lock file. // Just ignore it as NuGet itself will likely error. - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Package '{0}' could not be found in any package folder (stale lock file?). Skipping.", nugetLibrary.Name); + Log.LogMessage(MessageImportance.Low, "Package '{0}' could not be found in any package folder (stale lock file?). Skipping.", nugetLibrary.Name); continue; } @@ -343,10 +341,10 @@ private Dictionary GetPackageInfos() if (packageToIgnoreBuildFiles.Contains(nugetLibrary.Name) && nugetLibrary.Build.Count > 0) { - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Package '{0}' has {1} build file(s) but they are ignored via IgnorePackageBuildFiles", nugetLibrary.Name, nugetLibrary.Build.Count); + Log.LogMessage(MessageImportance.Low, "Package '{0}' has {1} build file(s) but they are ignored via IgnorePackageBuildFiles", nugetLibrary.Name, nugetLibrary.Build.Count); } - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Package '{0}' v{1}: {2} compile-time assembly(ies), {3} build file(s)", + Log.LogMessage(MessageImportance.Low, "Package '{0}' v{1}: {2} compile-time assembly(ies), {3} build file(s)", nugetLibrary.Name, nugetLibrary.Version, nugetLibraryAssemblies.Count, buildFiles.Count); // Add this package's assets, if there are any @@ -391,7 +389,6 @@ private Dictionary GetPackageInfos() packageInfos.Add(packageInfoBuilder.Key, packageInfoBuilder.Value.ToPackageInfo()); } - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Built package info for {0} package(s)", packageInfos.Count); return packageInfos; } @@ -405,13 +402,13 @@ private HashSet GetTargetFrameworkAssemblyNames() // See: https://github.com/dotnet/sdk/blob/main/src/Tasks/Common/ConflictResolution/FrameworkListReader.cs if (TargetFrameworkDirectories != null) { - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Scanning {0} TargetFrameworkDirectory(ies) for framework assemblies", TargetFrameworkDirectories.Length); + Log.LogMessage(MessageImportance.Low, "Scanning {0} TargetFrameworkDirectory(ies) for framework assemblies", TargetFrameworkDirectories.Length); foreach (ITaskItem targetFrameworkDirectory in TargetFrameworkDirectories) { string frameworkListPath = Path.Combine(targetFrameworkDirectory.ItemSpec, "RedistList", "FrameworkList.xml"); if (!File.Exists(frameworkListPath)) { - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: FrameworkList.xml not found at '{0}'", frameworkListPath); + Log.LogMessage(MessageImportance.Low, "FrameworkList.xml not found at '{0}'", frameworkListPath); continue; } @@ -436,7 +433,6 @@ private HashSet GetTargetFrameworkAssemblyNames() } } - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Found {0} target framework assembly name(s)", targetFrameworkAssemblyNames.Count); return targetFrameworkAssemblyNames; } @@ -452,12 +448,12 @@ private HashSet GetTargetFrameworkAssemblyNames() string nugetProjectModelFile = Path.Combine(Path.GetDirectoryName(NuGetRestoreTargets)!, assemblyName.Name + ".dll"); if (File.Exists(nugetProjectModelFile)) { - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Resolved assembly '{0}' from '{1}'", assemblyName.Name, nugetProjectModelFile); + Log.LogMessage(MessageImportance.Low, "Resolved assembly '{0}' from '{1}'", assemblyName.Name, nugetProjectModelFile); return Assembly.LoadFrom(nugetProjectModelFile); } else { - Log.LogMessage(MessageImportance.Low, "ReferenceTrimmer: Could not resolve assembly '{0}' - file not found at '{1}'", assemblyName.Name, nugetProjectModelFile); + Log.LogMessage(MessageImportance.Low, "Could not resolve assembly '{0}' - file not found at '{1}'", assemblyName.Name, nugetProjectModelFile); } } From 395238b5cb0f75ffd096610c90d1a1abc36eca72 Mon Sep 17 00:00:00 2001 From: Alex S Date: Thu, 12 Feb 2026 12:39:31 -0800 Subject: [PATCH 3/6] Add files to binlog --- src/Package/build/ReferenceTrimmer.targets | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Package/build/ReferenceTrimmer.targets b/src/Package/build/ReferenceTrimmer.targets index 18a6d36..767c619 100644 --- a/src/Package/build/ReferenceTrimmer.targets +++ b/src/Package/build/ReferenceTrimmer.targets @@ -47,9 +47,19 @@ + + + + + + + + \ No newline at end of file From c0d5824972a010777d6a043b0a7addee91506cec Mon Sep 17 00:00:00 2001 From: Alex S Date: Thu, 12 Feb 2026 13:05:33 -0800 Subject: [PATCH 4/6] Shuffle around targets --- src/Package/build/ReferenceTrimmer.targets | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Package/build/ReferenceTrimmer.targets b/src/Package/build/ReferenceTrimmer.targets index 767c619..4220bba 100644 --- a/src/Package/build/ReferenceTrimmer.targets +++ b/src/Package/build/ReferenceTrimmer.targets @@ -49,17 +49,19 @@ - - - - - + + + + + + + \ No newline at end of file From c32ea388edfb3ddc61ea3614a8795cb8fed0767b Mon Sep 17 00:00:00 2001 From: Alex S Date: Thu, 12 Feb 2026 13:20:30 -0800 Subject: [PATCH 5/6] Some log cleanup --- src/Tasks/CollectDeclaredReferencesTask.cs | 23 ++-------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/src/Tasks/CollectDeclaredReferencesTask.cs b/src/Tasks/CollectDeclaredReferencesTask.cs index 958b93d..2b293a1 100644 --- a/src/Tasks/CollectDeclaredReferencesTask.cs +++ b/src/Tasks/CollectDeclaredReferencesTask.cs @@ -61,9 +61,6 @@ public override bool Execute() AppDomain.CurrentDomain.AssemblyResolve += ResolveAssembly; try { - Log.LogMessage(MessageImportance.Low, "OutputFile='{0}', TargetFrameworkMoniker='{1}', TargetPlatformMoniker='{2}', RuntimeIdentifier='{3}'", - OutputFile, TargetFrameworkMoniker, TargetPlatformMoniker, RuntimeIdentifier); - List declaredReferences = new(); if (References != null) @@ -90,7 +87,7 @@ public override bool Execute() // Ignore references from packages. Those as handled later. if (reference.GetMetadata("NuGetPackageId").Length != 0) { - Log.LogMessage(MessageImportance.Low, "Skipping Reference '{0}' because it comes from NuGet package '{1}' (handled via PackageReferences)", reference.ItemSpec, reference.GetMetadata("NuGetPackageId")); + // Logs will be emitted for these references when processing the PackageReferences continue; } @@ -108,25 +105,15 @@ public override bool Execute() if (!string.IsNullOrEmpty(referenceHintPath) && File.Exists(referenceHintPath)) { referencePath = Path.GetFullPath(referenceHintPath); - Log.LogMessage(MessageImportance.Low, "Reference '{0}' resolved via HintPath to '{1}'", referenceSpec, referencePath); } else if (File.Exists(referenceSpec)) { referencePath = Path.GetFullPath(referenceSpec); - Log.LogMessage(MessageImportance.Low, "Reference '{0}' resolved via ItemSpec path to '{1}'", referenceSpec, referencePath); } else { var resolvedReference = ResolvedReferences.SingleOrDefault(rr => string.Equals(rr.GetMetadata("OriginalItemSpec"), referenceSpec, StringComparison.OrdinalIgnoreCase)); referencePath = resolvedReference is null ? null : resolvedReference.ItemSpec; - if (referencePath is not null) - { - Log.LogMessage(MessageImportance.Low, "Reference '{0}' resolved via ResolvedReferences to '{1}'", referenceSpec, referencePath); - } - else - { - Log.LogMessage(MessageImportance.Low, "Reference '{0}' could not be resolved to a file path", referenceSpec); - } } // If the reference is under the nuget package root, it's likely a Reference added in a package's props or targets. @@ -141,7 +128,6 @@ public override bool Execute() if (referencePath is not null) { - Log.LogMessage(MessageImportance.Low, "Including Reference '{0}' with resolved path '{1}'", referenceSpec, referencePath); declaredReferences.Add(new DeclaredReference(referencePath, DeclaredReferenceKind.Reference, referenceSpec)); } } @@ -168,15 +154,12 @@ public override bool Execute() bool isTransitiveDependency = !string.IsNullOrEmpty(projectReference.GetMetadata("NuGetPackageId")); if (isTransitiveDependency) { - // Ignore transitive project references since the project doesn't have direct control over them. - Log.LogMessage(MessageImportance.Low, "Skipping ProjectReference '{0}' because it is a transitive dependency (NuGetPackageId='{1}')", projectReference.ItemSpec, projectReference.GetMetadata("NuGetPackageId")); continue; } string projectReferenceAssemblyPath = Path.GetFullPath(projectReference.ItemSpec); string referenceProjectFile = projectReference.GetMetadata("OriginalProjectReferenceItemSpec"); - Log.LogMessage(MessageImportance.Low, "Including ProjectReference '{0}' (project file: '{1}', assembly path: '{2}')", projectReference.ItemSpec, referenceProjectFile, projectReferenceAssemblyPath); declaredReferences.Add(new DeclaredReference(projectReferenceAssemblyPath, DeclaredReferenceKind.ProjectReference, referenceProjectFile)); } } @@ -187,7 +170,6 @@ public override bool Execute() if (PackageReferences != null) { - Log.LogMessage(MessageImportance.Low, "Processing {0} PackageReference(s)", PackageReferences.Length); Dictionary packageInfos = GetPackageInfos(); foreach (ITaskItem packageReference in PackageReferences) { @@ -201,7 +183,7 @@ public override bool Execute() if (!packageInfos.TryGetValue(packageReference.ItemSpec, out PackageInfo packageInfo)) { // These are likely Analyzers, tools, etc. - Log.LogMessage(MessageImportance.Low, "Skipping PackageReference '{0}' because it has no compile-time assemblies or build files (likely an Analyzer, tool, or content-only package)", packageReference.ItemSpec); + Log.LogMessage(MessageImportance.Low, "Skipping PackageReference '{0}' because it has no compile-time assemblies (likely an Analyzer, tool, or content-only package)", packageReference.ItemSpec); continue; } @@ -215,7 +197,6 @@ public override bool Execute() continue; } - Log.LogMessage(MessageImportance.Low, "Including PackageReference '{0}' with {1} compile-time assembly(ies)", packageReference.ItemSpec, packageInfo.CompileTimeAssemblies.Count); foreach (string assemblyPath in packageInfo.CompileTimeAssemblies) { declaredReferences.Add(new DeclaredReference(assemblyPath, DeclaredReferenceKind.PackageReference, packageReference.ItemSpec)); From d03f1648fced065e7dbe4c2a3b0f1dc8c7ae5362 Mon Sep 17 00:00:00 2001 From: Alex S Date: Thu, 12 Feb 2026 13:22:06 -0800 Subject: [PATCH 6/6] Out back the comment --- src/Tasks/CollectDeclaredReferencesTask.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Tasks/CollectDeclaredReferencesTask.cs b/src/Tasks/CollectDeclaredReferencesTask.cs index 2b293a1..425d624 100644 --- a/src/Tasks/CollectDeclaredReferencesTask.cs +++ b/src/Tasks/CollectDeclaredReferencesTask.cs @@ -154,6 +154,7 @@ public override bool Execute() bool isTransitiveDependency = !string.IsNullOrEmpty(projectReference.GetMetadata("NuGetPackageId")); if (isTransitiveDependency) { + // Ignore transitive project references since the project doesn't have direct control over them. continue; }