Microsoft.CodeAnalysis.Diagnostics.OperationAnalysisContext.ReportDiagnostic(Microsoft.CodeAnalysis.Diagnostic)

Here are the examples of the csharp api Microsoft.CodeAnalysis.Diagnostics.OperationAnalysisContext.ReportDiagnostic(Microsoft.CodeAnalysis.Diagnostic) taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.

94 Examples 7

19 Source : BlockCallsAnalyzer.cs
with MIT License
from Azure

private void HandleMemberReference(OperationreplacedysisContext operationContext)
        {
            var memberReference = (IMemberReferenceOperation)operationContext.Operation;

            if (_blockConfig != null)
            {
                #region Handle property reference
                string containingType = memberReference.Member.ContainingType.ToString();
                if (!string.IsNullOrWhiteSpace(containingType) && _blockConfig.MatchesClreplacedToBlock(containingType))
                {
                    _blockConfig.GetMatchingClreplacedConfig(containingType)?.ForEach(cConfig => {
                        if (cConfig.MethodsToBlock?.Count > 0)
                        {
                            BlockConfig.GetMatchingBlockMessageList(cConfig.PropertiesToBlock, memberReference.Member.Name)?.ForEach(strMessage =>
                            {
                                operationContext.ReportDiagnostic(memberReference.CreateDiagnostic(blockCallsDiagnosticDescriptor,
                                        string.IsNullOrWhiteSpace(strMessage) ? new string[] { string.Format(DEFAULT_INVOCATION_BLOCK_MESSAGE_FORMAT, memberReference.Member.Name, containingType) } : new string[] { strMessage }
                                        ));
                            });
                        }
                        else
                        {
                            //No specific methods to block was indicated, however the type name did match the config, so the default action is to block all methods from this type
                            operationContext.ReportDiagnostic(memberReference.CreateDiagnostic(blockCallsDiagnosticDescriptor,
                                new string[] { string.Format(DEFAULT_PROPERTY_ACCESS_BLOCK_MESSAGE_FORMAT, "any property", containingType) }
                                ));
                        }
                    });
                }
                #endregion
            }

        }

19 Source : BlockCallsAnalyzer.cs
with MIT License
from Azure

private void HandleInvocation(OperationreplacedysisContext operationContext)
        {
            var invocation = (IInvocationOperation)operationContext.Operation;
            if (_blockConfig != null)
            {
                #region Handle PInvoke method calls
                if (invocation.TargetMethod.IsExtern && invocation.TargetMethod.GetDllImportData() != null)
                {
                    //This is a PInvoke call
                    string targetPInvokeDll = invocation.TargetMethod.GetDllImportData().ModuleName;
                    if (_blockConfig.MatchesPInvokeToBlock(targetPInvokeDll))
                    {
                        //Current DLL name is in the list of PInvoke DLL's that should be blocked.
                        //Evaluate if the specific call is blocked

                        _blockConfig.GetMatchingPInvokeConfig(targetPInvokeDll)?.ForEach(piConfig => {
                            if (piConfig.MethodsToBlock?.Count > 0)
                            {
                                string pInvokeFunctionName = !string.IsNullOrWhiteSpace(invocation.TargetMethod.GetDllImportData().EntryPointName)? invocation.TargetMethod.GetDllImportData().EntryPointName : invocation.TargetMethod.Name;

                                BlockConfig.GetMatchingBlockMessageList(piConfig.MethodsToBlock, pInvokeFunctionName)?.ForEach(strMessage =>
                                {
                                    operationContext.ReportDiagnostic(invocation.CreateDiagnostic(blockCallsDiagnosticDescriptor,
                                        string.IsNullOrWhiteSpace(strMessage) ? new string[] { string.Format(DEFAULT_INVOCATION_BLOCK_MESSAGE_FORMAT, invocation.TargetMethod.Name, targetPInvokeDll) } : new string[] { strMessage }
                                        ));
                                });
                            }
                            else
                            {
                                //No specific methods to block was indicated, however the DLL name did match the config, so the default action is to block all methods from this DLL
                                operationContext.ReportDiagnostic(invocation.CreateDiagnostic(blockCallsDiagnosticDescriptor,
                                    string.IsNullOrWhiteSpace(piConfig.MessageToShowWhenBlocked) ? new string[] { string.Format(DEFAULT_INVOCATION_BLOCK_MESSAGE_FORMAT, "any method", targetPInvokeDll) } : new string[] { piConfig.MessageToShowWhenBlocked }
                                    ));
                            }
                        });
                    }
                }
                #endregion

                #region Handle clreplaced and instance method invocation
                string containingType = invocation.TargetMethod.ContainingType.ToString();
                if (!string.IsNullOrWhiteSpace(containingType) && _blockConfig.MatchesClreplacedToBlock(containingType))
                {
                    _blockConfig.GetMatchingClreplacedConfig(containingType)?.ForEach(cConfig => {
                        if (cConfig.MethodsToBlock?.Count > 0)
                        {
                            BlockConfig.GetMatchingBlockMessageList(cConfig.MethodsToBlock, invocation.TargetMethod.Name)?.ForEach(strMessage => 
                            {
                                operationContext.ReportDiagnostic(invocation.CreateDiagnostic(blockCallsDiagnosticDescriptor,
                                        string.IsNullOrWhiteSpace(strMessage) ? new string[] { string.Format(DEFAULT_INVOCATION_BLOCK_MESSAGE_FORMAT, invocation.TargetMethod.Name, containingType) } : new string[] { strMessage }
                                        ));
                            });
                        }
                        else
                        {
                            //No specific methods to block was indicated, however the type name did match the config, so the default action is to block all methods from this type
                            operationContext.ReportDiagnostic(invocation.CreateDiagnostic(blockCallsDiagnosticDescriptor,
                                new string[] { string.Format(DEFAULT_INVOCATION_BLOCK_MESSAGE_FORMAT, "any method", containingType) } 
                                ));
                        }
                    });
                }

                containingType = invocation.Type.ToString(); //This is required to evaluate expressions where invocations take a generic Type as a parameter
                if (!string.IsNullOrWhiteSpace(containingType) && _blockConfig.MatchesClreplacedToBlock(containingType))
                {
                    bool blockedObjectCreation = false;
                    foreach (ClreplacedBlockConfig clreplacedConfig in _blockConfig.GetMatchingClreplacedConfig(containingType)?.Where(cConfig => cConfig?.IsObjectCreationBlocked == true))
                    {
                        blockedObjectCreation = true;
                        operationContext.ReportDiagnostic(invocation.CreateDiagnostic(blockCallsDiagnosticDescriptor,
                            string.IsNullOrWhiteSpace(clreplacedConfig.MessageToShowWhenBlocked) ? new string[] { string.Format(DEFAULT_INSTANTIATION_BLOCK_MESSAGE_FORMAT, containingType) } : new string[] { clreplacedConfig.MessageToShowWhenBlocked }
                            ));
                    }
                    if(!blockedObjectCreation)
                    {
                        _blockConfig.GetMatchingClreplacedConfig(containingType)?.ForEach(cConfig => {
                            if (cConfig.MethodsToBlock?.Count > 0)
                            {
                                BlockConfig.GetMatchingBlockMessageList(cConfig.MethodsToBlock, invocation.TargetMethod.Name)?.ForEach(strMessage =>
                                {
                                    operationContext.ReportDiagnostic(invocation.CreateDiagnostic(blockCallsDiagnosticDescriptor,
                                            string.IsNullOrWhiteSpace(strMessage) ? new string[] { string.Format(DEFAULT_INVOCATION_BLOCK_MESSAGE_FORMAT, invocation.TargetMethod.Name, containingType) } : new string[] { strMessage }
                                            ));
                                });
                            }
                            else
                            {
                                //No specific methods to block was indicated, however the type name did match the config, so the default action is to block all methods from this type
                                operationContext.ReportDiagnostic(invocation.CreateDiagnostic(blockCallsDiagnosticDescriptor,
                                    new string[] { string.Format(DEFAULT_INVOCATION_BLOCK_MESSAGE_FORMAT, "any method", containingType) }
                                    ));
                            }
                        });
                    }
                }

                #endregion 
            }
        }

19 Source : BlockCallsAnalyzer.cs
with MIT License
from Azure

