Skip to content

Commit

Permalink
Fix analyzer to account for issue 2557 (#180)
Browse files Browse the repository at this point in the history
  • Loading branch information
JamesTerwilliger authored Feb 7, 2024
1 parent 427f4c2 commit 1e0dae6
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -186,11 +186,11 @@ public class Fixture { }
[CollectionDefinition(""test"")]
public class TestCollection : ICollectionFixture<Fixture> { }
[Collection(""test"")]
public abstract class TestContext {
protected TestContext(Fixture fixture) { }
}
[Collection(""test"")]
public class TestClass : TestContext {
public TestClass(Fixture fixture) : base(fixture) { }
Expand All @@ -201,6 +201,68 @@ public void TestMethod() { }
await Verify.VerifyAnalyzer(source);
}

[Fact]
public async void WithGenericFixture_TriggersWithV2_DoesNotTriggerWithV3()
{
var source = @"
using Xunit;
public class Fixture<T> { }
[CollectionDefinition(""test"")]
public class TestCollection<TCollectionFixture> : ICollectionFixture<Fixture<TCollectionFixture>> { }
[Collection(""test"")]
public class TestClass {
public TestClass(Fixture<int> fixture) { }
[Fact]
public void TestMethod() { }
}";

var expectedV2 =
Verify
.Diagnostic()
.WithSpan(11, 35, 11, 42)
.WithArguments("fixture");

await Verify.VerifyAnalyzerV2(source, expectedV2);
await Verify.VerifyAnalyzerV3(source);
}

[Fact]
public async void WithInheritedGenericFixture_TriggersWithV2_DoesNotTriggerWithV3()
{
var source = @"
using Xunit;
public class Fixture<T> { }
[CollectionDefinition(""test"")]
public class TestCollection<TCollectionFixture> : ICollectionFixture<Fixture<TCollectionFixture>> { }
[Collection(""test"")]
public abstract class TestContext<TContextFixture> {
protected TestContext(Fixture<TContextFixture> fixture) { }
}
public class TestClass : TestContext<int> {
public TestClass(Fixture<int> fixture) : base(fixture) { }
[Fact]
public void TestMethod() { }
}";

var expectedV2 =
Verify
.Diagnostic()
.WithSpan(15, 35, 15, 42)
.WithArguments("fixture");

await Verify.VerifyAnalyzerV2(source, expectedV2);
await Verify.VerifyAnalyzerV3(source);
}

[Theory]
[InlineData("[Collection(nameof(TestCollection))]", "")]
[InlineData("", "[Collection(nameof(TestCollection))]")]
Expand Down
17 changes: 14 additions & 3 deletions src/xunit.analyzers/X1000/EnsureFixturesHaveASource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,17 @@ bool MatchCollectionDefinition(INamedTypeSymbol symbol) =>
{
var unboundGeneric = @interface.ConstructUnboundGenericType();
if (SymbolEqualityComparer.Default.Equals(classFixtureType, unboundGeneric)
|| SymbolEqualityComparer.Default.Equals(collectionFixtureType, unboundGeneric))
validConstructorArgumentTypes.Add(@interface.TypeArguments.First());
|| SymbolEqualityComparer.Default.Equals(collectionFixtureType, unboundGeneric))
{
var fixtureTypeSymbol = @interface.TypeArguments.First();
if (fixtureTypeSymbol is INamedTypeSymbol namedFixtureType)
{
if (xunitContext.HasV3References && namedFixtureType.IsGenericType && namedFixtureType.TypeArguments.Any(t => t is ITypeParameterSymbol))
namedFixtureType = namedFixtureType.ConstructedFrom;

validConstructorArgumentTypes.Add(namedFixtureType);
}
}
}
}
}
Expand All @@ -108,7 +117,9 @@ bool MatchCollectionDefinition(INamedTypeSymbol symbol) =>
.Select(a => a.ConstructorArguments[0].Value as ITypeSymbol)
);

foreach (var parameter in ctors[0].Parameters.Where(p => !p.IsOptional && !validConstructorArgumentTypes.Contains(p.Type)))
foreach (var parameter in ctors[0].Parameters.Where(p => !p.IsOptional
&& !validConstructorArgumentTypes.Contains(p.Type)
&& (xunitContext.HasV2References || p.Type is not INamedTypeSymbol nts || !nts.IsGenericType || !validConstructorArgumentTypes.Contains(nts.ConstructedFrom))))
context.ReportDiagnostic(
Diagnostic.Create(
Descriptors.X1041_EnsureFixturesHaveASource,
Expand Down

0 comments on commit 1e0dae6

Please sign in to comment.