internal override void AnalyzeCompilation(CompilationStartAnalysisContext compilationStartContext, XunitContext xunitContext) { compilationStartContext.RegisterSymbolAction(context => { if (context.Symbol.DeclaredAccessibility == Accessibility.Public) { return; } var classSymbol = (INamedTypeSymbol)context.Symbol; // RegisterSymbolAction guarantees by 2nd arg var doesClassContainTests = classSymbol .GetMembers() .OfType <IMethodSymbol>() .Any(m => m.GetAttributes() .Any(a => xunitContext.Core.FactAttributeType.IsAssignableFrom(a.AttributeClass))); if (!doesClassContainTests) { return; } context.ReportDiagnostic(Diagnostic.Create( Descriptors.X1000_TestClassMustBePublic, classSymbol.Locations.First(), classSymbol.Locations.Skip(1), classSymbol.Name)); }, SymbolKind.NamedType); }
internal override void AnalyzeCompilation(CompilationStartAnalysisContext compilationStartContext, XunitContext xunitContext) { compilationStartContext.RegisterSymbolAction(context => { if (context.Symbol.DeclaredAccessibility == Accessibility.Public) { return; } var classSymbol = (INamedTypeSymbol)context.Symbol; var doesClassContainCollectionDefinitionAttribute = classSymbol .GetAttributes() .Any(a => xunitContext.Core.CollectionDefinitionAttributeType.IsAssignableFrom(a.AttributeClass)); if (!doesClassContainCollectionDefinitionAttribute) { return; } context.ReportDiagnostic(Diagnostic.Create( Descriptors.X1027_CollectionDefinitionClassMustBePublic, classSymbol.Locations.First(), classSymbol.Locations.Skip(1), classSymbol.Name)); }, SymbolKind.NamedType); }
public static bool IsConvertible(Compilation compilation, ITypeSymbol source, ITypeSymbol destination, XunitContext xunitContext) { if (destination.TypeKind == TypeKind.TypeParameter) { return(IsConvertibleTypeParameter(source, (ITypeParameterSymbol)destination)); } var conversion = compilation.ClassifyConversion(source, destination); if (conversion.IsNumeric) { return(IsConvertibleNumeric(source, destination)); } 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.IsNullable)); }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.RegisterCompilationStartAction(compilationStartContext => { var xunitContext = new XunitContext(compilationStartContext.Compilation, capabilitiesFactory); if (xunitContext.FactAttributeType != null && ShouldAnalyze(xunitContext)) { AnalyzeCompilation(compilationStartContext, xunitContext); } }); }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.RegisterCompilationStartAction(compilationStartContext => { var xunitContext = new XunitContext(compilationStartContext.Compilation, versionOverride); if (ShouldAnalyze(xunitContext)) { AnalyzeCompilation(compilationStartContext, xunitContext); } }); }
public sealed override void Initialize(AnalysisContext context) { context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); context.EnableConcurrentExecution(); context.RegisterCompilationStartAction(context => { var xunitContext = new XunitContext(context.Compilation, versionOverride); if (ShouldAnalyze(xunitContext)) { AnalyzeCompilation(context, xunitContext); } }); }
private static void AnalyzeMethod(SymbolAnalysisContext context, XunitContext xunitContext) { var method = (IMethodSymbol)context.Symbol; var methodAllAttributes = method.GetAttributes(); if (!methodAllAttributes.ContainsAttributeType(xunitContext.Core.TheoryAttributeType)) { return; } var objectArrayType = TypeSymbolFactory.GetObjectArrayType(context.Compilation); var wellFormedInlineDataAttributes = methodAllAttributes .Where(a => a.AttributeClass == xunitContext.Core.InlineDataAttributeType && HasAttributeDeclarationNoCompilationErrors(a, objectArrayType)); AnalyzeInlineDataAttributesWithinTheory(context, wellFormedInlineDataAttributes); }
internal override void AnalyzeCompilation(CompilationStartAnalysisContext compilationStartContext, XunitContext xunitContext) { var xunitSupportsParameterArrays = xunitContext.Core.TheorySupportsParameterArrays; var xunitSupportsDefaultParameterValues = xunitContext.Core.TheorySupportsDefaultParameterValues; var compilation = compilationStartContext.Compilation; var systemRuntimeInteropServicesOptionalAttribute = compilation.GetTypeByMetadataName(Constants.Types.SystemRuntimeInteropServicesOptionalAttribute); var objectArrayType = compilation.CreateArrayTypeSymbol(compilation.ObjectType); compilationStartContext.RegisterSymbolAction(symbolContext => { var method = (IMethodSymbol)symbolContext.Symbol; var attributes = method.GetAttributes(); if (!attributes.ContainsAttributeType(xunitContext.Core.TheoryAttributeType)) { return; } foreach (var attribute in attributes) { symbolContext.CancellationToken.ThrowIfCancellationRequested(); if (!attribute.AttributeClass.Equals(xunitContext.Core.InlineDataAttributeType)) { continue; } // Check if the semantic model indicates there are no syntax/compilation errors if (attribute.ConstructorArguments.Length != 1 || !objectArrayType.Equals(attribute.ConstructorArguments.FirstOrDefault().Type)) { continue; } var attributeSyntax = (AttributeSyntax)attribute.ApplicationSyntaxReference.GetSyntax(symbolContext.CancellationToken); var arrayStyle = ParameterArrayStyleType.Initializer; var dataParameterExpressions = GetParameterExpressionsFromArrayArgument(attributeSyntax); if (dataParameterExpressions == null) { arrayStyle = ParameterArrayStyleType.Params; dataParameterExpressions = attributeSyntax.ArgumentList?.Arguments.Select(a => a.Expression).ToList() ?? new List <ExpressionSyntax>(); } var dataArrayArgument = attribute.ConstructorArguments.Single(); // Need to special case InlineData(null) as the compiler will treat the whole data array as being initialized to null var values = dataArrayArgument.IsNull ? ImmutableArray.Create(dataArrayArgument) : dataArrayArgument.Values; if (values.Length < method.Parameters.Count(p => RequiresMatchingValue(p, xunitSupportsParameterArrays, xunitSupportsDefaultParameterValues, systemRuntimeInteropServicesOptionalAttribute))) { var builder = ImmutableDictionary.CreateBuilder <string, string>(); builder[ParameterArrayStyle] = arrayStyle.ToString(); symbolContext.ReportDiagnostic(Diagnostic.Create( Descriptors.X1009_InlineDataMustMatchTheoryParameters_TooFewValues, attributeSyntax.GetLocation(), builder.ToImmutable())); } int valueIdx = 0, paramIdx = 0; for (; valueIdx < values.Length && paramIdx < method.Parameters.Length; valueIdx++) { var parameter = method.Parameters[paramIdx]; // unwrap parameter type when the argument is a parameter list var parameterType = xunitSupportsParameterArrays && parameter.IsParams && parameter.Type is IArrayTypeSymbol arrayParam ? arrayParam.ElementType : parameter.Type; if (Equals(parameterType, compilation.ObjectType)) { // Everything is assignable to object and 'params object[]' so move on if (xunitSupportsParameterArrays && parameter.IsParams) { valueIdx = values.Length; break; } else { paramIdx++; continue; } } var builder = ImmutableDictionary.CreateBuilder <string, string>(); builder[ParameterIndex] = paramIdx.ToString(); builder[ParameterName] = parameter.Name; var properties = builder.ToImmutable(); var value = values[valueIdx]; if (!value.IsNull) { var isConvertible = ConversionChecker.IsConvertible(compilation, value.Type, parameterType, xunitContext); if (!isConvertible) { symbolContext.ReportDiagnostic(Diagnostic.Create( Descriptors.X1010_InlineDataMustMatchTheoryParameters_IncompatibleValueType, dataParameterExpressions[valueIdx].GetLocation(), properties, parameter.Name, SymbolDisplay.ToDisplayString(parameterType))); } } if (value.IsNull && parameterType.IsValueType && parameterType.OriginalDefinition.SpecialType != SpecialType.System_Nullable_T) { symbolContext.ReportDiagnostic(Diagnostic.Create( Descriptors.X1012_InlineDataMustMatchTheoryParameters_NullShouldNotBeUsedForIncompatibleParameter, dataParameterExpressions[valueIdx].GetLocation(), properties, parameter.Name, SymbolDisplay.ToDisplayString(parameterType))); } if (!parameter.IsParams) { // Stop moving paramIdx forward if the argument is a parameter array, regardless of xunit's support for it paramIdx++; } } for (; valueIdx < values.Length; valueIdx++) { var builder = ImmutableDictionary.CreateBuilder <string, string>(); builder[ParameterIndex] = valueIdx.ToString(); symbolContext.ReportDiagnostic( Diagnostic.Create( Descriptors.X1011_InlineDataMustMatchTheoryParameters_ExtraValue, dataParameterExpressions[valueIdx].GetLocation(), builder.ToImmutable(), values[valueIdx].ToCSharpString())); } } }, SymbolKind.Method); }
internal override void AnalyzeCompilation(CompilationStartAnalysisContext compilationStartContext, XunitContext xunitContext) { compilationStartContext.RegisterSymbolAction(symbolContext => { var typeSymbol = (INamedTypeSymbol)symbolContext.Symbol; if (typeSymbol.TypeKind != TypeKind.Class) { return; } var methodsByName = typeSymbol.GetInheritedAndOwnMembers() .Where(s => s.Kind == SymbolKind.Method) .Cast <IMethodSymbol>() .Where(m => m.MethodKind == MethodKind.Ordinary) .GroupBy(m => m.Name); foreach (var grouping in methodsByName) { symbolContext.CancellationToken.ThrowIfCancellationRequested(); var methods = grouping.ToList(); var methodName = grouping.Key; if (methods.Count == 1 || !methods.Any(m => m.GetAttributes().ContainsAttributeType(xunitContext.Core.FactAttributeType))) { continue; } var methodsWithoutOverloads = new List <IMethodSymbol>(methods.Count); foreach (var method in methods) { if (!methods.Any(m => m.IsOverride && m.OverriddenMethod.Equals(method))) { methodsWithoutOverloads.Add(method); } } if (methodsWithoutOverloads.Count == 1) { continue; } foreach (var method in methodsWithoutOverloads.Where(m => m.ContainingType.Equals(typeSymbol))) { var otherType = methodsWithoutOverloads.Where(m => !m.Equals(method)) .OrderBy(m => m.ContainingType, TypeHierarchyComparer.Instance) .First().ContainingType; symbolContext.ReportDiagnostic(Diagnostic.Create( Descriptors.X1024_TestMethodCannotHaveOverloads, method.Locations.First(), methodName, method.ContainingType.ToDisplayString(), otherType.ToDisplayString())); } } }, SymbolKind.NamedType); }
internal override void AnalyzeCompilation(CompilationStartAnalysisContext context, XunitContext xunitContext) { context.RegisterSymbolAction(context => { var namedType = (INamedTypeSymbol)context.Symbol; if (namedType.TypeKind != TypeKind.Class) { return; } var isXunitSerializable = xunitContext.Abstractions.IXunitSerializableType?.IsAssignableFrom(namedType) ?? false; if (!isXunitSerializable) { return; } var parameterlessCtor = namedType.InstanceConstructors.FirstOrDefault(c => c.Parameters.IsEmpty); if (parameterlessCtor is object && parameterlessCtor.DeclaredAccessibility == Accessibility.Public) { return; } context.ReportDiagnostic( Diagnostic.Create( Descriptors.X3001_SerializableClassMustHaveParameterlessConstructor, namedType.Locations.First(), namedType.Name)); }, SymbolKind.NamedType); }
protected override bool ShouldAnalyze(XunitContext xunitContext) => xunitContext.HasAbstractionsReference;
internal override void AnalyzeCompilation(CompilationStartAnalysisContext compilationStartContext, XunitContext xunitContext) { compilationStartContext.RegisterSymbolAction( symbolContext => AnalyzeMethod(symbolContext, xunitContext), SymbolKind.Method); }
internal override void AnalyzeCompilation(CompilationStartAnalysisContext compilationStartContext, XunitContext xunitContext) { compilationStartContext.RegisterSyntaxNodeAction(syntaxNodeContext => { var classDeclaration = syntaxNodeContext.Node as ClassDeclarationSyntax; if (classDeclaration.Modifiers.Any(SyntaxKind.PublicKeyword)) { return; } var methods = classDeclaration.Members.Where(n => n.IsKind(SyntaxKind.MethodDeclaration)).Cast <MethodDeclarationSyntax>(); if (methods.Any(method => method.AttributeLists.ContainsAttributeType(syntaxNodeContext.SemanticModel, xunitContext.FactAttributeType))) { syntaxNodeContext.ReportDiagnostic(Diagnostic.Create( Descriptors.X1000_TestClassMustBePublic, classDeclaration.Identifier.GetLocation(), classDeclaration.Identifier.ValueText)); } }, SyntaxKind.ClassDeclaration); }
internal override void AnalyzeCompilation(CompilationStartAnalysisContext compilationStartContext, XunitContext xunitContext) { var taskType = compilationStartContext.Compilation.GetTypeByMetadataName(Constants.Types.SystemThreadingTasksTask); var configuredTaskAwaitableType = compilationStartContext.Compilation.GetTypeByMetadataName(Constants.Types.SystemRuntimeCompilerServicesConfiguredTaskAwaitable); var interfacesToIgnore = new List <INamedTypeSymbol> { compilationStartContext.Compilation.GetSpecialType(SpecialType.System_IDisposable), compilationStartContext.Compilation.GetTypeByMetadataName(Constants.Types.XunitIAsyncLifetime), }; compilationStartContext.RegisterSymbolAction(symbolContext => { var type = (INamedTypeSymbol)symbolContext.Symbol; if (type.TypeKind != TypeKind.Class || type.DeclaredAccessibility != Accessibility.Public || type.IsAbstract) { return; } var methodsToIgnore = interfacesToIgnore.Where(i => i != null && type.AllInterfaces.Contains(i)) .SelectMany(i => i.GetMembers()) .Select(m => type.FindImplementationForInterfaceMember(m)) .Where(s => s != null) .ToList(); var hasTestMethods = false; var violations = new List <IMethodSymbol>(); foreach (var member in type.GetMembers().Where(m => m.Kind == SymbolKind.Method)) { symbolContext.CancellationToken.ThrowIfCancellationRequested(); var method = (IMethodSymbol)member; // Check for method.IsAbstract and earlier for type.IsAbstract is done // twice to enable better diagnostics during code editing. It is useful with // incomplete code for abstract types - missing abstract keyword on type // or on abstract method if (method.MethodKind != MethodKind.Ordinary || method.IsAbstract) { continue; } var attributes = method.GetAttributes(); var isTestMethod = attributes.ContainsAttributeType(xunitContext.Core.FactAttributeType); hasTestMethods = hasTestMethods || isTestMethod; if (isTestMethod || attributes.Any(attribute => attribute.AttributeClass.GetAttributes() .Any(att => att.AttributeClass.Name.EndsWith("IgnoreXunitAnalyzersRule1013Attribute")))) { continue; } if (method.DeclaredAccessibility == Accessibility.Public && (method.ReturnsVoid || (taskType != null && Equals(method.ReturnType, taskType)) || (configuredTaskAwaitableType != null && Equals(method.ReturnType, configuredTaskAwaitableType)))) { var shouldIgnore = false; while (!shouldIgnore || method.IsOverride) { if (methodsToIgnore.Any(m => method.Equals(m))) { shouldIgnore = true; } if (!method.IsOverride) { break; } method = method.OverriddenMethod; if (method == null) { shouldIgnore = true; break; } } if (!shouldIgnore) { violations.Add(method); } } } if (hasTestMethods) { foreach (var method in violations) { var testType = method.Parameters.Any() ? "Theory" : "Fact"; symbolContext.ReportDiagnostic( Diagnostic.Create( Descriptors.X1013_PublicMethodShouldBeMarkedAsTest, method.Locations.First(), method.Name, method.ContainingType.Name, testType)); } } }, SymbolKind.NamedType); }
internal override void AnalyzeCompilation(CompilationStartAnalysisContext compilationStartContext, XunitContext xunitContext) { compilationStartContext.RegisterSymbolAction(symbolContext => { var method = (IMethodSymbol)symbolContext.Symbol; var parameter = method.Parameters.LastOrDefault(); if (!(parameter?.IsParams ?? false)) { return; } var attributes = method.GetAttributes(); if (attributes.ContainsAttributeType(xunitContext.Core.TheoryAttributeType)) { symbolContext.ReportDiagnostic( Diagnostic.Create( Descriptors.X1022_TheoryMethodCannotHaveParameterArray, parameter.DeclaringSyntaxReferences.First().GetSyntax(compilationStartContext.CancellationToken).GetLocation(), method.Name, method.ContainingType.ToDisplayString(), parameter.Name)); } }, SymbolKind.Method); }
protected virtual bool ShouldAnalyze(XunitContext xunitContext) => xunitContext.HasCoreReference;
internal abstract void AnalyzeCompilation(CompilationStartAnalysisContext context, XunitContext xunitContext);
internal override void AnalyzeCompilation(CompilationStartAnalysisContext context, XunitContext xunitContext) { context.RegisterSymbolAction(context => { if (context.Symbol.DeclaredAccessibility != Accessibility.Public) { return; } var classSymbol = (INamedTypeSymbol)context.Symbol; // RegisterSymbolAction guarantees by 2nd arg var doesClassContainTests = classSymbol .GetMembers() .OfType <IMethodSymbol>() .Any(m => m.GetAttributes().Any(a => xunitContext.Core.FactAttributeType.IsAssignableFrom(a.AttributeClass))); if (!doesClassContainTests) { return; } foreach (var interfaceOnTestClass in classSymbol.AllInterfaces) { var isFixtureInterface = interfaceOnTestClass.OriginalDefinition.IsAssignableFrom(xunitContext.Core.IClassFixtureType) || interfaceOnTestClass.OriginalDefinition.IsAssignableFrom(xunitContext.Core.ICollectionFixtureType); if (isFixtureInterface && interfaceOnTestClass.TypeArguments[0] is INamedTypeSymbol tFixtureDataType) { var hasConstructorWithTFixtureArg = classSymbol .Constructors .Any(x => x.Parameters.Length == 1 && x.Parameters.Any(p => Equals(p.Type, tFixtureDataType))); if (hasConstructorWithTFixtureArg) { continue; } var propertiesBuilder = ImmutableDictionary.CreateBuilder <string, string>(); propertiesBuilder.Add(TFixtureDisplayNamePropertyKey, tFixtureDataType.ToDisplayString()); propertiesBuilder.Add(TFixtureNamePropertyKey, tFixtureDataType.Name); propertiesBuilder.Add(TestClassNamePropertyKey, classSymbol.Name); context.ReportDiagnostic( Diagnostic.Create( Descriptors.X1033_TestClassShouldHaveTFixtureArgument, location: classSymbol.Locations.First(), properties: propertiesBuilder.ToImmutable(), classSymbol.ToDisplayString(), tFixtureDataType.ToDisplayString())); } } }, SymbolKind.NamedType); }
internal override void AnalyzeCompilation(CompilationStartAnalysisContext context, XunitContext xunitContext) { context.RegisterSymbolAction(context => { var symbol = (IMethodSymbol)context.Symbol; var attributes = symbol.GetAttributes(); if (attributes.ContainsAttributeType(xunitContext.Core.TheoryAttributeType) && (attributes.Length == 1 || !attributes.ContainsAttributeType(xunitContext.Core.DataAttributeType))) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.X1003_TheoryMethodMustHaveTestData, symbol.Locations.First())); } }, SymbolKind.Method); }
internal override void AnalyzeCompilation(CompilationStartAnalysisContext compilationStartContext, XunitContext xunitContext) { compilationStartContext.RegisterSyntaxNodeAction(syntaxNodeContext => { var methodDeclaration = syntaxNodeContext.Node as MethodDeclarationSyntax; if (methodDeclaration.ParameterList.Parameters.Count == 0) { return; } if (methodDeclaration.AttributeLists.ContainsAttributeType(syntaxNodeContext.SemanticModel, xunitContext.FactAttributeType, exactMatch: true)) { syntaxNodeContext.ReportDiagnostic(Diagnostic.Create( Descriptors.X1001_FactMethodMustNotHaveParameters, methodDeclaration.Identifier.GetLocation(), methodDeclaration.Identifier.ValueText)); } }, SyntaxKind.MethodDeclaration); }
internal override void AnalyzeCompilation(CompilationStartAnalysisContext context, XunitContext xunitContext) { var compilation = context.Compilation; var iEnumerableOfObjectArrayType = TypeSymbolFactory.IEnumerableOfObjectArray(compilation); var supportsNameofOperator = compilation is CSharpCompilation cSharpCompilation && cSharpCompilation.LanguageVersion >= LanguageVersion.CSharp6; context.RegisterSyntaxNodeAction(context => { var attribute = (AttributeSyntax)context.Node; var memberNameArgument = attribute.ArgumentList?.Arguments.FirstOrDefault(); if (memberNameArgument == null) { return; } var semanticModel = context.SemanticModel; if (!Equals(semanticModel.GetTypeInfo(attribute, context.CancellationToken).Type, xunitContext.Core.MemberDataAttributeType)) { return; } var constantValue = semanticModel.GetConstantValue(memberNameArgument.Expression, context.CancellationToken); if (!(constantValue.Value is string memberName)) { return; } var memberTypeArgument = attribute.ArgumentList.Arguments.FirstOrDefault(a => a.NameEquals?.Name.Identifier.ValueText == "MemberType"); ITypeSymbol memberTypeSymbol = null; if (memberTypeArgument?.Expression is TypeOfExpressionSyntax typeofExpression) { var typeSyntax = typeofExpression.Type; memberTypeSymbol = semanticModel.GetTypeInfo(typeSyntax, context.CancellationToken).Type; } var testClassTypeSymbol = semanticModel.GetDeclaredSymbol(attribute.FirstAncestorOrSelf <ClassDeclarationSyntax>()); var declaredMemberTypeSymbol = memberTypeSymbol ?? testClassTypeSymbol; var memberSymbol = FindMemberSymbol(memberName, declaredMemberTypeSymbol); if (memberSymbol == null) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.X1015_MemberDataMustReferenceExistingMember, attribute.GetLocation(), memberName, SymbolDisplay.ToDisplayString(declaredMemberTypeSymbol))); } else { if (memberSymbol.Kind != SymbolKind.Field && memberSymbol.Kind != SymbolKind.Property && memberSymbol.Kind != SymbolKind.Method) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.X1018_MemberDataMustReferenceValidMemberKind, attribute.GetLocation())); } else { if (supportsNameofOperator && memberNameArgument.Expression.IsKind(SyntaxKind.StringLiteralExpression)) { var builder = ImmutableDictionary.CreateBuilder <string, string>(); if (!Equals(memberSymbol.ContainingType, testClassTypeSymbol)) { builder.Add("DeclaringType", memberSymbol.ContainingType.ToDisplayString()); } context.ReportDiagnostic( Diagnostic.Create( Descriptors.X1014_MemberDataShouldUseNameOfOperator, memberNameArgument.Expression.GetLocation(), builder.ToImmutable(), memberName, memberSymbol.ContainingType.ToDisplayString())); } var memberProperties = new Dictionary <string, string> { { "DeclaringType", declaredMemberTypeSymbol.ToDisplayString() }, { "MemberName", memberName } }.ToImmutableDictionary(); if (memberSymbol.DeclaredAccessibility != Accessibility.Public) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.X1016_MemberDataMustReferencePublicMember, attribute.GetLocation(), memberProperties)); } if (!memberSymbol.IsStatic) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.X1017_MemberDataMustReferenceStaticMember, attribute.GetLocation(), memberProperties)); } var memberType = GetMemberType(memberSymbol); if (!iEnumerableOfObjectArrayType.IsAssignableFrom(memberType)) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.X1019_MemberDataMustReferenceMemberOfValidType, attribute.GetLocation(), memberProperties, SymbolDisplay.ToDisplayString(iEnumerableOfObjectArrayType), SymbolDisplay.ToDisplayString(memberType))); } if (memberSymbol.Kind == SymbolKind.Property && ((IPropertySymbol)memberSymbol).GetMethod == null) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.X1020_MemberDataPropertyMustHaveGetter, attribute.GetLocation())); } var extraArguments = attribute.ArgumentList.Arguments.Skip(1).TakeWhile(a => a.NameEquals == null).ToList(); if (memberSymbol.Kind == SymbolKind.Property || memberSymbol.Kind == SymbolKind.Field) { if (extraArguments.Any()) { var span = TextSpan.FromBounds(extraArguments.First().Span.Start, extraArguments.Last().Span.End); context.ReportDiagnostic( Diagnostic.Create( Descriptors.X1021_MemberDataNonMethodShouldNotHaveParameters, Location.Create(attribute.SyntaxTree, span))); } } if (memberSymbol.Kind == SymbolKind.Method) { // TODO: handle method parameter type matching, model after InlineDataMustMatchTheoryParameter } } } }, SyntaxKind.Attribute); }
internal override void AnalyzeCompilation(CompilationStartAnalysisContext context, XunitContext xunitContext) { var compilation = context.Compilation; var iEnumerableOfObjectArray = TypeSymbolFactory.IEnumerableOfObjectArray(compilation); context.RegisterSyntaxNodeAction(context => { var attribute = (AttributeSyntax)context.Node; if (!(attribute.ArgumentList?.Arguments.FirstOrDefault()?.Expression is TypeOfExpressionSyntax argumentExpression)) { return; } var semanticModel = context.SemanticModel; if (!Equals(semanticModel.GetTypeInfo(attribute).Type, xunitContext.Core.ClassDataAttributeType)) { return; } var classType = (INamedTypeSymbol)semanticModel.GetTypeInfo(argumentExpression.Type).Type; if (classType == null || classType.Kind == SymbolKind.ErrorType) { return; } var missingInterface = !iEnumerableOfObjectArray.IsAssignableFrom(classType); var isAbstract = classType.IsAbstract; var noValidConstructor = !classType.InstanceConstructors.Any(c => c.Parameters.IsEmpty && c.DeclaredAccessibility == Accessibility.Public); if (missingInterface || isAbstract || noValidConstructor) { context.ReportDiagnostic(Diagnostic.Create( Descriptors.X1007_ClassDataAttributeMustPointAtValidClass, argumentExpression.Type.GetLocation(), classType.Name)); } }, SyntaxKind.Attribute); }
internal override void AnalyzeCompilation(CompilationStartAnalysisContext compilationStartContext, XunitContext xunitContext) { compilationStartContext.RegisterSyntaxNodeAction(syntaxNodeContext => { var attribute = syntaxNodeContext.Node as AttributeSyntax; if (!(attribute.ArgumentList?.Arguments.Any() ?? false)) { return; } var attributeType = syntaxNodeContext.SemanticModel.GetTypeInfo(attribute).Type; if (!xunitContext.Core.FactAttributeType.IsAssignableFrom(attributeType)) { return; } var skipArgument = attribute.ArgumentList.Arguments .FirstOrDefault(arg => arg.NameEquals?.Name?.Identifier.ValueText == "Skip"); if (skipArgument != null) { syntaxNodeContext.ReportDiagnostic(Diagnostic.Create( Descriptors.X1004_TestMethodShouldNotBeSkipped, skipArgument.GetLocation())); } }, SyntaxKind.Attribute); }
internal override void AnalyzeCompilation(CompilationStartAnalysisContext compilationStartContext, XunitContext xunitContext) { compilationStartContext.RegisterSymbolAction(symbolContext => { var symbol = (IMethodSymbol)symbolContext.Symbol; var attributes = symbol.GetAttributes(); if (attributes.Length > 1 && attributes.ContainsAttributeType(xunitContext.Core.FactAttributeType, exactMatch: true) && !attributes.ContainsAttributeType(xunitContext.Core.TheoryAttributeType) && attributes.ContainsAttributeType(xunitContext.Core.DataAttributeType)) { symbolContext.ReportDiagnostic(Diagnostic.Create(Descriptors.X1005_FactMethodShouldNotHaveTestData, symbol.Locations.First())); } }, SymbolKind.Method); }
internal override void AnalyzeCompilation(CompilationStartAnalysisContext context, XunitContext xunitContext) { context.RegisterSymbolAction(context => { var symbol = (IMethodSymbol)context.Symbol; var attributeTypes = new HashSet <INamedTypeSymbol>(); var count = 0; foreach (var attribute in symbol.GetAttributes()) { var attributeType = attribute.AttributeClass; if (xunitContext.Core.FactAttributeType.IsAssignableFrom(attributeType)) { attributeTypes.Add(attributeType); count++; } } if (count > 1) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.X1002_TestMethodMustNotHaveMultipleFactAttributes, symbol.Locations.First(), properties: attributeTypes.ToImmutableDictionary(t => t.ToDisplayString(), t => string.Empty))); } }, SymbolKind.Method); }
internal override void AnalyzeCompilation(CompilationStartAnalysisContext compilationStartContext, XunitContext xunitContext) { compilationStartContext.RegisterSyntaxNodeAction(syntaxNodeContext => { var classDeclaration = (ClassDeclarationSyntax)syntaxNodeContext.Node; if (classDeclaration.BaseList == null) { return; } var semanticModel = syntaxNodeContext.SemanticModel; foreach (var baseType in classDeclaration.BaseList.Types) { var type = semanticModel.GetTypeInfo(baseType.Type, compilationStartContext.CancellationToken).Type; if (xunitContext.Abstractions.IXunitSerializableType?.IsAssignableFrom(type) == true) { if (!classDeclaration.Members.OfType <ConstructorDeclarationSyntax>().Any()) { return; } var parameterlessCtor = classDeclaration.Members.OfType <ConstructorDeclarationSyntax>().FirstOrDefault(c => c.ParameterList.Parameters.Count == 0); if (parameterlessCtor == null || !parameterlessCtor.Modifiers.Any(m => m.Text == "public")) { syntaxNodeContext.ReportDiagnostic( Diagnostic.Create( Descriptors.X3001_SerializableClassMustHaveParameterlessConstructor, classDeclaration.Identifier.GetLocation(), classDeclaration.Identifier.ValueText)); } return; } } }, SyntaxKind.ClassDeclaration); }
protected override bool ShouldAnalyze(XunitContext xunitContext) { return(!xunitContext.Capabilities.TheorySupportsDefaultParameterValues); }
internal override void AnalyzeCompilation(CompilationStartAnalysisContext compilationStartContext, XunitContext xunitContext) { compilationStartContext.RegisterSymbolAction(symbolContext => { var methodSymbol = (IMethodSymbol)symbolContext.Symbol; var attributes = methodSymbol.GetAttributes(); if (attributes.Length == 0) { return; } // Instead of checking for Theory, we check for any Fact. If it is a Fact which is not a Theory, // we will let other rules (i.e. FactMethodShouldNotHaveTestData) handle that case. if (!attributes.ContainsAttributeType(xunitContext.FactAttributeType) && attributes.ContainsAttributeType(xunitContext.DataAttributeType)) { symbolContext.ReportDiagnostic(Diagnostic.Create(Descriptors.X1008_DataAttributeShouldBeUsedOnATheory, methodSymbol.Locations.First())); } }, SymbolKind.Method); }
internal override void AnalyzeCompilation(CompilationStartAnalysisContext compilationStartContext, XunitContext xunitContext) { compilationStartContext.RegisterSyntaxNodeAction(syntaxNodeContext => { var methodSyntax = (MethodDeclarationSyntax)syntaxNodeContext.Node; if (methodSyntax.ParameterList.Parameters.Count == 0) { return; } var methodSymbol = syntaxNodeContext.SemanticModel.GetDeclaredSymbol(methodSyntax); var attributes = methodSymbol.GetAttributes(); if (!attributes.ContainsAttributeType(xunitContext.Core.TheoryAttributeType)) { return; } AnalyzeTheoryParameters(syntaxNodeContext, methodSyntax, methodSymbol); }, SyntaxKind.MethodDeclaration); }
internal override void AnalyzeCompilation(CompilationStartAnalysisContext compilationStartContext, XunitContext xunitContext) { compilationStartContext.RegisterSymbolAction(symbolContext => { var method = (IMethodSymbol)symbolContext.Symbol; var attributes = method.GetAttributes(); if (!attributes.ContainsAttributeType(xunitContext.TheoryAttributeType)) { return; } foreach (var parameter in method.Parameters) { symbolContext.CancellationToken.ThrowIfCancellationRequested(); if (parameter.HasExplicitDefaultValue) { var syntaxNode = parameter.DeclaringSyntaxReferences.First() .GetSyntax(compilationStartContext.CancellationToken) .FirstAncestorOrSelf <ParameterSyntax>(); symbolContext.ReportDiagnostic(Diagnostic.Create( Descriptors.X1023_TheoryMethodCannotHaveDefaultParameter, syntaxNode.Default.GetLocation(), method.Name, method.ContainingType.ToDisplayString(), parameter.Name)); } } }, SymbolKind.Method); }