Skip to content

Commit 62e51a9

Browse files
author
eddie.stanley
committed
[andrewabestGH-87] Added convention to enforce a project file treats a given compiler warning as an error
1 parent be5b0b6 commit 62e51a9

File tree

6 files changed

+113
-0
lines changed

6 files changed

+113
-0
lines changed

src/Core/Conventional.Tests/Conventional/Conventions/Assemblies/AssemblyConventionSpecificationTests.cs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,5 +336,61 @@ public void MustSetPropertyValue_NoValues_Failure()
336336
result.IsSatisfied.Should().BeFalse();
337337
result.Failures.Single().Should().Be("SdkClassLibrary1 should have property ThisPropertyShouldNeverEverExist with value x");
338338
}
339+
340+
[Theory]
341+
[TestCase("CS0162")]
342+
[TestCase("CS4014")]
343+
public void MustTreatWarningAsError_MultipleWarnings_Success(string warning)
344+
{
345+
var result = TheAssembly
346+
.WithNameMatching("TestProjectTwo")
347+
.MustConformTo(Convention.MustTreatWarningAsError(warning));
348+
349+
result.IsSatisfied.Should().BeTrue();
350+
}
351+
352+
[Test]
353+
public void MustTreatWarningAsError_SingleWarning_Success()
354+
{
355+
var result = TheAssembly
356+
.WithNameMatching("SdkClassLibrary1")
357+
.MustConformTo(Convention.MustTreatWarningAsError("CS0162"));
358+
359+
result.IsSatisfied.Should().BeTrue();
360+
}
361+
362+
[Test]
363+
public void MustTreatWarningAsError_MultipleWarnings_Failure()
364+
{
365+
var result = TheAssembly
366+
.WithNameMatching("TestProjectTwo")
367+
.MustConformTo(Convention.MustTreatWarningAsError("XX9999"));
368+
369+
result.IsSatisfied.Should().BeFalse();
370+
result.Failures.Single().Should().Be("Assembly TestProjectTwo should treat warning XX9999 as an error but does not");
371+
}
372+
373+
[Test]
374+
public void MustTreatWarningAsError_SingleWarnings_Failure()
375+
{
376+
var result = TheAssembly
377+
.WithNameMatching("SdkClassLibrary1")
378+
.MustConformTo(Convention.MustTreatWarningAsError("XX9999"));
379+
380+
result.IsSatisfied.Should().BeFalse();
381+
result.Failures.Single().Should().Be("Assembly SdkClassLibrary1 should treat warning XX9999 as an error but does not");
382+
}
383+
384+
[Test]
385+
public void MustTreatWarningAsError_NoWarnings_Failure()
386+
{
387+
var result = TheAssembly
388+
.WithNameMatching("TestSolution.TestProject")
389+
.MustConformTo(Convention.MustTreatWarningAsError("CS0162"));
390+
391+
// TestSolution.TestProject does not set the WarningsAsErrors property, at time of writing
392+
result.IsSatisfied.Should().BeFalse();
393+
result.Failures.Single().Should().Be("Assembly TestSolution.TestProject should treat warning CS0162 as an error but does not");
394+
}
339395
}
340396
}

src/Core/Conventional/Convention.Assembly.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,5 +121,15 @@ public static MustSetPropertyValueAssemblyConventionSpecification MustSetPropert
121121
{
122122
return new MustSetPropertyValueAssemblyConventionSpecification(propertyName, value);
123123
}
124+
125+
/// <summary>
126+
/// Require this project to treat the specified compiler warning as an error
127+
/// </summary>
128+
/// <param name="warning">The warning code to treat as fatal (e.g. CS0162)</param>
129+
/// <remarks>This convention is unaware of shared build prop files (Directory.Build.Props + Directory.Build.Targets) - see https://github.com/andrewabest/Conventional/issues/88</remarks>
130+
public static MustTreatWarningAsErrorAssemblyConventionSpecification MustTreatWarningAsError(string warning)
131+
{
132+
return new MustTreatWarningAsErrorAssemblyConventionSpecification(warning);
133+
}
124134
}
125135
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
using System;
2+
using System.Linq;
3+
using System.Xml.Linq;
4+
using System.Xml.XPath;
5+
6+
namespace Conventional.Conventions.Assemblies
7+
{
8+
public class MustTreatWarningAsErrorAssemblyConventionSpecification : AssemblyConventionSpecification
9+
{
10+
private readonly string _warning;
11+
12+
public MustTreatWarningAsErrorAssemblyConventionSpecification(string warning)
13+
{
14+
_warning = warning;
15+
}
16+
17+
protected override ConventionResult IsSatisfiedByLegacyCsprojFormat(string assemblyName, XDocument projectDocument)
18+
{
19+
return IsSatisfiedBy(assemblyName, projectDocument);
20+
}
21+
22+
protected override ConventionResult IsSatisfiedBy(string assemblyName, XDocument projectDocument)
23+
{
24+
// The Project element (and descendants) are namespaced in legacy csproj files, so our XPath ignores the
25+
// namespace by considering the local element name only. Once we no-longer need to support legacy csproj
26+
// files, the XPath can be simplified to /Project/ItemGroup/ProjectReference
27+
var warningsAsErrors = projectDocument.XPathSelectElements("/*[local-name() = 'Project']/*[local-name() = 'PropertyGroup']/*[local-name() = 'WarningsAsErrors']")
28+
.SingleOrDefault()
29+
?.Value ?? "";
30+
31+
var warnings = warningsAsErrors.Split(new[] {' ', ','}, StringSplitOptions.RemoveEmptyEntries);
32+
if (!warnings.Contains(_warning))
33+
{
34+
return ConventionResult.NotSatisfied(assemblyName, string.Format(FailureMessage, assemblyName, _warning));
35+
}
36+
37+
return ConventionResult.Satisfied(assemblyName);
38+
}
39+
40+
protected override string FailureMessage => "Assembly {0} should treat warning {1} as an error but does not";
41+
}
42+
}

src/Core/TestSolution/TestProjectTwo/TestProjectTwo.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
<AssemblyName>TestProjectTwo</AssemblyName>
1212
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
1313
<FileAlignment>512</FileAlignment>
14+
<WarningsAsErrors>CS0162,CS4014</WarningsAsErrors>
1415
</PropertyGroup>
1516
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
1617
<DebugSymbols>true</DebugSymbols>
Binary file not shown.

src/Core/TestSolution/TestSolution.TestProject/SdkClassLibrary1/SdkClassLibrary1.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
<PropertyGroup>
1010
<TargetFramework>netstandard2.1</TargetFramework>
1111
</PropertyGroup>
12+
13+
<PropertyGroup>
14+
<WarningsAsErrors>CS0162</WarningsAsErrors>
15+
</PropertyGroup>
1216

1317
<ItemGroup>
1418
<PackageReference Include="coverlet.collector" Version="6.0.0">

0 commit comments

Comments
 (0)