private void HandleObjectCreation(OperationreplacedysisContext operationContext)
        {
            var objectCreation = (IObjectCreationOperation)operationContext.Operation;
            if (_blockConfig != null)
            {
                #region Handle object instantiation
                string typeBeingInstantiated = objectCreation.Type.ToString();
                if (!string.IsNullOrWhiteSpace(typeBeingInstantiated) && _blockConfig.MatchesClreplacedToBlock(typeBeingInstantiated))
                {
                    foreach (ClreplacedBlockConfig clreplacedConfig in _blockConfig.GetMatchingClreplacedConfig(typeBeingInstantiated)?.Where(cConfig => cConfig?.IsObjectCreationBlocked == true))
                    {
                        operationContext.ReportDiagnostic(objectCreation.CreateDiagnostic(blockCallsDiagnosticDescriptor,
                            string.IsNullOrWhiteSpace(clreplacedConfig.MessageToShowWhenBlocked)? new string[] { string.Format(DEFAULT_INSTANTIATION_BLOCK_MESSAGE_FORMAT, typeBeingInstantiated) } : new string[] { clreplacedConfig.MessageToShowWhenBlocked }
                            ));
                    }
                }
                #endregion
            }
        }

19 Source : AsyncAnalyzer.cs
with MIT License
from Azure

private static void ReportConfigureAwaitDiagnostic(OperationreplacedysisContext context, IOperation operation)
        {
            var location = operation.Syntax.GetLocation();
            var diagnostic = Diagnostic.Create(AZC0100, location);
            context.ReportDiagnostic(diagnostic);
        }

19 Source : TaskCompletionSourceAnalyzer.cs
with MIT License
from Azure

private static void ReportDiagnostics(OperationreplacedysisContext context, TextSpan textSpan) 
        {
            var location = context.Operation.Syntax.SyntaxTree.GetLocation(textSpan);
            var diagnostic = Diagnostic.Create(Descriptors.AZC0013, location);
            context.ReportDiagnostic(diagnostic);
        }

19 Source : UniTaskAnalyzer.cs
with MIT License
from Cysharp

private static void replacedyzeOperation(OperationreplacedysisContext context)
        {
            var token = context.Compilation.GetTypeByMetadataName(typeof(CancellationToken).FullName);
            if (token == null) return;

            if (context.Operation is IInvocationOperation invocation)
            {
                foreach (var arg in invocation.Arguments)
                {
                    if (arg.ArgumentKind == ArgumentKind.DefaultValue)
                    {
                        if (SymbolEqualityComparer.Default.Equals(arg.Parameter.Type, token))
                        {
                            var diagnostic = Diagnostic.Create(Rule, arg.Syntax.GetLocation());
                            context.ReportDiagnostic(diagnostic);
                        }
                    }
                }
            }
        }

19 Source : IMM005.cs
with MIT License
from dbolin

private static void CheckOperation(IOperation operation, OperationreplacedysisContext context, bool hasReportedThisCapture)
        {
            if(operation is IInstanceReferenceOperation op
                && op.ReferenceKind == InstanceReferenceKind.ContainingTypeInstance
                && (op.Parent is IArgumentOperation
                    || op.Parent is ISymbolInitializerOperation
                    || op.Parent is IreplacedignmentOperation))
            {
                var diagnostic = Diagnostic.Create(Rule, op.Syntax.GetLocation());
                context.ReportDiagnostic(diagnostic);
            }

            bool reportedThisCapture = false;

            if (!hasReportedThisCapture)
            {
                if (operation.Syntax is AnonymousFunctionExpressionSyntax syntax)
                {
                    var model = operation.SemanticModel;
                    var dataFlowreplacedysis = model.replacedyzeDataFlow(syntax);
                    var capturedVariables = dataFlowreplacedysis.Captured;
                    if (capturedVariables.Any(x => x is IParameterSymbol p && p.IsThis))
                    {
                        var diagnostic = Diagnostic.Create(Rule, operation.Syntax.GetLocation());
                        context.ReportDiagnostic(diagnostic);
                        reportedThisCapture = true;
                    }
                }
            }

            foreach (var child in operation.Children)
            {
                CheckOperation(child, context, reportedThisCapture || hasReportedThisCapture);
            }
        }

19 Source : PointerMemberAnalyzer.cs
with MIT License
from devlooped

void replacedyzeOperation(OperationreplacedysisContext context)
        {
            var invocation = (IInvocationOperation)context.Operation;

            // Get the matching symbol for the given generator attribute from the current compilation.
            var generator = context.Compilation.GetTypeByMetadataName(generatorAttribute.FullName);
            if (generator == null)
                return;

            if (invocation.TargetMethod.GetAttributes().Any(x =>
                SymbolEqualityComparer.Default.Equals(x.AttributeClreplaced, generator)))
            {
                var args = invocation.TargetMethod.TypeArguments
                    .OfType<INamedTypeSymbol>()
                    .Where(t => t.GetMembers()
                    .OfType<IMethodSymbol>()
                    .SelectMany(method => method.Parameters)
                    .Any(parameter => parameter.Type.Kind == SymbolKind.PointerType))
                    .ToArray();

                if (args.Length > 0)
                {
                    var diagnostic = Diagnostic.Create(
                        AvatarDiagnostics.PointerMember,
                        invocation.Syntax.GetLocation(),
                        string.Join(", ", args.Select(t => t.Name)));

                    context.ReportDiagnostic(diagnostic);
                }
            }
        }

19 Source : ValidateTypesAnalyzer.cs
with MIT License
from devlooped

void replacedyzeOperation(OperationreplacedysisContext context)
        {
            var invocation = (IInvocationOperation)context.Operation;

            // Get the matching symbol for the given generator attribute from the current compilation.
            var generator = context.Compilation.GetTypeByMetadataName(generatorAttribute.FullName);
            if (generator == null)
                return;

            if (invocation.TargetMethod.GetAttributes().Any(x => SymbolEqualityComparer.Default.Equals(x.AttributeClreplaced, generator)))
            {
                foreach (var enumType in invocation.TargetMethod.TypeArguments.Where(x => x.TypeKind == TypeKind.Enum))
                {
                    context.ReportDiagnostic(Diagnostic.Create(
                        AvatarDiagnostics.EnumType,
                        invocation.Syntax.GetLocation(),
                        enumType.Name));
                }

                var clreplacedes = invocation.TargetMethod.TypeArguments.Where(x => x.TypeKind == TypeKind.Clreplaced).ToArray();
                if (clreplacedes.Length > 1)
                {
                    context.ReportDiagnostic(Diagnostic.Create(
                        AvatarDiagnostics.DuplicateBaseType,
                        invocation.Syntax.GetLocation()));
                }
                if (clreplacedes.Length == 1)
                {
                    if (clreplacedes[0].IsSealed)
                    {
                        context.ReportDiagnostic(Diagnostic.Create(
                            AvatarDiagnostics.SealedBaseType,
                            invocation.Syntax.GetLocation(),
                            clreplacedes[0].Name));
                    }
                    else if (invocation.TargetMethod.TypeArguments.IndexOf(clreplacedes[0]) != 0)
                    {
                        context.ReportDiagnostic(Diagnostic.Create(
                            AvatarDiagnostics.BaseTypeNotFirst,
                            invocation.Syntax.GetLocation(),
                            clreplacedes[0].Name));
                    }
                }
            }
        }

19 Source : TransitionAnalyzer.cs
with MIT License
from innerspacetrainings

private static void replacedyzeChildTransition(OperationreplacedysisContext context)
        {
            var invocationOperation = (IInvocationOperation)context.Operation;
            if (!invocationOperation.Syntax.Parent.IsKind(SyntaxKind.Argument)) return;

            var atomicStateNodeDefinitionType = context.Compilation.GetTypeByMetadataName("Statecharts.NET.Model.IAtomicStatenodeDefinition");
            if (atomicStateNodeDefinitionType == null) return;

            var isAtomicStatenodeDefinition = invocationOperation.Type.AllInterfaces.Any(i => i.Equals(atomicStateNodeDefinitionType));
            if (!isAtomicStatenodeDefinition) return;

            var statenodeName = ((LiteralExpressionSyntax)invocationOperation.Syntax.DescendantNodes()
                .FirstOrDefault(node => node.IsKind(SyntaxKind.StringLiteralExpression)))?.Token.ValueText;

            var childTransitionExpressions = invocationOperation
                .Descendants()
                .OfType<IInvocationOperation>()
                .Where(invocation => invocation.TargetMethod.Name == "Child")
                .Select(operation => (InvocationExpressionSyntax)operation.Syntax);

            foreach (var expression in childTransitionExpressions)
            {
                var location = Location.Create(
                    expression.SyntaxTree,
                    TextSpan.FromBounds(
                        expression.ArgumentList.SpanStart - 5, // 5: "Child"
                        expression.ArgumentList.CloseParenToken.Span.End));

                context.ReportDiagnostic(Diagnostic.Create(NoChildTransitionOnAtomicStatenode, location, statenodeName));
            }
        }

