File: Diagnostics\OperationTestAnalyzer.cs
Web Access
Project: src\src\Compilers\Test\Core\Microsoft.CodeAnalysis.Test.Utilities.csproj (Microsoft.CodeAnalysis.Test.Utilities)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
#nullable disable
 
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;
 
namespace Microsoft.CodeAnalysis.UnitTests.Diagnostics
{
    // These analyzers are not intended for any actual use. They exist solely to test IOperation support.
 
    /// <summary>Analyzer used to test for bad statements and expressions.</summary>
    public class BadStuffTestAnalyzer : DiagnosticAnalyzer
    {
        public static readonly DiagnosticDescriptor InvalidExpressionDescriptor = new DiagnosticDescriptor(
            "InvalidExpression",
            "Invalid Expression",
            "Invalid expression found.",
            "Testing",
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public static readonly DiagnosticDescriptor InvalidStatementDescriptor = new DiagnosticDescriptor(
            "InvalidStatement",
            "Invalid Statement",
            "Invalid statement found.",
            "Testing",
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public static readonly DiagnosticDescriptor IsInvalidDescriptor = new DiagnosticDescriptor(
            "IsInvalid",
            "Is Invalid",
            "Operation found that is invalid.",
            "Testing",
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
        {
            get { return ImmutableArray.Create(InvalidExpressionDescriptor, InvalidStatementDescriptor, IsInvalidDescriptor); }
        }
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                 (operationContext) =>
                 {
                     var invalidOperation = (IInvalidOperation)operationContext.Operation;
                     if (invalidOperation.Type == null)
                     {
                         operationContext.ReportDiagnostic(Diagnostic.Create(InvalidStatementDescriptor, operationContext.Operation.Syntax.GetLocation()));
                     }
                     else
                     {
                         operationContext.ReportDiagnostic(Diagnostic.Create(InvalidExpressionDescriptor, operationContext.Operation.Syntax.GetLocation()));
                     }
                 },
                 OperationKind.Invalid);
 
            context.RegisterOperationAction(
                 (operationContext) =>
                 {
                     if (operationContext.Operation.HasErrors(operationContext.Compilation, operationContext.CancellationToken))
                     {
                         operationContext.ReportDiagnostic(Diagnostic.Create(IsInvalidDescriptor, operationContext.Operation.Syntax.GetLocation()));
                     }
                 },
                 OperationKind.Invocation,
                 OperationKind.Invalid);
        }
    }
 
    /// <summary>Analyzer used to test for operations within symbols of certain names.</summary>
    public class OwningSymbolTestAnalyzer : DiagnosticAnalyzer
    {
        public static readonly DiagnosticDescriptor ExpressionDescriptor = new DiagnosticDescriptor(
            "Expression",
            "Expression",
            "Expression found.",
            "Testing",
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
        {
            get { return ImmutableArray.Create(ExpressionDescriptor); }
        }
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationBlockStartAction(
                (operationBlockContext) =>
                {
                    if (operationBlockContext.Compilation.Language != "Stumble")
                    {
                        operationBlockContext.RegisterOperationAction(
                             (operationContext) =>
                             {
                                 if (operationContext.ContainingSymbol.Name.StartsWith("Funky") && operationContext.Compilation.Language != "Mumble")
                                 {
                                     operationContext.ReportDiagnostic(Diagnostic.Create(ExpressionDescriptor, operationContext.Operation.Syntax.GetLocation()));
                                 }
                             },
                             OperationKind.LocalReference,
                             OperationKind.Literal);
                    }
                });
        }
    }
 
    /// <summary>Analyzer used to test for loop IOperations.</summary>
    public class BigForTestAnalyzer : DiagnosticAnalyzer
    {
        /// <summary>Diagnostic category "Reliability".</summary>
        private const string ReliabilityCategory = "Reliability";
 
        public static readonly DiagnosticDescriptor BigForDescriptor = new DiagnosticDescriptor(
            "BigForRule",
            "Big For Loop",
            "For loop iterates more than one million times",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        /// <summary>Gets the set of supported diagnostic descriptors from this analyzer.</summary>
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
        {
            get { return ImmutableArray.Create(BigForDescriptor); }
        }
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(AnalyzeOperation, OperationKind.Loop);
        }
 
