diff --git a/.editorconfig b/.editorconfig index 61ac74f8..4c91d0bf 100644 --- a/.editorconfig +++ b/.editorconfig @@ -226,6 +226,7 @@ dotnet_diagnostic.CA1000.severity = none # Do not declare static members on ge dotnet_diagnostic.CA1002.severity = none # Do not expose generic lists dotnet_diagnostic.CA1014.severity = none # Mark assemblies with CLSCompliantAttribute dotnet_diagnostic.CA1034.severity = none # Do not nest types +dotnet_diagnostic.CA1050.severity = none # Declare types in namespaces dotnet_diagnostic.CA1303.severity = none # Do not pass literals as localized parameters dotnet_diagnostic.CA1707.severity = none # Remove the underscores from type name dotnet_diagnostic.CA1720.severity = none # Identifier contains type name diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 9e32a5fc..6f830b21 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -77,9 +77,9 @@ - - - + + + diff --git a/src/xunit.analyzers.fixes/X1000/DataAttributeShouldBeUsedOnATheoryFixer.cs b/src/xunit.analyzers.fixes/X1000/DataAttributeShouldBeUsedOnATheoryFixer.cs index b77b9cbe..0dc6525e 100644 --- a/src/xunit.analyzers.fixes/X1000/DataAttributeShouldBeUsedOnATheoryFixer.cs +++ b/src/xunit.analyzers.fixes/X1000/DataAttributeShouldBeUsedOnATheoryFixer.cs @@ -1,4 +1,5 @@ using System.Composition; +using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; @@ -29,6 +30,13 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) if (methodDeclaration is null) return; + var diagnostic = context.Diagnostics.FirstOrDefault(); + if (diagnostic is null) + return; + + if (!diagnostic.Properties.TryGetValue(Constants.Properties.DataAttributeTypeName, out var dataAttributeTypeName) || dataAttributeTypeName is null) + return; + context.RegisterCodeFix( CodeAction.Create( "Mark as [Theory]", @@ -44,7 +52,7 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) Key_RemoveDataAttributes, context.Document, methodDeclaration.AttributeLists, - Constants.Types.Xunit.Sdk.DataAttribute + dataAttributeTypeName ), context.Diagnostics ); diff --git a/src/xunit.analyzers.fixes/X1000/FactMethodShouldNotHaveTestDataFixer.cs b/src/xunit.analyzers.fixes/X1000/FactMethodShouldNotHaveTestDataFixer.cs index 34244353..15b0d2c1 100644 --- a/src/xunit.analyzers.fixes/X1000/FactMethodShouldNotHaveTestDataFixer.cs +++ b/src/xunit.analyzers.fixes/X1000/FactMethodShouldNotHaveTestDataFixer.cs @@ -1,4 +1,5 @@ using System.Composition; +using System.Linq; using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeFixes; @@ -25,13 +26,20 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) if (methodDeclaration is null) return; + var diagnostic = context.Diagnostics.FirstOrDefault(); + if (diagnostic is null) + return; + + if (!diagnostic.Properties.TryGetValue(Constants.Properties.DataAttributeTypeName, out var dataAttributeTypeName) || dataAttributeTypeName is null) + return; + context.RegisterCodeFix( new RemoveAttributesOfTypeCodeAction( "Remove data attributes", Key_RemoveDataAttributes, context.Document, methodDeclaration.AttributeLists, - Constants.Types.Xunit.Sdk.DataAttribute + dataAttributeTypeName ), context.Diagnostics ); diff --git a/src/xunit.analyzers.tests/Analyzers/X1000/EnsureFixturesHaveASourceTests.cs b/src/xunit.analyzers.tests/Analyzers/X1000/EnsureFixturesHaveASourceTests.cs index 8a226ec9..1b330201 100644 --- a/src/xunit.analyzers.tests/Analyzers/X1000/EnsureFixturesHaveASourceTests.cs +++ b/src/xunit.analyzers.tests/Analyzers/X1000/EnsureFixturesHaveASourceTests.cs @@ -49,7 +49,7 @@ public async Task V3SupportedTypes(string attribute) using Xunit.v3; {attribute} public class TestClass {{ - public TestClass(_ITestOutputHelper _1, ITestContextAccessor _2) {{ }} + public TestClass(ITestOutputHelper _1, ITestContextAccessor _2) {{ }} [Fact] public void TestMethod() {{ }} }}"; diff --git a/src/xunit.analyzers.tests/Utility/CodeAnalyzerHelper.cs b/src/xunit.analyzers.tests/Utility/CodeAnalyzerHelper.cs index 891333a1..a2a6328c 100644 --- a/src/xunit.analyzers.tests/Utility/CodeAnalyzerHelper.cs +++ b/src/xunit.analyzers.tests/Utility/CodeAnalyzerHelper.cs @@ -39,8 +39,8 @@ static CodeAnalyzerHelper() new PackageIdentity("System.Collections.Immutable", "1.6.0"), new PackageIdentity("System.Threading.Tasks.Extensions", "4.5.4"), new PackageIdentity("xunit.abstractions", "2.0.3"), - new PackageIdentity("xunit.assert", "2.8.2-pre.9"), - new PackageIdentity("xunit.core", "2.8.2-pre.9") + new PackageIdentity("xunit.assert", "2.8.2-pre.19"), + new PackageIdentity("xunit.core", "2.8.2-pre.19") ) ); @@ -51,7 +51,7 @@ static CodeAnalyzerHelper() new PackageIdentity("System.Collections.Immutable", "1.6.0"), new PackageIdentity("System.Threading.Tasks.Extensions", "4.5.4"), new PackageIdentity("xunit.abstractions", "2.0.3"), - new PackageIdentity("xunit.runner.utility", "2.8.2-pre.9") + new PackageIdentity("xunit.runner.utility", "2.8.2-pre.19") ) ); @@ -61,9 +61,9 @@ static CodeAnalyzerHelper() new PackageIdentity("Microsoft.Extensions.Primitives", "8.0.0"), new PackageIdentity("System.Threading.Tasks.Extensions", "4.5.4"), new PackageIdentity("System.Text.Json", "8.0.0"), - new PackageIdentity("xunit.v3.assert", "0.1.1-pre.445"), - new PackageIdentity("xunit.v3.common", "0.1.1-pre.445"), - new PackageIdentity("xunit.v3.extensibility.core", "0.1.1-pre.445") + new PackageIdentity("xunit.v3.assert", "0.2.0-pre.4"), + new PackageIdentity("xunit.v3.common", "0.2.0-pre.4"), + new PackageIdentity("xunit.v3.extensibility.core", "0.2.0-pre.4") ) ); @@ -73,8 +73,8 @@ static CodeAnalyzerHelper() new PackageIdentity("Microsoft.Extensions.Primitives", "8.0.0"), new PackageIdentity("System.Threading.Tasks.Extensions", "4.5.4"), new PackageIdentity("System.Text.Json", "8.0.0"), - new PackageIdentity("xunit.v3.common", "0.1.1-pre.445"), - new PackageIdentity("xunit.v3.runner.utility", "0.1.1-pre.445") + new PackageIdentity("xunit.v3.common", "0.2.0-pre.4"), + new PackageIdentity("xunit.v3.runner.utility", "0.2.0-pre.4") ) ); } diff --git a/src/xunit.analyzers.tests/xunit.analyzers.tests.csproj b/src/xunit.analyzers.tests/xunit.analyzers.tests.csproj index 43f6a0a7..888f4179 100644 --- a/src/xunit.analyzers.tests/xunit.analyzers.tests.csproj +++ b/src/xunit.analyzers.tests/xunit.analyzers.tests.csproj @@ -12,12 +12,12 @@ - - - - - - + + + + + + diff --git a/src/xunit.analyzers/Utility/Constants.cs b/src/xunit.analyzers/Utility/Constants.cs index 4a6a5f4e..d1a6f702 100644 --- a/src/xunit.analyzers/Utility/Constants.cs +++ b/src/xunit.analyzers/Utility/Constants.cs @@ -92,6 +92,7 @@ public static class Properties { public const string ArgumentValue = nameof(ArgumentValue); public const string AssertMethodName = nameof(AssertMethodName); + public const string DataAttributeTypeName = nameof(DataAttributeTypeName); public const string DeclaringType = nameof(DeclaringType); public const string IgnoreCase = nameof(IgnoreCase); public const string IsStatic = nameof(IsStatic); @@ -125,15 +126,59 @@ public static class System public static class Xunit { + public const string AssemblyFixtureAttribute_V3 = "Xunit.AssemblyFixtureAttribute"; + public const string Assert = "Xunit.Assert"; + public const string ClassDataAttribute = "Xunit.ClassDataAttribute"; + public const string CollectionAttribute = "Xunit.CollectionAttribute"; + public const string CollectionDefinitionAttribute = "Xunit.CollectionDefinitionAttribute"; + public const string DataAttribute_V2 = "Xunit.Sdk.DataAttribute"; + public const string DataAttribute_V3 = "Xunit.v3.DataAttribute"; public const string FactAttribute = "Xunit.FactAttribute"; - public const string LongLivedMarshalByRefObject = "Xunit.LongLivedMarshalByRefObject"; + public const string IAssemblyInfo_V2 = "Xunit.Abstractions.IAssemblyInfo"; + public const string IAsyncLifetime = "Xunit.IAsyncLifetime"; + public const string IAttributeInfo_V2 = "Xunit.Abstractions.IAttributeInfo"; + public const string IClassFixtureOfT = "Xunit.IClassFixture`1"; + public const string ICollectionFixtureOfT = "Xunit.ICollectionFixture`1"; + public const string IMessageSink_V2 = "Xunit.Abstractions.IMessageSink"; + public const string IMessageSink_V3 = "Xunit.Sdk.IMessageSink"; + public const string IMessageSinkMessage_V2 = "Xunit.Abstractions.IMessageSinkMessage"; + public const string IMethodInfo_V2 = "Xunit.Abstractions.IMethodInfo"; + public const string IParameterInfo_V2 = "Xunit.Abstractions.IParameterInfo"; + public const string InlineDataAttribute = "Xunit.InlineDataAttribute"; + public const string ISourceInformation_V2 = "Xunit.Abstractions.ISourceInformation"; + public const string ISourceInformationProvider_V2 = "Xunit.Abstractions.ISourceInformationProvider"; + public const string ISourceInformationProvider_V3 = "Xunit.Runner.Common.ISourceInformationProvider"; + public const string ITest_V2 = "Xunit.Abstractions.ITest"; + public const string ITest_V3 = "Xunit.Sdk.ITest"; + public const string ITestAssembly_V2 = "Xunit.Abstractions.ITestAssembly"; + public const string ITestAssembly_V3 = "Xunit.Sdk.ITestAssembly"; + public const string ITestCase_V2 = "Xunit.Abstractions.ITestCase"; + public const string ITestCase_V3 = "Xunit.Sdk.ITestCase"; + public const string ITestClass_V2 = "Xunit.Abstractions.ITestClass"; + public const string ITestClass_V3 = "Xunit.Sdk.ITestClass"; + public const string ITestCollection_V2 = "Xunit.Abstractions.ITestCollection"; + public const string ITestCollection_V3 = "Xunit.Sdk.ITestCollection"; + public const string ITestContextAccessor_V3 = "Xunit.ITestContextAccessor"; + public const string ITestFramework_V2 = "Xunit.Abstractions.ITestFramework"; + public const string ITestFramework_V3 = "Xunit.v3.ITestFramework"; + public const string ITestFrameworkDiscoverer_V2 = "Xunit.Abstractions.ITestFrameworkDiscoverer"; + public const string ITestFrameworkDiscoverer_V3 = "Xunit.v3.ITestFrameworkDiscoverer"; + public const string ITestFrameworkExecutor_V2 = "Xunit.Abstractions.ITestFrameworkExecutor"; + public const string ITestFrameworkExecutor_V3 = "Xunit.v3.ITestFrameworkExecutor"; + public const string ITestMethod_V2 = "Xunit.Abstractions.ITestMethod"; + public const string ITestMethod_V3 = "Xunit.Sdk.ITestMethod"; + public const string ITestOutputHelper_V2 = "Xunit.Abstractions.ITestOutputHelper"; + public const string ITestOutputHelper_V3 = "Xunit.ITestOutputHelper"; + public const string ITheoryDataRow_V3 = "Xunit.ITheoryDataRow"; + public const string ITypeInfo_V2 = "Xunit.Abstractions.ITypeInfo"; + public const string IXunitSerializable_V2 = "Xunit.Abstractions.IXunitSerializable"; + public const string IXunitSerializable_V3 = "Xunit.Sdk.IXunitSerializable"; + public const string LongLivedMarshalByRefObject_Execution_V2 = "Xunit.LongLivedMarshalByRefObject"; + public const string LongLivedMarshalByRefObject_RunnerUtility = "Xunit.Sdk.LongLivedMarshalByRefObject"; + public const string MemberDataAttribute = "Xunit.MemberDataAttribute"; public const string TheoryAttribute = "Xunit.TheoryAttribute"; - - public static class Sdk - { - public const string DataAttribute = "Xunit.Sdk.DataAttribute"; - public const string LongLivedMarshalByRefObject = "Xunit.Sdk.LongLivedMarshalByRefObject"; - } + public const string TheoryData = "Xunit.TheoryData"; + public const string TheoryDataRow_V3 = "Xunit.TheoryDataRow"; } } } diff --git a/src/xunit.analyzers/Utility/EmptyAbstractionsContext.cs b/src/xunit.analyzers/Utility/EmptyAbstractionsContext.cs new file mode 100644 index 00000000..9e5de31f --- /dev/null +++ b/src/xunit.analyzers/Utility/EmptyAbstractionsContext.cs @@ -0,0 +1,38 @@ +using System; +using Microsoft.CodeAnalysis; + +namespace Xunit.Analyzers; + +public class EmptyAbstractionsContext : IAbstractionsContext +{ + EmptyAbstractionsContext() + { } + + public static EmptyAbstractionsContext Instance { get; } = new(); + + public INamedTypeSymbol? IMessageSinkType => null; + + public INamedTypeSymbol? ISourceInformationProviderType => null; + + public INamedTypeSymbol? ITestAssemblyType => null; + + public INamedTypeSymbol? ITestCaseType => null; + + public INamedTypeSymbol? ITestClassType => null; + + public INamedTypeSymbol? ITestCollectionType => null; + + public INamedTypeSymbol? ITestFrameworkDiscovererType => null; + + public INamedTypeSymbol? ITestFrameworkExecutorType => null; + + public INamedTypeSymbol? ITestFrameworkType => null; + + public INamedTypeSymbol? ITestMethodType => null; + + public INamedTypeSymbol? ITestType => null; + + public INamedTypeSymbol? IXunitSerializableType => null; + + public Version Version => new(); +} diff --git a/src/xunit.analyzers/Utility/EmptyRunnerUtilityContext.cs b/src/xunit.analyzers/Utility/EmptyRunnerUtilityContext.cs index f090d9fc..0410fcc7 100644 --- a/src/xunit.analyzers/Utility/EmptyRunnerUtilityContext.cs +++ b/src/xunit.analyzers/Utility/EmptyRunnerUtilityContext.cs @@ -1,4 +1,5 @@ using System; +using Microsoft.CodeAnalysis; namespace Xunit.Analyzers; @@ -9,6 +10,8 @@ public class EmptyRunnerUtilityContext : IRunnerUtilityContext public static EmptyRunnerUtilityContext Instance { get; } = new(); + public INamedTypeSymbol? LongLivedMarshalByRefObjectType => null; + public string Platform => "N/A"; public Version Version { get; } = new(); diff --git a/src/xunit.analyzers/Utility/IAbstractionsContext.cs b/src/xunit.analyzers/Utility/IAbstractionsContext.cs new file mode 100644 index 00000000..be5389bd --- /dev/null +++ b/src/xunit.analyzers/Utility/IAbstractionsContext.cs @@ -0,0 +1,76 @@ +using System; +using Microsoft.CodeAnalysis; + +namespace Xunit.Analyzers; + +/// +/// Context with information from xunit.abstractions (in v2) or xunit.v3.common or xunit.v3.core (in v3). +/// The types here are the ones common to both. +/// +public interface IAbstractionsContext +{ + /// + /// Gets a reference to type IMessageSink, if available. + /// + INamedTypeSymbol? IMessageSinkType { get; } + + /// + /// Gets a reference to type ISourceInformationProvider, if available. + /// + INamedTypeSymbol? ISourceInformationProviderType { get; } + + /// + /// Gets a reference to type ITestAssembly, if available. + /// + INamedTypeSymbol? ITestAssemblyType { get; } + + /// + /// Gets a reference to type ITestCase, if available. + /// + INamedTypeSymbol? ITestCaseType { get; } + + /// + /// Gets a reference to type ITestClass, if available. + /// + INamedTypeSymbol? ITestClassType { get; } + + /// + /// Gets a reference to type ITestCollection, if available. + /// + INamedTypeSymbol? ITestCollectionType { get; } + + /// + /// Gets a reference to type ITestFrameworkDiscoverer, if available. + /// + INamedTypeSymbol? ITestFrameworkDiscovererType { get; } + + /// + /// Gets a reference to type ITestFrameworkExecutor, if available. + /// + INamedTypeSymbol? ITestFrameworkExecutorType { get; } + + /// + /// Gets a reference to type ITestFramework, if available. + /// + INamedTypeSymbol? ITestFrameworkType { get; } + + /// + /// Gets a reference to type ITestMethod, if available. + /// + INamedTypeSymbol? ITestMethodType { get; } + + /// + /// Gets a reference to type ITest, if available. + /// + INamedTypeSymbol? ITestType { get; } + + /// + /// Gets a reference to type IXunitSerializable, if available. + /// + INamedTypeSymbol? IXunitSerializableType { get; } + + /// + /// Gets the version number of the xunit.abstractions or xunit.v3.common assembly. + /// + public Version Version { get; } +} diff --git a/src/xunit.analyzers/Utility/ICoreContext.cs b/src/xunit.analyzers/Utility/ICoreContext.cs index eb77f521..977b1e55 100644 --- a/src/xunit.analyzers/Utility/ICoreContext.cs +++ b/src/xunit.analyzers/Utility/ICoreContext.cs @@ -6,59 +6,57 @@ namespace Xunit.Analyzers; public interface ICoreContext { /// - /// Gets a reference to type Xunit.ClassDataAttribute, if available. + /// Gets a reference to type ClassDataAttribute, if available. /// INamedTypeSymbol? ClassDataAttributeType { get; } /// - /// Gets a reference to type Xunit.CollectionAttribute, if available. + /// Gets a reference to type CollectionAttribute, if available. /// INamedTypeSymbol? CollectionAttributeType { get; } /// - /// Gets a reference to type Xunit.CollectionDefinitionAttribute, if available. + /// Gets a reference to type CollectionDefinitionAttribute, if available. /// INamedTypeSymbol? CollectionDefinitionAttributeType { get; } /// - /// Gets a reference to type Xunit.Sdk.DataAttribute, if available. + /// Gets a reference to type DataAttribute, if available. /// INamedTypeSymbol? DataAttributeType { get; } /// - /// Gets a reference to type Xunit.FactAttribute, if available. + /// Gets a reference to type FactAttribute, if available. /// INamedTypeSymbol? FactAttributeType { get; } /// - /// Gets a reference to type Xunit.IClassFixture<T>, if available. + /// Gets a reference to type IClassFixture<T>, if available. /// INamedTypeSymbol? IClassFixtureType { get; } /// - /// Gets a reference to type Xunit.ICollectionFixture<T>, if available. + /// Gets a reference to type ICollectionFixture<T>, if available. /// INamedTypeSymbol? ICollectionFixtureType { get; } /// - /// Gets a reference to type Xunit.InlineDataAttribute, if available. + /// Gets a reference to type InlineDataAttribute, if available. /// INamedTypeSymbol? InlineDataAttributeType { get; } - // TODO: This will need to be updated when v3 names are finalized /// - /// Gets a reference to type Xunit.Abstractions.ITestOutputHelper (v2) - /// or Xunit.v3._ITestOutputHelper, if available. + /// Gets a reference to type ITestOutputHelper, if available. /// INamedTypeSymbol? ITestOutputHelperType { get; } /// - /// Gets a reference to type Xunit.MemberDataAttribute, if available. + /// Gets a reference to type MemberDataAttribute, if available. /// INamedTypeSymbol? MemberDataAttributeType { get; } /// - /// Gets a reference to type Xunit.TheoryAttribute, if available. + /// Gets a reference to type TheoryAttribute, if available. /// INamedTypeSymbol? TheoryAttributeType { get; } diff --git a/src/xunit.analyzers/Utility/IRunnerUtilityContext.cs b/src/xunit.analyzers/Utility/IRunnerUtilityContext.cs index 3a3f20ad..144e3087 100644 --- a/src/xunit.analyzers/Utility/IRunnerUtilityContext.cs +++ b/src/xunit.analyzers/Utility/IRunnerUtilityContext.cs @@ -1,9 +1,15 @@ using System; +using Microsoft.CodeAnalysis; namespace Xunit.Analyzers; public interface IRunnerUtilityContext { + /// + /// Gets a reference to type Xunit.Sdk.LongLivedMarshalByRefObject, if available. + /// + INamedTypeSymbol? LongLivedMarshalByRefObjectType { get; } + /// /// Gets a description of the target platform for the runner utility (i.e., "net452"). This is /// typically extracted from the assembly name (i.e., "xunit.runner.utility.net452"). diff --git a/src/xunit.analyzers/Utility/SerializableTypeSymbols.cs b/src/xunit.analyzers/Utility/SerializableTypeSymbols.cs index 2071713e..5c19f0bb 100644 --- a/src/xunit.analyzers/Utility/SerializableTypeSymbols.cs +++ b/src/xunit.analyzers/Utility/SerializableTypeSymbols.cs @@ -30,16 +30,12 @@ public sealed class SerializableTypeSymbols bigInteger = new(() => TypeSymbolFactory.BigInteger(compilation)); dateOnly = new(() => TypeSymbolFactory.DateOnly(compilation)); dateTimeOffset = new(() => TypeSymbolFactory.DateTimeOffset(compilation)); + iXunitSerializable = new(() => xunitContext.Abstractions.IXunitSerializableType); type = new(() => TypeSymbolFactory.Type(compilation)); timeOnly = new(() => TypeSymbolFactory.TimeOnly(compilation)); timeSpan = new(() => TypeSymbolFactory.TimeSpan(compilation)); traitDictionary = new(() => GetTraitDictionary(compilation)); - if (xunitContext.HasV3References) - iXunitSerializable = new(() => TypeSymbolFactory.IXunitSerializable_V3(compilation)); - else - iXunitSerializable = new(() => xunitContext.V2Abstractions?.IXunitSerializableType); - ClassDataAttribute = classDataAttribute; DataAttribute = dataAttribute; MemberDataAttribute = memberDataAttribute; diff --git a/src/xunit.analyzers/Utility/TypeSymbolFactory.cs b/src/xunit.analyzers/Utility/TypeSymbolFactory.cs index 993b7996..eef9743f 100644 --- a/src/xunit.analyzers/Utility/TypeSymbolFactory.cs +++ b/src/xunit.analyzers/Utility/TypeSymbolFactory.cs @@ -19,10 +19,10 @@ public static class TypeSymbolFactory Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("System.ArraySegment`1"); public static INamedTypeSymbol? AssemblyFixtureAttribute_V3(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.AssemblyFixtureAttribute"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.AssemblyFixtureAttribute_V3); public static INamedTypeSymbol? Assert(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.Assert"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.Assert); public static INamedTypeSymbol? AttributeUsageAttribute(Compilation compilation) => Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("System.AttributeUsageAttribute"); @@ -31,13 +31,13 @@ public static class TypeSymbolFactory Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("System.Numerics.BigInteger"); public static INamedTypeSymbol? ClassDataAttribute(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.ClassDataAttribute"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.ClassDataAttribute); public static INamedTypeSymbol? CollectionAttribute(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.CollectionAttribute"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.CollectionAttribute); public static INamedTypeSymbol? CollectionDefinitionAttribute(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.CollectionDefinitionAttribute"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.CollectionDefinitionAttribute); public static INamedTypeSymbol? ConfigureAwaitOptions(Compilation compilation) => Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("System.Threading.Tasks.ConfigureAwaitOptions"); @@ -45,8 +45,11 @@ public static class TypeSymbolFactory public static INamedTypeSymbol? ConfiguredTaskAwaitable(Compilation compilation) => Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("System.Runtime.CompilerServices.ConfiguredTaskAwaitable"); - public static INamedTypeSymbol? DataAttribute(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.Sdk.DataAttribute); + public static INamedTypeSymbol? DataAttribute_V2(Compilation compilation) => + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.DataAttribute_V2); + + public static INamedTypeSymbol? DataAttribute_V3(Compilation compilation) => + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.DataAttribute_V3); public static INamedTypeSymbol? DateOnly(Compilation compilation) => Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("System.DateOnly"); @@ -66,7 +69,7 @@ public static class TypeSymbolFactory Guard.ArgumentNotNull(compilation).GetTypeByMetadataName($"System.Func`{ValidateArity(arity, min: 1, max: 17)}"); public static INamedTypeSymbol? IAssemblyInfo_V2(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.Abstractions.IAssemblyInfo"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.IAssemblyInfo_V2); public static INamedTypeSymbol? IAsyncEnumerableOfITheoryDataRow(Compilation compilation) { @@ -74,7 +77,7 @@ public static class TypeSymbolFactory if (iAsyncEnumerableOfT is null) return null; - var iTheoryDataRow = ITheoryDataRow(compilation); + var iTheoryDataRow = ITheoryDataRow_V3(compilation); if (iTheoryDataRow is null) return null; @@ -95,19 +98,19 @@ public static class TypeSymbolFactory Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("System.Collections.Generic.IAsyncEnumerable`1"); public static INamedTypeSymbol? IAsyncLifetime(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.IAsyncLifetime"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.IAsyncLifetime); public static INamedTypeSymbol? IAttributeInfo_V2(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.Abstractions.IAttributeInfo"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.IAttributeInfo_V2); public static INamedTypeSymbol? IClassFixureOfT(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.IClassFixture`1"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.IClassFixtureOfT); public static INamedTypeSymbol? ICollection(Compilation compilation) => Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("System.Collections.ICollection"); public static INamedTypeSymbol? ICollectionFixtureOfT(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.ICollectionFixture`1"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.ICollectionFixtureOfT); public static INamedTypeSymbol ICollectionOfT(Compilation compilation) => Guard.ArgumentNotNull(compilation).GetSpecialType(SpecialType.System_Collections_Generic_ICollection_T); @@ -120,7 +123,7 @@ public static INamedTypeSymbol IDisposable(Compilation compilation) => public static INamedTypeSymbol? IEnumerableOfITheoryDataRow(Compilation compilation) { - var iTheoryDataRow = ITheoryDataRow(compilation); + var iTheoryDataRow = ITheoryDataRow_V3(compilation); if (iTheoryDataRow is null) return null; @@ -134,19 +137,22 @@ public static INamedTypeSymbol IEnumerableOfT(Compilation compilation) => Guard.ArgumentNotNull(compilation).GetSpecialType(SpecialType.System_Collections_Generic_IEnumerable_T); public static INamedTypeSymbol? IMessageSink_V2(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.Abstractions.IMessageSink"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.IMessageSink_V2); + + public static INamedTypeSymbol? IMessageSink_V3(Compilation compilation) => + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.IMessageSink_V3); public static INamedTypeSymbol? IMessageSinkMessage_V2(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.Abstractions.IMessageSinkMessage"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.IMessageSinkMessage_V2); public static INamedTypeSymbol? IMethodInfo_V2(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.Abstractions.IMethodInfo"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.IMethodInfo_V2); public static INamedTypeSymbol? InlineDataAttribute(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.InlineDataAttribute"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.InlineDataAttribute); public static INamedTypeSymbol? IParameterInfo_V2(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.Abstractions.IParameterInfo"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.IParameterInfo_V2); public static INamedTypeSymbol? IValueTaskSource(Compilation compilation) => Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("System.Threading.Tasks.Sources.IValueTaskSource"); @@ -164,71 +170,100 @@ public static INamedTypeSymbol IReadOnlyCollectionOfT(Compilation compilation) = Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("System.Collections.Generic.ISet`1"); public static INamedTypeSymbol? ISourceInformation_V2(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.Abstractions.ISourceInformation"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.ISourceInformation_V2); public static INamedTypeSymbol? ISourceInformationProvider_V2(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.Abstractions.ISourceInformationProvider"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.ISourceInformationProvider_V2); + + public static INamedTypeSymbol? ISourceInformationProvider_V3(Compilation compilation) => + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.ISourceInformationProvider_V3); public static INamedTypeSymbol? ITest_V2(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.Abstractions.ITest"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.ITest_V2); + + public static INamedTypeSymbol? ITest_V3(Compilation compilation) => + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.ITest_V3); public static INamedTypeSymbol? ITestAssembly_V2(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.Abstractions.ITestAssembly"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.ITestAssembly_V2); + + public static INamedTypeSymbol? ITestAssembly_V3(Compilation compilation) => + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.ITestAssembly_V3); public static INamedTypeSymbol? ITestCase_V2(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.Abstractions.ITestCase"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.ITestCase_V2); + + public static INamedTypeSymbol? ITestCase_V3(Compilation compilation) => + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.ITestCase_V3); public static INamedTypeSymbol? ITestClass_V2(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.Abstractions.ITestClass"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.ITestClass_V2); + + public static INamedTypeSymbol? ITestClass_V3(Compilation compilation) => + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.ITestClass_V3); public static INamedTypeSymbol? ITestCollection_V2(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.Abstractions.ITestCollection"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.ITestCollection_V2); + + public static INamedTypeSymbol? ITestCollection_V3(Compilation compilation) => + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.ITestCollection_V3); public static INamedTypeSymbol? ITestContextAccessor_V3(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.ITestContextAccessor"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.ITestContextAccessor_V3); public static INamedTypeSymbol? ITestFramework_V2(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.Abstractions.ITestFramework"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.ITestFramework_V2); + + public static INamedTypeSymbol? ITestFramework_V3(Compilation compilation) => + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.ITestFramework_V3); public static INamedTypeSymbol? ITestFrameworkDiscoverer_V2(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.Abstractions.ITestFrameworkDiscoverer"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.ITestFrameworkDiscoverer_V2); + + public static INamedTypeSymbol? ITestFrameworkDiscoverer_V3(Compilation compilation) => + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.ITestFrameworkDiscoverer_V3); public static INamedTypeSymbol? ITestFrameworkExecutor_V2(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.Abstractions.ITestFrameworkExecutor"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.ITestFrameworkExecutor_V2); + + public static INamedTypeSymbol? ITestFrameworkExecutor_V3(Compilation compilation) => + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.ITestFrameworkExecutor_V3); public static INamedTypeSymbol? ITestMethod_V2(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.Abstractions.ITestMethod"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.ITestMethod_V2); + + public static INamedTypeSymbol? ITestMethod_V3(Compilation compilation) => + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.ITestMethod_V3); public static INamedTypeSymbol? ITestOutputHelper_V2(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.Abstractions.ITestOutputHelper"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.ITestOutputHelper_V2); - // TODO: This will need to be updated when v3 names are finalized public static INamedTypeSymbol? ITestOutputHelper_V3(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.v3._ITestOutputHelper"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.ITestOutputHelper_V3); - public static INamedTypeSymbol? ITheoryDataRow(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.ITheoryDataRow"); + public static INamedTypeSymbol? ITheoryDataRow_V3(Compilation compilation) => + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.ITheoryDataRow_V3); public static INamedTypeSymbol? ITypeInfo_V2(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.Abstractions.ITypeInfo"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.ITypeInfo_V2); public static INamedTypeSymbol? IXunitSerializable_V2(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.Abstractions.IXunitSerializable"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.IXunitSerializable_V2); public static INamedTypeSymbol? IXunitSerializable_V3(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.Sdk.IXunitSerializable"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.IXunitSerializable_V3); public static INamedTypeSymbol? ListOfT(Compilation compilation) => Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("System.Collections.Generic.List`1"); public static INamedTypeSymbol? LongLivedMarshalByRefObject_ExecutionV2(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.LongLivedMarshalByRefObject); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.LongLivedMarshalByRefObject_Execution_V2); - public static INamedTypeSymbol? LongLivedMarshalByRefObject_RunnerUtilityV2(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.Sdk.LongLivedMarshalByRefObject); + public static INamedTypeSymbol? LongLivedMarshalByRefObject_RunnerUtility(Compilation compilation) => + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.LongLivedMarshalByRefObject_RunnerUtility); public static INamedTypeSymbol? MemberDataAttribute(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.MemberDataAttribute"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.MemberDataAttribute); public static INamedTypeSymbol NullableOfT(Compilation compilation) => Guard.ArgumentNotNull(compilation).GetSpecialType(SpecialType.System_Nullable_T); @@ -261,7 +296,7 @@ public static INamedTypeSymbol String(Compilation compilation) => Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.TheoryAttribute); public static INamedTypeSymbol? TheoryData(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.TheoryData"); + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.TheoryData); // Centralized here so we don't repeat knowledge of how many arities exist // (in case we decide to add more later). @@ -275,7 +310,7 @@ public static Dictionary TheoryData_ByGenericArgumentCoun for (int i = 1; i <= 10; i++) { - type = compilation.GetTypeByMetadataName("Xunit.TheoryData`" + i.ToString(CultureInfo.InvariantCulture)); + type = compilation.GetTypeByMetadataName(Constants.Types.Xunit.TheoryData + "`" + i.ToString(CultureInfo.InvariantCulture)); if (type is not null) result[i] = type; } @@ -283,25 +318,22 @@ public static Dictionary TheoryData_ByGenericArgumentCoun return result; } - // Namespace fallback for builds before TheoryDataRow was moved from Xunit.Sdk to Xunit, should - // eventually be able to get rid of this fallback once v3 goes 1.0. - public static INamedTypeSymbol? TheoryDataRow(Compilation compilation) => - Guard.ArgumentNotNull(compilation).GetTypeByMetadataName("Xunit.TheoryDataRow") - ?? compilation.GetTypeByMetadataName("Xunit.Sdk.TheoryDataRow"); + public static INamedTypeSymbol? TheoryDataRow_V3(Compilation compilation) => + Guard.ArgumentNotNull(compilation).GetTypeByMetadataName(Constants.Types.Xunit.TheoryDataRow_V3); // Centralized here so we don't repeat knowledge of how many arities exist // (in case we decide to add more later). - public static Dictionary TheoryDataRow_ByGenericArgumentCount(Compilation compilation) + public static Dictionary TheoryDataRow_ByGenericArgumentCount_V3(Compilation compilation) { var result = new Dictionary(); - var type = TheoryDataRow(compilation); + var type = TheoryDataRow_V3(compilation); if (type is not null) result[0] = type; for (int i = 1; i <= 10; i++) { - type = compilation.GetTypeByMetadataName("Xunit.TheoryDataRow`" + i.ToString(CultureInfo.InvariantCulture)); + type = compilation.GetTypeByMetadataName(Constants.Types.Xunit.TheoryDataRow_V3 + "`" + i.ToString(CultureInfo.InvariantCulture)); if (type is not null) result[i] = type; } diff --git a/src/xunit.analyzers/Utility/V2AbstractionsContext.cs b/src/xunit.analyzers/Utility/V2AbstractionsContext.cs index a25f3f9d..4bf98965 100644 --- a/src/xunit.analyzers/Utility/V2AbstractionsContext.cs +++ b/src/xunit.analyzers/Utility/V2AbstractionsContext.cs @@ -4,7 +4,7 @@ namespace Xunit.Analyzers; -public class V2AbstractionsContext +public class V2AbstractionsContext : IAbstractionsContext { readonly Lazy lazyIAssemblyInfoType; readonly Lazy lazyIAttributeInfoType; @@ -54,121 +54,97 @@ public class V2AbstractionsContext } /// - /// Gets a reference to type Xunit.Abstractions.IAssemblyInfo, if available. + /// Gets a reference to type IAssemblyInfo, if available. /// public INamedTypeSymbol? IAssemblyInfoType => lazyIAssemblyInfoType.Value; /// - /// Gets a reference to type Xunit.Abstractions.IAttributeInfo, if available. + /// Gets a reference to type IAttributeInfo, if available. /// public INamedTypeSymbol? IAttributeInfoType => lazyIAttributeInfoType.Value; /// - /// Gets a reference to type Xunit.Abstractions.IMessageSinkMessage, if available. + /// Gets a reference to type IMessageSinkMessage, if available. /// public INamedTypeSymbol? IMessageSinkMessageType => lazyIMessageSinkMessageType.Value; - /// - /// Gets a reference to type Xunit.Abstractions.IMessageSink, if available. - /// + /// public INamedTypeSymbol? IMessageSinkType => lazyIMessageSinkType.Value; /// - /// Gets a reference to type Xunit.Abstractions.IMethodInfo, if available. + /// Gets a reference to type IMethodInfo, if available. /// public INamedTypeSymbol? IMethodInfoType => lazyIMethodInfoType.Value; /// - /// Gets a reference to type Xunit.Abstractions.IParameterInfo, if available. + /// Gets a reference to type IParameterInfo, if available. /// public INamedTypeSymbol? IParameterInfoType => lazyIParameterInfoType.Value; - /// - /// Gets a reference to type Xunit.Abstractions.ISourceInformationProvider, if available. - /// + /// public INamedTypeSymbol? ISourceInformationProviderType => lazyISourceInformationProviderType.Value; /// - /// Gets a reference to type Xunit.Abstractions.ISourceInformation, if available. + /// Gets a reference to type ISourceInformation, if available. /// public INamedTypeSymbol? ISourceInformationType => lazyISourceInformationType.Value; - /// - /// Gets a reference to type Xunit.Abstractions.ITestAssembly, if available. - /// + /// public INamedTypeSymbol? ITestAssemblyType => lazyITestAssemblyType.Value; - /// - /// Gets a reference to type Xunit.Abstractions.ITestCase, if available. - /// + /// public INamedTypeSymbol? ITestCaseType => lazyITestCaseType.Value; - /// - /// Gets a reference to type Xunit.Abstractions.ITestClass, if available. - /// + /// public INamedTypeSymbol? ITestClassType => lazyITestClassType.Value; - /// - /// Gets a reference to type Xunit.Abstractions.ITestCollection, if available. - /// + /// public INamedTypeSymbol? ITestCollectionType => lazyITestCollectionType.Value; - /// - /// Gets a reference to type Xunit.Abstractions.ITestFrameworkDiscoverer, if available. - /// + /// public INamedTypeSymbol? ITestFrameworkDiscovererType => lazyITestFrameworkDiscovererType.Value; - /// - /// Gets a reference to type Xunit.Abstractions.ITestFrameworkExecutor, if available. - /// + /// public INamedTypeSymbol? ITestFrameworkExecutorType => lazyITestFrameworkExecutorType.Value; - /// - /// Gets a reference to type Xunit.Abstractions.ITestFramework, if available. - /// + /// public INamedTypeSymbol? ITestFrameworkType => lazyITestFrameworkType.Value; - /// - /// Gets a reference to type Xunit.Abstractions.ITestMethod, if available. - /// + /// public INamedTypeSymbol? ITestMethodType => lazyITestMethodType.Value; - /// - /// Gets a reference to type Xunit.Abstractions.ITest, if available. - /// + /// public INamedTypeSymbol? ITestType => lazyITestType.Value; /// - /// Gets a reference to type Xunit.Abstractions.ITypeInfo, if available. + /// Gets a reference to type ITypeInfo, if available. /// public INamedTypeSymbol? ITypeInfoType => lazyITypeInfoType.Value; - /// - /// Gets a reference to type Xunit.Abstractions.IXunitSerializable, if available. - /// + /// public INamedTypeSymbol? IXunitSerializableType => lazyIXunitSerializableType.Value; /// - /// Gets the version number of the abstractions assembly. + /// Gets the version number of the xunit.abstractions assembly. /// public Version Version { get; } diff --git a/src/xunit.analyzers/Utility/V2CoreContext.cs b/src/xunit.analyzers/Utility/V2CoreContext.cs index 32a196c8..ca34c2a9 100644 --- a/src/xunit.analyzers/Utility/V2CoreContext.cs +++ b/src/xunit.analyzers/Utility/V2CoreContext.cs @@ -30,7 +30,7 @@ public class V2CoreContext : ICoreContext lazyClassDataAttributeType = new(() => TypeSymbolFactory.ClassDataAttribute(compilation)); lazyCollectionAttributeType = new(() => TypeSymbolFactory.CollectionAttribute(compilation)); lazyCollectionDefinitionAttributeType = new(() => TypeSymbolFactory.CollectionDefinitionAttribute(compilation)); - lazyDataAttributeType = new(() => TypeSymbolFactory.DataAttribute(compilation)); + lazyDataAttributeType = new(() => TypeSymbolFactory.DataAttribute_V2(compilation)); lazyFactAttributeType = new(() => TypeSymbolFactory.FactAttribute(compilation)); lazyIClassFixtureType = new(() => TypeSymbolFactory.IClassFixureOfT(compilation)); lazyICollectionFixtureType = new(() => TypeSymbolFactory.ICollectionFixtureOfT(compilation)); diff --git a/src/xunit.analyzers/Utility/V2RunnerUtilityContext.cs b/src/xunit.analyzers/Utility/V2RunnerUtilityContext.cs index 27ffa2b3..74698cff 100644 --- a/src/xunit.analyzers/Utility/V2RunnerUtilityContext.cs +++ b/src/xunit.analyzers/Utility/V2RunnerUtilityContext.cs @@ -17,12 +17,10 @@ public class V2RunnerUtilityContext : IRunnerUtilityContext Platform = platform; Version = version; - lazyLongLivedMarshalByRefObjectType = new(() => TypeSymbolFactory.LongLivedMarshalByRefObject_RunnerUtilityV2(compilation)); + lazyLongLivedMarshalByRefObjectType = new(() => TypeSymbolFactory.LongLivedMarshalByRefObject_RunnerUtility(compilation)); } - /// - /// Gets a reference to type Xunit.Sdk.LongLivedMarshalByRefObject, if available. - /// + /// public INamedTypeSymbol? LongLivedMarshalByRefObjectType => lazyLongLivedMarshalByRefObjectType.Value; diff --git a/src/xunit.analyzers/Utility/V3AbstractionsContext.cs b/src/xunit.analyzers/Utility/V3AbstractionsContext.cs new file mode 100644 index 00000000..53cdcb44 --- /dev/null +++ b/src/xunit.analyzers/Utility/V3AbstractionsContext.cs @@ -0,0 +1,112 @@ +using System; +using System.Linq; +using Microsoft.CodeAnalysis; + +namespace Xunit.Analyzers; + +// Technically xunit.abstractions doesn't exist in v3; all the co-existent/updated types are present in xunit.v3.common, instead. + +public class V3AbstractionsContext : IAbstractionsContext +{ + readonly Lazy lazyIMessageSinkType; + readonly Lazy lazyISourceInformationProviderType; + readonly Lazy lazyITestAssemblyType; + readonly Lazy lazyITestCaseType; + readonly Lazy lazyITestClassType; + readonly Lazy lazyITestCollectionType; + readonly Lazy lazyITestFrameworkDiscovererType; + readonly Lazy lazyITestFrameworkExecutorType; + readonly Lazy lazyITestFrameworkType; + readonly Lazy lazyITestMethodType; + readonly Lazy lazyITestType; + readonly Lazy lazyIXunitSerializableType; + + V3AbstractionsContext( + Compilation compilation, + Version version) + { + Version = version; + + lazyIMessageSinkType = new(() => TypeSymbolFactory.IMessageSink_V3(compilation)); + lazyISourceInformationProviderType = new(() => TypeSymbolFactory.ISourceInformationProvider_V3(compilation)); + lazyITestAssemblyType = new(() => TypeSymbolFactory.ITestAssembly_V3(compilation)); + lazyITestCaseType = new(() => TypeSymbolFactory.ITestCase_V3(compilation)); + lazyITestClassType = new(() => TypeSymbolFactory.ITestClass_V3(compilation)); + lazyITestCollectionType = new(() => TypeSymbolFactory.ITestCollection_V3(compilation)); + lazyITestFrameworkDiscovererType = new(() => TypeSymbolFactory.ITestFrameworkDiscoverer_V3(compilation)); + lazyITestFrameworkExecutorType = new(() => TypeSymbolFactory.ITestFrameworkExecutor_V3(compilation)); + lazyITestFrameworkType = new(() => TypeSymbolFactory.ITestFramework_V3(compilation)); + lazyITestMethodType = new(() => TypeSymbolFactory.ITestMethod_V3(compilation)); + lazyITestType = new(() => TypeSymbolFactory.ITest_V3(compilation)); + lazyIXunitSerializableType = new(() => TypeSymbolFactory.IXunitSerializable_V3(compilation)); + } + + /// + public INamedTypeSymbol? IMessageSinkType => + lazyIMessageSinkType.Value; + + /// + public INamedTypeSymbol? ISourceInformationProviderType => + lazyISourceInformationProviderType.Value; + + /// + public INamedTypeSymbol? ITestAssemblyType => + lazyITestAssemblyType.Value; + + /// + public INamedTypeSymbol? ITestCaseType => + lazyITestCaseType.Value; + + /// + public INamedTypeSymbol? ITestClassType => + lazyITestClassType.Value; + + /// + public INamedTypeSymbol? ITestCollectionType => + lazyITestCollectionType.Value; + + /// + public INamedTypeSymbol? ITestFrameworkDiscovererType => + lazyITestFrameworkDiscovererType.Value; + + /// + public INamedTypeSymbol? ITestFrameworkExecutorType => + lazyITestFrameworkExecutorType.Value; + + /// + public INamedTypeSymbol? ITestFrameworkType => + lazyITestFrameworkType.Value; + + /// + public INamedTypeSymbol? ITestMethodType => + lazyITestMethodType.Value; + + /// + public INamedTypeSymbol? ITestType => + lazyITestType.Value; + + /// + public INamedTypeSymbol? IXunitSerializableType => + lazyIXunitSerializableType.Value; + + /// + /// Gets the version number of the xunit.v3.common assembly. + /// + public Version Version { get; } + + public static V3AbstractionsContext? Get( + Compilation compilation, + Version? versionOverride = null) + { + Guard.ArgumentNotNull(compilation); + + var version = + versionOverride ?? + compilation + .ReferencedAssemblyNames + .FirstOrDefault(a => a.Name.Equals("xunit.v3.common", StringComparison.OrdinalIgnoreCase)) + ?.Version; + + return version is null ? null : new(compilation, version); + } +} diff --git a/src/xunit.analyzers/Utility/V3CoreContext.cs b/src/xunit.analyzers/Utility/V3CoreContext.cs index 69c8742a..cf94107d 100644 --- a/src/xunit.analyzers/Utility/V3CoreContext.cs +++ b/src/xunit.analyzers/Utility/V3CoreContext.cs @@ -30,7 +30,7 @@ public class V3CoreContext : ICoreContext lazyClassDataAttributeType = new(() => TypeSymbolFactory.ClassDataAttribute(compilation)); lazyCollectionAttributeType = new(() => TypeSymbolFactory.CollectionAttribute(compilation)); lazyCollectionDefinitionAttributeType = new(() => TypeSymbolFactory.CollectionDefinitionAttribute(compilation)); - lazyDataAttributeType = new(() => TypeSymbolFactory.DataAttribute(compilation)); + lazyDataAttributeType = new(() => TypeSymbolFactory.DataAttribute_V3(compilation)); lazyFactAttributeType = new(() => TypeSymbolFactory.FactAttribute(compilation)); lazyIClassFixtureType = new(() => TypeSymbolFactory.IClassFixureOfT(compilation)); lazyICollectionFixtureType = new(() => TypeSymbolFactory.ICollectionFixtureOfT(compilation)); @@ -81,10 +81,7 @@ public class V3CoreContext : ICoreContext public INamedTypeSymbol? ITestContextAccessorType => lazyITestContextAccessorType.Value; - // TODO: This will need to be updated when v3 names are finalized - /// - /// Gets a reference to type Xunit.v3._ITestOutputHelper, if available. - /// + /// public INamedTypeSymbol? ITestOutputHelperType => lazyITestOutputHelperType.Value; diff --git a/src/xunit.analyzers/Utility/V3RunnerUtilityContext.cs b/src/xunit.analyzers/Utility/V3RunnerUtilityContext.cs index 8ee3b886..7d970d2e 100644 --- a/src/xunit.analyzers/Utility/V3RunnerUtilityContext.cs +++ b/src/xunit.analyzers/Utility/V3RunnerUtilityContext.cs @@ -7,15 +7,23 @@ namespace Xunit.Analyzers; public class V3RunnerUtilityContext : IRunnerUtilityContext { const string assemblyPrefix = "xunit.v3.runner.utility."; + readonly Lazy lazyLongLivedMarshalByRefObjectType; V3RunnerUtilityContext( + Compilation compilation, string platform, Version version) { Platform = platform; Version = version; + + lazyLongLivedMarshalByRefObjectType = new(() => TypeSymbolFactory.LongLivedMarshalByRefObject_RunnerUtility(compilation)); } + /// + public INamedTypeSymbol? LongLivedMarshalByRefObjectType => + lazyLongLivedMarshalByRefObjectType.Value; + /// public string Platform { get; } @@ -39,6 +47,6 @@ public class V3RunnerUtilityContext : IRunnerUtilityContext var version = versionOverride ?? assembly.Version; var platform = assembly.Name.Substring(assemblyPrefix.Length); - return version is null ? null : new(platform, version); + return version is null ? null : new(compilation, platform, version); } } diff --git a/src/xunit.analyzers/Utility/XunitContext.cs b/src/xunit.analyzers/Utility/XunitContext.cs index 485aad64..a90b73c8 100644 --- a/src/xunit.analyzers/Utility/XunitContext.cs +++ b/src/xunit.analyzers/Utility/XunitContext.cs @@ -8,6 +8,7 @@ namespace Xunit.Analyzers; /// public class XunitContext { + IAbstractionsContext? abstractions; IAssertContext? assert; ICoreContext? core; IRunnerUtilityContext? runnerUtility; @@ -28,12 +29,26 @@ public XunitContext(Compilation compilation) V2Core = V2CoreContext.Get(compilation); V2Execution = V2ExecutionContext.Get(compilation); V2RunnerUtility = V2RunnerUtilityContext.Get(compilation); + V3Abstractions = V3AbstractionsContext.Get(compilation); V3Assert = V3AssertContext.Get(compilation); V3Core = V3CoreContext.Get(compilation); } /// - /// Gets a combine view of the assertion library features available to either v2 tests (linked + /// Gets a combined view of features available to either v2 tests (linked against + /// xunit.abstractions) or v3 tests (linked against xunit.v3.common and xunit.v3.core). + /// + public IAbstractionsContext Abstractions + { + get + { + abstractions ??= V3Abstractions ?? (IAbstractionsContext?)V2Abstractions ?? EmptyAbstractionsContext.Instance; + return abstractions; + } + } + + /// + /// Gets a combined view of the assertion library features available to either v2 tests (linked /// against xunit.assert or xunit.assert.source) or v3 tests (linked against xunit.v3.assert or /// xunit.v3.assert.source). /// @@ -71,7 +86,7 @@ public ICoreContext Core /// (including assert and core references). /// public bool HasV3References => - V3Assert is not null || V3Core is not null; + V3Abstractions is not null || V3Assert is not null || V3Core is not null; /// /// Gets a combined view of features available to either v2 runners (linked against xunit.runner.utility.*) @@ -116,6 +131,13 @@ public IRunnerUtilityContext RunnerUtility /// public V2RunnerUtilityContext? V2RunnerUtility { get; private set; } + /// + /// Gets information about the v3 equivalent to v2's xunit.abstractions, which comes from a mix + /// of xunit.v3.common and xunit.v3.core. If the project does not reference xunit.v3.common, then + /// returns null. + /// + public V3AbstractionsContext? V3Abstractions { get; private set; } + /// /// Gets information about the reference to xunit.v3.assert or xunit.v3.assert.source (v3). /// If the project does not reference the v3 assertion library, then returns null. @@ -136,7 +158,7 @@ public IRunnerUtilityContext RunnerUtility /// /// Used to create a context object for test purposes, which only contains a reference to - /// xunit.abstraction (which is always set to version 2.0.3, since it did not float version). + /// xunit.abstraction (which is always set to version 2.0.3, since it did not float versions). /// /// The Roslyn compilation object used to look up types public static XunitContext ForV2Abstractions(Compilation compilation) => @@ -146,8 +168,8 @@ public static XunitContext ForV2Abstractions(Compilation compilation) => }; /// - /// Used to create a context object for testing purposes, which is stuck to a specific version - /// of xunit.assert (xunit.abstractions is always version 2.0.3, since it did not float versions). + /// Used to create a context object for testing purposes, which is optionally stuck to a specific version + /// of xunit.assert. /// /// The Roslyn compilation object used to look up types /// The overridden version for xunit.core and xunit.execution.* @@ -160,7 +182,7 @@ public static XunitContext ForV2Assert( }; /// - /// Used to create a context object for testing purposes, which is stuck to a specific version + /// Used to create a context object for testing purposes, which is optionally stuck to a specific version /// of xunit.core (xunit.abstractions is always version 2.0.3, since it did not float versions). /// /// The Roslyn compilation object used to look up types @@ -175,7 +197,7 @@ public static XunitContext ForV2Core( }; /// - /// Used to create a context object for testing purposes, which is stuck to a specific version + /// Used to create a context object for testing purposes, which is optionally stuck to a specific version /// of xunit.execution.* (xunit.abstractions is always version 2.0.3, since it did not float /// versions). /// @@ -191,7 +213,7 @@ public static XunitContext ForV2Execution( }; /// - /// Used to create a context object for testing purposes, which is stuck to a specific version + /// Used to create a context object for testing purposes, which is optionally stuck to a specific version /// of xunit.runner.utility.* (xunit.abstractions is always version 2.0.3, since it did not float /// versions). /// @@ -207,30 +229,32 @@ public static XunitContext ForV2RunnerUtility( }; /// - /// Used to create a context object for testing purposes, which is stuck to a specific version - /// of xunit.assert (xunit.abstractions is always version 2.0.3, since it did not float versions). + /// Used to create a context object for testing purposes, which is optionally stuck to a specific version + /// of the v3 assemblies. /// /// The Roslyn compilation object used to look up types - /// The overridden version for xunit.core and xunit.execution.* + /// The overridden version public static XunitContext ForV3Assert( Compilation compilation, - Version? v2VersionOverride = null) => + Version? v3VersionOverride = null) => new() { - V3Assert = V3AssertContext.Get(compilation, v2VersionOverride), + V3Assert = V3AssertContext.Get(compilation, v3VersionOverride), }; /// - /// Used to create a context object for testing purposes, which is stuck to a specific version - /// of xunit.v3.core. + /// Used to create a context object for testing purposes, which is optionally stuck to a specific version + /// of the v3 assemblies. /// /// The Roslyn compilation object used to look up types - /// The overridden version for xunit.v3.core + /// The overridden version public static XunitContext ForV3Core( Compilation compilation, Version? v3VersionOverride = null) => new() { + V3Abstractions = V3AbstractionsContext.Get(compilation, v3VersionOverride), + V3Assert = V3AssertContext.Get(compilation, v3VersionOverride), V3Core = V3CoreContext.Get(compilation, v3VersionOverride), }; } diff --git a/src/xunit.analyzers/X1000/ClassDataAttributeMustPointAtValidClass.cs b/src/xunit.analyzers/X1000/ClassDataAttributeMustPointAtValidClass.cs index 5a9ec694..9ed3c2b9 100644 --- a/src/xunit.analyzers/X1000/ClassDataAttributeMustPointAtValidClass.cs +++ b/src/xunit.analyzers/X1000/ClassDataAttributeMustPointAtValidClass.cs @@ -38,7 +38,7 @@ public override void AnalyzeCompilation( var iEnumerableOfTheoryDataRow = TypeSymbolFactory.IEnumerableOfITheoryDataRow(compilation); var iAsyncEnumerableOfObjectArray = TypeSymbolFactory.IAsyncEnumerableOfObjectArray(compilation); var iAsyncEnumerableOfTheoryDataRow = TypeSymbolFactory.IAsyncEnumerableOfITheoryDataRow(compilation); - var theoryDataRowTypes = TypeSymbolFactory.TheoryDataRow_ByGenericArgumentCount(compilation); + var theoryDataRowTypes = TypeSymbolFactory.TheoryDataRow_ByGenericArgumentCount_V3(compilation); context.RegisterSyntaxNodeAction(context => { diff --git a/src/xunit.analyzers/X1000/DataAttributeShouldBeUsedOnATheory.cs b/src/xunit.analyzers/X1000/DataAttributeShouldBeUsedOnATheory.cs index e0a82502..68449c83 100644 --- a/src/xunit.analyzers/X1000/DataAttributeShouldBeUsedOnATheory.cs +++ b/src/xunit.analyzers/X1000/DataAttributeShouldBeUsedOnATheory.cs @@ -1,3 +1,5 @@ +using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; @@ -33,12 +35,23 @@ public override void AnalyzeCompilation( // Instead of checking for Theory, we check for any Fact. If it is a Fact which is not a Theory, // we will let other rules (i.e. FactMethodShouldNotHaveTestData) handle that case. if (!attributes.ContainsAttributeType(xunitContext.Core.FactAttributeType) && attributes.ContainsAttributeType(xunitContext.Core.DataAttributeType)) + { + var properties = new Dictionary + { + [Constants.Properties.DataAttributeTypeName] = + xunitContext.HasV3References + ? Constants.Types.Xunit.DataAttribute_V3 + : Constants.Types.Xunit.DataAttribute_V2 + }.ToImmutableDictionary(); + context.ReportDiagnostic( Diagnostic.Create( Descriptors.X1008_DataAttributeShouldBeUsedOnATheory, - methodSymbol.Locations.First() + methodSymbol.Locations.First(), + properties ) ); + } }, SymbolKind.Method); } } diff --git a/src/xunit.analyzers/X1000/FactMethodShouldNotHaveTestData.cs b/src/xunit.analyzers/X1000/FactMethodShouldNotHaveTestData.cs index 84a98cc6..7a225831 100644 --- a/src/xunit.analyzers/X1000/FactMethodShouldNotHaveTestData.cs +++ b/src/xunit.analyzers/X1000/FactMethodShouldNotHaveTestData.cs @@ -1,3 +1,5 @@ +using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; @@ -32,10 +34,19 @@ public override void AnalyzeCompilation( !attributes.ContainsAttributeType(xunitContext.Core.TheoryAttributeType) && attributes.ContainsAttributeType(xunitContext.Core.DataAttributeType)) { + var properties = new Dictionary + { + [Constants.Properties.DataAttributeTypeName] = + xunitContext.HasV3References + ? Constants.Types.Xunit.DataAttribute_V3 + : Constants.Types.Xunit.DataAttribute_V2 + }.ToImmutableDictionary(); + context.ReportDiagnostic( Diagnostic.Create( Descriptors.X1005_FactMethodShouldNotHaveTestData, - symbol.Locations.First() + symbol.Locations.First(), + properties ) ); } diff --git a/src/xunit.analyzers/X1000/MemberDataShouldReferenceValidMember.cs b/src/xunit.analyzers/X1000/MemberDataShouldReferenceValidMember.cs index 02153795..3c93fe42 100644 --- a/src/xunit.analyzers/X1000/MemberDataShouldReferenceValidMember.cs +++ b/src/xunit.analyzers/X1000/MemberDataShouldReferenceValidMember.cs @@ -49,7 +49,7 @@ public override void AnalyzeCompilation( var compilation = context.Compilation; var theoryDataTypes = TypeSymbolFactory.TheoryData_ByGenericArgumentCount(compilation); - var theoryDataRowTypes = TypeSymbolFactory.TheoryDataRow_ByGenericArgumentCount(compilation); + var theoryDataRowTypes = TypeSymbolFactory.TheoryDataRow_ByGenericArgumentCount_V3(compilation); context.RegisterSyntaxNodeAction(context => { diff --git a/src/xunit.analyzers/X1000/TheoryDataRowArgumentsShouldBeSerializable.cs b/src/xunit.analyzers/X1000/TheoryDataRowArgumentsShouldBeSerializable.cs index cc520931..d398d594 100644 --- a/src/xunit.analyzers/X1000/TheoryDataRowArgumentsShouldBeSerializable.cs +++ b/src/xunit.analyzers/X1000/TheoryDataRowArgumentsShouldBeSerializable.cs @@ -23,7 +23,7 @@ public override void AnalyzeCompilation( Guard.ArgumentNotNull(context); Guard.ArgumentNotNull(xunitContext); - var theoryDataRowTypes = TypeSymbolFactory.TheoryDataRow_ByGenericArgumentCount(context.Compilation); + var theoryDataRowTypes = TypeSymbolFactory.TheoryDataRow_ByGenericArgumentCount_V3(context.Compilation); if (theoryDataRowTypes.Count == 0) return; diff --git a/src/xunit.analyzers/X3000/CrossAppDomainClassesMustBeLongLivedMarshalByRefObject.cs b/src/xunit.analyzers/X3000/CrossAppDomainClassesMustBeLongLivedMarshalByRefObject.cs index 4d6bfccb..c8f97179 100644 --- a/src/xunit.analyzers/X3000/CrossAppDomainClassesMustBeLongLivedMarshalByRefObject.cs +++ b/src/xunit.analyzers/X3000/CrossAppDomainClassesMustBeLongLivedMarshalByRefObject.cs @@ -62,8 +62,8 @@ public override void AnalyzeCompilation( var builder = ImmutableDictionary.CreateBuilder(); builder[Constants.Properties.NewBaseType] = - xunitContext.V2RunnerUtility is not null ? Constants.Types.Xunit.Sdk.LongLivedMarshalByRefObject : - xunitContext.V2Execution is not null ? Constants.Types.Xunit.LongLivedMarshalByRefObject : + xunitContext.V2RunnerUtility is not null ? Constants.Types.Xunit.LongLivedMarshalByRefObject_RunnerUtility : + xunitContext.V2Execution is not null ? Constants.Types.Xunit.LongLivedMarshalByRefObject_Execution_V2 : null; context.ReportDiagnostic(