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);
        }
Esempio n. 3
0
            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);
        }
Esempio n. 8
0
        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);
        }
Esempio n. 10
0
        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);
        }
Esempio n. 11
0
 protected override bool ShouldAnalyze(XunitContext xunitContext)
 => xunitContext.HasAbstractionsReference;
 internal override void AnalyzeCompilation(CompilationStartAnalysisContext compilationStartContext, XunitContext xunitContext)
 {
     compilationStartContext.RegisterSymbolAction(
         symbolContext => AnalyzeMethod(symbolContext, xunitContext), SymbolKind.Method);
 }
Esempio n. 13
0
        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);
        }
Esempio n. 19
0
 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);
 }
Esempio n. 20
0
        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);
        }
Esempio n. 23
0
        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);
        }
Esempio n. 24
0
 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);
 }
Esempio n. 25
0
        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);
        }
Esempio n. 26
0
        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);
        }
Esempio n. 27
0
 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);
        }
Esempio n. 30
0
 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);
 }