19 Source : ContextExtensions.cs
with MIT License
from meziantou

public static void ReportDiagnostic(this OperationreplacedysisContext context, DiagnosticDescriptor descriptor, ImmutableDictionary<string, string?>? properties, IInvocationOperation operation, DiagnosticReportOptions options, params string[] messageArgs)
        {
            if (options.HasFlag(DiagnosticReportOptions.ReportOnMethodName) &&
                operation.Syntax.ChildNodes().FirstOrDefault() is MemberAccessExpressionSyntax memberAccessExpression)
            {
                context.ReportDiagnostic(Diagnostic.Create(descriptor, memberAccessExpression.Name.GetLocation(), properties, messageArgs));
                return;
            }

            context.ReportDiagnostic(descriptor, properties, operation, messageArgs);
        }

19 Source : ContextExtensions.cs
with MIT License
from meziantou

public static void ReportDiagnostic(this OperationreplacedysisContext context, DiagnosticDescriptor descriptor, ImmutableDictionary<string, string?>? properties, SyntaxToken token, params string[] messageArgs)
        {
            context.ReportDiagnostic(CreateDiagnostic(descriptor, token.GetLocation(), properties, messageArgs));
        }

19 Source : ContextExtensions.cs
with MIT License
from meziantou

public static void ReportDiagnostic(this OperationreplacedysisContext context, DiagnosticDescriptor descriptor, ImmutableDictionary<string, string?>? properties, IOperation operation, params string[] messageArgs)
        {
            context.ReportDiagnostic(CreateDiagnostic(descriptor, operation.Syntax.GetLocation(), properties, messageArgs));
        }

19 Source : ContextExtensions.cs
with MIT License
from meziantou

public static void ReportDiagnostic(this OperationreplacedysisContext context, DiagnosticDescriptor descriptor, ImmutableDictionary<string, string?>? properties, IInvocationOperation operation, DiagnosticReportOptions options, params string[] messageArgs)
        {
            if (options.HasFlag(DiagnosticReportOptions.ReportOnMethodName) &&
                operation.Syntax.ChildNodes().FirstOrDefault() is MemberAccessExpressionSyntax memberAccessExpression)
            {
                context.ReportDiagnostic(Diagnostic.Create(descriptor, memberAccessExpression.Name.GetLocation(), properties, messageArgs));
                return;
            }

            context.ReportDiagnostic(descriptor, properties, operation, messageArgs);
        }

19 Source : AnonymousDelegatesShouldNotBeUsedToUnsubscribeFromEventsAnalyzer.cs
with MIT License
from meziantou

private static void replacedyzeOperation(OperationreplacedysisContext context)
        {
            var operation = (IEventreplacedignmentOperation)context.Operation;
            if (operation.Adds)
                return;

            var handler = operation.HandlerValue;
            while (handler is IConversionOperation op)
            {
                handler = op.Operand;
            }

            if (handler != null && handler is IDelegateCreationOperation delegateCreation)
            {
                if (delegateCreation.Target is IAnonymousFunctionOperation)
                {
                    context.ReportDiagnostic(s_rule, operation);
                }
            }
        }

19 Source : ArgumentExceptionShouldSpecifyArgumentNameAnalyzer.cs
with MIT License
from meziantou

private static void replacedyze(OperationreplacedysisContext context)
        {
            var op = (IObjectCreationOperation)context.Operation;
            if (op == null)
                return;

            var type = op.Type;
            if (type == null)
                return;

            var exceptionType = context.Compilation.GetTypeByMetadataName("System.ArgumentException");
            if (exceptionType == null)
                return;

            if (!type.IsEqualTo(exceptionType) && !type.InheritsFrom(exceptionType))
                return;

            var parameterName = "paramName";
            if (type.IsEqualTo(context.Compilation.GetTypeByMetadataName("System.ComponentModel.InvalidEnumArgumentException")))
            {
                parameterName = "argumentName";
            }

            foreach (var argument in op.Arguments)
            {
                if (argument.Parameter == null || !string.Equals(argument.Parameter.Name, parameterName, StringComparison.Ordinal))
                    continue;

                if (argument.Value.ConstantValue.HasValue)
                {
                    if (argument.Value.ConstantValue.Value is string value)
                    {
                        var parameterNames = GetParameterNames(op);
                        if (parameterNames.Contains(value, StringComparer.Ordinal))
                        {
                            if (!(argument.Value is INameOfOperation))
                            {
                                var properties = ImmutableDictionary<string, string?>.Empty.Add(ArgumentNameKey, value);
                                context.ReportDiagnostic(s_nameofRule, properties, argument.Value);
                            }

                            return;
                        }

                        context.ReportDiagnostic(s_rule, argument, $"'{value}' is not a valid parameter name");
                        return;
                    }
                }

                // Cannot determine the value of the argument
                return;
            }

            context.ReportDiagnostic(Diagnostic.Create(s_rule, op.Syntax.GetLocation(), $"Use an overload of '{type.ToDisplayString()}' with the parameter name"));
        }

19 Source : ArgumentExceptionShouldSpecifyArgumentNameAnalyzer.cs
with MIT License
from meziantou

private static void replacedyze(OperationreplacedysisContext context)
        {
            var op = (IObjectCreationOperation)context.Operation;
            if (op == null)
                return;

            var type = op.Type;
            if (type == null)
                return;

            var exceptionType = context.Compilation.GetTypeByMetadataName("System.ArgumentException");
            if (exceptionType == null)
                return;

            if (!type.IsEqualTo(exceptionType) && !type.InheritsFrom(exceptionType))
                return;

            var parameterName = "paramName";
            if (type.IsEqualTo(context.Compilation.GetTypeByMetadataName("System.ComponentModel.InvalidEnumArgumentException")))
            {
                parameterName = "argumentName";
            }

            foreach (var argument in op.Arguments)
            {
                if (argument.Parameter == null || !string.Equals(argument.Parameter.Name, parameterName, StringComparison.Ordinal))
                    continue;

                if (argument.Value.ConstantValue.HasValue)
                {
                    if (argument.Value.ConstantValue.Value is string value)
                    {
                        var parameterNames = GetParameterNames(op);
                        if (parameterNames.Contains(value, StringComparer.Ordinal))
                        {
                            if (!(argument.Value is INameOfOperation))
                            {
                                var properties = ImmutableDictionary<string, string?>.Empty.Add(ArgumentNameKey, value);
                                context.ReportDiagnostic(s_nameofRule, properties, argument.Value);
                            }

                            return;
                        }

                        context.ReportDiagnostic(s_rule, argument, $"'{value}' is not a valid parameter name");
                        return;
                    }
                }

                // Cannot determine the value of the argument
                return;
            }

            context.ReportDiagnostic(Diagnostic.Create(s_rule, op.Syntax.GetLocation(), $"Use an overload of '{type.ToDisplayString()}' with the parameter name"));
        }

19 Source : AvoidComparisonWithBoolConstantAnalyzer.cs
with MIT License
from meziantou

private static void replacedyzeBinaryOperation(OperationreplacedysisContext context)
        {
            var binaryOperation = (IBinaryOperation)context.Operation;

            if (binaryOperation.OperatorKind != BinaryOperatorKind.Equals &&
                binaryOperation.OperatorKind != BinaryOperatorKind.NotEquals)
            {
                return;
            }

            // There must be 2 valid operands
            if (binaryOperation.LeftOperand?.Type is null || binaryOperation.RightOperand?.Type is null)
                return;

            // Operands must be explicit
            if (binaryOperation.LeftOperand.IsImplicit || binaryOperation.RightOperand.IsImplicit)
                return;

            // Neither operand can be dynamic
            if (binaryOperation.LeftOperand.Type.TypeKind == TypeKind.Dynamic || binaryOperation.RightOperand.Type.TypeKind == TypeKind.Dynamic)
                return;

            IOperation nodeToKeep;
            IOperation nodeToRemove;
            if (IsConstantBool(binaryOperation.LeftOperand))
            {
                nodeToKeep = binaryOperation.RightOperand;
                nodeToRemove = binaryOperation.LeftOperand;
            }
            else if (IsConstantBool(binaryOperation.RightOperand))
            {
                nodeToKeep = binaryOperation.LeftOperand;
                nodeToRemove = binaryOperation.RightOperand;
            }
            else
            {
                return;
            }

            // The fixer will need to prefix the remaining operand with '!' if the original comparison is "!= true" or "== false"
            var logicalNotOperatorNeeded = (bool)nodeToRemove.ConstantValue.Value! ?
                binaryOperation.OperatorKind == BinaryOperatorKind.NotEquals :
                binaryOperation.OperatorKind == BinaryOperatorKind.Equals;

            var properties = ImmutableDictionary.Create<string, string?>()
                .Add("NodeToKeepSpanStart", nodeToKeep.Syntax.Span.Start.ToString(CultureInfo.InvariantCulture))
                .Add("NodeToKeepSpanLength", nodeToKeep.Syntax.Span.Length.ToString(CultureInfo.InvariantCulture))
                .Add("LogicalNotOperatorNeeded", logicalNotOperatorNeeded.ToString());

            var operatorTokenLocation = ((BinaryExpressionSyntax)binaryOperation.Syntax).OperatorToken.GetLocation();
            var diagnostic = Diagnostic.Create(s_rule, operatorTokenLocation, properties);
            context.ReportDiagnostic(diagnostic);
        }

