Repository: xunit/xunit.analyzers
Branch: main
Commit: 8da2743cb286
Files: 373
Total size: 1.3 MB
Directory structure:
gitextract_bu8u1mqd/
├── .config/
│ └── dotnet-tools.json
├── .editorconfig
├── .gitattributes
├── .github/
│ ├── FUNDING.yml
│ └── workflows/
│ ├── ci-signed.yaml
│ ├── ci-unsigned.yaml
│ └── pull-request.yaml
├── .gitignore
├── .gitmodules
├── .vscode/
│ ├── launch.json
│ ├── settings.json
│ └── tasks.json
├── BUILDING.md
├── LICENSE
├── NuGet.Config
├── README.md
├── build
├── build.ps1
├── global.json
├── src/
│ ├── Directory.Build.props
│ ├── Directory.Build.targets
│ ├── common/
│ │ ├── CallerArgumentExpressionAttribute.cs
│ │ └── Guard.cs
│ ├── compat/
│ │ ├── Directory.Build.props
│ │ ├── xunit.analyzers.latest/
│ │ │ └── xunit.analyzers.latest.csproj
│ │ ├── xunit.analyzers.latest.fixes/
│ │ │ └── xunit.analyzers.latest.fixes.csproj
│ │ └── xunit.analyzers.latest.tests/
│ │ └── xunit.analyzers.latest.tests.csproj
│ ├── signing.snk
│ ├── xunit.analyzers/
│ │ ├── Properties/
│ │ │ └── AssemblyInfo.cs
│ │ ├── Suppressors/
│ │ │ ├── ConsiderCallingConfigureAwaitSuppressor.cs
│ │ │ ├── MakeTypesInternalSuppressor.cs
│ │ │ ├── NonNullableFieldInitializationSuppressor.cs
│ │ │ └── UseAsyncSuffixForAsyncMethodsSuppressor.cs
│ │ ├── Utility/
│ │ │ ├── AssertUsageAnalyzerBase.cs
│ │ │ ├── Category.cs
│ │ │ ├── CodeAnalysisExtensions.cs
│ │ │ ├── Constants.cs
│ │ │ ├── ConversionChecker.cs
│ │ │ ├── Descriptors.Suppressors.cs
│ │ │ ├── Descriptors.cs
│ │ │ ├── Descriptors.xUnit1xxx.cs
│ │ │ ├── Descriptors.xUnit2xxx.cs
│ │ │ ├── Descriptors.xUnit3xxx.cs
│ │ │ ├── EmptyAssertContext.cs
│ │ │ ├── EmptyCommonContext.cs
│ │ │ ├── EmptyCoreContext.cs
│ │ │ ├── EmptyRunnerUtilityContext.cs
│ │ │ ├── EnumerableExtensions.cs
│ │ │ ├── IAssertContext.cs
│ │ │ ├── ICommonContext.cs
│ │ │ ├── ICoreContext.cs
│ │ │ ├── IRunnerUtilityContext.cs
│ │ │ ├── Serializability.cs
│ │ │ ├── SerializabilityAnalyzer.cs
│ │ │ ├── SerializableTypeSymbols.cs
│ │ │ ├── SymbolExtensions.cs
│ │ │ ├── SyntaxExtensions.cs
│ │ │ ├── TypeHierarchyComparer.cs
│ │ │ ├── TypeSymbolFactory.cs
│ │ │ ├── V2AbstractionsContext.cs
│ │ │ ├── V2AssertContext.cs
│ │ │ ├── V2CoreContext.cs
│ │ │ ├── V2ExecutionContext.cs
│ │ │ ├── V2RunnerUtilityContext.cs
│ │ │ ├── V3AssertContext.cs
│ │ │ ├── V3CommonContext.cs
│ │ │ ├── V3CoreContext.cs
│ │ │ ├── V3RunnerCommonContext.cs
│ │ │ ├── V3RunnerUtilityContext.cs
│ │ │ ├── XunitContext.cs
│ │ │ ├── XunitDiagnosticAnalyzer.cs
│ │ │ ├── XunitDiagnosticSuppressor.cs
│ │ │ ├── XunitV2DiagnosticAnalyzer.cs
│ │ │ ├── XunitV2DiagnosticSuppressor.cs
│ │ │ ├── XunitV3DiagnosticAnalyzer.cs
│ │ │ └── XunitV3DiagnosticSuppressor.cs
│ │ ├── X1000/
│ │ │ ├── ClassDataAttributeMustPointAtValidClass.cs
│ │ │ ├── CollectionDefinitionsMustBePublic.cs
│ │ │ ├── ConstructorsOnFactAttributeSubclassShouldBePublic.cs
│ │ │ ├── DataAttributeShouldBeUsedOnATheory.cs
│ │ │ ├── DoNotUseAsyncVoidForTestMethods.cs
│ │ │ ├── DoNotUseBlockingTaskOperations.cs
│ │ │ ├── DoNotUseConfigureAwait.cs
│ │ │ ├── EnsureFixturesHaveASource.cs
│ │ │ ├── FactMethodMustNotHaveParameters.cs
│ │ │ ├── FactMethodShouldNotHaveTestData.cs
│ │ │ ├── InlineDataMustMatchTheoryParameters.cs
│ │ │ ├── InlineDataShouldBeUniqueWithinTheory.cs
│ │ │ ├── LocalFunctionsCannotBeTestFunctions.cs
│ │ │ ├── MemberDataShouldReferenceValidMember.cs
│ │ │ ├── PublicMethodShouldBeMarkedAsTest.cs
│ │ │ ├── TestClassCannotBeNestedInGenericClass.cs
│ │ │ ├── TestClassMustBePublic.cs
│ │ │ ├── TestClassShouldHaveTFixtureArgument.cs
│ │ │ ├── TestMethodCannotHaveOverloads.cs
│ │ │ ├── TestMethodMustNotHaveMultipleFactAttributes.cs
│ │ │ ├── TestMethodShouldNotBeSkipped.cs
│ │ │ ├── TestMethodSupportedReturnType.cs
│ │ │ ├── TheoryDataRowArgumentsShouldBeSerializable.cs
│ │ │ ├── TheoryDataShouldNotUseTheoryDataRow.cs
│ │ │ ├── TheoryDataTypeArgumentsShouldBeSerializable.cs
│ │ │ ├── TheoryMethodCannotHaveDefaultParameter.cs
│ │ │ ├── TheoryMethodCannotHaveParamsArray.cs
│ │ │ ├── TheoryMethodMustHaveTestData.cs
│ │ │ ├── TheoryMethodShouldHaveParameters.cs
│ │ │ ├── TheoryMethodShouldUseAllParameters.cs
│ │ │ └── UseCancellationToken.cs
│ │ ├── X2000/
│ │ │ ├── AssertCollectionContainsShouldNotUseBoolCheck.cs
│ │ │ ├── AssertEmptyCollectionCheckShouldNotBeUsed.cs
│ │ │ ├── AssertEmptyOrNotEmptyShouldNotBeUsedForContainsChecks.cs
│ │ │ ├── AssertEnumerableAnyCheckShouldNotBeUsedForCollectionContainsCheck.cs
│ │ │ ├── AssertEqualGenericShouldNotBeUsedForStringValue.cs
│ │ │ ├── AssertEqualLiteralValueShouldBeFirst.cs
│ │ │ ├── AssertEqualPrecisionShoulBeInRange.cs
│ │ │ ├── AssertEqualShouldNotBeUsedForBoolLiteralCheck.cs
│ │ │ ├── AssertEqualShouldNotBeUsedForCollectionSizeCheck.cs
│ │ │ ├── AssertEqualShouldNotBeUsedForNullCheck.cs
│ │ │ ├── AssertEqualsShouldNotBeUsed.cs
│ │ │ ├── AssertIsTypeShouldNotBeUsedForAbstractType.cs
│ │ │ ├── AssertIsTypeShouldUseGenericOverloadType.cs
│ │ │ ├── AssertNullShouldNotBeCalledOnValueTypes.cs
│ │ │ ├── AssertRegexMatchShouldNotUseBoolLiteralCheck.cs
│ │ │ ├── AssertSameShouldNotBeCalledOnValueTypes.cs
│ │ │ ├── AssertSingleShouldBeUsedForSingleParameter.cs
│ │ │ ├── AssertSingleShouldUseTwoArgumentCall.cs
│ │ │ ├── AssertStringEqualityCheckShouldNotUseBoolCheck.cs
│ │ │ ├── AssertSubstringCheckShouldNotUseBoolCheck.cs
│ │ │ ├── AssertThrowsShouldNotBeUsedForAsyncThrowsCheck.cs
│ │ │ ├── AssertThrowsShouldUseGenericOverloadCheck.cs
│ │ │ ├── AssignableFromAssertionIsConfusinglyNamed.cs
│ │ │ ├── AsyncAssertsShouldBeAwaited.cs
│ │ │ ├── BooleanAssertsShouldNotBeNegated.cs
│ │ │ ├── BooleanAssertsShouldNotBeUsedForSimpleEqualityCheck.cs
│ │ │ ├── DoNotUseAssertEmptyWithProblematicTypes.cs
│ │ │ ├── SetEqualityAnalyzer.cs
│ │ │ └── UseAssertFailInsteadOfBooleanAssert.cs
│ │ ├── X3000/
│ │ │ ├── CrossAppDomainClassesMustBeLongLivedMarshalByRefObject.cs
│ │ │ ├── DoNotTestForConcreteTypeOfJsonSerializableTypes.cs
│ │ │ ├── FactAttributeDerivedClassesShouldProvideSourceInformationConstructor.cs
│ │ │ └── SerializableClassMustHaveParameterlessConstructor.cs
│ │ ├── xunit.analyzers.csproj
│ │ └── xunit.analyzers.nuspec
│ ├── xunit.analyzers.fixes/
│ │ ├── Properties/
│ │ │ └── AssemblyInfo.cs
│ │ ├── Utility/
│ │ │ ├── AsyncHelper.cs
│ │ │ ├── CodeAnalysisExtensions.cs
│ │ │ ├── ConvertAttributeCodeAction.cs
│ │ │ ├── RemoveAttributesOfTypeCodeAction.cs
│ │ │ ├── XunitCodeAction.cs
│ │ │ ├── XunitCodeFixProvider.cs
│ │ │ └── XunitMemberFixProvider.cs
│ │ ├── X1000/
│ │ │ ├── ClassDataAttributeMustPointAtValidClassFixer.cs
│ │ │ ├── CollectionDefinitionClassesMustBePublicFixer.cs
│ │ │ ├── ConvertToFactFix.cs
│ │ │ ├── ConvertToTheoryFix.cs
│ │ │ ├── DataAttributeShouldBeUsedOnATheoryFixer.cs
│ │ │ ├── DoNotUseAsyncVoidForTestMethodsFixer.cs
│ │ │ ├── DoNotUseConfigureAwaitFixer.cs
│ │ │ ├── FactMethodMustNotHaveParametersFixer.cs
│ │ │ ├── FactMethodShouldNotHaveTestDataFixer.cs
│ │ │ ├── InlineDataMustMatchTheoryParameters_ExtraValueFixer.cs
│ │ │ ├── InlineDataMustMatchTheoryParameters_NullShouldNotBeUsedForIncompatibleParameterFixer.cs
│ │ │ ├── InlineDataMustMatchTheoryParameters_TooFewValuesFixer.cs
│ │ │ ├── InlineDataShouldBeUniqueWithinTheoryFixer.cs
│ │ │ ├── LocalFunctionsCannotBeTestFunctionsFixer.cs
│ │ │ ├── MemberDataShouldReferenceValidMember_ExtraValueFixer.cs
│ │ │ ├── MemberDataShouldReferenceValidMember_NameOfFixer.cs
│ │ │ ├── MemberDataShouldReferenceValidMember_NullShouldNotBeUsedForIncompatibleParameterFixer.cs
│ │ │ ├── MemberDataShouldReferenceValidMember_ParamsForNonMethodFixer.cs
│ │ │ ├── MemberDataShouldReferenceValidMember_ReturnTypeFixer.cs
│ │ │ ├── MemberDataShouldReferenceValidMember_StaticFixer.cs
│ │ │ ├── MemberDataShouldReferenceValidMember_VisibilityFixer.cs
│ │ │ ├── PublicMethodShouldBeMarkedAsTestFixer.cs
│ │ │ ├── RemoveMethodParameterFix.cs
│ │ │ ├── TestClassCannotBeNestedInGenericClassFixer.cs
│ │ │ ├── TestClassMustBePublicFixer.cs
│ │ │ ├── TestClassShouldHaveTFixtureArgumentFixer.cs
│ │ │ ├── TestMethodMustNotHaveMultipleFactAttributesFixer.cs
│ │ │ ├── TestMethodShouldNotBeSkippedFixer.cs
│ │ │ ├── TheoryDataShouldNotUseTheoryDataRowFixer.cs
│ │ │ ├── TheoryMethodCannotHaveDefaultParameterFixer.cs
│ │ │ └── UseCancellationTokenFixer.cs
│ │ ├── X2000/
│ │ │ ├── AssertCollectionContainsShouldNotUseBoolCheckFixer.cs
│ │ │ ├── AssertEmptyCollectionCheckShouldNotBeUsedFixer.cs
│ │ │ ├── AssertEmptyOrNotEmptyShouldNotBeUsedForContainsChecksFixer.cs
│ │ │ ├── AssertEnumerableAnyCheckShouldNotBeUsedForCollectionContainsCheckFixer.cs
│ │ │ ├── AssertEqualGenericShouldNotBeUsedForStringValueFixer.cs
│ │ │ ├── AssertEqualLiteralValueShouldBeFirstFixer.cs
│ │ │ ├── AssertEqualPrecisionShouldBeInRangeFixer.cs
│ │ │ ├── AssertEqualShouldNotBeUsedForBoolLiteralCheckFixer.cs
│ │ │ ├── AssertEqualShouldNotBeUsedForCollectionSizeCheckFixer.cs
│ │ │ ├── AssertEqualShouldNotBeUsedForNullCheckFixer.cs
│ │ │ ├── AssertEqualsShouldNotBeUsedFixer.cs
│ │ │ ├── AssertIsTypeShouldNotBeUsedForAbstractTypeFixer.cs
│ │ │ ├── AssertNullShouldNotBeCalledOnValueTypesFixer.cs
│ │ │ ├── AssertRegexMatchShouldNotUseBoolLiteralCheckFixer.cs
│ │ │ ├── AssertSameShouldNotBeCalledOnValueTypesFixer.cs
│ │ │ ├── AssertSingleShouldBeUsedForSingleParameterFixer.cs
│ │ │ ├── AssertSingleShouldUseTwoArgumentCallFixer.cs
│ │ │ ├── AssertStringEqualityCheckShouldNotUseBoolCheckFixer.cs
│ │ │ ├── AssertSubstringCheckShouldNotUseBoolCheckFixer.cs
│ │ │ ├── AssertThrowsShouldNotBeUsedForAsyncThrowsCheckFixer.cs
│ │ │ ├── AssignableFromAssertionIsConfusinglyNamedFixer.cs
│ │ │ ├── AsyncAssertsShouldBeAwaitedFixer.cs
│ │ │ ├── BooleanAssertsShouldNotBeNegatedFixer.cs
│ │ │ ├── BooleanAssertsShouldNotBeUsedForSimpleEqualityCheckBooleanFixer.cs
│ │ │ ├── BooleanAssertsShouldNotBeUsedForSimpleEqualityCheckNonBooleanFixer.cs
│ │ │ ├── UseAssertFailInsteadOfBooleanAssertFixer.cs
│ │ │ └── UseGenericOverloadFix.cs
│ │ ├── X3000/
│ │ │ ├── CrossAppDomainClassesMustBeLongLivedMarshalByRefObjectFixer.cs
│ │ │ └── SerializableClassMustHaveParameterlessConstructorFixer.cs
│ │ ├── tools/
│ │ │ ├── install.ps1
│ │ │ └── uninstall.ps1
│ │ └── xunit.analyzers.fixes.csproj
│ └── xunit.analyzers.tests/
│ ├── Analyzers/
│ │ ├── X1000/
│ │ │ ├── ClassDataAttributeMustPointAtValidClassTests.cs
│ │ │ ├── CollectionDefinitionClassesMustBePublicTests.cs
│ │ │ ├── ConstructorsOnFactAttributeSubclassShouldBePublicTests.cs
│ │ │ ├── DataAttributeShouldBeUsedOnATheoryTests.cs
│ │ │ ├── DoNotUseAsyncVoidForTestMethodsTests.cs
│ │ │ ├── DoNotUseBlockingTaskOperationsTests.cs
│ │ │ ├── DoNotUseConfigureAwaitTests.cs
│ │ │ ├── EnsureFixturesHaveASourceTests.cs
│ │ │ ├── FactMethodMustNotHaveParametersTests.cs
│ │ │ ├── FactMethodShouldNotHaveTestDataTests.cs
│ │ │ ├── InlineDataMustMatchTheoryParametersTests.cs
│ │ │ ├── InlineDataShouldBeUniqueWithinTheoryTests.cs
│ │ │ ├── LocalFunctionsCannotBeTestFunctionsTests.cs
│ │ │ ├── MemberDataShouldReferenceValidMemberTests.cs
│ │ │ ├── PublicMethodShouldBeMarkedAsTestTests.cs
│ │ │ ├── TestClassCannotBeNestedInGenericClassTests.cs
│ │ │ ├── TestClassMustBePublicTests.cs
│ │ │ ├── TestClassShouldHaveTFixtureArgumentTests.cs
│ │ │ ├── TestMethodCannotHaveOverloadsTests.cs
│ │ │ ├── TestMethodMustNotHaveMultipleFactAttributesTests.cs
│ │ │ ├── TestMethodShouldNotBeSkippedTests.cs
│ │ │ ├── TestMethodSupportedReturnTypeTests.cs
│ │ │ ├── TheoryDataRowArgumentsShouldBeSerializableTests.cs
│ │ │ ├── TheoryDataShouldNotUseTheoryDataRowTests.cs
│ │ │ ├── TheoryDataTypeArgumentsShouldBeSerializableTests.cs
│ │ │ ├── TheoryMethodCannotHaveDefaultParameterTests.cs
│ │ │ ├── TheoryMethodCannotHaveParamsArrayTests.cs
│ │ │ ├── TheoryMethodMustHaveTestDataTests.cs
│ │ │ ├── TheoryMethodShouldHaveParametersTests.cs
│ │ │ ├── TheoryMethodShouldUseAllParametersTests.cs
│ │ │ └── UseCancellationTokenTests.cs
│ │ ├── X2000/
│ │ │ ├── AssertCollectionContainsShouldNotUseBoolCheckTests.cs
│ │ │ ├── AssertEmptyCollectionCheckShouldNotBeUsedTests.cs
│ │ │ ├── AssertEmptyOrNotEmptyShouldNotBeUsedForContainsChecksTests.cs
│ │ │ ├── AssertEnumerableAnyCheckShouldNotBeUsedForCollectionContainsCheckTests.cs
│ │ │ ├── AssertEqualGenericShouldNotBeUsedForStringValueTests.cs
│ │ │ ├── AssertEqualLiteralValueShouldBeFirstTests.cs
│ │ │ ├── AssertEqualPrecisionShouldBeInRangeTest.cs
│ │ │ ├── AssertEqualShouldNotBeUsedForBoolLiteralCheckTests.cs
│ │ │ ├── AssertEqualShouldNotBeUsedForCollectionSizeCheckTests.cs
│ │ │ ├── AssertEqualShouldNotBeUsedForNullCheckTests.cs
│ │ │ ├── AssertEqualsShouldNotBeUsedTests.cs
│ │ │ ├── AssertIsTypeShouldNotBeUsedForAbstractTypeTests.cs
│ │ │ ├── AssertIsTypeShouldUseGenericOverloadTypeTests.cs
│ │ │ ├── AssertNullShouldNotBeCalledOnValueTypesTests.cs
│ │ │ ├── AssertRegexMatchShouldNotUseBoolLiteralCheckTests.cs
│ │ │ ├── AssertSameShouldNotBeCalledOnValueTypesTests.cs
│ │ │ ├── AssertSingleShouldBeUsedForSingleParameterTests.cs
│ │ │ ├── AssertSingleShouldUseTwoArgumentCallTests.cs
│ │ │ ├── AssertStringEqualityCheckShouldNotUseBoolCheckTest.cs
│ │ │ ├── AssertSubstringCheckShouldNotUseBoolCheckTests.cs
│ │ │ ├── AssertThrowsShouldNotBeUsedForAsyncThrowsCheckTests.cs
│ │ │ ├── AssertThrowsShouldUseGenericOverloadCheckTests.cs
│ │ │ ├── AssignableFromAssertionIsConfusinglyNamedTests.cs
│ │ │ ├── AsyncAssertsShouldBeAwaitedTests.cs
│ │ │ ├── BooleanAssertsShouldNotBeNegatedTests.cs
│ │ │ ├── BooleanAssertsShouldNotBeUsedForSimpleEqualityCheckTests.cs
│ │ │ ├── DoNotUseAssertEmptyWithProblematicTypesTests.cs
│ │ │ ├── SetEqualityAnalyzerTests.cs
│ │ │ └── UseAssertFailInsteadOfBooleanAssertTests.cs
│ │ └── X3000/
│ │ ├── CrossAppDomainClassesMustBeLongLivedMarshalByRefObjectTests.cs
│ │ ├── DoNotTestForConcreteTypeOfJsonSerializableTypesTests.cs
│ │ ├── FactAttributeDerivedClassesShouldProvideSourceInformationConstructorTests.cs
│ │ └── SerializableClassMustHaveParameterlessConstructorTests.cs
│ ├── Fixes/
│ │ ├── X1000/
│ │ │ ├── ClassDataAttributeMustPointAtValidClassFixerTests.cs
│ │ │ ├── CollectionDefinitionClassesMustBePublicFixerTests.cs
│ │ │ ├── ConvertToFactFixTests.cs
│ │ │ ├── ConvertToTheoryFixTests.cs
│ │ │ ├── DataAttributeShouldBeUsedOnATheoryFixerTests.cs
│ │ │ ├── DoNotUseAsyncVoidForTestMethodsFixerTests.cs
│ │ │ ├── DoNotUseConfigureAwaitFixerTests.cs
│ │ │ ├── FactMethodMustNotHaveParametersFixerTests.cs
│ │ │ ├── FactMethodShouldNotHaveTestDataFixerTests.cs
│ │ │ ├── InlineDataMustMatchTheoryParameters_ExtraValueFixerTests.cs
│ │ │ ├── InlineDataMustMatchTheoryParameters_NullShouldNotBeUsedForIncompatibleParameterFixerTests.cs
│ │ │ ├── InlineDataMustMatchTheoryParameters_TooFewValuesFixerTests.cs
│ │ │ ├── InlineDataShouldBeUniqueWithinTheoryFixerTests.cs
│ │ │ ├── LocalFunctionsCannotBeTestFunctionsFixerTests.cs
│ │ │ ├── MemberDataShouldReferenceValidMember_ExtraValueFixerTests.cs
│ │ │ ├── MemberDataShouldReferenceValidMember_NameOfFixerTests.cs
│ │ │ ├── MemberDataShouldReferenceValidMember_NullShouldNotBeUsedForIncompatibleParameterFixerTests.cs
│ │ │ ├── MemberDataShouldReferenceValidMember_ParamsForNonMethodFixerTests.cs
│ │ │ ├── MemberDataShouldReferenceValidMember_ReturnTypeFixerTests.cs
│ │ │ ├── MemberDataShouldReferenceValidMember_StaticFixerTests.cs
│ │ │ ├── MemberDataShouldReferenceValidMember_VisibilityFixerTests.cs
│ │ │ ├── PublicMethodShouldBeMarkedAsTestFixerTests.cs
│ │ │ ├── RemoveMethodParameterFixTests.cs
│ │ │ ├── TestClassCannotBeNestedInGenericClassFixerTests.cs
│ │ │ ├── TestClassMustBePublicFixerTests.cs
│ │ │ ├── TestClassShouldHaveTFixtureArgumentFixerTests.cs
│ │ │ ├── TestMethodMustNotHaveMultipleFactAttributesFixerTests.cs
│ │ │ ├── TestMethodShouldNotBeSkippedFixerTests.cs
│ │ │ ├── TheoryDataShouldNotUseTheoryDataRowFixerTests.cs
│ │ │ ├── TheoryMethodCannotHaveDefaultParameterFixerTests.cs
│ │ │ └── UseCancellationTokenFixerTests.cs
│ │ ├── X2000/
│ │ │ ├── AssertCollectionContainsShouldNotUseBoolCheckFixerTests.cs
│ │ │ ├── AssertEmptyCollectionCheckShouldNotBeUsedFixerTests.cs
│ │ │ ├── AssertEmptyOrNotEmptyShouldNotBeUsedForContainsChecksFixerTests.cs
│ │ │ ├── AssertEnumerableAnyCheckShouldNotBeUsedForCollectionContainsCheckFixerTests.cs
│ │ │ ├── AssertEqualGenericShouldNotBeUsedForStringValueFixerTests.cs
│ │ │ ├── AssertEqualLiteralValueShouldBeFirstFixerTests.cs
│ │ │ ├── AssertEqualPrecisionShouldBeInRangeFixerTests.cs
│ │ │ ├── AssertEqualShouldNotBeUsedForBoolLiteralCheckFixerTests.cs
│ │ │ ├── AssertEqualShouldNotBeUsedForCollectionSizeCheckFixerTests.cs
│ │ │ ├── AssertEqualShouldNotBeUsedForNullCheckFixerTests.cs
│ │ │ ├── AssertEqualsShouldNotBeUsedFixerTests.cs
│ │ │ ├── AssertIsTypeShouldNotBeUsedForAbstractTypeFixerTests.cs
│ │ │ ├── AssertNullShouldNotBeCalledOnValueTypesFixerTests.cs
│ │ │ ├── AssertRegexMatchShouldNotUseBoolLiteralCheckFixerTests.cs
│ │ │ ├── AssertSameShouldNotBeCalledOnValueTypesFixerTests.cs
│ │ │ ├── AssertSingleShouldBeUsedForSingleParameterFixerTests.cs
│ │ │ ├── AssertSingleShouldUseTwoArgumentCallFixerTests.cs
│ │ │ ├── AssertStringEqualityCheckShouldNotUseBoolCheckFixerTests.cs
│ │ │ ├── AssertSubstringCheckShouldNotUseBoolCheckFixerTests.cs
│ │ │ ├── AssertThrowsShouldNotBeUsedForAsyncThrowsCheckFixerTests.cs
│ │ │ ├── AssignableFromAssertionIsConfusinglyNamedFixerTests.cs
│ │ │ ├── AsyncAssertsShouldBeAwaitedFixerTests.cs
│ │ │ ├── BooleanAssertsShouldNotBeNegatedFixerTests.cs
│ │ │ ├── BooleanAssertsShouldNotBeUsedForSimpleEqualityCheckBooleanFixerTests.cs
│ │ │ ├── BooleanAssertsShouldNotBeUsedForSimpleEqualityCheckNonBooleanFixerTests.cs
│ │ │ ├── UseAssertFailInsteadOfBooleanAssertFixerTests.cs
│ │ │ └── UseGenericOverloadFixTests.cs
│ │ └── X3000/
│ │ ├── CrossAppDomainClassesMustBeLongLivedMarshalByRefObjectFixerTests.cs
│ │ └── SerializableClassMustHaveParameterlessConstructorFixerTests.cs
│ ├── Suppressors/
│ │ ├── ConsiderCallingConfigureAwaitSuppressorTests.cs
│ │ ├── MakeTypesInternalSuppressorTests.cs
│ │ ├── NonNullableFieldInitializationSuppressorTests.cs
│ │ └── UseAsyncSuffixForAsyncMethodsSuppressorTests.cs
│ ├── Utility/
│ │ ├── 3rdPartyAnalyzers/
│ │ │ ├── AnalyzerLoaderBase.cs
│ │ │ ├── CodeAnalysisNetAnalyzers.cs
│ │ │ └── VsThreadingAnalyzers.cs
│ │ ├── AssertsExtensions/
│ │ │ ├── EmptyException.cs
│ │ │ ├── EqualException.cs
│ │ │ └── NotEmptyException.cs
│ │ ├── CSharpVerifier.Analyzers.RunnerUtility.cs
│ │ ├── CSharpVerifier.Analyzers.cs
│ │ ├── CSharpVerifier.CodeFixes.RunnerUtility.cs
│ │ ├── CSharpVerifier.CodeFixes.cs
│ │ ├── CSharpVerifier.Suppressors.cs
│ │ ├── CSharpVerifier.cs
│ │ ├── CodeAnalyzerHelper.cs
│ │ ├── CodeFixProviderDiscovery.cs
│ │ ├── XunitVerifier.cs
│ │ ├── XunitVerifierV2.cs
│ │ └── XunitVerifierV3.cs
│ ├── xunit.analyzers.tests.csproj
│ └── xunit.runner.json
├── tools/
│ ├── SignClient/
│ │ └── appsettings.json
│ └── builder/
│ ├── .vscode/
│ │ ├── launch.json
│ │ ├── settings.json
│ │ └── tasks.json
│ ├── Program.cs
│ ├── build.csproj
│ ├── models/
│ │ └── BuildContext.cs
│ └── targets/
│ ├── Build.cs
│ ├── Packages.cs
│ ├── SignAssemblies.cs
│ └── Test.cs
├── version.json
└── xunit.analyzers.sln
================================================
FILE CONTENTS
================================================
================================================
FILE: .config/dotnet-tools.json
================================================
{
"version": 1,
"isRoot": true,
"tools": {
"sign": {
"version": "0.9.1-beta.25330.2",
"commands": [
"sign"
],
"rollForward": false
}
}
}
================================================
FILE: .editorconfig
================================================
# top-most EditorConfig file
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = tab
[*.{ps1,sln}]
end_of_line = crlf
# Visual Studio demands 2-spaced project files
# Tabs are not legal whitespace for YAML files
[*.{csproj,json,props,targets,xslt,yaml,yml}]
indent_style = space
indent_size = 2
[*.cs]
# Organize usings
dotnet_separate_import_directive_groups = false
dotnet_sort_system_directives_first = true
file_header_template = unset
# this. and Me. preferences
dotnet_style_qualification_for_event = false
dotnet_style_qualification_for_field = false
dotnet_style_qualification_for_method = false
dotnet_style_qualification_for_property = false
# Language keywords vs BCL types preferences
dotnet_style_predefined_type_for_locals_parameters_members = true
dotnet_style_predefined_type_for_member_access = true
# Parentheses preferences
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity
dotnet_style_parentheses_in_other_operators = never_if_unnecessary
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity
# Modifier preferences
dotnet_style_require_accessibility_modifiers = for_non_interface_members
# Expression-level preferences
dotnet_style_coalesce_expression = true
dotnet_style_collection_initializer = true
dotnet_style_explicit_tuple_names = true
dotnet_style_namespace_match_folder = false
dotnet_style_null_propagation = true
dotnet_style_object_initializer = true
dotnet_style_operator_placement_when_wrapping = beginning_of_line
dotnet_style_prefer_auto_properties = true
dotnet_style_prefer_compound_assignment = true
dotnet_style_prefer_conditional_expression_over_assignment = true
dotnet_style_prefer_conditional_expression_over_return = false
dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed
dotnet_style_prefer_inferred_anonymous_type_member_names = true
dotnet_style_prefer_inferred_tuple_names = true
dotnet_style_prefer_is_null_check_over_reference_equality_method = true
dotnet_style_prefer_simplified_boolean_expressions = true
dotnet_style_prefer_simplified_interpolation = true
# Field preferences
dotnet_style_readonly_field = true
# Parameter preferences
dotnet_code_quality_unused_parameters = all
# Suppression preferences
dotnet_remove_unnecessary_suppression_exclusions = none
# New line preferences
dotnet_style_allow_multiple_blank_lines_experimental = true
dotnet_style_allow_statement_immediately_after_block_experimental = true
#### C# Coding Conventions ####
# var preferences
csharp_style_var_elsewhere = true
csharp_style_var_for_built_in_types = true
csharp_style_var_when_type_is_apparent = true
# Expression-bodied members
csharp_style_expression_bodied_accessors = true
csharp_style_expression_bodied_constructors = false
csharp_style_expression_bodied_indexers = true
csharp_style_expression_bodied_lambdas = true
csharp_style_expression_bodied_local_functions = false
csharp_style_expression_bodied_methods = false
csharp_style_expression_bodied_operators = false
csharp_style_expression_bodied_properties = true
# Pattern matching preferences
csharp_style_pattern_matching_over_as_with_null_check = true
csharp_style_pattern_matching_over_is_with_cast_check = true
csharp_style_prefer_extended_property_pattern = true
csharp_style_prefer_not_pattern = true
csharp_style_prefer_pattern_matching = true
csharp_style_prefer_switch_expression = true
# Null-checking preferences
csharp_style_conditional_delegate_call = true
# Modifier preferences
csharp_prefer_static_local_function = true
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async
# Code-block preferences
csharp_prefer_braces = false
csharp_prefer_simple_using_statement = true
csharp_style_namespace_declarations = file_scoped
# Expression-level preferences
csharp_prefer_simple_default_expression = true
csharp_style_deconstructed_variable_declaration = true
csharp_style_implicit_object_creation_when_type_is_apparent = true
csharp_style_inlined_variable_declaration = true
csharp_style_pattern_local_over_anonymous_function = true
csharp_style_prefer_index_operator = true
csharp_style_prefer_null_check_over_type_check = true
csharp_style_prefer_range_operator = true
csharp_style_throw_expression = true
csharp_style_unused_value_assignment_preference = discard_variable
csharp_style_unused_value_expression_statement_preference = discard_variable
# 'using' directive preferences
csharp_using_directive_placement = outside_namespace:warning
# New line preferences
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true
csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true
csharp_style_allow_embedded_statements_on_same_line_experimental = true
#### C# Formatting Rules ####
# New line preferences
csharp_new_line_before_catch = true
csharp_new_line_before_else = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_open_brace = all
csharp_new_line_between_query_expression_clauses = true
# Indentation preferences
csharp_indent_block_contents = true
csharp_indent_braces = false
csharp_indent_case_contents = true
csharp_indent_case_contents_when_block = true
csharp_indent_labels = one_less_than_current
csharp_indent_switch_labels = true
# Space preferences
csharp_space_after_cast = false
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_after_comma = true
csharp_space_after_dot = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_after_semicolon_in_for_statement = true
csharp_space_around_binary_operators = before_and_after
csharp_space_around_declaration_statements = false
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_before_comma = false
csharp_space_before_dot = false
csharp_space_before_open_square_brackets = false
csharp_space_before_semicolon_in_for_statement = false
csharp_space_between_empty_square_brackets = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false
# Wrapping preferences
csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = true
#### Naming styles ####
# Naming rules
dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
# Symbol specifications
dotnet_naming_symbols.interface.applicable_kinds = interface
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.interface.required_modifiers =
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.types.required_modifiers =
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.non_field_members.required_modifiers =
# Naming styles
dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case
dotnet_naming_style.begins_with_i.required_prefix = I
dotnet_naming_style.begins_with_i.required_suffix =
dotnet_naming_style.begins_with_i.word_separator =
dotnet_naming_style.begins_with_i.capitalization = pascal_case
#### Roslyn diagnostics ####
dotnet_diagnostic.CA1000.severity = none # Do not declare static members on generic types
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.CA1200.severity = none # Avoid using cref tags with a prefix
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
dotnet_diagnostic.CA1724.severity = none # Type names should not match namespaces
dotnet_diagnostic.CA1859.severity = none # Use concrete types when possible for improved performance
dotnet_diagnostic.CA1861.severity = none # Avoid constant arrays as arguments
dotnet_diagnostic.CA2211.severity = none # Non-constant fields should not be visible
dotnet_diagnostic.CA2241.severity = error # Provide correct arguments to formatting methods/The format argument is not a valid string
dotnet_diagnostic.CS1591.severity = none # Missing XML comment
dotnet_diagnostic.IDE0010.severity = none # Populate switch
dotnet_diagnostic.IDE0021.severity = none # Use block body for method
dotnet_diagnostic.IDE0022.severity = none # Use block body for method
dotnet_diagnostic.IDE0040.severity = none # Add accessibility modifiers
dotnet_diagnostic.IDE0058.severity = none # Remove unnecessary expression value
dotnet_diagnostic.IDE0072.severity = none # Populate switch
dotnet_diagnostic.IDE1006.severity = none # Naming rule violation
================================================
FILE: .gitattributes
================================================
* text=auto eol=lf
*.cs text diff=csharp
*.csproj text merge=union
*.ico binary
*.resx text merge=union
*.ps1 eol=crlf
*.sln text eol=crlf merge=union
*.snk binary
*.vbproj text merge=union
*.xls binary
================================================
FILE: .github/FUNDING.yml
================================================
github: xunit
================================================
FILE: .github/workflows/ci-signed.yaml
================================================
name: xUnit.net Analyzers CI Build (signed)
on:
push:
branches:
- main
- 'rel/**'
workflow_dispatch:
jobs:
deployment:
name: "Build"
runs-on: windows-latest
environment: signing
permissions:
id-token: write # Required for Azure CLI Login
env:
DOTNET_CLI_WORKLOAD_UPDATE_NOTIFY_DISABLE: true
DOTNET_NOLOGO: true
steps:
- name: Clone source
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- name: Install .NET SDK
uses: actions/setup-dotnet@v4
with:
dotnet-version: |
8.0.x
10.0.x
- name: Get .NET information
run: dotnet --info
- name: "Build target: BuildAll"
run: dotnet run --project tools/builder --no-launch-profile -- BuildAll --timing
- name: Login to Azure CLI
uses: azure/login@v2
with:
client-id: ${{ vars.KEYVAULT_APP_ID }}
tenant-id: ${{ vars.KEYVAULT_TENANT_ID }}
subscription-id: ${{ vars.KEYVAULT_SUBSCRIPTION_ID }}
- name: "Build target: PublishPackages"
env:
PUSH_APIKEY: ${{ secrets.FEEDZ_PUSH_KEY }}
PUSH_URI: ${{ vars.FEEDZ_PUSH_URL }}
SIGN_APP_ID: ${{ vars.KEYVAULT_APP_ID }}
SIGN_CERT_NAME: ${{ vars.KEYVAULT_CERT_NAME }}
SIGN_TIMESTAMP_URI: ${{ vars.KEYVAULT_TIMESTAMP_URL }}
SIGN_VAULT_URI: ${{ vars.KEYVAULT_URL }}
run: dotnet run --project tools/builder --no-launch-profile -- PublishPackages --timing
- name: "Upload artifact: build"
uses: actions/upload-artifact@v4
with:
name: build
path: artifacts/build
compression-level: 9
if: always()
- name: "Upload artifact: test"
uses: actions/upload-artifact@v4
with:
name: test
path: artifacts/test
compression-level: 9
if: always()
- name: "Upload artifact: packages"
uses: actions/upload-artifact@v4
with:
name: packages
path: artifacts/packages
compression-level: 0
if: always()
- name: Publish Test Report
uses: ctrf-io/github-test-reporter@v1
with:
report-path: './artifacts/test/*.ctrf'
github-report: true
if: always()
================================================
FILE: .github/workflows/ci-unsigned.yaml
================================================
name: xUnit.net Analyzers CI Build (unsigned)
on:
push:
branches-ignore:
- main
- 'rel/**'
workflow_dispatch:
jobs:
build:
name: "Build"
runs-on: windows-latest
env:
DOTNET_CLI_WORKLOAD_UPDATE_NOTIFY_DISABLE: true
DOTNET_NOLOGO: true
steps:
- name: Clone source
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- name: Install .NET SDK
uses: actions/setup-dotnet@v4
with:
dotnet-version: |
8.0.x
10.0.x
- name: Get .NET information
run: dotnet --info
- name: "Build target: BuildAll"
run: dotnet run --project tools/builder --no-launch-profile -- BuildAll --timing
- name: "Upload artifact: test"
uses: actions/upload-artifact@v4
with:
name: test
path: artifacts/test
compression-level: 9
if: always()
- name: "Upload artifact: packages"
uses: actions/upload-artifact@v4
with:
name: packages
path: artifacts/packages
compression-level: 0
if: always()
- name: Publish Test Report
uses: ctrf-io/github-test-reporter@v1
with:
report-path: './artifacts/test/*.ctrf'
github-report: true
if: always()
================================================
FILE: .github/workflows/pull-request.yaml
================================================
name: xUnit.net Analyzers PR Build
on:
- pull_request
- workflow_dispatch
jobs:
build:
name: "Build"
runs-on: ${{ matrix.os }}
env:
DOTNET_CLI_WORKLOAD_UPDATE_NOTIFY_DISABLE: true
DOTNET_NOLOGO: true
strategy:
fail-fast: false
matrix:
os: [windows-latest, ubuntu-latest, macOS-latest]
steps:
- name: Clone source
uses: actions/checkout@v4
with:
fetch-depth: 0
submodules: true
- name: Install .NET SDK
uses: actions/setup-dotnet@v4
with:
dotnet-version: |
8.0.x
10.0.x
- name: Get .NET information
run: dotnet --info
- name: Install Mono (Ubuntu)
run: >
sudo apt-get -y install apt-transport-https dirmngr gnupg ca-certificates software-properties-common &&
curl 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x3fa7e0328081bff6a14da29aa6a19b38d3d831ef' | sudo tee /etc/apt/trusted.gpg.d/mono-official-stable.asc &&
sudo apt-add-repository -y --no-update 'deb https://download.mono-project.com/repo/ubuntu stable-focal main' &&
sudo apt-get update &&
sudo apt-get -y install mono-complete mono-vbnc
if: ${{ matrix.os == 'ubuntu-latest' }}
- name: Install Mono (macOS)
run: brew install mono
if: ${{ matrix.os == 'macOS-latest' }}
- name: Get Mono information
run: mono --version
if: ${{ matrix.os != 'windows-latest' }}
- name: "Build target: BuildAll"
run: dotnet run --project tools/builder --no-launch-profile -- BuildAll
- name: "Upload artifact: test-${{ matrix.os }}"
uses: actions/upload-artifact@v4
with:
name: test-${{ matrix.os }}
path: artifacts/test
compression-level: 9
if: always()
- name: Publish Test Report
uses: ctrf-io/github-test-reporter@v1
with:
report-path: './artifacts/test/*.ctrf'
github-report: true
pull-request: true
update-comment: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
if: always()
================================================
FILE: .gitignore
================================================
# Visual Studio
launchSettings.json
# NCrunch
*.ncrunchsolution
*.ncrunchsolution.user
*.ncrunchproject
# Mono's local registry
.mono
##### Copied from https://github.com/github/gitignore/blob/7b22f8ab6c85b4ef1469d72a8ba96462e2a44853/VisualStudio.gitignore
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.tlog
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
*.vbp
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
*.dsw
*.dsp
# Visual Studio 6 technical files
*.ncb
*.aps
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# Visual Studio History (VSHistory) files
.vshistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd
# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp
# JetBrains Rider
*.sln.iml
.idea/
================================================
FILE: .gitmodules
================================================
[submodule "tools/media"]
path = tools/media
url = https://github.com/xunit/media
[submodule "tools/builder/common"]
path = tools/builder/common
url = https://github.com/xunit/build-tools-v3
================================================
FILE: .vscode/launch.json
================================================
{
"version": "0.2.0",
"configurations": []
}
================================================
FILE: .vscode/settings.json
================================================
{
"cSpell.words": [
"LLMBRO",
"MBRO",
"app",
"nuget",
"nupkg",
"parallelization",
"veyor"
],
"files.exclude": {
"**/.git": true,
"**/.DS_Store": true,
"**/bin": true,
"**/obj": true,
"artifacts": true,
"packages": true
}
}
================================================
FILE: .vscode/tasks.json
================================================
{
"version": "2.0.0",
"tasks": [
{
"label": "Build",
"type": "process",
"command": "dotnet",
"args": [
"run",
"--project",
"tools/builder",
"--no-launch-profile",
"--",
"Build"
],
"options": {
"cwd": "${workspaceRoot}"
},
"group": "build",
"presentation": {
"focus": true
},
"problemMatcher": []
},
{
"label": "Pre-PR Validation",
"type": "process",
"command": "dotnet",
"args": [
"run",
"--project",
"tools/builder",
"--no-launch-profile",
"--",
"Packages"
],
"options": {
"cwd": "${workspaceRoot}"
},
"group": "build",
"presentation": {
"focus": true
},
"problemMatcher": []
},
{
"label": "Unit Tests (.NET Core)",
"type": "process",
"command": "dotnet",
"args": [
"run",
"--project",
"tools/builder",
"--no-launch-profile",
"--",
"TestCore"
],
"options": {
"cwd": "${workspaceRoot}"
},
"group": "build",
"presentation": {
"focus": true
},
"problemMatcher": []
},
{
"label": "Unit Tests (.NET Framework)",
"type": "process",
"command": "dotnet",
"args": [
"run",
"--project",
"tools/builder",
"--no-launch-profile",
"--",
"TestFx"
],
"options": {
"cwd": "${workspaceRoot}"
},
"group": "build",
"presentation": {
"focus": true
},
"problemMatcher": []
}
]
}
================================================
FILE: BUILDING.md
================================================
# Building xUnit.net Analyzers
The primary build system for xUnit.net Analyzers is done via command line, and officially supports Linux and Windows. Users running macOS can generally follow the Linux instructions (while installing the macOS equivalents of the dependencies).
# Pre-Requisites
You will need the following software installed (regardless of OS):
* [.NET SDK 8.0](https://dotnet.microsoft.com/download/dotnet/8.0)
* [git](https://git-scm.com/downloads)
## Linux Pre-Requisites
Linux users will additionally need:
* [Mono](https://www.mono-project.com/download/stable/) 6.12+
* [bash](https://www.gnu.org/software/bash/)
Note: Linux users cannot run the .NET Framework tests, as they are incompatible. For this reason, we recommend that users either work primarily in Windows, or verify their tests work as expected in a Windows VM, before submitting PRs.
## Windows Pre-Requisites
Windows users will additionally need:
* .NET Framework 4.7.2 or later (part of the Windows OS)
* [PowerShell 7+](https://learn.microsoft.com/powershell/scripting/install/installing-powershell-on-windows)
Ensure that you have configured PowerShell to be able to run local unsigned scripts (either by running `Set-ExecutionPolicy RemoteSigned` from within PowerShell, or by launching PowerShell with the `-ExecutionPolicy RemoteSigned` command line switch).
_Note that the built-in version of PowerShell may work, but is unsupported by us. If you have PowerShell-related issues, please make sure you have installed PowerShell 7+ and the command prompt you opened is for PowerShell 7+, and not the built-in version of PowerShell._
# Command-Line Build
1. **Linux users:** Open a terminal to your favorite shell.
**Windows users:** Open PowerShell 7+.
1. From the root folder of the source repo, this command will build the code & run all tests:
`./build`
To build a specific target (or multiple targets):
`./build [target [target...]]`
The common targets (case-insensitive) include:
* `Restore`: Perform package restore
* `Build`: Build the source
* `Test`: Run all unit tests
You can get a list of options:
`./build --help`
# Editing source
The primary projects for editing are:
* `xunit.analyzers` (for code analysis)
* `xunit.analyzers.fixes` (for automated fixes for issues raised in code analysis)
* `xunit.analyzers.tests` (for unit tests of both above projects)
These are targeting our lowest common denominator for Roslyn (current version 3.11, the version that's supported in Visual Studio 2019 16.11).
There are also three projects which build against the latest version of Roslyn:
* `xunit.analyzers.latest`
* `xunit.analyzers.latest.fixes`
* `xunit.analyzers.latest.tests`
When running a command line build, we run a matrix of 4 test projects: Roslyn 3.11 vs. latest, and .NET Framework vs. .NET. It's important that you run `./build` (or `./build test`) from Windows before submitting PRs, because some bugs are often found only in one of the four combinations (and Mono cannot run the .NET Framework tests).
You will also occasionally see tests which only run in specific environments. Common `#if` statements you may see (or may need to use) include:
* `#if NETFRAMEWORK` (only runs for .NET Framework)
* `#if NETCOREAPP` (only runs for .NET)
* `#if ROSLYN_LATEST` (only runs with latest Roslyn, which includes getting analysis test support to C# language > version 9)
In production code, we try to minimize these when possible, and prefer to fall back to use dynamic runtime environment detection when we can (as we'd like to light up features in newer versions of Roslyn when available). While this isn't always possible, it is generally a goal we try to achieve. In test code, we tend to use these to more frequently to ensure we have complete coverage of features that should be available dynamically (whether they are lit up based on `#if` or by runtime environment detection).
================================================
FILE: LICENSE
================================================
Unless otherwise noted, the source code here is covered by the following license:
Copyright (c) .NET Foundation and Contributors
All Rights Reserved
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
The source in src/xunit.analyzers.tests/Utilities/XunitVerifier.cs was adapted from code
that is covered the following license (copied from
https://github.com/dotnet/roslyn-sdk/blob/35d5e46fd5c403194692c645d912a17d36ed74f5/LICENSE.txt):
The MIT License (MIT)
Copyright (c) .NET Foundation and Contributors
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: NuGet.Config
================================================
================================================
FILE: README.md
================================================
# About This Project
This project contains source code analysis and cleanup rules for xUnit.net. Analysis and fixes are only supported with C#.
**Requirements**: xUnit.net v2 or v3. Supported in Visual Studio 2019, 2022, and 2026 (as well as via command line builds with Roslyn 3.11+). Other environments (such as Mono or JetBrains Rider) may be able to use these analyzers as well; support and issue resolution will be provided by those third parties and not by xUnit.net itself.
**Documentation**: a list of supported rules is available at https://xunit.net/xunit.analyzers/rules/
**Bugs and issues**: please visit the [core xUnit.net project issue tracker](https://github.com/xunit/xunit/issues).
**Building**: see [BUILDING.md](https://github.com/xunit/xunit.analyzers/blob/main/BUILDING.md).
> _**Note:** Our minimum supported versions of Visual Studio 2019, 2022, and 2026 align with the "Baseline" column of the "Support for Older Versions" table of [Visual Studio Product Lifecycle and Servicing](https://learn.microsoft.com/visualstudio/releases/2026/servicing-vs#support-for-older-versions), as these are the minimum versions supported by Microsoft. If you are experiencing issues with an older version of Visual Studio, please upgrade and verify the issue still exists before opening issues._
## How to install
- xUnit.net v3: the analyzer package is referenced by the main [`xunit.v3` NuGet package](https://www.nuget.org/packages/xunit.v3) out of the box. If you choose to reference [`xunit.v3.core`](https://www.nuget.org/packages/xunit.v3.core) instead, you can reference [`xunit.analyzers`](https://www.nuget.org/packages/xunit.analyzers) explicitly.
- xUnit.net v2 2.3.0 and higher: the analyzer package is referenced by the main [`xunit` NuGet package](https://www.nuget.org/packages/xunit) out of the box. If you choose to reference [`xunit.core`](https://www.nuget.org/packages/xunit.core) instead, you can reference [`xunit.analyzers`](https://www.nuget.org/packages/xunit.analyzers) explicitly.
- xUnit.net v2 2.2.0 and earlier: you have to install the [`xunit.analyzers` NuGet package](https://www.nuget.org/packages/xunit.analyzers) explicitly.
## How to uninstall
- If you are using xUnit.net v3 and do not wish to use the analyzers package, replace the package reference to [`xunit.v3`](https://www.nuget.org/packages/xunit.v3) with the corresponding versions of [`xunit.v3.core`](https://www.nuget.org/packages/xunit.v3.core) and [`xunit.v3.assert`](https://www.nuget.org/packages/xunit.v3.assert).
- If you are using xUnit.net v2 2.3.0 or higher and do not wish to use the analyzers package, replace the package reference to [`xunit`](https://www.nuget.org/packages/xunit) with the corresponding versions of [`xunit.core`](https://www.nuget.org/packages/xunit.core) and [`xunit.assert`](https://www.nuget.org/packages/xunit.assert).
- If you are using xUnit.net v2 v2.2.0 or earlier: remove the reference to the [`xunit.analyzers` NuGet package](https://www.nuget.org/packages/xunit.analyzers).
## Analysis and Code Fix in Action

# About xUnit.net
xUnit.net is a free, open source, community-focused unit testing tool for C#, F#, and Visual Basic.
xUnit.net works with the [.NET SDK](https://dotnet.microsoft.com/download) command line tools, [Visual Studio](https://visualstudio.microsoft.com/), [Visual Studio Code](https://code.visualstudio.com/), [JetBrains Rider](https://www.jetbrains.com/rider/), [NCrunch](https://www.ncrunch.net/), and any development environment compatible with [Microsoft Testing Platform](https://learn.microsoft.com/dotnet/core/testing/microsoft-testing-platform-intro) (xUnit.net v3) or [VSTest](https://github.com/microsoft/vstest) (all versions of xUnit.net).
xUnit.net is part of the [.NET Foundation](https://www.dotnetfoundation.org/) and operates under their [code of conduct](https://www.dotnetfoundation.org/code-of-conduct). It is licensed under [Apache 2](https://opensource.org/licenses/Apache-2.0) (an OSI approved license). The project is [governed](https://xunit.net/governance) by a Project Lead.
For project documentation, please visit the [xUnit.net project home](https://xunit.net/).
* _New to xUnit.net? Get started with the [.NET SDK](https://xunit.net/docs/getting-started/v3/getting-started)._
* _Need some help building the source? See [BUILDING.md](https://github.com/xunit/xunit/tree/main/BUILDING.md)._
* _Want to contribute to the project? See [CONTRIBUTING.md](https://github.com/xunit/.github/tree/main/CONTRIBUTING.md)._
* _Want to contribute to the assertion library? See the [suggested contribution workflow](https://github.com/xunit/assert.xunit/tree/main/README.md#suggested-contribution-workflow) in the assertion library project, as it is slightly more complex due to code being spread across two GitHub repositories._
## Latest Builds
| | Latest stable | Latest CI ([how to use](https://xunit.net/docs/using-ci-builds)) | Build status
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------
| `xunit.v3` | [](https://www.nuget.org/packages/xunit.v3) | [](https://feedz.io/org/xunit/repository/xunit/packages/xunit.v3) | [](https://actions-badge.atrox.dev/xunit/xunit/goto?ref=main)
| `xunit` | [](https://www.nuget.org/packages/xunit) | [](https://feedz.io/org/xunit/repository/xunit/packages/xunit) | [](https://actions-badge.atrox.dev/xunit/xunit/goto?ref=v2)
| `xunit.analyzers` | [](https://www.nuget.org/packages/xunit.analyzers) | [](https://feedz.io/org/xunit/repository/xunit/packages/xunit.analyzers) | [](https://actions-badge.atrox.dev/xunit/xunit.analyzers/goto?ref=main)
| `xunit.runner.visualstudio` | [](https://www.nuget.org/packages/xunit.runner.visualstudio) | [](https://feedz.io/org/xunit/repository/xunit/packages/xunit.runner.visualstudio) | [](https://actions-badge.atrox.dev/xunit/visualstudio.xunit/goto?ref=main)
*For complete CI package lists, please visit the [feedz.io package search](https://feedz.io/org/xunit/repository/xunit/search). A free login is required.*
## Sponsors
Help support this project by becoming a sponsor through [GitHub Sponsors](https://github.com/sponsors/xunit).
================================================
FILE: build
================================================
#!/usr/bin/env bash
set -euo pipefail
PUSHED=0
cleanup () {
if [[ $PUSHED == 1 ]]; then
popd >/dev/null
PUSHED=0
fi
}
trap cleanup EXIT ERR INT TERM
if which git > /dev/null; then
git submodule status | while read line; do
if [ "$(echo $line | cut -b1)" == "-" ]; then
pieces=( $line )
git submodule update --init ${pieces[1]}
echo ""
fi
done
else
echo "error(1): Could not find 'git'; please install the Git CLI" 2>&1
exit 1
fi
if which dotnet > /dev/null; then
if [ $(dotnet --version | cut -d. -f1) -lt 8 ]; then
echo "error(1): .NET SDK version $(dotnet --version) is too low; please install 8.0 or later"
exit 1
fi
if [ `uname -o` = Msys ] || which mono > /dev/null ; then
pushd $( cd "$(dirname "$0")" ; pwd -P ) >/dev/null
PUSHED=1
dotnet run --project tools/builder --no-launch-profile -- "$@"
else
echo "error(1): Could not find 'mono'; please install Mono" 2>&1
exit 1
fi
else
echo "error(1): Could not find 'dotnet'; please install the .NET Core SDK" 2>&1
exit 1
fi
================================================
FILE: build.ps1
================================================
#!/usr/bin/env pwsh
#Requires -Version 5.1
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
if ($null -eq (Get-Command "git" -ErrorAction Ignore)) {
throw "Could not find 'git'; please install the Git command line tooling"
}
& git submodule status | ForEach-Object {
if ($_[0] -eq '-') {
$pieces = $_.Split(' ')
& git submodule update --init "$($pieces[1])"
Write-Host ""
}
}
if ($null -eq (Get-Command "dotnet" -ErrorAction Ignore)) {
throw "Could not find 'dotnet'; please install the .NET Core SDK"
}
$version = [Version]$([regex]::matches((&dotnet --version), '^(\d+\.)?(\d+\.)?(\*|\d+)').value)
if ($version.Major -lt 8) {
throw ".NET SDK version ($version) is too low; please install version 8.0 or later"
}
Push-Location (Split-Path $MyInvocation.MyCommand.Definition)
try {
& dotnet run --project tools/builder --no-launch-profile -- $args
}
finally {
Pop-Location
}
================================================
FILE: global.json
================================================
{
"sdk": {
"version": "10.0.100",
"rollForward": "latestMinor"
}
}
================================================
FILE: src/Directory.Build.props
================================================
8.0.10trueembeddedtruefalsefalsefalsefalsefalsefalsefalsefalsetrue14.03.11falseenabletrueruntime; build; native; contentfiles; analyzers; buildtransitivealllatest-All$(MSBuildThisFileDirectory)signing.snktruetruetruetruetruetruetruetrue$(DefineConstants);XUNIT_NULLABLE;XUNIT_POINTERS;XUNIT_VISIBILITY_INTERNALtruetruetrue
================================================
FILE: src/Directory.Build.targets
================================================
runtime; build; native; contentfiles; analyzers; buildtransitiveallruntime; build; native; contentfiles; analyzers; buildtransitiveall-dev$(BuildVersionSimple)$(BuildVersionSimple)$(BuildVersionSimple)$(PrereleaseVersion)$(PrereleaseSuffix)+$(GitCommitIdShort)signed\-dev$(BuildVersionSimple)$(PrereleaseVersion)$(PrereleaseSuffix)https://xunit.net/releases/analyzers/$(PackageVersion)
Configuration=$(Configuration);
GitCommitId=$(GitCommitId);
PackageVersion=$(PackageVersion);
SignedPath=$(SignedPath);
================================================
FILE: src/common/CallerArgumentExpressionAttribute.cs
================================================
#if !NETCOREAPP
namespace System.Runtime.CompilerServices;
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
internal sealed class CallerArgumentExpressionAttribute(string parameterName) :
Attribute
{
public string ParameterName { get; } = parameterName;
}
#endif
================================================
FILE: src/common/Guard.cs
================================================
using System;
using System.Collections;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
namespace Xunit;
///
/// Helper class for guarding value arguments and valid state.
///
static class Guard
{
///
/// Ensures that a nullable reference type argument is not null.
///
/// The argument type
/// The value of the argument
/// The name of the argument
/// The argument value as a non-null value
/// Thrown when the argument is null
public static T ArgumentNotNull(
[NotNull] T? argValue,
[CallerArgumentExpression(nameof(argValue))] string? argName = null)
where T : class
{
if (argValue is null)
throw new ArgumentNullException(argName?.TrimStart('@'));
return argValue;
}
///
/// Ensures that a nullable enumerable type argument is not null or empty.
///
/// The argument type
/// The value of the argument
/// The name of the argument
/// The argument value as a non-null, non-empty value
/// Thrown when the argument is null or empty
public static T ArgumentNotNullOrEmpty(
[NotNull] T? argValue,
[CallerArgumentExpression(nameof(argValue))] string? argName = null)
where T : class, IEnumerable
{
ArgumentNotNull(argValue, argName);
if (!argValue.GetEnumerator().MoveNext())
throw new ArgumentException("Argument was empty", argName?.TrimStart('@'));
return argValue;
}
///
/// Ensures that an argument is valid.
///
/// The exception message to use when the argument is not valid
/// The validity test value
/// The name of the argument
/// The argument value as a non-null value
/// Thrown when the argument is not valid
public static void ArgumentValid(
string message,
bool test,
string? argName = null)
{
if (!test)
throw new ArgumentException(message, argName);
}
///
/// Ensures that an argument is valid.
///
/// The creator for an exception message to use when the argument is not valid
/// The validity test value
/// The name of the argument
/// The argument value as a non-null value
/// Thrown when the argument is not valid
public static void ArgumentValid(
Func messageFunc,
bool test,
string? argName = null)
{
if (!test)
throw new ArgumentException(messageFunc?.Invoke(), argName);
}
}
================================================
FILE: src/compat/Directory.Build.props
================================================
$(DefineConstants);ROSLYN_LATEST4.14.0
================================================
FILE: src/compat/xunit.analyzers.latest/xunit.analyzers.latest.csproj
================================================
Xunit.Analyzersnetstandard2.0
================================================
FILE: src/compat/xunit.analyzers.latest.fixes/xunit.analyzers.latest.fixes.csproj
================================================
Xunit.Analyzers.Fixesnetstandard2.0
================================================
FILE: src/compat/xunit.analyzers.latest.tests/xunit.analyzers.latest.tests.csproj
================================================
xunit.analyzers.latest.tests.$(TargetFramework)Exexunit.analyzers.latest.testsXunit.Analyzersnet8.0;net472
================================================
FILE: src/xunit.analyzers/Properties/AssemblyInfo.cs
================================================
using System.Reflection;
[assembly: AssemblyCompany(".NET Foundation")]
[assembly: AssemblyProduct("xUnit.net Testing Framework")]
[assembly: AssemblyCopyright("Copyright (C) .NET Foundation")]
[assembly: AssemblyTitle("xUnit.net Code Analysis (Analyzers)")]
================================================
FILE: src/xunit.analyzers/Suppressors/ConsiderCallingConfigureAwaitSuppressor.cs
================================================
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Xunit.Analyzers;
namespace Xunit.Suppressors;
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public sealed class ConsiderCallingConfigureAwaitSuppressor : XunitDiagnosticSuppressor
{
public ConsiderCallingConfigureAwaitSuppressor() :
base(Descriptors.CA2007_Suppression)
{ }
protected override bool ShouldSuppress(
Diagnostic diagnostic,
SuppressionAnalysisContext context,
XunitContext xunitContext)
{
if (diagnostic.Location.SourceTree is null)
return false;
var factAttributeType = xunitContext.Core.FactAttributeType;
var theoryAttributeType = xunitContext.Core.TheoryAttributeType;
if (factAttributeType is null || theoryAttributeType is null)
return false;
var root = diagnostic.Location.SourceTree.GetRoot(context.CancellationToken);
if (root?.FindNode(diagnostic.Location.SourceSpan) is not InvocationExpressionSyntax invocationSyntax)
return false;
var current = invocationSyntax.Parent;
while (true)
{
if (current is null or LocalFunctionStatementSyntax or LambdaExpressionSyntax)
return false;
if (current is MethodDeclarationSyntax)
break;
current = current.Parent;
}
var semanticModel = context.GetSemanticModel(diagnostic.Location.SourceTree);
var methodSymbol = semanticModel.GetDeclaredSymbol(current);
if (methodSymbol is null)
return false;
var attributes = ImmutableHashSet.Create(SymbolEqualityComparer.Default, factAttributeType, theoryAttributeType);
return
methodSymbol
.GetAttributes()
.Any(a => attributes.Contains(a.AttributeClass));
}
}
================================================
FILE: src/xunit.analyzers/Suppressors/MakeTypesInternalSuppressor.cs
================================================
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Xunit.Analyzers;
namespace Xunit.Suppressors;
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public sealed class MakeTypesInternalSuppressor : XunitDiagnosticSuppressor
{
public MakeTypesInternalSuppressor() :
base(Descriptors.CA1515_Suppression)
{ }
protected override bool ShouldSuppress(
Diagnostic diagnostic,
SuppressionAnalysisContext context,
XunitContext xunitContext)
{
if (diagnostic.Location.SourceTree is null)
return false;
var root = diagnostic.Location.SourceTree.GetRoot(context.CancellationToken);
if (root?.FindNode(diagnostic.Location.SourceSpan) is not ClassDeclarationSyntax classDeclaration)
return false;
var semanticModel = context.GetSemanticModel(diagnostic.Location.SourceTree);
var classSymbol = semanticModel.GetDeclaredSymbol(classDeclaration) as ITypeSymbol;
return classSymbol.IsTestClass(xunitContext, strict: false);
}
}
================================================
FILE: src/xunit.analyzers/Suppressors/NonNullableFieldInitializationSuppressor.cs
================================================
using System.Globalization;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Xunit.Analyzers;
namespace Xunit.Suppressors;
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public sealed class NonNullableFieldInitializationSuppressor : XunitDiagnosticSuppressor
{
public NonNullableFieldInitializationSuppressor() :
base(Descriptors.CS8618_Suppression)
{ }
protected override bool ShouldSuppress(
Diagnostic diagnostic,
SuppressionAnalysisContext context,
XunitContext xunitContext)
{
if (diagnostic.Location.SourceTree is null)
return false;
var asyncLifetimeType = TypeSymbolFactory.IAsyncLifetime(context.Compilation);
if (asyncLifetimeType is null)
return false;
var root = diagnostic.Location.SourceTree.GetRoot(context.CancellationToken);
var node = root?.FindNode(diagnostic.Location.SourceSpan);
if (node is null)
return false;
var semanticModel = context.GetSemanticModel(diagnostic.Location.SourceTree);
var memberSymbol = ResolveMemberSymbol(diagnostic, node, semanticModel, context);
if (memberSymbol is null)
return false;
var containingType = memberSymbol.ContainingType;
if (containingType is null)
return false;
if (!containingType.AllInterfaces.Contains(asyncLifetimeType, SymbolEqualityComparer.Default))
return false;
// Find the InitializeAsync method implementation
var initializeAsyncInterfaceMethod = asyncLifetimeType.GetMembers("InitializeAsync").FirstOrDefault();
if (initializeAsyncInterfaceMethod is null)
return false;
var initializeAsyncImpl = containingType.FindImplementationForInterfaceMember(initializeAsyncInterfaceMethod);
if (initializeAsyncImpl is null)
return false;
return IsMemberAssignedInMethod(initializeAsyncImpl, memberSymbol, context);
}
static ISymbol? ResolveMemberSymbol(
Diagnostic diagnostic,
SyntaxNode node,
SemanticModel semanticModel,
SuppressionAnalysisContext context)
{
// CS8618 can target field variable declarators or property declarations directly
ISymbol? memberSymbol = node switch
{
VariableDeclaratorSyntax variableDeclarator => semanticModel.GetDeclaredSymbol(variableDeclarator),
PropertyDeclarationSyntax propertyDeclaration => semanticModel.GetDeclaredSymbol(propertyDeclaration),
_ => null,
};
if (memberSymbol is not null)
return memberSymbol;
// Check AdditionalLocations (some compiler versions include member location here)
foreach (var additionalLocation in diagnostic.AdditionalLocations)
{
if (additionalLocation.SourceTree is null)
continue;
var addRoot = additionalLocation.SourceTree.GetRoot(context.CancellationToken);
var addNode = addRoot.FindNode(additionalLocation.SourceSpan);
var addModel = context.GetSemanticModel(additionalLocation.SourceTree);
var symbol = addModel.GetDeclaredSymbol(addNode, context.CancellationToken);
if (symbol is IFieldSymbol or IPropertySymbol)
return symbol;
}
// Fallback: CS8618 on a constructor — extract member name from diagnostic message
var declaredSymbol = semanticModel.GetDeclaredSymbol(node, context.CancellationToken);
if (declaredSymbol is IMethodSymbol { MethodKind: MethodKind.Constructor } constructorSymbol)
{
var message = diagnostic.GetMessage(CultureInfo.InvariantCulture);
var startQuote = message.IndexOf('\'');
if (startQuote >= 0)
{
var endQuote = message.IndexOf('\'', startQuote + 1);
if (endQuote > startQuote)
{
var memberName = message.Substring(startQuote + 1, endQuote - startQuote - 1);
return constructorSymbol.ContainingType
.GetMembers(memberName)
.FirstOrDefault(m => m is IFieldSymbol or IPropertySymbol);
}
}
}
return null;
}
static bool IsMemberAssignedInMethod(
ISymbol methodSymbol,
ISymbol targetMember,
SuppressionAnalysisContext context)
{
foreach (var syntaxRef in methodSymbol.DeclaringSyntaxReferences)
{
var methodSyntax = syntaxRef.GetSyntax(context.CancellationToken);
if (methodSyntax is not MethodDeclarationSyntax methodDecl)
continue;
var methodSemanticModel = context.GetSemanticModel(methodSyntax.SyntaxTree);
foreach (var assignment in methodDecl.DescendantNodes().OfType())
{
var assignedSymbol = methodSemanticModel.GetSymbolInfo(assignment.Left).Symbol;
if (assignedSymbol is not null && SymbolEqualityComparer.Default.Equals(assignedSymbol, targetMember))
return true;
}
}
return false;
}
}
================================================
FILE: src/xunit.analyzers/Suppressors/UseAsyncSuffixForAsyncMethodsSuppressor.cs
================================================
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Xunit.Analyzers;
namespace Xunit.Suppressors;
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class UseAsyncSuffixForAsyncMethodsSuppressor : XunitDiagnosticSuppressor
{
public UseAsyncSuffixForAsyncMethodsSuppressor() :
base(Descriptors.VSTHRD200_Suppression)
{ }
protected override bool ShouldSuppress(
Diagnostic diagnostic,
SuppressionAnalysisContext context,
XunitContext xunitContext)
{
var attributeUsageType = TypeSymbolFactory.AttributeUsageAttribute(context.Compilation);
if (attributeUsageType is null)
return false;
if (diagnostic?.Location.SourceTree is null)
return false;
if (diagnostic.Location.SourceTree.GetRoot().FindNode(diagnostic.Location.SourceSpan) is not MethodDeclarationSyntax methodDeclaration)
return false;
var semanticModel = context.GetSemanticModel(diagnostic.Location.SourceTree);
var methodSymbol = semanticModel.GetDeclaredSymbol(methodDeclaration) as IMethodSymbol;
return methodSymbol.IsTestMethod(xunitContext, attributeUsageType, strict: false);
}
}
================================================
FILE: src/xunit.analyzers/Utility/AssertUsageAnalyzerBase.cs
================================================
using System;
using System.Collections.Generic;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;
namespace Xunit.Analyzers;
public abstract class AssertUsageAnalyzerBase(
DiagnosticDescriptor[] descriptors,
IEnumerable methods) :
XunitDiagnosticAnalyzer(descriptors)
{
readonly HashSet targetMethods = new(methods, StringComparer.Ordinal);
protected AssertUsageAnalyzerBase(
DiagnosticDescriptor descriptor,
IEnumerable methods)
: this([descriptor], methods)
{ }
public sealed override void AnalyzeCompilation(
CompilationStartAnalysisContext context,
XunitContext xunitContext)
{
Guard.ArgumentNotNull(context);
Guard.ArgumentNotNull(xunitContext);
var assertType = TypeSymbolFactory.Assert(context.Compilation);
if (assertType is null)
return;
context.RegisterOperationAction(context =>
{
if (context.Operation is IInvocationOperation invocationOperation)
{
var methodSymbol = invocationOperation.TargetMethod;
if (methodSymbol.MethodKind != MethodKind.Ordinary || !SymbolEqualityComparer.Default.Equals(methodSymbol.ContainingType, assertType) || !targetMethods.Contains(methodSymbol.Name))
return;
AnalyzeInvocation(context, xunitContext, invocationOperation, methodSymbol);
}
}, OperationKind.Invocation);
}
protected abstract void AnalyzeInvocation(
OperationAnalysisContext context,
XunitContext xunitContext,
IInvocationOperation invocationOperation,
IMethodSymbol method);
}
================================================
FILE: src/xunit.analyzers/Utility/Category.cs
================================================
namespace Xunit.Analyzers;
public enum Category
{
// 1xxx
Usage,
// 2xxx
Assertions,
// 3xxx
Extensibility,
}
================================================
FILE: src/xunit.analyzers/Utility/CodeAnalysisExtensions.cs
================================================
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Operations;
namespace Xunit.Analyzers;
static class CodeAnalysisExtensions
{
public static INamedTypeSymbol? FindNamedType(
this IAssemblySymbol assembly,
Func selector)
{
Guard.ArgumentNotNull(assembly);
Guard.ArgumentNotNull(selector);
var visitor = new NamedTypeVisitor(selector);
visitor.Visit(assembly);
return visitor.MatchingType;
}
public static ImmutableArray GetAttributesWithInheritance(
this IMethodSymbol method,
ITypeSymbol? attributeUsageType)
{
var result = new Dictionary>(SymbolEqualityComparer.Default);
foreach (var attribute in method.GetAttributes())
if (attribute.AttributeClass is not null)
result.Add(attribute.AttributeClass, attribute);
if (method.IsOverride && attributeUsageType is not null)
for (var baseMethod = method.OverriddenMethod; baseMethod != null; baseMethod = baseMethod.OverriddenMethod)
foreach (var attribute in baseMethod.GetAttributes())
{
if (attribute.AttributeClass is null || result.ContainsKey(attribute.AttributeClass))
continue;
var inherited = true;
var allowMultiple = false;
var usageAttribute = attribute.AttributeClass.GetAttributes().FirstOrDefault(a => SymbolEqualityComparer.Default.Equals(a.AttributeClass, attributeUsageType));
if (usageAttribute is not null)
{
var inheritedNamedArgument =
usageAttribute
.NamedArguments
.FirstOrDefault(n => n.Key == nameof(AttributeUsageAttribute.Inherited));
if (inheritedNamedArgument.Value.Value is not null)
inherited = (bool)inheritedNamedArgument.Value.Value;
var allowMultipleNamedArgument =
usageAttribute
.NamedArguments
.FirstOrDefault(n => n.Key == nameof(AttributeUsageAttribute.AllowMultiple));
if (allowMultipleNamedArgument.Value.Value is not null)
allowMultiple = (bool)allowMultipleNamedArgument.Value.Value;
}
if ((allowMultiple || !result.ContainsKey(attribute.AttributeClass)) && inherited)
result.Add(attribute.AttributeClass, attribute);
}
return result.Values.SelectMany(x => x).ToImmutableArray();
}
public static (bool isInTestMethod, IOperation? lambdaOwner) IsInTestMethod(
this IOperation operation,
XunitContext xunitContext)
{
Guard.ArgumentNotNull(operation);
Guard.ArgumentNotNull(xunitContext);
if (xunitContext.Core.FactAttributeType is null || xunitContext.Core.TheoryAttributeType is null)
return (false, null);
var semanticModel = operation.SemanticModel;
if (semanticModel is null)
return (false, null);
IOperation? lambdaOwner = null;
for (var parent = operation.Parent; parent is not null; parent = parent.Parent)
{
if (parent is IAnonymousFunctionOperation)
{
if (lambdaOwner is null)
{
lambdaOwner = parent;
if (parent.Parent is IDelegateCreationOperation)
for (var target = parent.Parent.Parent; target is not null; target = target.Parent)
if (target is IArgumentOperation && target.Parent is IInvocationOperation invocationOperation)
{
lambdaOwner = invocationOperation;
break;
}
}
continue;
}
if (parent is ILocalFunctionOperation)
{
lambdaOwner = parent;
continue;
}
if (parent is not IMethodBodyOperation methodBodyOperation)
continue;
if (methodBodyOperation.Syntax is not MethodDeclarationSyntax methodSyntax)
continue;
var insideTestMethod = methodSyntax.AttributeLists.SelectMany(list => list.Attributes).Any(attr =>
{
var typeInfo = semanticModel.GetTypeInfo(attr);
if (typeInfo.Type is null)
return false;
return
SymbolEqualityComparer.Default.Equals(typeInfo.Type, xunitContext.Core.FactAttributeType) ||
SymbolEqualityComparer.Default.Equals(typeInfo.Type, xunitContext.Core.TheoryAttributeType);
});
if (!insideTestMethod)
return (false, null);
return (true, lambdaOwner);
}
return (false, null);
}
public static bool IsPointer(
this ExpressionSyntax expression,
SemanticModel? semanticModel) =>
semanticModel?.GetTypeInfo(expression).Type?.TypeKind == TypeKind.Pointer;
public static bool IsTestClass(
this ITypeSymbol? type,
XunitContext xunitContext,
bool strict)
{
Guard.ArgumentNotNull(xunitContext);
if (type is null)
return false;
if (strict)
return IsTestClassStrict(type, xunitContext);
else
return IsTestClassNonStrict(type, xunitContext);
}
static bool IsTestClassNonStrict(
ITypeSymbol type,
XunitContext xunitContext)
{
var factAttributeType = xunitContext.Core.FactAttributeType;
if (factAttributeType is null)
return false;
return
type
.GetMembers()
.OfType()
.Any(method =>
method
.GetAttributes()
.Select(a => a.AttributeClass)
.Any(t => factAttributeType.IsAssignableFrom(t))
);
}
static bool IsTestClassStrict(
ITypeSymbol type,
XunitContext xunitContext)
{
var factAttributeType = xunitContext.Core.FactAttributeType;
var theoryAttributeType = xunitContext.Core.TheoryAttributeType;
if (factAttributeType is null || theoryAttributeType is null)
return false;
var testMethodAttributes =
new[] { factAttributeType, theoryAttributeType }
.ToImmutableHashSet(SymbolEqualityComparer.Default);
return
type
.GetMembers()
.OfType()
.Any(method =>
method
.GetAttributes()
.Select(a => a.AttributeClass)
.Any(t => testMethodAttributes.Contains(t, SymbolEqualityComparer.Default))
);
}
public static bool IsTestMethod(
this IMethodSymbol? method,
XunitContext xunitContext,
ITypeSymbol attributeUsageType,
bool strict)
{
Guard.ArgumentNotNull(xunitContext);
if (method is null)
return false;
var factAttributeType = xunitContext.Core.FactAttributeType;
var theoryAttributeType = xunitContext.Core.TheoryAttributeType;
if (factAttributeType is null || theoryAttributeType is null)
return false;
var attributes = method.GetAttributesWithInheritance(attributeUsageType);
var comparer = SymbolEqualityComparer.Default;
return
strict
? attributes.Any(a => comparer.Equals(a.AttributeClass, factAttributeType) || comparer.Equals(a.AttributeClass, theoryAttributeType))
: attributes.Any(a => factAttributeType.IsAssignableFrom(a.AttributeClass));
}
public static IOperation WalkDownImplicitConversions(this IOperation operation)
{
Guard.ArgumentNotNull(operation);
var current = operation;
while (current is IConversionOperation conversion && conversion.Conversion.IsImplicit)
current = conversion.Operand;
return current;
}
sealed class NamedTypeVisitor(Func selector) :
SymbolVisitor
{
readonly Func selector = Guard.ArgumentNotNull(selector);
public INamedTypeSymbol? MatchingType { get; private set; }
public override void VisitAssembly(IAssemblySymbol symbol) =>
Guard.ArgumentNotNull(symbol).GlobalNamespace.Accept(this);
public override void VisitNamespace(INamespaceSymbol symbol)
{
Guard.ArgumentNotNull(symbol);
if (MatchingType is not null)
return;
foreach (var member in symbol.GetMembers())
member.Accept(this);
}
public override void VisitNamedType(INamedTypeSymbol symbol)
{
Guard.ArgumentNotNull(symbol);
if (MatchingType is not null)
return;
if (selector(symbol))
{
MatchingType = symbol;
return;
}
foreach (var nestedType in symbol.GetTypeMembers())
nestedType.Accept(this);
}
}
}
================================================
FILE: src/xunit.analyzers/Utility/Constants.cs
================================================
namespace Xunit.Analyzers;
public static class Constants
{
///
/// Argument names for Assert methods
///
public static class AssertArguments
{
public const string Actual = "actual";
public const string Expected = "expected";
public const string IgnoreCase = "ignoreCase";
}
///
/// Method names from Assert
///
public static class Asserts
{
public const string All = nameof(All);
public const string AllAsync = nameof(AllAsync);
public const string Collection = nameof(Collection);
public const string CollectionAsync = nameof(CollectionAsync);
public const string Contains = nameof(Contains);
public const string Distinct = nameof(Distinct);
public const string DoesNotContain = nameof(DoesNotContain);
public const string DoesNotMatch = nameof(DoesNotMatch);
public const string Empty = nameof(Empty);
public const string EndsWith = nameof(EndsWith);
public const string Equal = nameof(Equal);
public const string Equivalent = nameof(Equivalent);
public const string Fail = nameof(Fail);
public const string False = nameof(False);
public const string InRange = nameof(InRange);
public const string IsAssignableFrom = nameof(IsAssignableFrom);
public const string IsNotAssignableFrom = nameof(IsNotAssignableFrom);
public const string IsNotType = nameof(IsNotType);
public const string IsType = nameof(IsType);
public const string Matches = nameof(Matches);
public const string Multiple = nameof(Multiple);
public const string NotEmpty = nameof(NotEmpty);
public const string NotEqual = nameof(NotEqual);
public const string NotInRange = nameof(NotInRange);
public const string NotNull = nameof(NotNull);
public const string NotSame = nameof(NotSame);
public const string NotStrictEqual = nameof(NotStrictEqual);
public const string Null = nameof(Null);
public const string ProperSubset = nameof(ProperSubset);
public const string ProperSuperset = nameof(ProperSuperset);
public const string PropertyChanged = nameof(PropertyChanged);
public const string PropertyChangedAsync = nameof(PropertyChangedAsync);
public const string Raises = nameof(Raises);
public const string RaisesAny = nameof(RaisesAny);
public const string RaisesAnyAsync = nameof(RaisesAnyAsync);
public const string RaisesAsync = nameof(RaisesAsync);
public const string Same = nameof(Same);
public const string Single = nameof(Single);
public const string StartsWith = nameof(StartsWith);
public const string StrictEqual = nameof(StrictEqual);
public const string Subset = nameof(Subset);
public const string Superset = nameof(Superset);
public const string Throws = nameof(Throws);
public const string ThrowsAny = nameof(ThrowsAny);
public const string ThrowsAnyAsync = nameof(ThrowsAnyAsync);
public const string ThrowsAsync = nameof(ThrowsAsync);
public const string True = nameof(True);
}
///
/// Attribute names (without the Attribute suffix unless otherwise noted)
///
public static class Attributes
{
public const string Fact = nameof(Fact);
public const string Theory = nameof(Theory);
}
///
/// Property names from xUnit.net attributes
///
public static class AttributeProperties
{
public const string DeclaringType = nameof(DeclaringType);
public const string MemberName = nameof(MemberName);
public const string MemberType = nameof(MemberType);
}
///
/// Properties placed into diagnostics to be picked up by fixes
///
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 IsCtorObsolete = nameof(IsCtorObsolete);
public const string IsStatic = nameof(IsStatic);
public const string IsStaticMethodCall = nameof(IsStaticMethodCall);
public const string LiteralValue = nameof(LiteralValue);
public const string MemberName = nameof(MemberName);
public const string MethodName = nameof(MethodName);
public const string NewBaseType = nameof(NewBaseType);
public const string ParameterArrayStyle = nameof(ParameterArrayStyle);
public const string ParameterIndex = nameof(ParameterIndex);
public const string ParameterName = nameof(ParameterName);
public const string ParameterSpecialType = nameof(ParameterSpecialType);
public const string Replacement = nameof(Replacement);
public const string SizeValue = nameof(SizeValue);
public const string SubstringMethodName = nameof(SubstringMethodName);
public const string TestClassName = nameof(TestClassName);
public const string TFixtureDisplayName = nameof(TFixtureDisplayName);
public const string TFixtureName = nameof(TFixtureName);
public const string TypeName = nameof(TypeName);
public const string UseExactMatch = nameof(UseExactMatch);
}
///
/// Type names as strings for runtime lookup
///
public static class Types
{
public static class System
{
public const string ObsoleteAttribute = "System.ObsoleteAttribute";
}
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 ClassDataAttributeOfT_V3 = "Xunit.ClassDataAttribute`1";
public const string CollectionAttribute = "Xunit.CollectionAttribute";
public const string CollectionAttributeOfT_V3 = "Xunit.CollectionAttribute`1";
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 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 IDataAttribute_V3 = "Xunit.v3.IDataAttribute";
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 IRunnerReporter_V3 = "Xunit.Runner.Common.IRunnerReporter";
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 IXunitSerializer_V3 = "Xunit.Sdk.IXunitSerializer";
public const string JsonTypeIDAttribute_V3 = "Xunit.Sdk.JsonTypeIDAttribute";
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 Record = "Xunit.Record";
public const string RegisterXunitSerializerAttribute_V3 = "Xunit.Sdk.RegisterXunitSerializerAttribute";
public const string TestContext_V3 = "Xunit.TestContext";
public const string TheoryAttribute = "Xunit.TheoryAttribute";
public const string TheoryData = "Xunit.TheoryData";
public const string TheoryDataRow_V3 = "Xunit.TheoryDataRow";
}
}
}
================================================
FILE: src/xunit.analyzers/Utility/ConversionChecker.cs
================================================
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
namespace Xunit.Analyzers;
static class ConversionChecker
{
static readonly HashSet SignedIntegralTypes = [
SpecialType.System_SByte,
SpecialType.System_Int16,
SpecialType.System_Int32,
SpecialType.System_Int64,
];
static readonly HashSet UnsignedIntegralTypes = [
SpecialType.System_Byte,
SpecialType.System_UInt16,
SpecialType.System_UInt32,
SpecialType.System_UInt64,
];
public static bool IsConvertible(
Compilation compilation,
ITypeSymbol source,
ITypeSymbol destination,
XunitContext xunitContext,
object? valueSource = null)
{
Guard.ArgumentNotNull(compilation);
Guard.ArgumentNotNull(source);
Guard.ArgumentNotNull(destination);
Guard.ArgumentNotNull(xunitContext);
if (destination.TypeKind == TypeKind.Array)
{
var destinationElementType = ((IArrayTypeSymbol)destination).ElementType;
if (destinationElementType.TypeKind == TypeKind.TypeParameter)
return IsConvertibleTypeParameter(source, (ITypeParameterSymbol)destinationElementType);
}
if (destination.TypeKind == TypeKind.TypeParameter)
return IsConvertibleTypeParameter(source, (ITypeParameterSymbol)destination);
var conversion = compilation.ClassifyConversion(source, destination);
if (conversion.IsNumeric)
return IsConvertibleNumeric(source, destination, valueSource);
if (destination.SpecialType == SpecialType.System_DateTime
|| (xunitContext.Core.TheorySupportsConversionFromStringToDateTimeOffsetAndGuid && IsDateTimeOffsetOrGuid(destination)))
{
// Allow all conversions from strings. All parsing issues will be reported at runtime.
return source.SpecialType == SpecialType.System_String;
}
// Rules of last resort
return conversion.IsImplicit
|| conversion.IsUnboxing
|| (conversion.IsExplicit && conversion.IsUserDefined)
|| (conversion.IsExplicit && conversion.IsNullable);
}
static bool IsConvertibleTypeParameter(
ITypeSymbol source,
ITypeParameterSymbol destination)
{
if (destination.HasValueTypeConstraint && !source.IsValueType)
return false;
if (destination.HasReferenceTypeConstraint && source.IsValueType)
return false;
return destination.ConstraintTypes.All(c => c.IsAssignableFrom(source));
}
static bool IsConvertibleNumeric(
ITypeSymbol source,
ITypeSymbol destination,
object? valueSource = null)
{
var isIntegral = long.TryParse(valueSource?.ToString(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var integralValue);
if (isIntegral && integralValue < 0 && IsSigned(source) && IsUnsigned(destination))
return false;
if (destination.SpecialType == SpecialType.System_Char
&& (source.SpecialType == SpecialType.System_Double || source.SpecialType == SpecialType.System_Single))
{
// Conversions from float to char (though numeric) do not actually work at runtime, so report them
return false;
}
return true; // Allow all numeric conversions. Narrowing conversion issues will be reported at runtime.
}
static bool IsDateTimeOffsetOrGuid(ITypeSymbol destination)
{
if (destination.ContainingNamespace?.Name != nameof(System))
return false;
return destination.MetadataName is (nameof(DateTimeOffset)) or (nameof(Guid));
}
static bool IsSigned(ITypeSymbol typeSymbol) =>
SignedIntegralTypes.Contains(typeSymbol.SpecialType);
static bool IsUnsigned(ITypeSymbol typeSymbol) =>
UnsignedIntegralTypes.Contains(typeSymbol.SpecialType);
}
================================================
FILE: src/xunit.analyzers/Utility/Descriptors.Suppressors.cs
================================================
using Microsoft.CodeAnalysis;
namespace Xunit.Analyzers;
public static partial class Descriptors
{
public static SuppressionDescriptor CA1515_Suppression { get; } =
Suppression("CA1515", "xUnit.net's test classes must be public.");
public static SuppressionDescriptor CA2007_Suppression { get; } =
Suppression("CA2007", "xUnit.net test methods should not call ConfigureAwait");
public static SuppressionDescriptor CS8618_Suppression { get; } =
Suppression("CS8618", "Non-nullable member is initialized in IAsyncLifetime.InitializeAsync");
public static SuppressionDescriptor VSTHRD200_Suppression { get; } =
Suppression("VSTHRD200", "xUnit.net test methods are not directly callable and do not benefit from this naming rule");
}
================================================
FILE: src/xunit.analyzers/Utility/Descriptors.cs
================================================
using System.Collections.Concurrent;
using Microsoft.CodeAnalysis;
namespace Xunit.Analyzers;
public static partial class Descriptors
{
static readonly ConcurrentDictionary categoryMapping = new();
static DiagnosticDescriptor Diagnostic(
string id,
string title,
Category category,
DiagnosticSeverity defaultSeverity,
string messageFormat)
{
var helpLink = $"https://xunit.net/xunit.analyzers/rules/{id}";
var categoryString = categoryMapping.GetOrAdd(category, c => c.ToString());
return new DiagnosticDescriptor(id, title, messageFormat, categoryString, defaultSeverity, isEnabledByDefault: true, helpLinkUri: helpLink);
}
static SuppressionDescriptor Suppression(
string suppressedDiagnosticId,
string justification) =>
new("xUnitSuppress-" + suppressedDiagnosticId, suppressedDiagnosticId, justification);
}
================================================
FILE: src/xunit.analyzers/Utility/Descriptors.xUnit1xxx.cs
================================================
using Microsoft.CodeAnalysis;
using static Microsoft.CodeAnalysis.DiagnosticSeverity;
using static Xunit.Analyzers.Category;
namespace Xunit.Analyzers;
public static partial class Descriptors
{
public static DiagnosticDescriptor X1000_TestClassMustBePublic { get; } =
Diagnostic(
"xUnit1000",
"Test classes must be public",
Usage,
Error,
"Test classes must be public. Add or change the visibility modifier of the test class to public."
);
public static DiagnosticDescriptor X1001_FactMethodMustNotHaveParameters { get; } =
Diagnostic(
"xUnit1001",
"Fact methods cannot have parameters",
Usage,
Error,
"Fact methods cannot have parameters. Remove the parameters from the method or convert it into a Theory."
);
public static DiagnosticDescriptor X1002_TestMethodMustNotHaveMultipleFactAttributes { get; } =
Diagnostic(
"xUnit1002",
"Test methods cannot have multiple Fact or Theory attributes",
Usage,
Error,
"Test methods cannot have multiple Fact or Theory attributes. Remove all but one of the attributes."
);
public static DiagnosticDescriptor X1003_TheoryMethodMustHaveTestData { get; } =
Diagnostic(
"xUnit1003",
"Theory methods must have test data",
Usage,
Error,
"Theory methods must have test data. Use InlineData, MemberData, or ClassData to provide test data for the Theory."
);
public static DiagnosticDescriptor X1004_TestMethodShouldNotBeSkipped { get; } =
Diagnostic(
"xUnit1004",
"Test methods should not be skipped",
Usage,
Info,
"Test methods should not be skipped. Remove the Skip property to start running the test again."
);
public static DiagnosticDescriptor X1005_FactMethodShouldNotHaveTestData { get; } =
Diagnostic(
"xUnit1005",
"Fact methods should not have test data",
Usage,
Warning,
"Fact methods should not have test data. Remove the test data, or convert the Fact to a Theory."
);
public static DiagnosticDescriptor X1006_TheoryMethodShouldHaveParameters { get; } =
Diagnostic(
"xUnit1006",
"Theory methods should have parameters",
Usage,
Warning,
"Theory methods should have parameters. Add parameter(s) to the theory method."
);
public static DiagnosticDescriptor X1007_ClassDataAttributeMustPointAtValidClass { get; } =
Diagnostic(
"xUnit1007",
"ClassData must point at a valid class",
Usage,
Error,
"ClassData must point at a valid class. The class {0} must be public, not sealed, with an empty constructor, and implement {1}."
);
public static DiagnosticDescriptor X1008_DataAttributeShouldBeUsedOnATheory { get; } =
Diagnostic(
"xUnit1008",
"Test data attribute should only be used on a Theory",
Usage,
Warning,
"Test data attribute should only be used on a Theory. Remove the test data, or add the Theory attribute to the test method."
);
public static DiagnosticDescriptor X1009_InlineDataMustMatchTheoryParameters_TooFewValues { get; } =
Diagnostic(
"xUnit1009",
"InlineData values must match the number of method parameters",
Usage,
Error,
"InlineData values must match the number of method parameters. Remove unused parameters, or add more data for the missing parameters."
);
public static DiagnosticDescriptor X1010_InlineDataMustMatchTheoryParameters_IncompatibleValueType { get; } =
Diagnostic(
"xUnit1010",
"The value is not convertible to the method parameter type",
Usage,
Error,
"The value is not convertible to the method parameter '{0}' of type '{1}'. Use a compatible data value."
);
public static DiagnosticDescriptor X1011_InlineDataMustMatchTheoryParameters_ExtraValue { get; } =
Diagnostic(
"xUnit1011",
"There is no matching method parameter",
Usage,
Error,
"There is no matching method parameter for value: {0}. Remove unused value(s), or add more parameter(s)."
);
public static DiagnosticDescriptor X1012_InlineDataMustMatchTheoryParameters_NullShouldNotBeUsedForIncompatibleParameter { get; } =
Diagnostic(
"xUnit1012",
"Null should only be used for nullable parameters",
Usage,
Warning,
"Null should not be used for type parameter '{0}' of type '{1}'. Use a non-null value, or convert the parameter to a nullable type."
);
public static DiagnosticDescriptor X1013_PublicMethodShouldBeMarkedAsTest { get; } =
Diagnostic(
"xUnit1013",
"Public method should be marked as test",
Usage,
Warning,
"Public method '{0}' on test class '{1}' should be marked as a {2}. Reduce the visibility of the method, or add a {2} attribute to the method."
);
public static DiagnosticDescriptor X1014_MemberDataShouldUseNameOfOperator { get; } =
Diagnostic(
"xUnit1014",
"MemberData should use nameof operator for member name",
Usage,
Warning,
"MemberData should use nameof operator to reference member '{0}' on type '{1}'. Replace the constant string with nameof."
);
public static DiagnosticDescriptor X1015_MemberDataMustReferenceExistingMember { get; } =
Diagnostic(
"xUnit1015",
"MemberData must reference an existing member",
Usage,
Error,
"MemberData must reference an existing member '{0}' on type '{1}'. Fix the member reference, or add the missing data member."
);
public static DiagnosticDescriptor X1016_MemberDataMustReferencePublicMember { get; } =
Diagnostic(
"xUnit1016",
"MemberData must reference a public member",
Usage,
Error,
"MemberData must reference a public member. Add or change the visibility of the data member to public."
);
public static DiagnosticDescriptor X1017_MemberDataMustReferenceStaticMember { get; } =
Diagnostic(
"xUnit1017",
"MemberData must reference a static member",
Usage,
Error,
"MemberData must reference a static member. Add the static modifier to the data member."
);
public static DiagnosticDescriptor X1018_MemberDataMustReferenceValidMemberKind { get; } =
Diagnostic(
"xUnit1018",
"MemberData must reference a valid member kind",
Usage,
Error,
"MemberData must reference a property, field, or method. Convert the data member to a compatible member type."
);
public static DiagnosticDescriptor X1019_MemberDataMustReferenceMemberOfValidType { get; } =
Diagnostic(
"xUnit1019",
"MemberData must reference a member providing a valid data type",
Usage,
Error,
"MemberData must reference a data type assignable to {0}. The referenced type '{1}' is not valid."
);
public static DiagnosticDescriptor X1020_MemberDataPropertyMustHaveGetter { get; } =
Diagnostic(
"xUnit1020",
"MemberData must reference a property with a public getter",
Usage,
Error,
"MemberData must reference a property with a public getter. Add a public getter to the data member, or change the visibility of the existing getter to public."
);
public static DiagnosticDescriptor X1021_MemberDataNonMethodShouldNotHaveParameters { get; } =
Diagnostic(
"xUnit1021",
"MemberData should not have parameters if the referenced member is not a method",
Usage,
Warning,
"MemberData should not have parameters if the referenced member is not a method. Remove the parameter values, or convert the data member to a method with parameters."
);
public static DiagnosticDescriptor X1022_TheoryMethodCannotHaveParameterArray { get; } =
Diagnostic(
"xUnit1022",
"Theory methods cannot have a parameter array",
Usage,
Error,
"Theory method '{0}' on test class '{1}' cannot have a parameter array '{2}'. Upgrade to xUnit.net 2.2 or later to enable this feature."
);
public static DiagnosticDescriptor X1023_TheoryMethodCannotHaveDefaultParameter { get; } =
Diagnostic(
"xUnit1023",
"Theory methods cannot have default parameter values",
Usage,
Error,
"Theory method '{0}' on test class '{1}' parameter '{2}' cannot have a default value. Upgrade to xUnit.net 2.2 or later to enable this feature."
);
public static DiagnosticDescriptor X1024_TestMethodCannotHaveOverloads { get; } =
Diagnostic(
"xUnit1024",
"Test methods cannot have overloads",
Usage,
Error,
"Test method '{0}' on test class '{1}' has the same name as another method declared on class '{2}'. Rename method(s) so that there are no overloaded names."
);
public static DiagnosticDescriptor X1025_InlineDataShouldBeUniqueWithinTheory { get; } =
Diagnostic(
"xUnit1025",
"InlineData should be unique within the Theory it belongs to",
Usage,
Warning,
"Theory method '{0}' on test class '{1}' has InlineData duplicate(s). Remove redundant attribute(s) from the theory method."
);
public static DiagnosticDescriptor X1026_TheoryMethodShouldUseAllParameters { get; } =
Diagnostic(
"xUnit1026",
"Theory methods should use all of their parameters",
Usage,
Warning,
"Theory method '{0}' on test class '{1}' does not use parameter '{2}'. Use the parameter, or remove the parameter and associated data."
);
public static DiagnosticDescriptor X1027_CollectionDefinitionClassMustBePublic { get; } =
Diagnostic(
"xUnit1027",
"Collection definition classes must be public",
Usage,
Error,
"Collection definition classes must be public. Add or change the visibility modifier of the collection definition class to public."
);
public static DiagnosticDescriptor X1028_TestMethodHasInvalidReturnType { get; } =
Diagnostic(
"xUnit1028",
"Test method must have valid return type",
Usage,
Error,
"Test methods must have a supported return type. Valid types are: {0}. Change the return type to one of the compatible types."
);
public static DiagnosticDescriptor X1029_LocalFunctionsCannotBeTestFunctions { get; } =
Diagnostic(
"xUnit1029",
"Local functions cannot be test functions",
Usage,
Error,
"Local functions cannot be test functions. Remove '{0}'."
);
public static DiagnosticDescriptor X1030_DoNotUseConfigureAwait { get; } =
Diagnostic(
"xUnit1030",
"Do not call ConfigureAwait(false) in test method",
Usage,
Warning,
"Test methods should not call ConfigureAwait({0}), as it may bypass parallelization limits. {1}"
);
public static DiagnosticDescriptor X1031_DoNotUseBlockingTaskOperations { get; } =
Diagnostic(
"xUnit1031",
"Do not use blocking task operations in test method",
Usage,
Warning,
"Test methods should not use blocking task operations, as they can cause deadlocks. Use an async test method and await instead."
);
public static DiagnosticDescriptor X1032_TestClassCannotBeNestedInGenericClass { get; } =
Diagnostic(
"xUnit1032",
"Test classes cannot be nested within a generic class",
Usage,
Error,
"Test classes cannot be nested within a generic class. Move the test class out of the class it is nested in."
);
public static DiagnosticDescriptor X1033_TestClassShouldHaveTFixtureArgument { get; } =
Diagnostic(
"xUnit1033",
"Test classes decorated with 'Xunit.IClassFixture' or 'Xunit.ICollectionFixture' should add a constructor argument of type TFixture",
Usage,
Info,
"Test class '{0}' does not contain constructor argument of type '{1}'. Add a constructor argument to consume the fixture data."
);
public static DiagnosticDescriptor X1034_MemberDataArgumentsMustMatchMethodParameters_NullShouldNotBeUsedForIncompatibleParameter { get; } =
Diagnostic(
"xUnit1034",
"Null should only be used for nullable parameters",
Usage,
Warning,
"Null should not be used for type parameter '{0}' of type '{1}'. Use a non-null value, or convert the parameter to a nullable type."
);
public static DiagnosticDescriptor X1035_MemberDataArgumentsMustMatchMethodParameters_IncompatibleValueType { get; } =
Diagnostic(
"xUnit1035",
"The value is not convertible to the method parameter type",
Usage,
Error,
"The value is not convertible to the method parameter '{0}' of type '{1}'. Use a compatible data value."
);
public static DiagnosticDescriptor X1036_MemberDataArgumentsMustMatchMethodParameters_ExtraValue { get; } =
Diagnostic(
"xUnit1036",
"There is no matching method parameter",
Usage,
Error,
"There is no matching method parameter for value: {0}. Remove unused value(s), or add more parameter(s)."
);
public static DiagnosticDescriptor X1037_TheoryDataTypeArgumentsMustMatchTestMethodParameters_TooFewTypeParameters { get; } =
Diagnostic(
"xUnit1037",
"There are fewer theory data type arguments than required by the parameters of the test method",
Usage,
Error,
"There are fewer {0} type arguments than required by the parameters of the test method. Add more type parameters to match the method signature, or remove parameters from the test method."
);
public static DiagnosticDescriptor X1038_TheoryDataTypeArgumentsMustMatchTestMethodParameters_ExtraTypeParameters { get; } =
Diagnostic(
"xUnit1038",
"There are more theory data type arguments than allowed by the parameters of the test method",
Usage,
Error,
"There are more {0} type arguments than allowed by the parameters of the test method. Remove unused type arguments, or add more parameters."
);
public static DiagnosticDescriptor X1039_TheoryDataTypeArgumentsMustMatchTestMethodParameters_IncompatibleTypes { get; } =
Diagnostic(
"xUnit1039",
"The type argument to theory data is not compatible with the type of the corresponding test method parameter",
Usage,
Error,
"The type argument {0} from {1} is not compatible with the type of the corresponding test method parameter {2}."
);
public static DiagnosticDescriptor X1040_TheoryDataTypeArgumentsMustMatchTestMethodParameters_IncompatibleNullability { get; } =
Diagnostic(
"xUnit1040",
"The type argument to theory data is nullable, while the type of the corresponding test method parameter is not",
Usage,
Warning,
"The type argument {0} from {1} is nullable, while the type of the corresponding test method parameter {2} is not. Make the theory data type non-nullable, or make the test method parameter nullable."
);
public static DiagnosticDescriptor X1041_EnsureFixturesHaveASource { get; } =
Diagnostic(
"xUnit1041",
"Fixture arguments to test classes must have fixture sources",
Usage,
Warning,
"Fixture argument '{0}' does not have a fixture source (if it comes from a collection definition, ensure the definition is in the same assembly as the test)"
);
public static DiagnosticDescriptor X1042_MemberDataTheoryDataIsRecommendedForStronglyTypedAnalysis { get; } =
Diagnostic(
"xUnit1042",
"The member referenced by the MemberData attribute returns untyped data rows",
Usage,
Info,
"The member referenced by the MemberData attribute returns untyped data rows, such as object[]. Consider using {0} as the return type to provide better type safety."
);
public static DiagnosticDescriptor X1043_ConstructorOnFactAttributeSubclassShouldBePublic { get; } =
Diagnostic(
"xUnit1043",
"Constructors on classes derived from FactAttribute must be public when used on test methods",
Usage,
Error,
"Constructor '{0}' must be public to be used on a test method."
);
public static DiagnosticDescriptor X1044_AvoidUsingTheoryDataTypeArgumentsThatAreNotSerializable { get; } =
Diagnostic(
"xUnit1044",
"Avoid using TheoryData type arguments that are not serializable",
Usage,
Info,
"The type argument {0} is not serializable, which will cause Test Explorer to not enumerate individual data rows. Consider using a type that is known to be serializable."
);
public static DiagnosticDescriptor X1045_AvoidUsingTheoryDataTypeArgumentsThatMightNotBeSerializable { get; } =
Diagnostic(
"xUnit1045",
"Avoid using TheoryData type arguments that might not be serializable",
Usage,
Info,
"The type argument {0} might not be serializable, which may cause Test Explorer to not enumerate individual data rows. Consider using a type that is known to be serializable."
);
public static DiagnosticDescriptor X1046_AvoidUsingTheoryDataRowArgumentsThatAreNotSerializable { get; } =
Diagnostic(
"xUnit1046",
"Avoid using TheoryDataRow arguments that are not serializable",
Usage,
Info,
"The argument '{0}' of type '{1}' is not serializable, which will cause Test Explorer to not enumerate individual data rows. Consider using a value that is known to be serializable."
);
public static DiagnosticDescriptor X1047_AvoidUsingTheoryDataRowArgumentsThatMightNotBeSerializable { get; } =
Diagnostic(
"xUnit1047",
"Avoid using TheoryDataRow arguments that might not be serializable",
Usage,
Info,
"The argument '{0}' of type '{1}' might not be serializable, which may cause Test Explorer to not enumerate individual data rows. Consider using a value that is known to be serializable."
);
public static DiagnosticDescriptor X1048_DoNotUseAsyncVoidForTestMethods_V2 { get; } =
Diagnostic(
"xUnit1048",
"Avoid using 'async void' for test methods as it is deprecated in xUnit.net v3",
Usage,
Warning,
"Support for 'async void' unit tests is being removed from xUnit.net v3. To simplify upgrading, convert the test to 'async Task' instead."
);
public static DiagnosticDescriptor X1049_DoNotUseAsyncVoidForTestMethods_V3 { get; } =
Diagnostic(
"xUnit1049",
"Do not use 'async void' for test methods as it is no longer supported",
Usage,
Error,
"Support for 'async void' unit tests has been removed from xUnit.net v3. Convert the test to 'async Task' or 'async ValueTask' instead."
);
public static DiagnosticDescriptor X1050_ClassDataTheoryDataRowIsRecommendedForStronglyTypedAnalysis { get; } =
Diagnostic(
"xUnit1050",
"The class referenced by the ClassData attribute returns untyped data rows",
Usage,
Info,
"The class referenced by the ClassData attribute returns untyped data rows, such as object[] or ITheoryDataRow. Consider using generic TheoryDataRow<> as the row type to provide better type safety."
);
public static DiagnosticDescriptor X1051_UseCancellationToken { get; } =
Diagnostic(
"xUnit1051",
"Calls to methods which accept CancellationToken should use TestContext.Current.CancellationToken",
Usage,
Warning,
"Calls to methods which accept CancellationToken should use TestContext.Current.CancellationToken to allow test cancellation to be more responsive."
);
public static DiagnosticDescriptor X1052_TheoryDataShouldNotUseITheoryDataRow { get; } =
Diagnostic(
"xUnit1052",
"Avoid using 'TheoryData<...>' with types that implement 'ITheoryDataRow'.",
Usage,
Warning,
"'TheoryData<...>' should not be used with one or more type arguments that implement 'ITheoryDataRow' or a derived variant. This usage is not supported. Use either 'TheoryData' or a type of 'ITheoryDataRow' exclusively."
);
public static DiagnosticDescriptor X1053_MemberDataMemberMustBeStaticallyWrittenTo { get; } =
Diagnostic(
"xUnit1053",
"The static member used as theory data must be statically initialized.",
Usage,
Warning,
"The member {0} referenced by MemberData is not initialized before use. Add an inline initializer or initialize the value in the static constructor."
);
// Placeholder for rule X1054
// Placeholder for rule X1055
// Placeholder for rule X1056
// Placeholder for rule X1057
// Placeholder for rule X1058
// Placeholder for rule X1059
// Placeholder for rule X1060
}
================================================
FILE: src/xunit.analyzers/Utility/Descriptors.xUnit2xxx.cs
================================================
using Microsoft.CodeAnalysis;
using static Microsoft.CodeAnalysis.DiagnosticSeverity;
using static Xunit.Analyzers.Category;
namespace Xunit.Analyzers;
public static partial class Descriptors
{
public static DiagnosticDescriptor X2000_AssertEqualLiteralValueShouldBeFirst { get; } =
Diagnostic(
"xUnit2000",
"Constants and literals should be the expected argument",
Assertions,
Warning,
"The literal or constant value {0} should be passed as the 'expected' argument in the call to '{1}' in method '{2}' on type '{3}'. Swap the parameter values."
);
public static DiagnosticDescriptor X2001_AssertEqualsShouldNotBeUsed { get; } =
Diagnostic(
"xUnit2001",
"Do not use invalid equality check",
Assertions,
Hidden,
"Do not use {0}. Use Assert.{1} instead."
);
public static DiagnosticDescriptor X2002_AssertNullShouldNotBeCalledOnValueTypes { get; } =
Diagnostic(
"xUnit2002",
"Do not use null check on value type",
Assertions,
Warning,
"Do not use {0} on value type '{1}'. Remove this assert."
);
public static DiagnosticDescriptor X2003_AssertEqualShouldNotUsedForNullCheck { get; } =
Diagnostic(
"xUnit2003",
"Do not use equality check to test for null value",
Assertions,
Warning,
"Do not use {0} to check for null value. Use Assert.{1} instead."
);
public static DiagnosticDescriptor X2004_AssertEqualShouldNotUsedForBoolLiteralCheck { get; } =
Diagnostic(
"xUnit2004",
"Do not use equality check to test for boolean conditions",
Assertions,
Warning,
"Do not use {0} to check for boolean conditions. Use Assert.{1} instead."
);
public static DiagnosticDescriptor X2005_AssertSameShouldNotBeCalledOnValueTypes { get; } =
Diagnostic(
"xUnit2005",
"Do not use identity check on value type",
Assertions,
Warning,
"Do not use {0} on value type '{1}'. Value types do not have identity. Use Assert.{2} instead."
);
public static DiagnosticDescriptor X2006_AssertEqualGenericShouldNotBeUsedForStringValue { get; } =
Diagnostic(
"xUnit2006",
"Do not use invalid string equality check",
Assertions,
Warning,
"Do not use {0} to test for string equality. Use {1} instead."
);
public static DiagnosticDescriptor X2007_AssertIsTypeShouldUseGenericOverload { get; } =
Diagnostic(
"xUnit2007",
"Do not use typeof expression to check the type",
Assertions,
Warning,
"Do not use typeof({0}) expression to check the type. Use Assert.IsType<{0}> instead."
);
public static DiagnosticDescriptor X2008_AssertRegexMatchShouldNotUseBoolLiteralCheck { get; } =
Diagnostic(
"xUnit2008",
"Do not use boolean check to match on regular expressions",
Assertions,
Warning,
"Do not use {0} to match on regular expressions. Use Assert.{1} instead."
);
public static DiagnosticDescriptor X2009_AssertSubstringCheckShouldNotUseBoolCheck { get; } =
Diagnostic(
"xUnit2009",
"Do not use boolean check to check for substrings",
Assertions,
Warning,
"Do not use {0} to check for substrings. Use Assert.{1} instead."
);
public static DiagnosticDescriptor X2010_AssertStringEqualityCheckShouldNotUseBoolCheckFixer { get; } =
Diagnostic(
"xUnit2010",
"Do not use boolean check to check for string equality",
Assertions,
Warning,
"Do not use {0} to check for string equality. Use Assert.{1} instead."
);
public static DiagnosticDescriptor X2011_AssertEmptyCollectionCheckShouldNotBeUsed { get; } =
Diagnostic(
"xUnit2011",
"Do not use empty collection check",
Assertions,
Warning,
"Do not use {0} to check for empty collections. Add element inspectors (for non-empty collections), or use Assert.Empty (for empty collections) instead."
);
public static DiagnosticDescriptor X2012_AssertEnumerableAnyCheckShouldNotBeUsedForCollectionContainsCheck { get; } =
Diagnostic(
"xUnit2012",
"Do not use boolean check to check if a value exists in a collection",
Assertions,
Warning,
"Do not use {0} to check if a value exists in a collection. Use Assert.{1} instead."
);
public static DiagnosticDescriptor X2013_AssertEqualShouldNotBeUsedForCollectionSizeCheck { get; } =
Diagnostic(
"xUnit2013",
"Do not use equality check to check for collection size.",
Assertions,
Warning,
"Do not use {0} to check for collection size. Use Assert.{1} instead."
);
public static DiagnosticDescriptor X2014_AssertThrowsShouldNotBeUsedForAsyncThrowsCheck { get; } =
Diagnostic(
"xUnit2014",
"Do not use throws check to check for asynchronously thrown exception",
Assertions,
Error,
"Do not use {0} to check for asynchronously thrown exceptions. Use Assert.{1} instead."
);
public static DiagnosticDescriptor X2015_AssertThrowsShouldUseGenericOverload { get; } =
Diagnostic(
"xUnit2015",
"Do not use typeof expression to check the exception type",
Assertions,
Warning,
"Do not use typeof({1}) expression to check the exception type. Use Assert.{0}<{1}> instead."
);
public static DiagnosticDescriptor X2016_AssertEqualPrecisionShouldBeInRange { get; } =
Diagnostic(
"xUnit2016",
"Keep precision in the allowed range when asserting equality of doubles or decimals.",
Assertions,
Error,
"Keep precision in range {0} when asserting equality of {1} typed actual value."
);
public static DiagnosticDescriptor X2017_AssertCollectionContainsShouldNotUseBoolCheck { get; } =
Diagnostic(
"xUnit2017",
"Do not use Contains() to check if a value exists in a collection",
Assertions,
Warning,
"Do not use {0} to check if a value exists in a collection. Use Assert.{1} instead."
);
public static DiagnosticDescriptor X2018_AssertIsTypeShouldNotBeUsedForAbstractType { get; } =
Diagnostic(
"xUnit2018",
"Do not compare an object's exact type to an abstract class or interface",
Assertions,
Warning,
"Do not compare an object's exact type to the {0} '{1}'. Use {2} instead."
);
// Note: X2019 was already covered by X2014, and should not be reused
public static DiagnosticDescriptor X2020_UseAssertFailInsteadOfBooleanAssert { get; } =
Diagnostic(
"xUnit2020",
"Do not use always-failing boolean assertions",
Assertions,
Warning,
"Do not use Assert.{0}({1}, message) to fail a test. Use Assert.Fail(message) instead."
);
public static DiagnosticDescriptor X2021_AsyncAssertionsShouldBeAwaited { get; } =
Diagnostic(
"xUnit2021",
"Async assertions should be awaited",
Assertions,
Error,
"Assert.{0} is async. The resulting task should be awaited (or stored for later awaiting)."
);
public static DiagnosticDescriptor X2022_BooleanAssertionsShouldNotBeNegated { get; } =
Diagnostic(
"xUnit2022",
"Boolean assertions should not be negated",
Assertions,
Info,
"Do not negate your value when calling Assert.{0}. Call Assert.{1} without the negation instead."
);
public static DiagnosticDescriptor X2023_AssertSingleShouldBeUsedForSingleParameter { get; } =
Diagnostic(
"xUnit2023",
"Do not use collection methods for single-item collections",
Assertions,
Info,
"Do not use Assert.{0} if there is one element in the collection. Use Assert.Single instead."
);
public static DiagnosticDescriptor X2024_BooleanAssertionsShouldNotBeUsedForSimpleEqualityCheck { get; } =
Diagnostic(
"xUnit2024",
"Do not use boolean asserts for simple equality tests",
Assertions,
Info,
"Do not use Assert.{0} to test equality against null, numeric, string, or enum literals. Use Assert.{1} instead."
);
public static DiagnosticDescriptor X2025_BooleanAssertionCanBeSimplified { get; } =
Diagnostic(
"xUnit2025",
"The boolean assertion statement can be simplified",
Assertions,
Info,
"The use of Assert.{0} can be simplified to avoid using a boolean literal value in an equality test."
);
public static DiagnosticDescriptor X2026_SetsMustBeComparedWithEqualityComparer { get; } =
Diagnostic(
"xUnit2026",
"Comparison of sets must be done with IEqualityComparer",
Assertions,
Warning,
"Comparison of two sets may produce inconsistent results if GetHashCode() is not overriden. Consider using Assert.{0}(IEnumerable, IEnumerable, IEqualityComparer) instead."
);
public static DiagnosticDescriptor X2027_SetsShouldNotBeComparedToLinearContainers { get; } =
Diagnostic(
"xUnit2027",
"Comparison of sets to linear containers have undefined results",
Assertions,
Warning,
"Comparing an instance of {0} with an instance of {1} has undefined results, because the order of items in the set is not predictable. Create a stable order for the set (i.e., by using OrderBy from Linq)."
);
public static DiagnosticDescriptor X2028_DoNotUseAssertEmptyWithProblematicTypes { get; } =
Diagnostic(
"xUnit2028",
"Do not use Assert.Empty or Assert.NotEmpty with problematic types",
Assertions,
Warning,
"Using Assert.{0} with an instance of {1} is problematic, because {2}. Check the length with .Count instead."
);
public static DiagnosticDescriptor X2029_AssertEmptyShouldNotBeUsedForCollectionDoesNotContainCheck { get; } =
Diagnostic(
"xUnit2029",
"Do not use Assert.Empty to check if a value does not exist in a collection",
Assertions,
Warning,
"Do not use Assert.Empty to check if a value does not exist in a collection. Use Assert.DoesNotContain instead."
);
public static DiagnosticDescriptor X2030_AssertNotEmptyShouldNotBeUsedForCollectionContainsCheck { get; } =
Diagnostic(
"xUnit2030",
"Do not use Assert.NotEmpty to check if a value exists in a collection",
Assertions,
Warning,
"Do not use Assert.NotEmpty to check if a value exists in a collection. Use Assert.Contains instead."
);
public static DiagnosticDescriptor X2031_AssertSingleShouldUseTwoArgumentCall { get; } =
Diagnostic(
"xUnit2031",
"Do not use Where clause with Assert.Single",
Assertions,
Warning,
"Do not use a Where clause to filter before calling Assert.Single. Use the overload of Assert.Single that accepts a filtering function."
);
public static DiagnosticDescriptor X2032_AssignableFromAssertionIsConfusinglyNamed { get; } =
Diagnostic(
"xUnit2032",
"Type assertions based on 'assignable from' are confusingly named",
Assertions,
Info,
"The naming of Assert.{0} can be confusing. An overload of Assert.{1} is available with an exact match flag which can be set to false to perform the same operation."
);
// Placeholder for rule X2033
// Placeholder for rule X2034
// Placeholder for rule X2035
// Placeholder for rule X2036
// Placeholder for rule X2037
// Placeholder for rule X2038
// Placeholder for rule X2039
}
================================================
FILE: src/xunit.analyzers/Utility/Descriptors.xUnit3xxx.cs
================================================
using Microsoft.CodeAnalysis;
using static Microsoft.CodeAnalysis.DiagnosticSeverity;
using static Xunit.Analyzers.Category;
namespace Xunit.Analyzers;
public static partial class Descriptors
{
public static DiagnosticDescriptor X3000_CrossAppDomainClassesMustBeLongLivedMarshalByRefObject { get; } =
Diagnostic(
"xUnit3000",
"Classes which cross AppDomain boundaries must derive directly or indirectly from LongLivedMarshalByRefObject",
Extensibility,
Error,
"Class {0} must derive directly or indirectly from LongLivedMarshalByRefObject."
);
public static DiagnosticDescriptor X3001_SerializableClassMustHaveParameterlessConstructor { get; } =
Diagnostic(
"xUnit3001",
"Classes that are marked as serializable (or created by the test framework at runtime) must have a public parameterless constructor",
Extensibility,
Error,
"Class {0} must have a public parameterless constructor to support {1}."
);
public static DiagnosticDescriptor X3002_DoNotTestForConcreteTypeOfJsonSerializableTypes { get; } =
Diagnostic(
"xUnit3002",
"Classes which are JSON serializable should not be tested for their concrete type",
Extensibility,
Warning,
"Class {0} is JSON serializable and should not be tested for its concrete type. Test for its primary interface instead."
);
public static DiagnosticDescriptor X3003_ProvideConstructorForFactAttributeOverride { get; } =
Diagnostic(
"xUnit3003",
"Classes which extend FactAttribute (directly or indirectly) should provide a public constructor for source information",
Extensibility,
Warning,
"Class {0} extends FactAttribute. It should include a public constructor for source information."
);
// Placeholder for rule X3004
// Placeholder for rule X3005
// Placeholder for rule X3006
// Placeholder for rule X3007
// Placeholder for rule X3008
// Placeholder for rule X3009
}
================================================
FILE: src/xunit.analyzers/Utility/EmptyAssertContext.cs
================================================
using System;
using Microsoft.CodeAnalysis;
namespace Xunit.Analyzers;
public class EmptyAssertContext : IAssertContext
{
EmptyAssertContext()
{ }
public INamedTypeSymbol? AssertType => null;
public static EmptyAssertContext Instance { get; } = new();
public bool SupportsAssertFail => false;
public bool SupportsAssertNullWithPointers => false;
public bool SupportsInexactTypeAssertions => false;
public Version Version { get; } = new();
}
================================================
FILE: src/xunit.analyzers/Utility/EmptyCommonContext.cs
================================================
using System;
using Microsoft.CodeAnalysis;
namespace Xunit.Analyzers;
public class EmptyCommonContext : ICommonContext
{
EmptyCommonContext()
{ }
public static EmptyCommonContext 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();
}
================================================
FILE: src/xunit.analyzers/Utility/EmptyCoreContext.cs
================================================
using System;
using Microsoft.CodeAnalysis;
namespace Xunit.Analyzers;
public class EmptyCoreContext : ICoreContext
{
EmptyCoreContext()
{ }
public INamedTypeSymbol? ClassDataAttributeType => null;
public INamedTypeSymbol? CollectionAttributeType => null;
public INamedTypeSymbol? CollectionDefinitionAttributeType => null;
public INamedTypeSymbol? DataAttributeType => null;
public INamedTypeSymbol? FactAttributeType => null;
public INamedTypeSymbol? IClassFixtureType => null;
public INamedTypeSymbol? ICollectionFixtureType => null;
public INamedTypeSymbol? InlineDataAttributeType => null;
public INamedTypeSymbol? ITestOutputHelperType => null;
public static EmptyCoreContext Instance { get; } = new();
public INamedTypeSymbol? MemberDataAttributeType => null;
public INamedTypeSymbol? TheoryAttributeType => null;
public bool TheorySupportsConversionFromStringToDateTimeOffsetAndGuid => false;
public bool TheorySupportsDefaultParameterValues => false;
public bool TheorySupportsParameterArrays => false;
public Version Version { get; } = new();
}
================================================
FILE: src/xunit.analyzers/Utility/EmptyRunnerUtilityContext.cs
================================================
using System;
using Microsoft.CodeAnalysis;
namespace Xunit.Analyzers;
public class EmptyRunnerUtilityContext : IRunnerUtilityContext
{
EmptyRunnerUtilityContext()
{ }
public static EmptyRunnerUtilityContext Instance { get; } = new();
public INamedTypeSymbol? LongLivedMarshalByRefObjectType => null;
public string Platform => "N/A";
public Version Version { get; } = new();
}
================================================
FILE: src/xunit.analyzers/Utility/EnumerableExtensions.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;
///
/// Extension methods for .
///
static partial class EnumerableExtensions
{
static readonly Func