Skip to content

Commit

Permalink
[andrewabestGH-87] Added new convention to enforce that a given proje…
Browse files Browse the repository at this point in the history
…ct doesn't include project references to (any) other projects
  • Loading branch information
eddie.stanley committed Jan 6, 2024
1 parent 5a2ff26 commit 0dce893
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -219,5 +219,27 @@ public void MustBeIncludedInSetOfAssemblies_Failure()
// TODO: Use result.Should().AllSatisfy() once we've updated to fluentassertions 6.5.0+
result.Select(x => x.IsSatisfied).Distinct().Single().Should().BeFalse();
}

[Test]
public void MustNotIncludeProjectReferences_Success()
{
var result = TheAssembly
.WithNameMatching("TestProjectTwo")
.MustConformTo(Convention.MustNotIncludeProjectReferences);

// TestProjectTwo doesn't import any other projects (at time of writing)
result.IsSatisfied.Should().BeTrue();
}

[Test]
public void MustNotIncludeProjectReferences_Failure()
{
var result = TheAssembly
.WithNameMatching("Conventional.Tests")
.MustConformTo(Convention.MustNotIncludeProjectReferences); // It of course includes a reference to Conventional

result.IsSatisfied.Should().BeFalse();
result.Failures.Single().Should().StartWith("Conventional.Tests includes reference to project");
}
}
}
3 changes: 3 additions & 0 deletions src/Core/Conventional/Convention.Assembly.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,5 +81,8 @@ public static MustBeIncludedInSetOfAssembliesConventionSpecification MustBeInclu
{
return new MustBeIncludedInSetOfAssembliesConventionSpecification(assemblies, setName);
}

public static MustNotIncludeProjectReferencesConventionSpecification MustNotIncludeProjectReferences =>
new MustNotIncludeProjectReferencesConventionSpecification();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using System.Xml.XPath;

namespace Conventional.Conventions.Assemblies
{
public class MustNotIncludeProjectReferencesConventionSpecification : AssemblyConventionSpecification
{
protected override ConventionResult IsSatisfiedBy(string assemblyName, XDocument projectDocument)
{
var projectReferences = GetProjectReferences(projectDocument).ToArray();

if (projectReferences.Any())
{
return ConventionResult.NotSatisfied(assemblyName, string.Format(FailureMessage, assemblyName, projectReferences.First()));
}

return ConventionResult.Satisfied(assemblyName);
}

protected override ConventionResult IsSatisfiedByLegacyCsprojFormat(string assemblyName, XDocument projectDocument)
{
return IsSatisfiedBy(assemblyName, projectDocument);
}

private IEnumerable<string> GetProjectReferences(XDocument projectDocument)
{
// The Project element (and descendants) are namespaced in legacy csproj files, so our XPath ignores the
// namespace by considering the local element name only. Once we no-longer need to support legacy csproj
// files, the XPath can be simplified to /Project/ItemGroup/ProjectReference
return projectDocument.XPathSelectElements("/*[local-name() = 'Project']/*[local-name() = 'ItemGroup']/*[local-name() = 'ProjectReference']")
.Select(referenceElement => referenceElement.Attribute("Include")?.Value)
.Where(value => value != null);
}

protected override string FailureMessage => "{0} includes reference to project {1}";
}
}

0 comments on commit 0dce893

Please sign in to comment.