19 Source : AvoidLockingOnPubliclyAccessibleInstanceAnalyzer.cs
with MIT License
from meziantou

private static void replacedyzeOperation(OperationreplacedysisContext context)
        {
            var operation = (ILockOperation)context.Operation;
            if (operation.LockedValue is ITypeOfOperation)
            {
                context.ReportDiagnostic(s_rule, operation.LockedValue);
            }
            else if (operation.LockedValue is IInstanceReferenceOperation)
            {
                context.ReportDiagnostic(s_rule, operation.LockedValue);
            }
            else if (operation.LockedValue is IFieldReferenceOperation fieldReferenceOperation && fieldReferenceOperation.Field.IsVisibleOutsideOfreplacedembly())
            {
                context.ReportDiagnostic(s_rule, operation.LockedValue);
            }
            else if (operation.LockedValue is ILocalReferenceOperation localReference && localReference.Local.Type.IsEqualTo(context.Compilation.GetTypeByMetadataName("System.Type")))
            {
                context.ReportDiagnostic(s_rule, operation.LockedValue);
            }
        }

19 Source : AwaitTaskBeforeDisposingResourcesAnalyzer.cs
with MIT License
from meziantou

private void replacedyzeReturn(OperationreplacedysisContext context)
        {
            var op = (IReturnOperation)context.Operation;
            var returnedValue = op.ReturnedValue;
            if (returnedValue is null)
                return;

            var taskSymbol = context.Compilation.GetTypeByMetadataName("System.Threading.Tasks.Task");
            var taskOfTSymbol = context.Compilation.GetTypeByMetadataName("System.Threading.Tasks.Task`1");
            var valueTaskSymbol = context.Compilation.GetTypeByMetadataName("System.Threading.Tasks.ValueTask");
            var valueTaskOfTSymbol = context.Compilation.GetTypeByMetadataName("System.Threading.Tasks.ValueTask`1");

            if (IsTaskLike(returnedValue.Type))
            {
                // Must be in a using block
                if (!IsInUsingOperation(op))
                    return;

                if (!NeedAwait(returnedValue))
                    return;

                context.ReportDiagnostic(s_rule, op);
            }

            static bool IsInUsingOperation(IOperation operation)
            {
                foreach (var parent in operation.Ancestors())
                {
                    if (parent is IAnonymousFunctionOperation or ILocalFunctionOperation)
                        return false;

                    if (parent is IUsingOperation)
                        return true;
                }

19 Source : DoNotNaNInComparisonsAnalyzer.cs
with MIT License
from meziantou

private void replacedyzeOperand(OperationreplacedysisContext context, IOperation operation)
            {
                while (operation is IConversionOperation conversion)
                {
                    operation = conversion.Operand;
                }

                if (operation is IMemberReferenceOperation memberReference)
                {
                    if (memberReference.Member.IsEqualTo(DoubleNaN))
                    {
                        context.ReportDiagnostic(s_rule, operation, "System.Double");
                    }
                    else if (memberReference.Member.IsEqualTo(SingleNaN))
                    {
                        context.ReportDiagnostic(s_rule, operation, "System.Single");
                    }
                    else if (memberReference.Member.IsEqualTo(HalfNaN))
                    {
                        context.ReportDiagnostic(s_rule, operation, "System.Half");
                    }
                }
            }

19 Source : DoNotRaiseApplicationExceptionAnalyzer.cs
with MIT License
from meziantou

private static void replacedyze(OperationreplacedysisContext context, INamedTypeSymbol reservedExceptionType)
        {
            var operation = (IThrowOperation)context.Operation;
            if (operation == null || operation.Exception == null)
                return;

            var exceptionType = operation.Exception.GetActualType();
            if (exceptionType.IsEqualTo(reservedExceptionType))
            {
                context.ReportDiagnostic(s_rule, operation);
            }
        }

19 Source : DoNotRaiseReservedExceptionTypeAnalyzer.cs
with MIT License
from meziantou

private static void replacedyze(OperationreplacedysisContext context, IEnumerable<INamedTypeSymbol> reservedExceptionTypes)
        {
            var operation = (IThrowOperation)context.Operation;
            if (operation == null || operation.Exception == null)
                return;

            var exceptionType = operation.Exception.GetActualType();
            if (exceptionType == null)
                return;

            if (reservedExceptionTypes.Any(type => exceptionType.IsEqualTo(type) || exceptionType.InheritsFrom(type)))
            {
                context.ReportDiagnostic(s_rule, operation, exceptionType.ToDisplayString());
            }
        }

19 Source : DoNotRemoveOriginalExceptionFromThrowStatementAnalyzer.cs
with MIT License
from meziantou

private static void replacedyze(OperationreplacedysisContext context)
        {
            var operation = (IThrowOperation)context.Operation;
            if (operation.Exception == null)
                return;

            if (operation.Exception is not ILocalReferenceOperation localReferenceOperation)
                return;

            var catchOperation = operation.Ancestors().OfType<ICatchClauseOperation>().FirstOrDefault();
            if (catchOperation == null)
                return;

            if (catchOperation.Locals.Contains(localReferenceOperation.Local))
            {
                context.ReportDiagnostic(s_rule, operation);
            }
        }

19 Source : DoNotUseBlockingCallInAsyncContextAnalyzer.cs
with MIT License
from meziantou

private void ReportDiagnosticIfNeeded(OperationreplacedysisContext context, IOperation operation, string message)
            {
                if (!CanBeAsync(operation))
                    return;

                if (IsAsyncContext(operation))
                {
                    context.ReportDiagnostic(s_rule, operation, message);
                }
                else if (CanChangeParentMethodSignature(operation))
                {
                    context.ReportDiagnostic(s_rule2, operation, message + " and make method async");
                }
            }

19 Source : DoNotUseDefaultEqualsOnValueTypeAnalyzer.cs
with MIT License
from meziantou

public void replacedyzeInvocationOperation(OperationreplacedysisContext context)
            {
                var operation = (IInvocationOperation)context.Operation;

                if (operation.TargetMethod.Name == nameof(ValueType.GetHashCode))
                {
                    var actualType = operation.Children.FirstOrDefault()?.GetActualType();
                    if (actualType == null)
                        return;

                    if (IsStruct(actualType) && HasDefaultEqualsOrHashCodeImplementations(actualType))
                    {
                        context.ReportDiagnostic(s_rule, operation);
                    }
                }
                else if (operation.TargetMethod.Name == nameof(ValueType.Equals))
                {
                    var actualType = operation.Children.FirstOrDefault()?.GetActualType();
                    if (actualType == null)
                        return;

                    if (IsStruct(actualType) && HasDefaultEqualsOrHashCodeImplementations(actualType))
                    {
                        context.ReportDiagnostic(s_rule, operation);
                    }
                }
                else if (IsImmutableCreateMethod(operation.TargetMethod))
                {
                    var type = operation.TargetMethod.TypeArguments[0];
                    if (IsStruct(type) && HasDefaultEqualsOrHashCodeImplementations(type))
                    {
                        if (operation.TargetMethod.ContainingType.IsEqualTo(ImmutableSortedDictionarySymbol))
                        {
                            if (operation.TargetMethod.Parameters.Any(arg => arg.Type.IsEqualTo(IComparerSymbol?.Construct(type))))
                                return;
                        }
                        else
                        {
                            if (operation.TargetMethod.Parameters.Any(arg => arg.Type.IsEqualTo(IEqualityComparerSymbol?.Construct(type))))
                                return;
                        }

                        context.ReportDiagnostic(s_rule2, operation);
                    }
                }

                bool IsImmutableCreateMethod(IMethodSymbol methodSymbol)
                {
                    var names = new[]
                    {
                        "Create",
                        "CreateBuilder",
                        "CreateRange",
                    };

                    var builderTypes = new[]
                    {
                        ImmutableDictionarySymbol,
                        ImmutableHashSetSymbol,
                        ImmutableSortedDictionarySymbol,
                    };

                    return methodSymbol.Arity >= 1 && names.Contains(methodSymbol.Name, StringComparer.Ordinal) && builderTypes.Any(type => type.IsEqualTo(methodSymbol.ContainingType.OriginalDefinition));
                }
            }

19 Source : DoNotUseDefaultEqualsOnValueTypeAnalyzer.cs
with MIT License
from meziantou

public void replacedyzeFieldReferenceOperation(OperationreplacedysisContext context)
            {
                var operation = (IFieldReferenceOperation)context.Operation;
                if (operation.Field.Name == "Empty")
                {
                    var type = operation.Field.ContainingType;
                    if (type?.OriginalDefinition == null)
                        return;

                    if (HashSetSymbols.Any(t => type.OriginalDefinition.IsEqualTo(t)))
                    {
                        if (IsStruct(type.TypeArguments[0]) && HasDefaultEqualsOrHashCodeImplementations(type.TypeArguments[0]))
                        {
                            context.ReportDiagnostic(s_rule2, operation);
                        }
                    }
                }
            }

19 Source : DoNotUseDefaultEqualsOnValueTypeAnalyzer.cs
with MIT License
from meziantou

public void replacedyzeObjectCreationOperation(OperationreplacedysisContext context)
            {
                var operation = (IObjectCreationOperation)context.Operation;
                var type = operation.Type as INamedTypeSymbol;
                if (type?.OriginalDefinition == null)
                    return;

                if (operation.Constructor == null)
                    return;

                if (HashSetSymbols.Any(t => type.OriginalDefinition.IsEqualTo(t)))
                {
                    if (operation.Constructor.Parameters.Any(arg => arg.Type.IsEqualTo(IEqualityComparerSymbol?.Construct(type.TypeArguments[0]))))
                        return;

                    if (IsStruct(type.TypeArguments[0]) && HasDefaultEqualsOrHashCodeImplementations(type.TypeArguments[0]))
                    {
                        context.ReportDiagnostic(s_rule2, operation);
                    }
                }
            }

19 Source : DoNotUseEqualityComparerDefaultOfStringAnalyzer.cs
with MIT License
from meziantou

private static void replacedyze(OperationreplacedysisContext context)
        {
            var operation = (IPropertyReferenceOperation)context.Operation;
            if (!string.Equals(operation.Member.Name, nameof(EqualityComparer<string>.Default), StringComparison.Ordinal))
                return;

            var equalityComparerSymbol = context.Compilation.GetTypeByMetadataName("System.Collections.Generic.EqualityComparer`1");
            if (equalityComparerSymbol == null)
                return;

            var equalityComparerStringSymbol = equalityComparerSymbol.Construct(context.Compilation.GetSpecialType(SpecialType.System_String));
            if (operation.Member.ContainingType.IsEqualTo(equalityComparerStringSymbol))
            {
                if (operation.IsInNameofOperation())
                    return;

                context.ReportDiagnostic(s_rule, operation, operation.Member.Name);
            }
        }

19 Source : DoNotUseEqualityOperatorsForSpanOfCharAnalyzer.cs
with MIT License
from meziantou

public void replacedyzeBinaryOperator(OperationreplacedysisContext context)
            {
                var operation = (IBinaryOperation)context.Operation;
                if (operation.OperatorKind == BinaryOperatorKind.Equals ||
                    operation.OperatorKind == BinaryOperatorKind.NotEquals)
                {
                    if (!IsSpanOfString(operation.LeftOperand.Type) || !IsSpanOfString(operation.RightOperand.Type))
                        return;

                    // EnreplacedyFramework Core doesn't support StringComparison and evaluates everything client side...
                    // https://github.com/aspnet/EnreplacedyFrameworkCore/issues/1222
                    if (operation.IsInExpressionArgument())
                        return;

                    context.ReportDiagnostic(s_rule, operation, $"{operation.OperatorKind} operator");
                }
            }

19 Source : DoNotUseImplicitCultureSensitiveToStringAnalyzer.cs
with MIT License
from meziantou

private static void replacedyzeBinaryOperation(OperationreplacedysisContext context)
        {
            var operation = (IBinaryOperation)context.Operation;
            if (operation.OperatorKind != BinaryOperatorKind.Add)
                return;

            if (!operation.Type.IsString())
                return;

            if (operation.ConstantValue.HasValue)
                return;

            if (!IsValidOperand(operation.LeftOperand))
            {
                context.ReportDiagnostic(s_stringConcatRule, operation.LeftOperand);
            }

            if (!IsValidOperand(operation.RightOperand))
            {
                context.ReportDiagnostic(s_stringConcatRule, operation.RightOperand);
            }
        }

19 Source : DoNotUseImplicitCultureSensitiveToStringAnalyzer.cs
with MIT License
from meziantou

private static void replacedyzeInterpolatedString(OperationreplacedysisContext context)
        {
            // Check if parent is InterpolatedString.Invariant($"") or conversion to string?
            var operation = (IInterpolatedStringOperation)context.Operation;

            if (operation.ConstantValue.HasValue)
                return;

            var parent = operation.Parent;
            if (parent is IConversionOperation conversionOperation)
            {
                // `FormattableString _ = $""` is valid whereas `string _ = $""` may not be
                if (conversionOperation.Type.IsEqualTo(context.Compilation.GetTypeByMetadataName("System.FormattableString")))
                    return;
            }

            foreach (var part in operation.Parts.OfType<IInterpolationOperation>())
            {
                var expression = part.Expression;
                var type = expression.Type;
                if (expression == null || type == null)
                    continue;

                if (IsFormattableType(context.Compilation, type) && !IsConstantPositiveNumber(expression))
                {
                    context.ReportDiagnostic(s_stringInterpolationRule, part);
                }
            }
        }

19 Source : DoNotUseServerCertificateValidationCallbackAnalyzer.cs
with MIT License
from meziantou

private static void replacedyze(OperationreplacedysisContext context, List<ISymbol> eventSymbols)
        {
            var operation = (IPropertyReferenceOperation)context.Operation;
            if (eventSymbols.Contains(operation.Property))
            {
                context.ReportDiagnostic(s_rule, operation);
            }
        }

19 Source : DoNotUseZeroToInitializeAnEnumValue.cs
with MIT License
from meziantou

private static void ValidateConversionOperation(OperationreplacedysisContext context, IConversionOperation operation)
        {
            if (!operation.IsImplicit)
                return;

            if (!operation.Type.IsEnumeration())
                return;

            // Skip "default" keyword
            if (operation.Operand is ILiteralOperation && operation.Operand.ConstantValue.HasValue && operation.Operand.ConstantValue.Value is int i && i == 0)
            {
                context.ReportDiagnostic(s_rule, operation, operation.Type.ToDisplayString(SymbolDisplayFormat.CSharpShortErrorMessageFormat));
            }
        }

19 Source : DontUseDangerousThreadingMethodsAnalyzer.cs
with MIT License
from meziantou

private static void replacedyze(OperationreplacedysisContext context)
        {
            var op = (IInvocationOperation)context.Operation;
            if (string.Equals(op.TargetMethod.Name, "Abort", StringComparison.Ordinal) ||
                string.Equals(op.TargetMethod.Name, "Suspend", StringComparison.Ordinal) ||
                string.Equals(op.TargetMethod.Name, "Resume", StringComparison.Ordinal))
            {
                var types = context.Compilation.GetTypesByMetadataName("System.Threading.Thread");
                foreach (var type in types)
                {
                    if (op.TargetMethod.ContainingType.IsEqualTo(type))
                    {
                        context.ReportDiagnostic(s_rule, op);
                    }
                }
            }
        }

19 Source : EmbedCaughtExceptionAsInnerExceptionAnalyzer.cs
with MIT License
from meziantou

private static void replacedyzeThrow(OperationreplacedysisContext context)
        {
            var operation = (IThrowOperation)context.Operation;
            if (operation.Exception == null)
                return;

            var compilation = context.Compilation;
            var exceptionSymbol = compilation.GetTypeByMetadataName("System.Exception");
            if (exceptionSymbol == null)
                return;

            var catchOperation = operation.Ancestors().OfType<ICatchClauseOperation>().FirstOrDefault();
            if (catchOperation == null)
                return;

            if (operation.Exception is IObjectCreationOperation objectCreationOperation)
            {
                if (objectCreationOperation.Constructor == null)
                    return;

                var argument = objectCreationOperation.Arguments.FirstOrDefault(arg => IsPotentialParameter(arg?.Parameter, exceptionSymbol));
                if (argument == null)
                {
                    if (objectCreationOperation.Constructor.HasOverloadWithAdditionalParameterOfType(context.Compilation, exceptionSymbol))
                    {
                        context.ReportDiagnostic(s_rule, objectCreationOperation);
                    }
                }
            }
        }

19 Source : EventsShouldHaveProperArgumentsAnalyzer.cs
with MIT License
from meziantou

private static void replacedyzeRaiseEvent(OperationreplacedysisContext context)
        {
            var operation = (IInvocationOperation)context.Operation;
            var targetMethod = operation.TargetMethod;

            if (targetMethod.Name != nameof(EventHandler.Invoke))
                return;

            if (targetMethod.Parameters.Length != 2)
                return;

            if (!targetMethod.Parameters[0].Type.IsObject())
                return;

            var eventArgsSymbol = context.Compilation.GetTypeByMetadataName("System.EventArgs");
            if (!targetMethod.Parameters[1].Type.IsOrInheritFrom(eventArgsSymbol))
                return;

            var multicastDelegateSymbol = context.Compilation.GetTypeByMetadataName("System.MulticastDelegate");
            if (!targetMethod.ContainingType.IsOrInheritFrom(multicastDelegateSymbol))
                return;

            var instance = operation.Instance;
            if (instance == null)
                return;

            var ev = FindEvent(instance);
            if (ev == null)
                return;

            // Argument validation
            var senderArgument = operation.Arguments[0];
            if (ev.IsStatic)
            {
                if (!IsNull(senderArgument))
                {
                    context.ReportDiagnostic(s_senderStaticRule, senderArgument);
                }
            }
            else
            {
                if (!IsThis(senderArgument))
                {
                    context.ReportDiagnostic(s_senderInstanceRule, senderArgument);
                }
            }

            var eventArgsArgument = operation.Arguments[1];
            if (IsNull(eventArgsArgument))
            {
                context.ReportDiagnostic(s_eventArgsRule, eventArgsArgument);
            }
        }

19 Source : LocalVariablesShouldNotHideSymbolsAnalyzer.cs
with MIT License
from meziantou

private void replacedyzeVariableDeclaration(OperationreplacedysisContext context)
        {
            var operation = (IVariableDeclaratorOperation)context.Operation;
            var semanticModel = operation.SemanticModel!;
            var localSymbol = operation.Symbol;
            if (localSymbol.IsImplicitlyDeclared || !localSymbol.CanBeReferencedByName)
                return;

            var containingType = localSymbol.ContainingType;
            if (containingType == null)
                return;

            foreach (var member in GetSymbols(containingType, localSymbol.Name))
            {
                if (!semanticModel.IsAccessible(operation.Syntax.SpanStart, member))
                    continue;

                if (member is IFieldSymbol)
                {
                    ReportDiagnostic("field");
                    return;
                }

                if (member is IPropertySymbol)
                {
                    ReportDiagnostic("property");
                    return;
                }
            }

            void ReportDiagnostic(string type)
            {
                if (operation.Syntax is VariableDeclaratorSyntax declarator)
                {
                    context.ReportDiagnostic(s_rule, declarator.Identifier, localSymbol.Name, type);
                }
                else
                {
                    context.ReportDiagnostic(s_rule, operation, localSymbol.Name, type);
                }
            }
        }

19 Source : OptimizeLinqUsageAnalyzer.cs
with MIT License
from meziantou

private static void WhereShouldBeBeforeOrderBy(OperationreplacedysisContext context, IInvocationOperation operation, List<INamedTypeSymbol> enumerableSymbols)
        {
            if (string.Equals(operation.TargetMethod.Name, nameof(Enumerable.OrderBy), StringComparison.Ordinal) ||
                string.Equals(operation.TargetMethod.Name, nameof(Enumerable.OrderByDescending), StringComparison.Ordinal))
            {
                var parent = GetParentLinqOperation(operation);
                if (parent != null && enumerableSymbols.Contains(parent.TargetMethod.ContainingType))
                {
                    if (string.Equals(parent.TargetMethod.Name, nameof(Enumerable.Where), StringComparison.Ordinal))
                    {
                        var properties = CreateProperties(OptimizeLinqUsageData.CombineWhereWithNextMethod)
                           .Add("FirstOperationStart", operation.Syntax.Span.Start.ToString(CultureInfo.InvariantCulture))
                           .Add("FirstOperationLength", operation.Syntax.Span.Length.ToString(CultureInfo.InvariantCulture))
                           .Add("LastOperationStart", parent.Syntax.Span.Start.ToString(CultureInfo.InvariantCulture))
                           .Add("LastOperationLength", parent.Syntax.Span.Length.ToString(CultureInfo.InvariantCulture))
                           .Add("MethodName", parent.TargetMethod.Name);

                        context.ReportDiagnostic(s_optimizeWhereAndOrderByRule, properties, parent, operation.TargetMethod.Name);
                    }
                }
            }
        }

19 Source : OptimizeLinqUsageAnalyzer.cs
with MIT License
from meziantou

private static void UseCountPropertyInsteadOfMethod(OperationreplacedysisContext context, IInvocationOperation operation)
        {
            if (operation.Arguments.Length != 1)
                return;

            if (string.Equals(operation.TargetMethod.Name, nameof(Enumerable.Count), StringComparison.Ordinal))
            {
                var collectionOfTSymbol = context.Compilation.GetTypeByMetadataName("System.Collections.Generic.ICollection`1");
                var readOnlyCollectionOfTSymbol = context.Compilation.GetTypeByMetadataName("System.Collections.Generic.IReadOnlyCollection`1");
                if (collectionOfTSymbol == null && readOnlyCollectionOfTSymbol == null)
                    return;

                var actualType = operation.Arguments[0].Value.GetActualType();
                if (actualType == null)
                    return;

                if (actualType.TypeKind == TypeKind.Array)
                {
                    var properties = CreateProperties(OptimizeLinqUsageData.UseLengthProperty);
                    context.ReportDiagnostic(s_listMethodsRule, properties, operation, DiagnosticReportOptions.ReportOnMethodName, "Length", operation.TargetMethod.Name);
                    return;
                }

                if (actualType.AllInterfaces.Any(i => i.OriginalDefinition.IsEqualTo(collectionOfTSymbol) || i.OriginalDefinition.IsEqualTo(readOnlyCollectionOfTSymbol)))
                {
                    // Ensure the Count property is not an explicit implementation
                    var count = actualType.GetMembers("Count").OfType<IPropertySymbol>().FirstOrDefault(m => m.ExplicitInterfaceImplementations.Length == 0);
                    if (count != null)
                    {
                        var properties = CreateProperties(OptimizeLinqUsageData.UseCountProperty);
                        context.ReportDiagnostic(s_listMethodsRule, properties, operation, DiagnosticReportOptions.ReportOnMethodName, "Count", operation.TargetMethod.Name);
                        return;
                    }
                }
            }
            else if (string.Equals(operation.TargetMethod.Name, nameof(Enumerable.LongCount), StringComparison.Ordinal))
            {
                var actualType = operation.Arguments[0].Value.GetActualType();
                if (actualType != null && actualType.TypeKind == TypeKind.Array)
                {
                    var properties = CreateProperties(OptimizeLinqUsageData.UseLongLengthProperty);
                    context.ReportDiagnostic(s_listMethodsRule, properties, operation, DiagnosticReportOptions.ReportOnMethodName, "LongLength", operation.TargetMethod.Name);
                }
            }
        }

19 Source : OptimizeLinqUsageAnalyzer.cs
with MIT License
from meziantou

private static void UseFindInsteadOfFirstOrDefault(OperationreplacedysisContext context, IInvocationOperation operation)
        {
            if (!string.Equals(operation.TargetMethod.Name, nameof(Enumerable.FirstOrDefault), StringComparison.Ordinal))
                return;

            if (operation.Arguments.Length != 2)
                return;

            var listSymbol = context.Compilation.GetTypeByMetadataName("System.Collections.Generic.List`1");
            var firstArgumentType = operation.Arguments[0].Value.GetActualType();
            if (firstArgumentType == null)
                return;

            if (firstArgumentType.OriginalDefinition.IsEqualTo(listSymbol))
            {
                var properties = CreateProperties(OptimizeLinqUsageData.UseFindMethod);
                context.ReportDiagnostic(s_listMethodsRule, properties, operation, DiagnosticReportOptions.ReportOnMethodName, "Find()", operation.TargetMethod.Name);
            }
        }

19 Source : OptimizeLinqUsageAnalyzer.cs
with MIT License
from meziantou

private static void UseIndexerInsteadOfElementAt(OperationreplacedysisContext context, IInvocationOperation operation)
        {
            ImmutableDictionary<string, string?>? properties = null;

            var argCount = -1;
            if (string.Equals(operation.TargetMethod.Name, nameof(Enumerable.ElementAt), StringComparison.Ordinal))
            {
                properties = CreateProperties(OptimizeLinqUsageData.UseIndexer);
                argCount = 2;
            }
            else if (string.Equals(operation.TargetMethod.Name, nameof(Enumerable.First), StringComparison.Ordinal))
            {
                properties = CreateProperties(OptimizeLinqUsageData.UseIndexerFirst);
                argCount = 1;
            }
            else if (string.Equals(operation.TargetMethod.Name, nameof(Enumerable.Last), StringComparison.Ordinal))
            {
                properties = CreateProperties(OptimizeLinqUsageData.UseIndexerLast);
                argCount = 1;
            }

            if (argCount < 0)
                return;

            if (operation.Arguments.Length != argCount)
                return;

            var listSymbol = context.Compilation.GetTypeByMetadataName("System.Collections.Generic.IList`1");
            var readOnlyListSymbol = context.Compilation.GetTypeByMetadataName("System.Collections.Generic.IReadOnlyList`1");
            if (listSymbol == null && readOnlyListSymbol == null)
                return;

            var actualType = operation.Arguments[0].Value.GetActualType();
            if (actualType == null)
                return;

            if (actualType.AllInterfaces.Any(i => i.OriginalDefinition.IsEqualTo(listSymbol) || i.OriginalDefinition.IsEqualTo(readOnlyListSymbol)))
            {
                context.ReportDiagnostic(s_indexerInsteadOfElementAtRule, properties, operation, DiagnosticReportOptions.ReportOnMethodName, "[]", operation.TargetMethod.Name);
            }
        }

19 Source : OptimizeLinqUsageAnalyzer.cs
with MIT License
from meziantou

private static void UseCastInsteadOfSelect(OperationreplacedysisContext context, IInvocationOperation operation)
        {
            var semanticModel = operation.SemanticModel!;

            if (!string.Equals(operation.TargetMethod.Name, nameof(Enumerable.Select), StringComparison.Ordinal))
                return;

            // A valid 'Select' operation always has 2 arguments, regardless of whether the underlying code syntax is
            // that of a call to an extension method:   source.Select(selector);
            // or to a static method:                   Enumerable.Select(source, selector);
            //  Operation's first argument  -> 'source'
            //  Operation's second argument -> 'selector'
            if (operation.Arguments.Length != 2)
                return;

            var selectorArg = operation.Arguments[1];

            var returnOp = selectorArg.Descendants().OfType<IReturnOperation>().FirstOrDefault();
            if (returnOp is null)
                return;

            // If what's returned is not a cast value or the cast is done by 'as' operator
            if (returnOp.ReturnedValue is not IConversionOperation castOp || castOp.IsTryCast || castOp.Type == null)
                return;

            // If the cast is not applied directly to the source element (one of the selector's arguments)
            if (castOp.Operand.Kind != OperationKind.ParameterReference)
                return;

            // Ensure the code is valid after replacement. The semantic may be different if you use Cast<T>() instead of Select(x => (T)x).
            // Current conversion: (Type)value
            // Cast<T>() conversion: (Type)(object)value
            if (!CanReplaceByCast(castOp))
                return;

            // Determine if we're casting to a nullable type.
            // TODO: Revisit this once https://github.com/dotnet/roslyn/pull/42403 is merged.
            var selectMethodSymbol = semanticModel.GetSymbolInfo(operation.Syntax).Symbol as IMethodSymbol;
            var nullableFlowState = selectMethodSymbol?.TypeArgumentNullableAnnotations[1] == NullableAnnotation.Annotated ?
                NullableFlowState.MaybeNull :
                NullableFlowState.None;

            // Get the cast type's minimally qualified name, in the current context
            var castType = castOp.Type.ToMinimalDisplayString(semanticModel, nullableFlowState, operation.Syntax.SpanStart);
            var properties = CreateProperties(OptimizeLinqUsageData.UseCastInsteadOfSelect)
               .Add("CastType", castType);

            context.ReportDiagnostic(s_useCastInsteadOfSelect, properties, operation, DiagnosticReportOptions.ReportOnMethodName, castType);

            static bool CanReplaceByCast(IConversionOperation op)
            {
                if (op.Conversion.IsUserDefined || op.Conversion.IsNumeric)
                    return false;

                // Handle enums: source.Select<MyEnum, byte>(item => (byte)item);
                // Using Cast<T> is only possible when the enum underlying type is the same as the conversion type
                var operandActualType = op.Operand.GetActualType();
                var enumerationType = operandActualType.GetEnumerationType();
                if (enumerationType != null)
                {
                    if (!enumerationType.IsEqualTo(op.Type))
                        return false;
                }

                return true;
            }
        }

19 Source : OptimizeStringBuilderUsageAnalyzer.cs
with MIT License
from meziantou

private static bool IsOptimizable(OperationreplacedysisContext context, IOperation operation, string methodName, IArgumentOperation argument)
        {
            if (argument.ConstantValue.HasValue)
                return false;

            var value = argument.Value;
            if (value is IInterpolatedStringOperation)
            {
                if (TryGetConstStringValue(value, out var constValue))
                {
                    if (constValue.Length == 0)
                    {
                        if (string.Equals(methodName, nameof(StringBuilder.AppendLine), System.StringComparison.Ordinal))
                        {
                            var properties = CreateProperties(OptimizeStringBuilderUsageData.RemoveArgument);
                            context.ReportDiagnostic(s_rule, properties, operation, "Remove the useless argument");
                        }
                        else
                        {
                            var properties = CreateProperties(OptimizeStringBuilderUsageData.RemoveMethod);
                            context.ReportDiagnostic(s_rule, properties, operation, "Remove this no-op call");
                        }

                        return true;
                    }
                    else if (constValue.Length == 1)
                    {
                        var properties = CreateProperties(OptimizeStringBuilderUsageData.ReplaceWithChar)
                            .Add("ConstantValue", constValue);
                        context.ReportDiagnostic(s_rule, properties, argument, $"Replace {methodName}(string) with {methodName}(char)");
                        return true;
                    }
                    return false;
                }
                else
                {
                    if (string.Equals(methodName, nameof(StringBuilder.Insert), System.StringComparison.Ordinal))
                        return false;

                    var properties = CreateProperties(OptimizeStringBuilderUsageData.SplitStringInterpolation);
                    context.ReportDiagnostic(s_rule, properties, operation, $"Replace string interpolation with multiple {methodName} calls");
                    return true;
                }
            }
            else if (TryGetConstStringValue(value, out var constValue))
            {
                if (constValue.Length == 0)
                {
                    if (string.Equals(methodName, nameof(StringBuilder.AppendLine), System.StringComparison.Ordinal))
                    {
                        var properties = CreateProperties(OptimizeStringBuilderUsageData.RemoveArgument);
                        context.ReportDiagnostic(s_rule, properties, operation, "Remove the useless argument");
                    }
                    else
                    {
                        var properties = CreateProperties(OptimizeStringBuilderUsageData.RemoveMethod);
                        context.ReportDiagnostic(s_rule, properties, operation, "Remove this no-op call");
                    }

                    return true;
                }
                else if (constValue.Length == 1)
                {
                    if (string.Equals(methodName, nameof(StringBuilder.Append), System.StringComparison.Ordinal) || string.Equals(methodName, nameof(StringBuilder.Insert), System.StringComparison.Ordinal))
                    {
                        var properties = CreateProperties(OptimizeStringBuilderUsageData.ReplaceWithChar)
                            .Add("ConstantValue", constValue);
                        context.ReportDiagnostic(s_rule, properties, argument, $"Replace {methodName}(string) with {methodName}(char)");
                        return true;
                    }
                }

                return false;
            }
            else if (value is IBinaryOperation binaryOperation)
            {
                if (string.Equals(methodName, nameof(StringBuilder.Append), System.StringComparison.Ordinal) || string.Equals(methodName, nameof(StringBuilder.AppendLine), System.StringComparison.Ordinal))
                {
                    if (binaryOperation.OperatorKind == BinaryOperatorKind.Add && value.Type.IsString())
                    {
                        if (IsConstString(binaryOperation.LeftOperand) && IsConstString(binaryOperation.RightOperand))
                            return false;

                        var properties = CreateProperties(OptimizeStringBuilderUsageData.SplitAddOperator);
                        context.ReportDiagnostic(s_rule, properties, operation, $"Replace the string concatenation by multiple {methodName} calls");
                        return true;
                    }
                }
            }
            else if (value is IInvocationOperation invocationOperation)
            {
                var targetMethod = invocationOperation.TargetMethod;
                if (string.Equals(targetMethod.Name, "ToString", System.StringComparison.Ordinal))
                {
                    if (targetMethod.Parameters.Length == 0 && targetMethod.ReturnType.IsString())
                    {
                        if (invocationOperation.Instance?.Type?.IsValueType == true && !IsPrimitive(invocationOperation.Instance.Type))
                            return false;

                        var properties = CreateProperties(OptimizeStringBuilderUsageData.RemoveToString);
                        if (string.Equals(methodName, nameof(StringBuilder.AppendLine), System.StringComparison.Ordinal))
                        {
                            context.ReportDiagnostic(s_rule, properties, operation, "Replace with Append().AppendLine()");
                        }
                        else
                        {
                            context.ReportDiagnostic(s_rule, properties, operation, "Remove the ToString call");
                        }

                        return true;
                    }

                    if (targetMethod.Parameters.Length == 2 &&
                        targetMethod.ReturnType.IsString() &&
                        targetMethod.Parameters[0].Type.IsString() &&
                        invocationOperation.Arguments[0].Value.ConstantValue.HasValue && // Only replace for constant formats
                        targetMethod.Parameters[1].Type.IsEqualTo(context.Compilation.GetTypeByMetadataName("System.IFormatProvider")))
                    {
                        if (string.Equals(methodName, nameof(StringBuilder.AppendLine), System.StringComparison.Ordinal))
                        {
                            var properties = CreateProperties(OptimizeStringBuilderUsageData.ReplaceWithAppendFormat);
                            context.ReportDiagnostic(s_rule, properties, operation, "Use AppendFormat().AppendLine()");
                            return true;
                        }
                        else
                        {
                            var properties = CreateProperties(OptimizeStringBuilderUsageData.ReplaceWithAppendFormat);
                            context.ReportDiagnostic(s_rule, properties, operation, "Use AppendFormat");
                            return true;
                        }
                    }
                }
                else if (string.Equals(targetMethod.Name, nameof(string.Substring), System.StringComparison.Ordinal) && targetMethod.ContainingType.IsString())
                {
                    var properties = CreateProperties(OptimizeStringBuilderUsageData.ReplaceSubstring);
                    context.ReportDiagnostic(s_rule, properties, operation, $"Use {methodName}(string, int, int) instead of Substring");
                    return true;
                }
            }

            return false;
        }

19 Source : RemoveUselessToStringAnalyzer.cs
with MIT License
from meziantou

private static void replacedyzeOperation(OperationreplacedysisContext context)
        {
            var operation = (IInvocationOperation)context.Operation;
            if (operation.IsImplicit)
                return;

            if (string.Equals(operation.TargetMethod.Name, nameof(string.ToString), StringComparison.Ordinal) &&
               operation.TargetMethod.ContainingType.IsString())
            {
                context.ReportDiagnostic(s_rule, operation);
            }
        }

19 Source : ReplaceEnumToStringWithNameofAnalyzer.cs
with MIT License
from meziantou

private static void replacedyze(OperationreplacedysisContext context)
        {
            var operation = (IInvocationOperation)context.Operation;
            if (operation.TargetMethod.Name != nameof(object.ToString))
                return;

            if (!operation.TargetMethod.ContainingType.IsEqualTo(context.Compilation.GetSpecialType(SpecialType.System_Enum)))
                return;

            if (operation.Children.First() is not IMemberReferenceOperation expression)
                return;

            if (expression.Member.ContainingType.EnumUnderlyingType == null)
                return;

            context.ReportDiagnostic(s_rule, operation);
        }

19 Source : UseAnOverloadThatHaveCancellationTokenAnalyzer.cs
with MIT License
from meziantou

public void replacedyzeInvocation(OperationreplacedysisContext context)
            {
                var operation = (IInvocationOperation)context.Operation;
                if (HasExplicitCancellationTokenArgument(operation))
                    return;

                if (!HasAnOverloadWithCancellationToken(operation))
                    return;

                var possibleCancellationTokens = string.Join(", ", FindCancellationTokens(operation));
                if (!string.IsNullOrEmpty(possibleCancellationTokens))
                {
                    context.ReportDiagnostic(s_useAnOverloadThatHaveCancellationTokenWhenACancellationTokenIsAvailableRule, operation, possibleCancellationTokens);
                }
                else
                {
                    var parentMethod = operation.GetContainingMethod();
                    if (parentMethod is not null && parentMethod.IsOverrideOrInterfaceImplementation())
                        return;

                    context.ReportDiagnostic(s_useAnOverloadThatHaveCancellationTokenRule, operation, possibleCancellationTokens);
                }
            }

19 Source : UseConfigureAwaitAnalyzer.cs
with MIT License
from meziantou

public void replacedyzeForEachStatement(OperationreplacedysisContext context)
            {
                if (context.Operation is not IForEachLoopOperation operation)
                    return;

                if (!operation.IsAsynchronous)
                    return;

                // ConfiguredCancelableAsyncEnumerable
                var collectionType = operation.Collection.GetActualType();
                if (collectionType == null)
                    return;

                if (collectionType.OriginalDefinition.IsEqualTo(ConfiguredCancelableAsyncEnumerableSymbol))
                {
                    // Enumerable().WithCancellation(ct) or Enumerable().ConfigureAwait(false)
                    if (HasConfigureAwait(operation.Collection) && HasPartOfTypeIAsyncEnumerable(operation.Collection))
                        return;

                    // Check if it's a variable reference that is already configured
                    // note: this doesn't check if the value is well-configured
                    // https://github.com/meziantou/Meziantou.replacedyzer/issues/232
                    if (operation.Collection.UnwrapImplicitConversionOperations() is ILocalReferenceOperation)
                        return;
                }

                if (!CanAddConfigureAwait(collectionType, operation.Collection))
                    return;

                if (MustUseConfigureAwait(operation.SemanticModel!, context.Options, operation.Syntax, context.CancellationToken))
                {
                    context.ReportDiagnostic(s_rule, operation.Collection);
                }

                static bool HasConfigureAwait(IOperation operation)
                {
                    if (operation is IInvocationOperation invocation)
                    {
                        if (invocation.TargetMethod.Name == "ConfigureAwait")
                            return true;
                    }

                    foreach (var child in operation.Children)
                    {
                        if (HasConfigureAwait(child))
                            return true;
                    }

                    return false;
                }

                bool HasPartOfTypeIAsyncEnumerable(IOperation operation)
                {
                    if (operation.Type.IsEqualTo(IAsyncEnumerableSymbol))
                        return true;

                    foreach (var child in operation.Children)
                    {
                        if (HasConfigureAwait(child))
                            return true;
                    }

                    return false;
                }
            }

19 Source : UseEventArgsEmptyAnalyzer.cs
with MIT License
from meziantou

private static void replacedyze(OperationreplacedysisContext context)
        {
            var operation = (IObjectCreationOperation)context.Operation;
            if (operation == null || operation.Constructor == null)
                return;

            if (operation.Arguments.Length > 0)
                return;

            var type = context.Compilation.GetTypeByMetadataName("System.EventArgs");
            if (operation.Constructor.ContainingType.IsEqualTo(type))
            {
                context.ReportDiagnostic(s_rule, operation);
            }
        }

19 Source : ValueReturnedByStreamReadShouldBeUsedAnalyzer.cs
with MIT License
from meziantou

private static void replacedyzeOperation(OperationreplacedysisContext context)
        {
            var invocation = (IInvocationOperation)context.Operation;
            var targetMethod = invocation.TargetMethod;
            if (targetMethod.Name != nameof(Stream.Read) && targetMethod.Name != nameof(Stream.ReadAsync))
                return;

            var streamSymbol = context.Compilation.GetTypeByMetadataName("System.IO.Stream");
            if (!targetMethod.ContainingType.IsOrInheritFrom(streamSymbol))
                return;

            var parent = invocation.Parent;
            if (parent is IAwaitOperation)
            {
                parent = parent.Parent;
            }

            if (parent == null || parent is IBlockOperation || parent is IExpressionStatementOperation)
            {
                context.ReportDiagnostic(s_rule, invocation, targetMethod.Name);
            }
        }

See More Examples