        private void AnalyzeOperation(OperationAnalysisContext operationContext)
        {
            ILoopOperation loop = (ILoopOperation)operationContext.Operation;
            if (loop.LoopKind == LoopKind.For)
            {
                IForLoopOperation forLoop = (IForLoopOperation)loop;
                IOperation forCondition = forLoop.Condition;
 
                if (forCondition.Kind == OperationKind.Binary)
                {
                    IBinaryOperation condition = (IBinaryOperation)forCondition;
                    IOperation conditionLeft = condition.LeftOperand;
                    IOperation conditionRight = condition.RightOperand;
 
                    if (conditionRight.ConstantValue.HasValue &&
                        conditionRight.Type.SpecialType == SpecialType.System_Int32 &&
                        conditionLeft.Kind == OperationKind.LocalReference)
                    {
                        // Test is known to be a comparison of a local against a constant.
 
                        int testValue = (int)conditionRight.ConstantValue.Value;
                        ILocalSymbol testVariable = ((ILocalReferenceOperation)conditionLeft).Local;
 
                        if (forLoop.Before.Length == 1)
                        {
                            IOperation setup = forLoop.Before[0];
                            if (setup.Kind == OperationKind.ExpressionStatement && ((IExpressionStatementOperation)setup).Operation.Kind == OperationKind.SimpleAssignment)
                            {
                                ISimpleAssignmentOperation setupAssignment = (ISimpleAssignmentOperation)((IExpressionStatementOperation)setup).Operation;
                                if (setupAssignment.Target.Kind == OperationKind.LocalReference &&
                                    ((ILocalReferenceOperation)setupAssignment.Target).Local == testVariable &&
                                    setupAssignment.Value.ConstantValue.HasValue &&
                                    setupAssignment.Value.Type.SpecialType == SpecialType.System_Int32)
                                {
                                    // Setup is known to be an assignment of a constant to the local used in the test.
 
                                    int initialValue = (int)setupAssignment.Value.ConstantValue.Value;
 
                                    if (forLoop.AtLoopBottom.Length == 1)
                                    {
                                        IOperation advance = forLoop.AtLoopBottom[0];
                                        if (advance.Kind == OperationKind.ExpressionStatement)
                                        {
                                            IOperation advanceExpression = ((IExpressionStatementOperation)advance).Operation;
 
                                            Optional<object> advanceIncrementOpt;
                                            BinaryOperatorKind? advanceOperationCode;
                                            GetOperationKindAndValue(testVariable, advanceExpression, out advanceOperationCode, out advanceIncrementOpt);
 
                                            if (advanceIncrementOpt.HasValue && advanceOperationCode.HasValue)
                                            {
                                                var incrementValue = (int)advanceIncrementOpt.Value;
                                                if (advanceOperationCode.Value == BinaryOperatorKind.Subtract)
                                                {
                                                    advanceOperationCode = BinaryOperatorKind.Add;
                                                    incrementValue = -incrementValue;
                                                }
 
                                                if (advanceOperationCode.Value == BinaryOperatorKind.Add &&
                                                    incrementValue != 0 &&
                                                    (condition.OperatorKind == BinaryOperatorKind.LessThan ||
                                                     condition.OperatorKind == BinaryOperatorKind.LessThanOrEqual ||
                                                     condition.OperatorKind == BinaryOperatorKind.NotEquals ||
                                                     condition.OperatorKind == BinaryOperatorKind.GreaterThan ||
                                                     condition.OperatorKind == BinaryOperatorKind.GreaterThanOrEqual))
                                                {
                                                    int iterationCount = (testValue - initialValue) / incrementValue;
                                                    if (iterationCount >= 1000000)
                                                    {
                                                        Report(operationContext, forLoop.Syntax, BigForDescriptor);
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
 
        private void GetOperationKindAndValue(
            ILocalSymbol testVariable, IOperation advanceExpression,
            out BinaryOperatorKind? advanceOperationCode, out Optional<object> advanceIncrementOpt)
        {
            advanceIncrementOpt = null;
            advanceOperationCode = null;
 
            if (advanceExpression.Kind == OperationKind.SimpleAssignment)
            {
                ISimpleAssignmentOperation advanceAssignment = (ISimpleAssignmentOperation)advanceExpression;
 
                if (advanceAssignment.Target.Kind == OperationKind.LocalReference &&
                    ((ILocalReferenceOperation)advanceAssignment.Target).Local == testVariable &&
                    advanceAssignment.Value.Kind == OperationKind.Binary &&
                    advanceAssignment.Value.Type.SpecialType == SpecialType.System_Int32)
                {
                    // Advance is known to be an assignment of a binary operation to the local used in the test.
 
                    IBinaryOperation advanceOperation = (IBinaryOperation)advanceAssignment.Value;
                    if (advanceOperation.OperatorMethod == null &&
                        advanceOperation.LeftOperand.Kind == OperationKind.LocalReference &&
                        ((ILocalReferenceOperation)advanceOperation.LeftOperand).Local == testVariable &&
                        advanceOperation.RightOperand.ConstantValue.HasValue &&
                        advanceOperation.RightOperand.Type.SpecialType == SpecialType.System_Int32)
                    {
                        // Advance binary operation is known to involve a reference to the local used in the test and a constant.
                        advanceIncrementOpt = advanceOperation.RightOperand.ConstantValue;
                        advanceOperationCode = advanceOperation.OperatorKind;
                    }
                }
            }
            else if (advanceExpression.Kind == OperationKind.CompoundAssignment)
            {
                ICompoundAssignmentOperation advanceAssignment = (ICompoundAssignmentOperation)advanceExpression;
 
                if (advanceAssignment.Target.Kind == OperationKind.LocalReference &&
                    ((ILocalReferenceOperation)advanceAssignment.Target).Local == testVariable &&
                    advanceAssignment.Value.ConstantValue.HasValue &&
                    advanceAssignment.Value.Type.SpecialType == SpecialType.System_Int32)
                {
                    // Advance binary operation is known to involve a reference to the local used in the test and a constant.
                    advanceIncrementOpt = advanceAssignment.Value.ConstantValue;
                    advanceOperationCode = advanceAssignment.OperatorKind;
                }
            }
            else if (advanceExpression.Kind == OperationKind.Increment)
            {
                IIncrementOrDecrementOperation advanceAssignment = (IIncrementOrDecrementOperation)advanceExpression;
 
                if (advanceAssignment.Target.Kind == OperationKind.LocalReference &&
                    ((ILocalReferenceOperation)advanceAssignment.Target).Local == testVariable)
                {
                    // Advance binary operation is known to involve a reference to the local used in the test and a constant.
                    advanceIncrementOpt = new Optional<object>(1);
                    advanceOperationCode = BinaryOperatorKind.Add;
                }
            }
        }
 
        private void Report(OperationAnalysisContext context, SyntaxNode syntax, DiagnosticDescriptor descriptor)
        {
            context.ReportDiagnostic(Diagnostic.Create(descriptor, syntax.GetLocation()));
        }
    }
 
    /// <summary>Analyzer used to test switch IOperations.</summary>
    public class SwitchTestAnalyzer : DiagnosticAnalyzer
    {
        /// <summary>Diagnostic category "Reliability".</summary>
        private const string ReliabilityCategory = "Reliability";
 
        public static readonly DiagnosticDescriptor SparseSwitchDescriptor = new DiagnosticDescriptor(
            "SparseSwitchRule",
            "Sparse switch",
            "Switch has less than one percent density",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public static readonly DiagnosticDescriptor NoDefaultSwitchDescriptor = new DiagnosticDescriptor(
            "NoDefaultSwitchRule",
            "No default switch",
            "Switch has no default case",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public static readonly DiagnosticDescriptor OnlyDefaultSwitchDescriptor = new DiagnosticDescriptor(
            "OnlyDefaultSwitchRule",
            "Only default switch",
            "Switch only has a default case",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        /// <summary>Gets the set of supported diagnostic descriptors from this analyzer.</summary>
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
        {
            get
            {
                return ImmutableArray.Create(SparseSwitchDescriptor,
                                              NoDefaultSwitchDescriptor,
                                              OnlyDefaultSwitchDescriptor);
            }
        }
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                 (operationContext) =>
                 {
                     ISwitchOperation switchOperation = (ISwitchOperation)operationContext.Operation;
                     long minCaseValue = long.MaxValue;
                     long maxCaseValue = long.MinValue;
                     long caseValueCount = 0;
                     bool hasDefault = false;
                     bool hasNonDefault = false;
                     foreach (ISwitchCaseOperation switchCase in switchOperation.Cases)
                     {
                         foreach (ICaseClauseOperation clause in switchCase.Clauses)
                         {
                             switch (clause.CaseKind)
                             {
                                 case CaseKind.SingleValue:
                                     {
                                         hasNonDefault = true;
                                         ISingleValueCaseClauseOperation singleValueClause = (ISingleValueCaseClauseOperation)clause;
                                         IOperation singleValueExpression = singleValueClause.Value;
                                         if (singleValueExpression != null &&
                                             singleValueExpression.ConstantValue.HasValue &&
                                             singleValueExpression.Type.SpecialType == SpecialType.System_Int32)
                                         {
                                             int singleValue = (int)singleValueExpression.ConstantValue.Value;
                                             caseValueCount += IncludeClause(singleValue, singleValue, ref minCaseValue, ref maxCaseValue);
                                         }
                                         else
                                         {
                                             return;
                                         }
 
                                         break;
                                     }
                                 case CaseKind.Range:
                                     {
                                         hasNonDefault = true;
                                         IRangeCaseClauseOperation rangeClause = (IRangeCaseClauseOperation)clause;
                                         IOperation rangeMinExpression = rangeClause.MinimumValue;
                                         IOperation rangeMaxExpression = rangeClause.MaximumValue;
                                         if (rangeMinExpression != null &&
                                             rangeMinExpression.ConstantValue.HasValue &&
                                             rangeMinExpression.Type.SpecialType == SpecialType.System_Int32 &&
                                             rangeMaxExpression != null &&
                                             rangeMaxExpression.ConstantValue.HasValue &&
                                             rangeMaxExpression.Type.SpecialType == SpecialType.System_Int32)
                                         {
                                             int rangeMinValue = (int)rangeMinExpression.ConstantValue.Value;
                                             int rangeMaxValue = (int)rangeMaxExpression.ConstantValue.Value;
                                             caseValueCount += IncludeClause(rangeMinValue, rangeMaxValue, ref minCaseValue, ref maxCaseValue);
                                         }
                                         else
                                         {
                                             return;
                                         }
 
                                         break;
                                     }
                                 case CaseKind.Relational:
                                     {
                                         hasNonDefault = true;
                                         IRelationalCaseClauseOperation relationalClause = (IRelationalCaseClauseOperation)clause;
                                         IOperation relationalValueExpression = relationalClause.Value;
                                         if (relationalValueExpression != null &&
                                             relationalValueExpression.ConstantValue.HasValue &&
                                             relationalValueExpression.Type.SpecialType == SpecialType.System_Int32)
                                         {
                                             int rangeMinValue = int.MaxValue;
                                             int rangeMaxValue = int.MinValue;
                                             int relationalValue = (int)relationalValueExpression.ConstantValue.Value;
                                             switch (relationalClause.Relation)
                                             {
                                                 case BinaryOperatorKind.Equals:
                                                     rangeMinValue = relationalValue;
                                                     rangeMaxValue = relationalValue;
                                                     break;
                                                 case BinaryOperatorKind.NotEquals:
                                                     return;
                                                 case BinaryOperatorKind.LessThan:
                                                     rangeMinValue = int.MinValue;
                                                     rangeMaxValue = relationalValue - 1;
                                                     break;
                                                 case BinaryOperatorKind.LessThanOrEqual:
                                                     rangeMinValue = int.MinValue;
                                                     rangeMaxValue = relationalValue;
                                                     break;
                                                 case BinaryOperatorKind.GreaterThanOrEqual:
                                                     rangeMinValue = relationalValue;
                                                     rangeMaxValue = int.MaxValue;
                                                     break;
                                                 case BinaryOperatorKind.GreaterThan:
                                                     rangeMinValue = relationalValue + 1;
                                                     rangeMaxValue = int.MaxValue;
                                                     break;
                                             }
 
                                             caseValueCount += IncludeClause(rangeMinValue, rangeMaxValue, ref minCaseValue, ref maxCaseValue);
                                         }
                                         else
                                         {
                                             return;
                                         }
 
                                         break;
                                     }
                                 case CaseKind.Default:
                                     {
                                         hasDefault = true;
                                         break;
                                     }
                             }
                         }
                     }
 
                     long span = maxCaseValue - minCaseValue + 1;
                     if (caseValueCount == 0 && !hasDefault ||
                         caseValueCount != 0 && span / caseValueCount > 100)
                     {
                         Report(operationContext, switchOperation.Value.Syntax, SparseSwitchDescriptor);
                     }
                     if (!hasDefault)
                     {
                         Report(operationContext, switchOperation.Value.Syntax, NoDefaultSwitchDescriptor);
                     }
                     if (hasDefault && !hasNonDefault)
                     {
                         Report(operationContext, switchOperation.Value.Syntax, OnlyDefaultSwitchDescriptor);
                     }
                 },
                 OperationKind.Switch);
        }
 
        private static int IncludeClause(int clauseMinValue, int clauseMaxValue, ref long minCaseValue, ref long maxCaseValue)
        {
            if (clauseMinValue < minCaseValue)
            {
                minCaseValue = clauseMinValue;
            }
 
            if (clauseMaxValue > maxCaseValue)
            {
                maxCaseValue = clauseMaxValue;
            }
 
            return clauseMaxValue - clauseMinValue + 1;
        }
 
        private void Report(OperationAnalysisContext context, SyntaxNode syntax, DiagnosticDescriptor descriptor)
        {
            context.ReportDiagnostic(Diagnostic.Create(descriptor, syntax.GetLocation()));
        }
    }
 
    /// <summary>Analyzer used to test invocation IOperations.</summary>
    public class InvocationTestAnalyzer : DiagnosticAnalyzer
    {
        /// <summary>Diagnostic category "Reliability".</summary>
        private const string ReliabilityCategory = "Reliability";
 
        public static readonly DiagnosticDescriptor BigParamArrayArgumentsDescriptor = new DiagnosticDescriptor(
            "BigParamarrayRule",
            "Big Paramarray",
            "Paramarray has more than 10 elements",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public static readonly DiagnosticDescriptor OutOfNumericalOrderArgumentsDescriptor = new DiagnosticDescriptor(
            "OutOfOrderArgumentsRule",
            "Out of order arguments",
            "Argument values are not in increasing order",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public static readonly DiagnosticDescriptor UseDefaultArgumentDescriptor = new DiagnosticDescriptor(
            "UseDefaultArgument",
            "Use default argument",
            "Invocation uses default argument {0}",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public static readonly DiagnosticDescriptor InvalidArgumentDescriptor = new DiagnosticDescriptor(
            "InvalidArgument",
            "Invalid argument",
            "Invocation has invalid argument",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        /// <summary>Gets the set of supported diagnostic descriptors from this analyzer.</summary>
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
        {
            get
            {
                return ImmutableArray.Create(BigParamArrayArgumentsDescriptor,
                                             OutOfNumericalOrderArgumentsDescriptor,
                                             UseDefaultArgumentDescriptor,
                                             InvalidArgumentDescriptor);
            }
        }
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                 (operationContext) =>
                 {
                     IInvocationOperation invocation = (IInvocationOperation)operationContext.Operation;
                     long priorArgumentValue = long.MinValue;
                     foreach (IArgumentOperation argument in invocation.Arguments)
                     {
                         if (argument.HasErrors(operationContext.Compilation, operationContext.CancellationToken))
                         {
                             operationContext.ReportDiagnostic(Diagnostic.Create(InvalidArgumentDescriptor, argument.Syntax.GetLocation()));
                             return;
                         }
 
                         if (argument.ArgumentKind == ArgumentKind.DefaultValue)
                         {
                             operationContext.ReportDiagnostic(Diagnostic.Create(UseDefaultArgumentDescriptor, invocation.Syntax.GetLocation(), argument.Parameter.Name));
                         }
 
                         TestAscendingArgument(operationContext, argument.Value, ref priorArgumentValue);
 
                         if (argument.ArgumentKind == ArgumentKind.ParamArray)
                         {
                             if (argument.Value is IArrayCreationOperation arrayArgument)
                             {
                                 var initializer = arrayArgument.Initializer;
                                 if (initializer != null)
                                 {
                                     if (initializer.ElementValues.Length > 10)
                                     {
                                         Report(operationContext, invocation.Syntax, BigParamArrayArgumentsDescriptor);
                                     }
 
                                     foreach (IOperation element in initializer.ElementValues)
                                     {
                                         TestAscendingArgument(operationContext, element, ref priorArgumentValue);
                                     }
                                 }
                             }
                         }
                     }
                 },
                 OperationKind.Invocation);
        }
 
        private static void TestAscendingArgument(OperationAnalysisContext operationContext, IOperation argument, ref long priorArgumentValue)
        {
            Optional<object> argumentValue = argument.ConstantValue;
            if (argumentValue.HasValue && argument.Type.SpecialType == SpecialType.System_Int32)
            {
                int integerArgument = (int)argumentValue.Value;
                if (integerArgument < priorArgumentValue)
                {
                    Report(operationContext, argument.Syntax, OutOfNumericalOrderArgumentsDescriptor);
                }
 
                priorArgumentValue = integerArgument;
            }
        }
 
        private static void Report(OperationAnalysisContext context, SyntaxNode syntax, DiagnosticDescriptor descriptor)
        {
            context.ReportDiagnostic(Diagnostic.Create(descriptor, syntax.GetLocation()));
        }
    }
 
    /// <summary>Analyzer used to test various contexts in which IOperations can occur.</summary>
    public class SeventeenTestAnalyzer : DiagnosticAnalyzer
    {
        /// <summary>Diagnostic category "Reliability".</summary>
        private const string ReliabilityCategory = "Reliability";
 
        public static readonly DiagnosticDescriptor SeventeenDescriptor = new DiagnosticDescriptor(
            "SeventeenRule",
            "Seventeen",
            "Seventeen is a recognized value",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        /// <summary>Gets the set of supported diagnostic descriptors from this analyzer.</summary>
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
        {
            get { return ImmutableArray.Create(SeventeenDescriptor); }
        }
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                 (operationContext) =>
                 {
                     ILiteralOperation literal = (ILiteralOperation)operationContext.Operation;
                     if (literal.Type.SpecialType == SpecialType.System_Int32 &&
                         literal.ConstantValue.HasValue &&
                         (int)literal.ConstantValue.Value == 17)
                     {
                         operationContext.ReportDiagnostic(Diagnostic.Create(SeventeenDescriptor, literal.Syntax.GetLocation()));
                     }
                 },
                 OperationKind.Literal);
        }
    }
 
    /// <summary>Analyzer used to test IArgument IOperations.</summary>
    public class NullArgumentTestAnalyzer : DiagnosticAnalyzer
    {
        /// <summary>Diagnostic category "Reliability".</summary>
        private const string ReliabilityCategory = "Reliability";
 
        public static readonly DiagnosticDescriptor NullArgumentsDescriptor = new DiagnosticDescriptor(
            "NullArgumentRule",
            "Null Argument",
            "Value of the argument is null",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        /// <summary>Gets the set of supported diagnostic descriptors from this analyzer.</summary>
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
        {
            get { return ImmutableArray.Create(NullArgumentsDescriptor); }
        }
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                 (operationContext) =>
                 {
                     var argument = (IArgumentOperation)operationContext.Operation;
                     if (argument.Value.ConstantValue.HasValue && argument.Value.ConstantValue.Value == null)
                     {
                         Report(operationContext, argument.Syntax, NullArgumentsDescriptor);
                     }
                 },
                 OperationKind.Argument);
        }
 
        private static void Report(OperationAnalysisContext context, SyntaxNode syntax, DiagnosticDescriptor descriptor)
        {
            context.ReportDiagnostic(Diagnostic.Create(descriptor, syntax.GetLocation()));
        }
    }
 
    /// <summary>Analyzer used to test IMemberInitializer IOperations.</summary>
    public class MemberInitializerTestAnalyzer : DiagnosticAnalyzer
    {
        /// <summary>Diagnostic category "Reliability".</summary>
        private const string ReliabilityCategory = "Reliability";
 
        public static readonly DiagnosticDescriptor DoNotUseFieldInitializerDescriptor = new DiagnosticDescriptor(
            "DoNotUseFieldInitializer",
            "Do Not Use Field Initializer",
            "a field initializer is used for object creation",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public static readonly DiagnosticDescriptor DoNotUsePropertyInitializerDescriptor = new DiagnosticDescriptor(
            "DoNotUsePropertyInitializer",
            "Do Not Use Property Initializer",
            "A property initializer is used for object creation",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        /// <summary>Gets the set of supported diagnostic descriptors from this analyzer.</summary>
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
        {
            get { return ImmutableArray.Create(DoNotUseFieldInitializerDescriptor, DoNotUsePropertyInitializerDescriptor); }
        }
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                 (operationContext) =>
                 {
                     var initializer = operationContext.Operation;
                     Report(operationContext, initializer.Syntax, initializer.Kind == OperationKind.FieldReference ? DoNotUseFieldInitializerDescriptor : DoNotUsePropertyInitializerDescriptor);
                 },
                 OperationKind.FieldReference,
                 OperationKind.PropertyReference);
        }
 
        private static void Report(OperationAnalysisContext context, SyntaxNode syntax, DiagnosticDescriptor descriptor)
        {
            context.ReportDiagnostic(Diagnostic.Create(descriptor, syntax.GetLocation()));
        }
    }
 
    /// <summary>Analyzer used to test IAssignmentExpression IOperations.</summary>
    public class AssignmentTestAnalyzer : DiagnosticAnalyzer
    {
        /// <summary>Diagnostic category "Reliability".</summary>
        private const string ReliabilityCategory = "Reliability";
 
        public static readonly DiagnosticDescriptor DoNotUseMemberAssignmentDescriptor = new DiagnosticDescriptor(
            "DoNotUseMemberAssignment",
            "Do Not Use Member Assignment",
            "Do not assign values to object members",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
        {
            get { return ImmutableArray.Create(DoNotUseMemberAssignmentDescriptor); }
        }
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                 (operationContext) =>
                 {
                     var assignment = (ISimpleAssignmentOperation)operationContext.Operation;
                     var kind = assignment.Target.Kind;
                     if (kind == OperationKind.FieldReference ||
                         kind == OperationKind.PropertyReference)
                     {
                         Report(operationContext, assignment.Syntax, DoNotUseMemberAssignmentDescriptor);
                     }
                 },
                 OperationKind.SimpleAssignment);
        }
 
        private static void Report(OperationAnalysisContext context, SyntaxNode syntax, DiagnosticDescriptor descriptor)
        {
            context.ReportDiagnostic(Diagnostic.Create(descriptor, syntax.GetLocation()));
        }
    }
 
    /// <summary>Analyzer used to test IArrayInitializer IOperations.</summary>
    public class ArrayInitializerTestAnalyzer : DiagnosticAnalyzer
    {
        /// <summary>Diagnostic category "Maintainability".</summary>
        private const string Maintainability = nameof(Maintainability);
 
        public static readonly DiagnosticDescriptor DoNotUseLargeListOfArrayInitializersDescriptor = new DiagnosticDescriptor(
            "DoNotUseLongListToInitializeArray",
            "Do not use long list to initialize array",
            "a list of more than 5 elements is used for an array initialization",
            Maintainability,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        /// <summary>Gets the set of supported diagnostic descriptors from this analyzer.</summary>
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
        {
            get { return ImmutableArray.Create(DoNotUseLargeListOfArrayInitializersDescriptor); }
        }
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                 (operationContext) =>
                 {
                     var initializer = (IArrayInitializerOperation)operationContext.Operation;
                     if (initializer.ElementValues.Length > 5)
                     {
                         Report(operationContext, initializer.Syntax, DoNotUseLargeListOfArrayInitializersDescriptor);
                     }
                 },
                 OperationKind.ArrayInitializer);
        }
 
        private static void Report(OperationAnalysisContext context, SyntaxNode syntax, DiagnosticDescriptor descriptor)
        {
            context.ReportDiagnostic(Diagnostic.Create(descriptor, syntax.GetLocation()));
        }
    }
 
    /// <summary>Analyzer used to test IVariableDeclarationStatement IOperations.</summary>
    public class VariableDeclarationTestAnalyzer : DiagnosticAnalyzer
    {
        /// <summary>Diagnostic category "Maintainability".</summary>
        private const string Maintainability = nameof(Maintainability);
 
        public static readonly DiagnosticDescriptor TooManyLocalVarDeclarationsDescriptor = new DiagnosticDescriptor(
            "TooManyLocalVarDeclarations",
            "Too many local variable declarations",
            "A declaration statement shouldn't have more than 3 variable declarations",
            Maintainability,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public static readonly DiagnosticDescriptor LocalVarInitializedDeclarationDescriptor = new DiagnosticDescriptor(
            "LocalVarInitializedDeclaration",
            "Local var initialized at declaration",
            "A local variable is initialized at declaration.",
            Maintainability,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        /// <summary>Gets the set of supported diagnostic descriptors from this analyzer.</summary>
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
        {
            get { return ImmutableArray.Create(TooManyLocalVarDeclarationsDescriptor, LocalVarInitializedDeclarationDescriptor); }
        }
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                 (operationContext) =>
                 {
                     var declarationStatement = (IVariableDeclarationGroupOperation)operationContext.Operation;
                     if (declarationStatement.GetDeclaredVariables().Count() > 3)
                     {
                         Report(operationContext, declarationStatement.Syntax, TooManyLocalVarDeclarationsDescriptor);
                     }
 
                     foreach (var decl in declarationStatement.Declarations.SelectMany(multiDecl => multiDecl.Declarators))
                     {
                         var initializer = decl.GetVariableInitializer();
                         if (initializer != null && !initializer.HasErrors(operationContext.Compilation, operationContext.CancellationToken))
                         {
                             Report(operationContext, decl.Symbol.DeclaringSyntaxReferences.Single().GetSyntax(), LocalVarInitializedDeclarationDescriptor);
                         }
                     }
                 },
                 OperationKind.VariableDeclarationGroup);
        }
 
        private static void Report(OperationAnalysisContext context, SyntaxNode syntax, DiagnosticDescriptor descriptor)
        {
            context.ReportDiagnostic(Diagnostic.Create(descriptor, syntax.GetLocation()));
        }
    }
 
    /// <summary>Analyzer used to test ICase and ICaseClause.</summary>
    public class CaseTestAnalyzer : DiagnosticAnalyzer
    {
        /// <summary>Diagnostic category "Maintainability".</summary>
        private const string Maintainability = nameof(Maintainability);
 
        public static readonly DiagnosticDescriptor HasDefaultCaseDescriptor = new DiagnosticDescriptor(
            "HasDefaultCase",
            "Has Default Case",
            "A default case clause is encountered",
            Maintainability,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public static readonly DiagnosticDescriptor MultipleCaseClausesDescriptor = new DiagnosticDescriptor(
            "MultipleCaseClauses",
            "Multiple Case Clauses",
            "A switch section has multiple case clauses",
            Maintainability,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        /// <summary>Gets the set of supported diagnostic descriptors from this analyzer.</summary>
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
        {
            get { return ImmutableArray.Create(HasDefaultCaseDescriptor, MultipleCaseClausesDescriptor); }
        }
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                 (operationContext) =>
                 {
                     switch (operationContext.Operation.Kind)
                     {
                         case OperationKind.CaseClause:
                             var caseClause = (ICaseClauseOperation)operationContext.Operation;
                             if (caseClause.CaseKind == CaseKind.Default)
                             {
                                 Report(operationContext, caseClause.Syntax, HasDefaultCaseDescriptor);
                             }
                             break;
                         case OperationKind.SwitchCase:
                             var switchSection = (ISwitchCaseOperation)operationContext.Operation;
                             if (!switchSection.HasErrors(operationContext.Compilation, operationContext.CancellationToken) && switchSection.Clauses.Length > 1)
                             {
                                 Report(operationContext, switchSection.Syntax, MultipleCaseClausesDescriptor);
                             }
                             break;
                     }
                 },
                 OperationKind.SwitchCase,
                 OperationKind.CaseClause);
        }
 
        private static void Report(OperationAnalysisContext context, SyntaxNode syntax, DiagnosticDescriptor descriptor)
        {
            context.ReportDiagnostic(Diagnostic.Create(descriptor, syntax.GetLocation()));
        }
    }
 
    /// <summary>Analyzer used to test for explicit vs. implicit instance references.</summary>
    public class ExplicitVsImplicitInstanceAnalyzer : DiagnosticAnalyzer
    {
        public static readonly DiagnosticDescriptor ImplicitInstanceDescriptor = new DiagnosticDescriptor(
            "ImplicitInstance",
            "Implicit Instance",
            "Implicit instance found.",
            "Testing",
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public static readonly DiagnosticDescriptor ExplicitInstanceDescriptor = new DiagnosticDescriptor(
            "ExplicitInstance",
            "Explicit Instance",
            "Explicit instance found.",
            "Testing",
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(ImplicitInstanceDescriptor, ExplicitInstanceDescriptor);
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                 (operationContext) =>
                 {
                     IInstanceReferenceOperation instanceReference = (IInstanceReferenceOperation)operationContext.Operation;
                     operationContext.ReportDiagnostic(Diagnostic.Create(instanceReference.IsImplicit ? ImplicitInstanceDescriptor : ExplicitInstanceDescriptor,
                                                                         instanceReference.Syntax.GetLocation()));
                 },
                 OperationKind.InstanceReference);
        }
    }
 
    /// <summary>Analyzer used to test for member references.</summary>
    public class MemberReferenceAnalyzer : DiagnosticAnalyzer
    {
        public static readonly DiagnosticDescriptor EventReferenceDescriptor = new DiagnosticDescriptor(
            "EventReference",
            "Event Reference",
            "Event reference found.",
            "Testing",
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public static readonly DiagnosticDescriptor InvalidEventDescriptor = new DiagnosticDescriptor(
            "InvalidEvent",
            "Invalid Event",
            "A EventAssignmentExpression with invalid event found.",
            "Testing",
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public static readonly DiagnosticDescriptor HandlerAddedDescriptor = new DiagnosticDescriptor(
            "HandlerAdded",
            "Handler Added",
            "Event handler added.",
            "Testing",
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public static readonly DiagnosticDescriptor HandlerRemovedDescriptor = new DiagnosticDescriptor(
            "HandlerRemoved",
            "Handler Removed",
            "Event handler removed.",
            "Testing",
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public static readonly DiagnosticDescriptor PropertyReferenceDescriptor = new DiagnosticDescriptor(
            "PropertyReference",
            "Property Reference",
            "Property reference found.",
            "Testing",
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public static readonly DiagnosticDescriptor FieldReferenceDescriptor = new DiagnosticDescriptor(
            "FieldReference",
            "Field Reference",
            "Field reference found.",
            "Testing",
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public static readonly DiagnosticDescriptor MethodBindingDescriptor = new DiagnosticDescriptor(
            "MethodBinding",
            "Method Binding",
            "Method binding found.",
            "Testing",
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics =>
            ImmutableArray.Create(EventReferenceDescriptor,
                HandlerAddedDescriptor,
                HandlerRemovedDescriptor,
                PropertyReferenceDescriptor,
                FieldReferenceDescriptor,
                MethodBindingDescriptor,
                InvalidEventDescriptor);
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                 (operationContext) =>
                 {
                     operationContext.ReportDiagnostic(Diagnostic.Create(EventReferenceDescriptor, operationContext.Operation.Syntax.GetLocation()));
                 },
                 OperationKind.EventReference);
 
            context.RegisterOperationAction(
                 (operationContext) =>
                 {
                     IEventAssignmentOperation eventAssignment = (IEventAssignmentOperation)operationContext.Operation;
                     operationContext.ReportDiagnostic(Diagnostic.Create(eventAssignment.Adds ? HandlerAddedDescriptor : HandlerRemovedDescriptor, operationContext.Operation.Syntax.GetLocation()));
 
                     if (eventAssignment.EventReference.Kind == OperationKind.Invalid || eventAssignment.HasErrors(operationContext.Compilation, operationContext.CancellationToken))
                     {
                         operationContext.ReportDiagnostic(Diagnostic.Create(InvalidEventDescriptor, eventAssignment.Syntax.GetLocation()));
                     }
                 },
                 OperationKind.EventAssignment);
 
            context.RegisterOperationAction(
                 (operationContext) =>
                 {
                     operationContext.ReportDiagnostic(Diagnostic.Create(PropertyReferenceDescriptor, operationContext.Operation.Syntax.GetLocation()));
                 },
                 OperationKind.PropertyReference);
 
            context.RegisterOperationAction(
                 (operationContext) =>
                 {
                     operationContext.ReportDiagnostic(Diagnostic.Create(FieldReferenceDescriptor, operationContext.Operation.Syntax.GetLocation()));
                 },
                 OperationKind.FieldReference);
 
            context.RegisterOperationAction(
                 (operationContext) =>
                 {
                     operationContext.ReportDiagnostic(Diagnostic.Create(MethodBindingDescriptor, operationContext.Operation.Syntax.GetLocation()));
                 },
                 OperationKind.MethodReference);
        }
    }
 
    /// <summary>Analyzer used to test IOperation treatment of params array arguments.</summary>
    public class ParamsArrayTestAnalyzer : DiagnosticAnalyzer
    {
        public static readonly DiagnosticDescriptor LongParamsDescriptor = new DiagnosticDescriptor(
            "LongParams",
            "Long Params",
            "Params array argument has more than 3 elements.",
            "Testing",
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public static readonly DiagnosticDescriptor InvalidConstructorDescriptor = new DiagnosticDescriptor(
            "InvalidConstructor",
            "Invalid Constructor",
            "Invalid Constructor.",
            "Testing",
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(LongParamsDescriptor, InvalidConstructorDescriptor);
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                 (operationContext) =>
                 {
                     IInvocationOperation invocation = (IInvocationOperation)operationContext.Operation;
 
                     foreach (IArgumentOperation argument in invocation.Arguments)
                     {
                         if (argument.Parameter.IsParams)
                         {
                             if (argument.Value is IArrayCreationOperation arrayValue)
                             {
                                 Optional<object> dimensionSize = arrayValue.DimensionSizes[0].ConstantValue;
                                 if (dimensionSize.HasValue && IntegralValue(dimensionSize.Value) > 3)
                                 {
                                     operationContext.ReportDiagnostic(Diagnostic.Create(LongParamsDescriptor, argument.Value.Syntax.GetLocation()));
                                 }
                             }
                         }
                     }
                 },
                 OperationKind.Invocation);
 
            context.RegisterOperationAction(
                (operationContext) =>
                {
                    IObjectCreationOperation creation = (IObjectCreationOperation)operationContext.Operation;
 
                    if (creation.Constructor == null)
                    {
                        operationContext.ReportDiagnostic(Diagnostic.Create(InvalidConstructorDescriptor, creation.Syntax.GetLocation()));
                    }
 
                    foreach (IArgumentOperation argument in creation.Arguments)
                    {
                        if (argument.Parameter.IsParams)
                        {
                            if (argument.Value is IArrayCreationOperation arrayValue)
                            {
                                Optional<object> dimensionSize = arrayValue.DimensionSizes[0].ConstantValue;
                                if (dimensionSize.HasValue && IntegralValue(dimensionSize.Value) > 3)
                                {
                                    operationContext.ReportDiagnostic(Diagnostic.Create(LongParamsDescriptor, argument.Value.Syntax.GetLocation()));
                                }
                            }
                        }
                    }
                },
                OperationKind.ObjectCreation);
        }
 
        private static long IntegralValue(object value)
        {
            if (value is long v)
            {
                return v;
            }
 
            if (value is int i)
            {
                return i;
            }
 
            return 0;
        }
    }
 
    /// <summary>Analyzer used to test for initializer constructs for members and parameters.</summary>
    public class EqualsValueTestAnalyzer : DiagnosticAnalyzer
    {
        public static readonly DiagnosticDescriptor EqualsValueDescriptor = new DiagnosticDescriptor(
            "EqualsValue",
            "Equals Value",
            "Equals value found.",
            "Testing",
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(EqualsValueDescriptor);
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                 (operationContext) =>
                 {
                     IFieldInitializerOperation equalsValue = (IFieldInitializerOperation)operationContext.Operation;
                     if (equalsValue.InitializedFields[0].Name.StartsWith("F"))
                     {
                         operationContext.ReportDiagnostic(Diagnostic.Create(EqualsValueDescriptor, equalsValue.Syntax.GetLocation()));
                     }
                 },
                 OperationKind.FieldInitializer);
 
            context.RegisterOperationAction(
                 (operationContext) =>
                 {
                     IParameterInitializerOperation equalsValue = (IParameterInitializerOperation)operationContext.Operation;
                     if (equalsValue.Parameter.Name.StartsWith("F"))
                     {
                         operationContext.ReportDiagnostic(Diagnostic.Create(EqualsValueDescriptor, equalsValue.Syntax.GetLocation()));
                     }
                 },
                 OperationKind.ParameterInitializer);
        }
    }
 
    /// <summary>Analyzer used to test None IOperations.</summary>
    public class NoneOperationTestAnalyzer : DiagnosticAnalyzer
    {
        private const string ReliabilityCategory = "Reliability";
 
        // We should not see this warning triggered by any code
        public static readonly DiagnosticDescriptor NoneOperationDescriptor = new DiagnosticDescriptor(
            "NoneOperation",
            "None operation found",
            "An IOperation of None kind is found",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
        {
            get { return ImmutableArray.Create(NoneOperationDescriptor); }
        }
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                 (operationContext) =>
                 {
                     operationContext.ReportDiagnostic(Diagnostic.Create(NoneOperationDescriptor, operationContext.Operation.Syntax.GetLocation()));
                 },
                 // None kind is only supposed to be used internally and will not actually register actions.
                 OperationKind.None);
        }
    }
 
    public class AddressOfTestAnalyzer : DiagnosticAnalyzer
    {
        private const string ReliabilityCategory = "Reliability";
 
        public static readonly DiagnosticDescriptor AddressOfDescriptor = new DiagnosticDescriptor(
            "AddressOfOperation",
            "AddressOf operation found",
            "An AddressOf operation found",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public static readonly DiagnosticDescriptor InvalidAddressOfReferenceDescriptor = new DiagnosticDescriptor(
            "InvalidAddressOfReference",
            "Invalid AddressOf reference found",
            "An invalid AddressOf reference found",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics =>
            ImmutableArray.Create(AddressOfDescriptor, InvalidAddressOfReferenceDescriptor);
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                 (operationContext) =>
                 {
                     var addressOfOperation = (IAddressOfOperation)operationContext.Operation;
                     operationContext.ReportDiagnostic(Diagnostic.Create(AddressOfDescriptor, addressOfOperation.Syntax.GetLocation()));
 
                     if (addressOfOperation.Reference.Kind == OperationKind.Invalid && addressOfOperation.HasErrors(operationContext.Compilation, operationContext.CancellationToken))
                     {
                         operationContext.ReportDiagnostic(Diagnostic.Create(InvalidAddressOfReferenceDescriptor, addressOfOperation.Reference.Syntax.GetLocation()));
                     }
                 },
                 OperationKind.AddressOf);
        }
    }
 
    /// <summary>Analyzer used to test LambdaExpression IOperations.</summary>
    public class LambdaTestAnalyzer : DiagnosticAnalyzer
    {
        private const string ReliabilityCategory = "Reliability";
 
        public static readonly DiagnosticDescriptor LambdaExpressionDescriptor = new DiagnosticDescriptor(
            "LambdaExpression",
            "Lambda expression found",
            "A Lambda expression is found",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public static readonly DiagnosticDescriptor TooManyStatementsInLambdaExpressionDescriptor = new DiagnosticDescriptor(
            "TooManyStatementsInLambdaExpression",
            "Too many statements in a Lambda expression",
            "More than 3 statements in a Lambda expression",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        // This warning should never be triggered.
        public static readonly DiagnosticDescriptor NoneOperationInLambdaExpressionDescriptor = new DiagnosticDescriptor(
            "NoneOperationInLambdaExpression",
            "None Operation found in Lambda expression",
            "None Operation is found Lambda expression",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics =>
            ImmutableArray.Create(LambdaExpressionDescriptor,
                                  TooManyStatementsInLambdaExpressionDescriptor,
                                  NoneOperationInLambdaExpressionDescriptor);
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                 (operationContext) =>
                 {
                     var lambdaExpression = (IAnonymousFunctionOperation)operationContext.Operation;
                     operationContext.ReportDiagnostic(Diagnostic.Create(LambdaExpressionDescriptor, operationContext.Operation.Syntax.GetLocation()));
                     var block = lambdaExpression.Body;
                     // TODO: Can this possibly be null? Remove check if not.
                     if (block == null)
                     {
                         return;
                     }
                     if (block.Operations.Length > 3)
                     {
                         operationContext.ReportDiagnostic(Diagnostic.Create(TooManyStatementsInLambdaExpressionDescriptor, operationContext.Operation.Syntax.GetLocation()));
                     }
                     bool flag = false;
                     foreach (var statement in block.Operations)
                     {
                         if (statement.Kind == OperationKind.None)
                         {
                             flag = true;
                             break;
                         }
                     }
                     if (flag)
                     {
                         operationContext.ReportDiagnostic(Diagnostic.Create(NoneOperationInLambdaExpressionDescriptor, operationContext.Operation.Syntax.GetLocation()));
                     }
                 },
                 OperationKind.AnonymousFunction);
        }
    }
 
    public class StaticMemberTestAnalyzer : DiagnosticAnalyzer
    {
        private const string ReliabilityCategory = "Reliability";
 
        public static readonly DiagnosticDescriptor StaticMemberDescriptor = new DiagnosticDescriptor(
            "StaticMember",
            "Static member found",
            "A static member reference expression is found",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        // We should not see this warning triggered by any code
        public static readonly DiagnosticDescriptor StaticMemberWithInstanceDescriptor = new DiagnosticDescriptor(
            "StaticMemberWithInstance",
            "Static member with non null Instance found",
            "A static member reference with non null Instance is found",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
        {
            get
            {
                return ImmutableArray.Create(StaticMemberDescriptor,
                                             StaticMemberWithInstanceDescriptor);
            }
        }
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                 (operationContext) =>
                 {
                     var operation = operationContext.Operation;
                     ISymbol memberSymbol;
                     IOperation receiver;
                     switch (operation.Kind)
                     {
                         case OperationKind.FieldReference:
                             memberSymbol = ((IFieldReferenceOperation)operation).Field;
                             receiver = ((IFieldReferenceOperation)operation).Instance;
                             break;
                         case OperationKind.PropertyReference:
                             memberSymbol = ((IPropertyReferenceOperation)operation).Property;
                             receiver = ((IPropertyReferenceOperation)operation).Instance;
                             break;
                         case OperationKind.EventReference:
                             memberSymbol = ((IEventReferenceOperation)operation).Event;
                             receiver = ((IEventReferenceOperation)operation).Instance;
                             break;
                         case OperationKind.MethodReference:
                             memberSymbol = ((IMethodReferenceOperation)operation).Method;
                             receiver = ((IMethodReferenceOperation)operation).Instance;
                             break;
                         case OperationKind.Invocation:
                             memberSymbol = ((IInvocationOperation)operation).TargetMethod;
                             receiver = ((IInvocationOperation)operation).Instance;
                             break;
                         default:
                             throw new ArgumentException();
                     }
                     if (memberSymbol.IsStatic)
                     {
                         operationContext.ReportDiagnostic(Diagnostic.Create(StaticMemberDescriptor, operation.Syntax.GetLocation()));
 
                         if (receiver != null)
                         {
                             operationContext.ReportDiagnostic(Diagnostic.Create(StaticMemberWithInstanceDescriptor, operation.Syntax.GetLocation()));
                         }
                     }
                 },
                 OperationKind.FieldReference,
                 OperationKind.PropertyReference,
                 OperationKind.EventReference,
                 OperationKind.MethodReference,
                 OperationKind.Invocation);
        }
    }
 
    public class LabelOperationsTestAnalyzer : DiagnosticAnalyzer
    {
        public static readonly DiagnosticDescriptor LabelDescriptor = new DiagnosticDescriptor(
           "Label",
           "Label found",
           "A label was was found",
           "Testing",
           DiagnosticSeverity.Warning,
           isEnabledByDefault: true);
 
        public static readonly DiagnosticDescriptor GotoDescriptor = new DiagnosticDescriptor(
          "Goto",
          "Goto found",
          "A goto was was found",
          "Testing",
          DiagnosticSeverity.Warning,
          isEnabledByDefault: true);
 
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(LabelDescriptor, GotoDescriptor);
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                (operationContext) =>
                {
                    ILabelSymbol label = ((ILabeledOperation)operationContext.Operation).Label;
                    if (label.Name == "Wilma" || label.Name == "Betty")
                    {
                        operationContext.ReportDiagnostic(Diagnostic.Create(LabelDescriptor, operationContext.Operation.Syntax.GetLocation()));
                    }
                },
                OperationKind.Labeled);
 
            context.RegisterOperationAction(
                (operationContext) =>
                {
                    IBranchOperation branch = (IBranchOperation)operationContext.Operation;
                    if (branch.BranchKind == BranchKind.GoTo)
                    {
                        ILabelSymbol label = branch.Target;
                        if (label.Name == "Wilma" || label.Name == "Betty")
                        {
                            operationContext.ReportDiagnostic(Diagnostic.Create(GotoDescriptor, branch.Syntax.GetLocation()));
                        }
                    }
                },
                OperationKind.Branch);
        }
    }
 
    public class UnaryAndBinaryOperationsTestAnalyzer : DiagnosticAnalyzer
    {
        public static readonly DiagnosticDescriptor OperatorAddMethodDescriptor = new DiagnosticDescriptor(
            "OperatorAddMethod",
            "Operator Add method found",
            "An operator Add method was found",
            "Testing",
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public static readonly DiagnosticDescriptor OperatorMinusMethodDescriptor = new DiagnosticDescriptor(
            "OperatorMinusMethod",
            "Operator Minus method found",
            "An operator Minus method was found",
            "Testing",
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public static readonly DiagnosticDescriptor DoubleMultiplyDescriptor = new DiagnosticDescriptor(
            "DoubleMultiply",
            "Double multiply found",
            "A double multiply was found",
            "Testing",
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public static readonly DiagnosticDescriptor BooleanNotDescriptor = new DiagnosticDescriptor(
            "BooleanNot",
            "Boolean not found",
            "A boolean not was found",
            "Testing",
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(OperatorAddMethodDescriptor, OperatorMinusMethodDescriptor, DoubleMultiplyDescriptor, BooleanNotDescriptor);
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                (operationContext) =>
                {
                    IBinaryOperation binary = (IBinaryOperation)operationContext.Operation;
                    if (binary.OperatorKind == BinaryOperatorKind.Add && binary.OperatorMethod != null && binary.OperatorMethod.Name.Contains("Addition"))
                    {
                        operationContext.ReportDiagnostic(Diagnostic.Create(OperatorAddMethodDescriptor, binary.Syntax.GetLocation()));
                    }
 
                    if (binary.OperatorKind == BinaryOperatorKind.Multiply && binary.Type.SpecialType == SpecialType.System_Double)
                    {
                        operationContext.ReportDiagnostic(Diagnostic.Create(DoubleMultiplyDescriptor, binary.Syntax.GetLocation()));
                    }
                },
                OperationKind.Binary);
 
            context.RegisterOperationAction(
                (operationContext) =>
                {
                    IUnaryOperation unary = (IUnaryOperation)operationContext.Operation;
                    if (unary.OperatorKind == UnaryOperatorKind.Minus && unary.OperatorMethod != null && unary.OperatorMethod.Name.Contains("UnaryNegation"))
                    {
                        operationContext.ReportDiagnostic(Diagnostic.Create(OperatorMinusMethodDescriptor, unary.Syntax.GetLocation()));
                    }
 
                    if (unary.OperatorKind == UnaryOperatorKind.Not)
                    {
                        operationContext.ReportDiagnostic(Diagnostic.Create(BooleanNotDescriptor, unary.Syntax.GetLocation()));
                    }
 
                    if (unary.OperatorKind == UnaryOperatorKind.BitwiseNegation)
                    {
                        operationContext.ReportDiagnostic(Diagnostic.Create(BooleanNotDescriptor, unary.Syntax.GetLocation()));
                    }
                },
                OperationKind.Unary);
        }
    }
 
    public class BinaryOperatorVBTestAnalyzer : DiagnosticAnalyzer
    {
        public static readonly DiagnosticDescriptor BinaryUserDefinedOperatorDescriptor = new DiagnosticDescriptor(
            "BinaryUserDefinedOperator",
            "Binary user defined operator found",
            "A Binary user defined operator {0} is found",
            "Testing",
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
            => ImmutableArray.Create(BinaryUserDefinedOperatorDescriptor);
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                (operationContext) =>
                {
                    var binary = (IBinaryOperation)operationContext.Operation;
                    if (binary.OperatorMethod != null)
                    {
                        operationContext.ReportDiagnostic(
                            Diagnostic.Create(BinaryUserDefinedOperatorDescriptor,
                                binary.Syntax.GetLocation(),
                                binary.OperatorKind.ToString()));
                    }
                },
                OperationKind.Binary);
        }
    }
 
    public class OperatorPropertyPullerTestAnalyzer : DiagnosticAnalyzer
    {
        public static readonly DiagnosticDescriptor BinaryOperatorDescriptor = new DiagnosticDescriptor(
            "BinaryOperator",
            "Binary operator found",
            "A Binary operator {0} was found",
            "Testing",
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public static readonly DiagnosticDescriptor UnaryOperatorDescriptor = new DiagnosticDescriptor(
           "UnaryOperator",
           "Unary operator found",
           "A Unary operator {0} was found",
           "Testing",
           DiagnosticSeverity.Warning,
           isEnabledByDefault: true);
 
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
            => ImmutableArray.Create(BinaryOperatorDescriptor, UnaryOperatorDescriptor);
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                (operationContext) =>
                {
                    var binary = (IBinaryOperation)operationContext.Operation;
                    var left = binary.LeftOperand;
                    var right = binary.RightOperand;
                    if (!left.HasErrors(operationContext.Compilation, operationContext.CancellationToken) &&
                        !right.HasErrors(operationContext.Compilation, operationContext.CancellationToken) &&
                        binary.OperatorMethod == null)
                    {
                        if (left.Kind == OperationKind.LocalReference)
                        {
                            var leftLocal = ((ILocalReferenceOperation)left).Local;
                            if (leftLocal.Name == "x")
                            {
                                if (right.Kind == OperationKind.Literal)
                                {
                                    var rightValue = right.ConstantValue;
                                    if (rightValue.HasValue && rightValue.Value is int && (int)rightValue.Value == 10)
                                    {
                                        operationContext.ReportDiagnostic(
                                            Diagnostic.Create(BinaryOperatorDescriptor,
                                            binary.Syntax.GetLocation(),
                                            binary.OperatorKind.ToString()));
                                    }
                                }
                            }
                        }
                    }
                },
                OperationKind.Binary);
 
            context.RegisterOperationAction(
                (operationContext) =>
                {
                    var unary = (IUnaryOperation)operationContext.Operation;
                    var operand = unary.Operand;
                    if (operand.Kind == OperationKind.LocalReference)
                    {
                        var operandLocal = ((ILocalReferenceOperation)operand).Local;
                        if (operandLocal.Name == "x")
                        {
                            if (!operand.HasErrors(operationContext.Compilation, operationContext.CancellationToken) && unary.OperatorMethod == null)
                            {
                                operationContext.ReportDiagnostic(
                                    Diagnostic.Create(UnaryOperatorDescriptor,
                                        unary.Syntax.GetLocation(),
                                        unary.OperatorKind.ToString()));
                            }
                        }
                    }
                },
                OperationKind.Unary);
        }
    }
 
    public class NullOperationSyntaxTestAnalyzer : DiagnosticAnalyzer
    {
        private const string ReliabilityCategory = "Reliability";
 
        // We should not see this warning triggered by any code
        public static readonly DiagnosticDescriptor NullOperationSyntaxDescriptor = new DiagnosticDescriptor(
            "NullOperationSyntax",
            "null operation Syntax found",
            "An IOperation with Syntax property of value null is found",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        // since we don't expect to see the first diagnostic, we created this one to make sure
        // the test didn't pass because the analyzer crashed.
        public static readonly DiagnosticDescriptor ParamsArrayOperationDescriptor = new DiagnosticDescriptor(
            "ParamsArray",
            "Params array argument found",
            "A params array argument is found",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
        {
            get { return ImmutableArray.Create(NullOperationSyntaxDescriptor, ParamsArrayOperationDescriptor); }
        }
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                (operationContext) =>
                {
                    var nullList = new List<IOperation>();
                    var paramsList = new List<IOperation>();
                    var collector = new Walker(nullList, paramsList);
                    collector.Visit(operationContext.Operation);
 
                    foreach (var nullSyntaxOperation in nullList)
                    {
                        operationContext.ReportDiagnostic(
                            Diagnostic.Create(NullOperationSyntaxDescriptor, null));
                    }
                    foreach (var paramsarrayArgumentOperation in paramsList)
                    {
                        operationContext.ReportDiagnostic(
                            Diagnostic.Create(ParamsArrayOperationDescriptor,
                                              paramsarrayArgumentOperation.Syntax.GetLocation()));
                    }
                },
                OperationKind.Invocation);
        }
 
        // this OperationWalker collect:
        // 1. all the operation with null Syntax property
        // 2. all the params array argument operations
        private sealed class Walker : OperationWalker
        {
            private readonly List<IOperation> _nullList;
            private readonly List<IOperation> _paramsList;
 
            public Walker(List<IOperation> nullList, List<IOperation> paramsList)
            {
                _nullList = nullList;
                _paramsList = paramsList;
            }
 
            public override void Visit(IOperation operation)
            {
                if (operation != null)
                {
                    if (operation.Syntax == null)
                    {
                        _nullList.Add(operation);
                    }
                    if (operation.Kind == OperationKind.Argument)
                    {
                        if (((IArgumentOperation)operation).ArgumentKind == ArgumentKind.ParamArray)
                        {
                            _paramsList.Add(operation);
                        }
                    }
                }
                base.Visit(operation);
            }
        }
    }
 
    public class InvalidOperatorExpressionTestAnalyzer : DiagnosticAnalyzer
    {
        private const string ReliabilityCategory = "Reliability";
 
        public static readonly DiagnosticDescriptor InvalidBinaryDescriptor = new DiagnosticDescriptor(
            "InvalidBinary",
            "Invalid binary expression operation with BinaryOperationKind.Invalid",
            "An Invalid binary expression operation with BinaryOperationKind.Invalid is found",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public static readonly DiagnosticDescriptor InvalidUnaryDescriptor = new DiagnosticDescriptor(
            "InvalidUnary",
            "Invalid unary expression operation with UnaryOperationKind.Invalid",
            "An Invalid unary expression operation with UnaryOperationKind.Invalid is found",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public static readonly DiagnosticDescriptor InvalidIncrementDescriptor = new DiagnosticDescriptor(
            "InvalidIncrement",
            "Invalid increment expression operation with ICompoundAssignmentExpression.BinaryOperationKind == BinaryOperationKind.Invalid",
            "An Invalid increment expression operation with ICompoundAssignmentExpression.BinaryOperationKind == BinaryOperationKind.Invalid is found",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(InvalidBinaryDescriptor,
                                                                                                                  InvalidUnaryDescriptor,
                                                                                                                  InvalidIncrementDescriptor);
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                 (operationContext) =>
                 {
                     var operation = operationContext.Operation;
                     if (operation.Kind == OperationKind.Binary)
                     {
                         var binary = (IBinaryOperation)operation;
                         if (binary.HasErrors(operationContext.Compilation, operationContext.CancellationToken))
                         {
                             operationContext.ReportDiagnostic(Diagnostic.Create(InvalidBinaryDescriptor, binary.Syntax.GetLocation()));
                         }
                     }
                     else if (operation.Kind == OperationKind.Unary)
                     {
                         var unary = (IUnaryOperation)operation;
                         if (unary.HasErrors(operationContext.Compilation, operationContext.CancellationToken))
                         {
                             operationContext.ReportDiagnostic(Diagnostic.Create(InvalidUnaryDescriptor, unary.Syntax.GetLocation()));
                         }
                     }
                     else if (operation.Kind == OperationKind.Increment)
                     {
                         var inc = (IIncrementOrDecrementOperation)operation;
                         if (inc.HasErrors(operationContext.Compilation))
                         {
                             operationContext.ReportDiagnostic(Diagnostic.Create(InvalidIncrementDescriptor, inc.Syntax.GetLocation()));
                         }
                     }
                 },
                 OperationKind.Binary,
                 OperationKind.Unary,
                 OperationKind.Increment);
        }
    }
 
    public class ConditionalAccessOperationTestAnalyzer : DiagnosticAnalyzer
    {
        public static readonly DiagnosticDescriptor ConditionalAccessOperationDescriptor = new DiagnosticDescriptor(
           "ConditionalAccessOperation",
           "Conditional access operation found",
           "Conditional access operation was found",
           "Testing",
           DiagnosticSeverity.Warning,
           isEnabledByDefault: true);
 
        public static readonly DiagnosticDescriptor ConditionalAccessInstanceOperationDescriptor = new DiagnosticDescriptor(
           "ConditionalAccessInstanceOperation",
           "Conditional access instance operation found",
           "Conditional access instance operation was found",
           "Testing",
           DiagnosticSeverity.Warning,
           isEnabledByDefault: true);
 
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
        {
            get { return ImmutableArray.Create(ConditionalAccessOperationDescriptor, ConditionalAccessInstanceOperationDescriptor); }
        }
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                 (operationContext) =>
                 {
                     IConditionalAccessOperation conditionalAccess = (IConditionalAccessOperation)operationContext.Operation;
                     if (conditionalAccess.WhenNotNull != null && conditionalAccess.Operation != null)
                     {
                         operationContext.ReportDiagnostic(Diagnostic.Create(ConditionalAccessOperationDescriptor, conditionalAccess.Syntax.GetLocation()));
                     }
                 },
                 OperationKind.ConditionalAccess);
 
            context.RegisterOperationAction(
                 (operationContext) =>
                 {
                     IConditionalAccessInstanceOperation conditionalAccessInstance = (IConditionalAccessInstanceOperation)operationContext.Operation;
                     operationContext.ReportDiagnostic(Diagnostic.Create(ConditionalAccessInstanceOperationDescriptor, conditionalAccessInstance.Syntax.GetLocation()));
                 },
                 OperationKind.ConditionalAccessInstance);
 
            // https://github.com/dotnet/roslyn/issues/21294
            //context.RegisterOperationAction(
            //    (operationContext) =>
            //    {
            //        IPlaceholderExpression placeholder = (IPlaceholderExpression)operationContext.Operation;
            //        operationContext.ReportDiagnostic(Diagnostic.Create(ConditionalAccessInstanceOperationDescriptor, placeholder.Syntax.GetLocation()));
            //    },
            //    OperationKind.PlaceholderExpression);
        }
    }
 
    public class ConversionExpressionCSharpTestAnalyzer : DiagnosticAnalyzer
    {
        private const string ReliabilityCategory = "Reliability";
 
        public static readonly DiagnosticDescriptor InvalidConversionExpressionDescriptor = new DiagnosticDescriptor(
            "InvalidConversionExpression",
            "Invalid conversion expression",
            "Invalid conversion expression.",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
        {
            get { return ImmutableArray.Create(InvalidConversionExpressionDescriptor); }
        }
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                 (operationContext) =>
                 {
                     var conversion = (IConversionOperation)operationContext.Operation;
                     if (conversion.HasErrors(operationContext.Compilation, operationContext.CancellationToken))
                     {
                         operationContext.ReportDiagnostic(Diagnostic.Create(InvalidConversionExpressionDescriptor, conversion.Syntax.GetLocation()));
                     }
                 },
                 OperationKind.Conversion);
        }
    }
 
    public class ForLoopConditionCrashVBTestAnalyzer : DiagnosticAnalyzer
    {
        private const string ReliabilityCategory = "Reliability";
 
        public static readonly DiagnosticDescriptor ForLoopConditionCrashDescriptor = new DiagnosticDescriptor(
            "ForLoopConditionCrash",
            "Ensure ForLoopCondition property doesn't crash",
            "Ensure ForLoopCondition property doesn't crash",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
        {
            get { return ImmutableArray.Create(ForLoopConditionCrashDescriptor); }
        }
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                 (operationContext) =>
                 {
                     ILoopOperation loop = (ILoopOperation)operationContext.Operation;
                     if (loop.LoopKind == LoopKind.ForTo)
                     {
                         var forLoop = (IForToLoopOperation)loop;
                         var forCondition = forLoop.LimitValue;
 
                         if (forCondition.HasErrors(operationContext.Compilation, operationContext.CancellationToken))
                         {
                             // Generate a warning to prove we didn't crash
                             operationContext.ReportDiagnostic(Diagnostic.Create(ForLoopConditionCrashDescriptor, forLoop.LimitValue.Syntax.GetLocation()));
                         }
                     }
                 },
                 OperationKind.Loop);
        }
    }
 
    public class TrueFalseUnaryOperationTestAnalyzer : DiagnosticAnalyzer
    {
        private const string ReliabilityCategory = "Reliability";
 
        public static readonly DiagnosticDescriptor UnaryTrueDescriptor = new DiagnosticDescriptor(
            "UnaryTrue",
            "An unary True operation is found",
            "A unary True operation is found",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public static readonly DiagnosticDescriptor UnaryFalseDescriptor = new DiagnosticDescriptor(
            "UnaryFalse",
            "An unary False operation is found",
            "A unary False operation is found",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
            => ImmutableArray.Create(UnaryTrueDescriptor, UnaryFalseDescriptor);
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                 (operationContext) =>
                 {
                     var unary = (IUnaryOperation)operationContext.Operation;
                     if (unary.OperatorKind == UnaryOperatorKind.True)
                     {
                         operationContext.ReportDiagnostic(Diagnostic.Create(UnaryTrueDescriptor, unary.Syntax.GetLocation()));
                     }
                     else if (unary.OperatorKind == UnaryOperatorKind.False)
                     {
                         operationContext.ReportDiagnostic(Diagnostic.Create(UnaryFalseDescriptor, unary.Syntax.GetLocation()));
                     }
                 },
                 OperationKind.Unary);
        }
    }
 
    public class AssignmentOperationSyntaxTestAnalyzer : DiagnosticAnalyzer
    {
        private const string ReliabilityCategory = "Reliability";
 
        public static readonly DiagnosticDescriptor AssignmentOperationDescriptor = new DiagnosticDescriptor(
            "AssignmentOperation",
            "An assignment operation is found",
            "An assignment operation is found",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public static readonly DiagnosticDescriptor AssignmentSyntaxDescriptor = new DiagnosticDescriptor(
            "AssignmentSyntax",
            "An assignment syntax is found",
            "An assignment syntax is found",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
        {
            get { return ImmutableArray.Create(AssignmentOperationDescriptor, AssignmentSyntaxDescriptor); }
        }
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                 (operationContext) =>
                 {
                     operationContext.ReportDiagnostic(Diagnostic.Create(AssignmentOperationDescriptor, operationContext.Operation.Syntax.GetLocation()));
                 },
                 OperationKind.SimpleAssignment);
 
            context.RegisterSyntaxNodeAction(
                 (syntaxContext) =>
                 {
 
                     syntaxContext.ReportDiagnostic(Diagnostic.Create(AssignmentSyntaxDescriptor, syntaxContext.Node.GetLocation()));
                 },
                 CSharp.SyntaxKind.SimpleAssignmentExpression);
        }
    }
 
    public class LiteralTestAnalyzer : DiagnosticAnalyzer
    {
        private const string ReliabilityCategory = "Reliability";
 
        public static readonly DiagnosticDescriptor LiteralDescriptor = new DiagnosticDescriptor(
            "Literal",
            "A literal is found",
            "A literal of value {0} is found",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
        {
            get { return ImmutableArray.Create(LiteralDescriptor); }
        }
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                 (operationContext) =>
                 {
                     var literal = (ILiteralOperation)operationContext.Operation;
                     operationContext.ReportDiagnostic(Diagnostic.Create(LiteralDescriptor, literal.Syntax.GetLocation(), literal.Syntax.ToString()));
                 },
                 OperationKind.Literal);
        }
    }
 
    // This analyzer is to test operation action registration method in AnalysisContext
    public class AnalysisContextAnalyzer : DiagnosticAnalyzer
    {
        private const string ReliabilityCategory = "Reliability";
 
        public static readonly DiagnosticDescriptor OperationActionDescriptor = new DiagnosticDescriptor(
            "AnalysisContext",
            "An operation related action is invoked",
            "An {0} action is invoked in {1} context.",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
            => ImmutableArray.Create(OperationActionDescriptor);
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterOperationAction(
                (operationContext) =>
                {
                    operationContext.ReportDiagnostic(
                        Diagnostic.Create(OperationActionDescriptor, operationContext.Operation.Syntax.GetLocation(), "Operation", "Analysis"));
                },
                OperationKind.Literal);
        }
    }
 
    // This analyzer is to test operation action registration method in CompilationStartAnalysisContext
    public class CompilationStartAnalysisContextAnalyzer : DiagnosticAnalyzer
    {
        private const string ReliabilityCategory = "Reliability";
 
        public static readonly DiagnosticDescriptor OperationActionDescriptor = new DiagnosticDescriptor(
            "CompilationStartAnalysisContext",
            "An operation related action is invoked",
            "An {0} action is invoked in {1} context.",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
            => ImmutableArray.Create(OperationActionDescriptor);
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterCompilationStartAction(
                (compilationStartContext) =>
                {
                    compilationStartContext.RegisterOperationAction(
                        (operationContext) =>
                        {
                            operationContext.ReportDiagnostic(
                                Diagnostic.Create(OperationActionDescriptor, operationContext.Operation.Syntax.GetLocation(), "Operation", "CompilationStart within Analysis"));
                        },
                        OperationKind.Literal);
                });
        }
    }
 
    // This analyzer is to test GetOperation method in SemanticModel
    public class SemanticModelAnalyzer : DiagnosticAnalyzer
    {
        private const string ReliabilityCategory = "Reliability";
 
        public static readonly DiagnosticDescriptor GetOperationDescriptor = new DiagnosticDescriptor(
            "GetOperation",
            "An IOperation is returned by SemanticModel",
            "An IOperation is returned by SemanticModel.",
            ReliabilityCategory,
            DiagnosticSeverity.Warning,
            isEnabledByDefault: true);
 
        public sealed override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
            => ImmutableArray.Create(GetOperationDescriptor);
 
        public sealed override void Initialize(AnalysisContext context)
        {
            context.RegisterSyntaxNodeAction(
                (syntaxContext) =>
                {
                    var node = syntaxContext.Node;
                    var model = syntaxContext.SemanticModel;
                    if (model.GetOperation(node) != null)
                    {
                        syntaxContext.ReportDiagnostic(Diagnostic.Create(GetOperationDescriptor, node.GetLocation()));
                    }
                },
                Microsoft.CodeAnalysis.CSharp.SyntaxKind.NumericLiteralExpression);
 
            context.RegisterSyntaxNodeAction(
                (syntaxContext) =>
                {
                    var node = syntaxContext.Node;
                    var model = syntaxContext.SemanticModel;
                    if (model.GetOperation(node) != null)
                    {
                        syntaxContext.ReportDiagnostic(Diagnostic.Create(GetOperationDescriptor, node.GetLocation()));
                    }
                },
                Microsoft.CodeAnalysis.VisualBasic.SyntaxKind.NumericLiteralExpression);
        }
    }
}