Esempio n. 1
0
        public override void VisitLocalReference(ILocalReferenceOperation operation)
        {
            var local         = operation.Local;
            var isDeclaration = operation.IsDeclaration;

            base.VisitLocalReference(operation);
        }
Esempio n. 2
0
        private void AnalyzeAssignment(OperationAnalysisContext context)
        {
            var assignmentOperation = (ISimpleAssignmentOperation)context.Operation;

            // Check if there are more then one assignment in a statement
            if (assignmentOperation.Target is not IMemberReferenceOperation operationTarget)
            {
                return;
            }

            // This analyzer makes sense only for reference type objects
            if (operationTarget.Instance?.Type?.IsReferenceType != true)
            {
                return;
            }

            bool isViolationFound = operationTarget.Instance switch
            {
                ILocalReferenceOperation localInstance =>
                AnalyzeAssignmentToMember(assignmentOperation, localInstance, (a, b) => a.Local.Equals(b.Local)),
                IMemberReferenceOperation memberInstance =>
                AnalyzeAssignmentToMember(assignmentOperation, memberInstance, (a, b) => a.Member.Equals(b.Member) && a.Instance?.Syntax.ToString() == b.Instance?.Syntax.ToString()),
                IParameterReferenceOperation parameterInstance =>
                AnalyzeAssignmentToMember(assignmentOperation, parameterInstance, (a, b) => a.Parameter.Equals(b.Parameter)),
                _ => false,
            };

            if (isViolationFound)
            {
                var diagnostic = operationTarget.CreateDiagnostic(Rule, operationTarget.Instance.Syntax, operationTarget.Member.Name);
                context.ReportDiagnostic(diagnostic);
            }
        }
Esempio n. 3
0
            // Local functions
            static bool IsArgumentValueEqual(IOperation targetArg, IOperation valueArg)
            {
                // Check if arguments are identical constant/local/parameter reference operations.
                //   1. Not identical: 'this[i] = this[j]'
                //   2. Identical: 'this[i] = this[i]', 'this[0] = this[0]'
                if (targetArg.Kind != valueArg.Kind)
                {
                    return(false);
                }

                if (targetArg.ConstantValue.HasValue != valueArg.ConstantValue.HasValue)
                {
                    return(false);
                }

                if (targetArg.ConstantValue.HasValue)
                {
                    return(Equals(targetArg.ConstantValue.Value, valueArg.ConstantValue.Value));
                }

#pragma warning disable IDE0055 // Fix formatting - Does not seem to be handling switch expressions.
                return(targetArg switch
                {
                    ILocalReferenceOperation targetLocalReference =>
                    Equals(targetLocalReference.Local, ((ILocalReferenceOperation)valueArg).Local),
                    IParameterReferenceOperation targetParameterReference =>
                    Equals(targetParameterReference.Parameter, ((IParameterReferenceOperation)valueArg).Parameter),
                    _ => false,
                });
            public override IdentifierInfo VisitLocalReference([NotNull] ILocalReferenceOperation operation,
                                                               [CanBeNull] object argument)
            {
                var name = new IdentifierName(operation.Local.Name,
                                              operation.Local.ToDisplayString(SymbolDisplayFormat.CSharpShortErrorMessageFormat));

                return(new IdentifierInfo(name, operation.Local.Type, "Variable"));
            }
Esempio n. 5
0
        public override void VisitLocalReference(ILocalReferenceOperation operation)
        {
            Assert.Equal(OperationKind.LocalReference, operation.Kind);
            Assert.NotNull(operation.Local);
            var isDeclaration = operation.IsDeclaration;

            Assert.Empty(operation.Children);
        }
Esempio n. 6
0
            private EvaluationResult AnalyzeLocalReference([NotNull] ILocalReferenceOperation local)
            {
                var assignmentWalker = new VariableAssignmentWalker(local.Local, this);

                assignmentWalker.VisitMethod();

                return(assignmentWalker.Result);
            }
        private static ILocalSymbol TryGetTupleElement([NotNull] IOperation elementOperation)
        {
            ILocalReferenceOperation localReference = elementOperation is IDeclarationExpressionOperation declarationExpression
                ? declarationExpression.Expression as ILocalReferenceOperation
                : elementOperation as ILocalReferenceOperation;

            return(localReference != null && localReference.IsDeclaration ? localReference.Local : null);
        }
Esempio n. 8
0
 internal static ISymbol?GetUnderlyingSymbol(IOperation?operation)
 {
     return(operation switch
     {
         IParameterReferenceOperation paramRef => paramRef.Parameter,
         ILocalReferenceOperation localRef => localRef.Local,
         IMemberReferenceOperation memberRef => memberRef.Member,
         _ => null,
     });
Esempio n. 9
0
        public override void VisitLocalReference(ILocalReferenceOperation operation)
        {
            if (operation.SemanticModel != null)
            {
                FindFromLocalSymbol(operation.SemanticModel, operation.Local);
            }

            base.VisitLocalReference(operation);
        }
            protected override ITypeSymbol GetSymbolType(
                SemanticModel semanticModel,
                ISymbol symbol
                )
            {
                var selectionOperation = semanticModel.GetOperation(
                    SelectionResult.GetContainingScope()
                    );

                switch (symbol)
                {
                case ILocalSymbol localSymbol
                    when localSymbol.NullableAnnotation == NullableAnnotation.Annotated:
                case IParameterSymbol parameterSymbol
                    when parameterSymbol.NullableAnnotation == NullableAnnotation.Annotated:

                    // For local symbols and parameters, we can check what the flow state
                    // for refences to the symbols are and determine if we can change
                    // the nullability to a less permissive state.
                    var references = selectionOperation
                                     .DescendantsAndSelf()
                                     .Where(IsSymbolReferencedByOperation);

                    if (AreAllReferencesNotNull(references))
                    {
                        return(base.GetSymbolType(semanticModel, symbol)
                               .WithNullableAnnotation(NullableAnnotation.NotAnnotated));
                    }

                    return(base.GetSymbolType(semanticModel, symbol));

                default:
                    return(base.GetSymbolType(semanticModel, symbol));
                }

                bool AreAllReferencesNotNull(IEnumerable <IOperation> references) =>
                references.All(
                    r =>
                    semanticModel.GetTypeInfo(r.Syntax).Nullability.FlowState
                    == NullableFlowState.NotNull
                    );

                bool IsSymbolReferencedByOperation(IOperation operation) =>
                operation switch
                {
                    ILocalReferenceOperation localReference
                    => localReference.Local.Equals(symbol),
                    IParameterReferenceOperation parameterReference
                    => parameterReference.Parameter.Equals(symbol),
                    IAssignmentOperation assignment
                    => IsSymbolReferencedByOperation(assignment.Target),
                    _ => false
                };
            }
        }
Esempio n. 11
0
        private static IOperation?GetLocalReferenceDeclaringOperation(ILocalReferenceOperation localReference, SemanticModel semanticModel, CancellationToken token)
        {
            var localSymbolDeclaringSyntax = localReference.Local.DeclaringSyntaxReferences.FirstOrDefault()?.GetSyntax(token);

            if (localSymbolDeclaringSyntax != null)
            {
                return(semanticModel.GetOperation(localSymbolDeclaringSyntax));
            }

            return(null);
        }
                public override void VisitLocalReference([NotNull] ILocalReferenceOperation operation)
                {
                    if (IsInvokingDelegateVariable(operation))
                    {
                        return;
                    }

                    var assignmentWalker = new VariableAssignmentWalker(operation.Local, operation.Syntax.GetLocation(), owner);

                    assignmentWalker.VisitBlockBody();

                    Result.CopyFrom(assignmentWalker.Result);
                }
            private Task VisitReferenceAsync(IOperation operation, CancellationToken cancellationToken)
            {
                Debug.Assert(operation is
                             ILocalReferenceOperation or
                             IParameterReferenceOperation or
                             IFieldReferenceOperation or
                             IPropertyReferenceOperation);

                if (IsContainedIn <IArgumentOperation>(operation, out var argumentOperation) && argumentOperation.Parameter is not null)
                {
                    if (argumentOperation.Parameter.IsRefOrOut())
                    {
                        // Always add ref or out parameters to track as assignments since the values count as
                        // assignments across method calls for the purposes of value tracking.
                        return(AddOperationAsync(operation, argumentOperation.Parameter, cancellationToken));
                    }

                    // If the parameter is not a ref or out param, track the reference assignments that count
                    // as input to the argument being passed to the method.
                    return(AddReference(operation, cancellationToken));
                }

                if (IsContainedIn <IReturnOperation>(operation) || IsContainedIn <IAssignmentOperation>(operation))
                {
                    // If the reference is part of a return operation or assignment operation we want to track where the values come from
                    // since they contribute to the "output" of the method/assignment and are relavent for value tracking.
                    return(AddReference(operation, cancellationToken));
                }

                return(Task.CompletedTask);

                Task AddReference(IOperation operation, CancellationToken cancellationToken)
                => operation switch
                {
                    IParameterReferenceOperation parameterReference => AddOperationAsync(operation, parameterReference.Parameter, cancellationToken),
                    IFieldReferenceOperation fieldReferenceOperation => AddOperationAsync(operation, fieldReferenceOperation.Member, cancellationToken),
                    IPropertyReferenceOperation propertyReferenceOperation => AddOperationAsync(operation, propertyReferenceOperation.Member, cancellationToken),
                    ILocalReferenceOperation localReferenceOperation => AddOperationAsync(operation, localReferenceOperation.Local, cancellationToken),
                    _ => Task.CompletedTask
                };
            }
Esempio n. 14
0
 private static bool IsReassignedInCatch(ICatchClauseOperation catchClause, ILocalReferenceOperation localReference)
 {
     var dataflow = catchClause.Language == LanguageNames.CSharp
         ? catchClause.SemanticModel.AnalyzeDataFlow(catchClause.Handler.Syntax)
         : catchClause.SemanticModel.AnalyzeDataFlow(catchClause.Handler.Operations[0].Syntax, catchClause.Handler.Operations[^ 1].Syntax);
Esempio n. 15
0
            public override GlobalFlowStateDictionaryAnalysisValue VisitLocalReference(ILocalReferenceOperation operation, object?argument)
            {
                var value = base.VisitLocalReference(operation, argument);

                return(VisitLocalOrParameter(operation.Local.Type?.OriginalDefinition, operation, value));
            }
Esempio n. 16
0
 public virtual void VisitLocalReference(ILocalReferenceOperation operation)
 {
     DefaultVisit(operation);
 }
Esempio n. 17
0
 public override void VisitLocalReference([NotNull] ILocalReferenceOperation operation)
 {
     base.VisitLocalReference(operation);
 }
        public override TAbstractAnalysisValue VisitLocalReference(ILocalReferenceOperation operation, object argument)
        {
            var value = base.VisitLocalReference(operation, argument);

            return(ComputeAnalysisValueForReferenceOperation(operation, value));
        }
 public override TAbstractAnalysisValue VisitLocalReference(ILocalReferenceOperation operation, object argument)
 {
     return(GetAbstractValue(operation.Local));
 }
Esempio n. 20
0
 public override Scope VisitLocalReference(ILocalReferenceOperation operation, Scope currentScope)
 => currentScope.Union(
     new LocalValue(operation.Local)
     );
Esempio n. 21
0
 public override bool VisitLocalReference([NotNull] ILocalReferenceOperation operation1,
                                          [CanBeNull] IOperation argument)
 {
     return(argument is ILocalReferenceOperation operation2 && AreBaseOperationsEqual(operation1, operation2) &&
            AreSymbolsEqual(operation1.Local, operation2.Local) && operation1.IsDeclaration == operation2.IsDeclaration);
 }
Esempio n. 22
0
 public override IOperation VisitLocalReference(ILocalReferenceOperation operation, object argument)
 {
     return(new LocalReferenceExpression(operation.Local, operation.IsDeclaration, ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit));
 }
Esempio n. 23
0
 public override void VisitLocalReference(ILocalReferenceOperation operation)
 {
     Callback(operation.Local.Type);
     base.VisitLocalReference(operation);
 }
 private static bool IsInvokingDelegateVariable([NotNull] ILocalReferenceOperation operation)
 {
     return(operation.Parent is IInvocationOperation);
 }
Esempio n. 25
0
        public override void Initialize(AnalysisContext context)
        {
            context.EnableConcurrentExecution();
            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
            context.RegisterCompilationStartAction(context =>
            {
                if (!context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemString, out INamedTypeSymbol? stringType) ||
                    !context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemChar, out INamedTypeSymbol? charType) ||
                    !context.Compilation.TryGetOrCreateTypeByMetadataName(WellKnownTypeNames.SystemStringComparison, out INamedTypeSymbol? stringComparisonType))
                {
                    return;
                }

                // First get all the string.IndexOf methods that we are interested in tagging
                var stringIndexOfMethods = stringType
                                           .GetMembers("IndexOf")
                                           .OfType <IMethodSymbol>()
                                           .WhereAsArray(s =>
                                                         s.Parameters.Length <= 2);

                var stringArgumentIndexOfMethod = stringIndexOfMethods.GetFirstOrDefaultMemberWithParameterInfos(
                    ParameterInfo.GetParameterInfo(stringType));
                var charArgumentIndexOfMethod = stringIndexOfMethods.GetFirstOrDefaultMemberWithParameterInfos(
                    ParameterInfo.GetParameterInfo(charType));
                var stringAndComparisonTypeArgumentIndexOfMethod = stringIndexOfMethods.GetFirstOrDefaultMemberWithParameterInfos(
                    ParameterInfo.GetParameterInfo(stringType),
                    ParameterInfo.GetParameterInfo(stringComparisonType));
                var charAndComparisonTypeArgumentIndexOfMethod = stringIndexOfMethods.GetFirstOrDefaultMemberWithParameterInfos(
                    ParameterInfo.GetParameterInfo(charType),
                    ParameterInfo.GetParameterInfo(stringComparisonType));

                // Check that the contains methods that take 2 parameters exist
                // string.Contains(char) is also .NETStandard2.1+
                var stringContainsMethods = stringType
                                            .GetMembers("Contains")
                                            .OfType <IMethodSymbol>()
                                            .WhereAsArray(s =>
                                                          s.Parameters.Length <= 2);
                var stringAndComparisonTypeArgumentContainsMethod = stringContainsMethods.GetFirstOrDefaultMemberWithParameterInfos(
                    ParameterInfo.GetParameterInfo(stringType),
                    ParameterInfo.GetParameterInfo(stringComparisonType));
                var charAndComparisonTypeArgumentContainsMethod = stringContainsMethods.GetFirstOrDefaultMemberWithParameterInfos(
                    ParameterInfo.GetParameterInfo(charType),
                    ParameterInfo.GetParameterInfo(stringComparisonType));
                var charArgumentContainsMethod = stringContainsMethods.GetFirstOrDefaultMemberWithParameterInfos(
                    ParameterInfo.GetParameterInfo(charType));
                if (stringAndComparisonTypeArgumentContainsMethod == null ||
                    charAndComparisonTypeArgumentContainsMethod == null ||
                    charArgumentContainsMethod == null)
                {
                    return;
                }

                // Roslyn doesn't yet support "FindAllReferences" at a file/block level. So instead, find references to local int variables in this block.
                context.RegisterOperationBlockStartAction(OnOperationBlockStart);
                return;

                void OnOperationBlockStart(OperationBlockStartAnalysisContext context)
                {
                    if (context.OwningSymbol is not IMethodSymbol method)
                    {
                        return;
                    }

                    // Algorithm:
                    // We aim to change string.IndexOf -> string.Contains
                    // 1. We register 1 callback for invocations of IndexOf.
                    //      1a. Check if invocation.Parent is a binary operation we care about (string.IndexOf >= 0 OR string.IndexOf == -1). If so, report a diagnostic and return from the callback.
                    //      1b. Otherwise, check if invocation.Parent is a variable declarator. If so, add the invocation as a potential violation to track into variableNameToOperationsMap.
                    // 2. We register another callback for local references
                    //      2a. If the local reference is not a type int, bail out.
                    //      2b. If the local reference operation's parent is not a binary operation, add it to "localsToBailOut".
                    // 3. In an operation block end, we check if entries in "variableNameToOperationsMap" exist in "localToBailOut". If an entry is NOT present, we report a diagnostic at that invocation.
                    PooledConcurrentSet <ILocalSymbol> localsToBailOut = PooledConcurrentSet <ILocalSymbol> .GetInstance();
                    PooledConcurrentDictionary <ILocalSymbol, IInvocationOperation> variableNameToOperationsMap = PooledConcurrentDictionary <ILocalSymbol, IInvocationOperation> .GetInstance();

                    context.RegisterOperationAction(PopulateLocalReferencesSet, OperationKind.LocalReference);

                    context.RegisterOperationAction(AnalyzeInvocationOperation, OperationKind.Invocation);

                    context.RegisterOperationBlockEndAction(OnOperationBlockEnd);

                    return;

                    // Local Functions
                    void PopulateLocalReferencesSet(OperationAnalysisContext context)
                    {
                        ILocalReferenceOperation localReference = (ILocalReferenceOperation)context.Operation;
                        if (localReference.Local.Type.SpecialType != SpecialType.System_Int32)
                        {
                            return;
                        }

                        var parent = localReference.Parent;
                        if (parent is IBinaryOperation binaryOperation)
                        {
                            var otherOperand = binaryOperation.LeftOperand is ILocalReferenceOperation ? binaryOperation.RightOperand : binaryOperation.LeftOperand;
                            if (CheckOperatorKindAndOperand(binaryOperation, otherOperand))
                            {
                                // Do nothing. This is a valid case to the tagged in the analyzer
                                return;
                            }
                        }
                        localsToBailOut.Add(localReference.Local);
                    }

                    void AnalyzeInvocationOperation(OperationAnalysisContext context)
                    {
                        var invocationOperation = (IInvocationOperation)context.Operation;
                        if (!IsDesiredTargetMethod(invocationOperation.TargetMethod))
                        {
                            return;
                        }

                        var parent = invocationOperation.Parent;
                        if (parent is IBinaryOperation binaryOperation)
                        {
                            var otherOperand = binaryOperation.LeftOperand is IInvocationOperation ? binaryOperation.RightOperand : binaryOperation.LeftOperand;
                            if (CheckOperatorKindAndOperand(binaryOperation, otherOperand))
                            {
                                context.ReportDiagnostic(binaryOperation.CreateDiagnostic(Rule));
                            }
                        }
                        else if (parent is IVariableInitializerOperation variableInitializer)
                        {
                            if (variableInitializer.Parent is IVariableDeclaratorOperation variableDeclaratorOperation)
                            {
                                variableNameToOperationsMap.TryAdd(variableDeclaratorOperation.Symbol, invocationOperation);
                            }
                            else if (variableInitializer.Parent is IVariableDeclarationOperation variableDeclarationOperation && variableDeclarationOperation.Declarators.Length == 1)
                            {
                                variableNameToOperationsMap.TryAdd(variableDeclarationOperation.Declarators[0].Symbol, invocationOperation);
                            }
                        }
                    }

                    static bool CheckOperatorKindAndOperand(IBinaryOperation binaryOperation, IOperation otherOperand)
                    {
                        var operatorKind = binaryOperation.OperatorKind;
                        if (otherOperand.ConstantValue.HasValue && otherOperand.ConstantValue.Value is int intValue)
                        {
                            if ((operatorKind == BinaryOperatorKind.Equals && intValue < 0) ||
                                (operatorKind == BinaryOperatorKind.GreaterThanOrEqual && intValue == 0))
                            {
                                // This is the only case we are targeting in this analyzer
                                return(true);
                            }
                        }
                        return(false);
                    }

                    void OnOperationBlockEnd(OperationBlockAnalysisContext context)
                    {
                        foreach (var variableNameAndLocation in variableNameToOperationsMap)
                        {
                            ILocalSymbol variable = variableNameAndLocation.Key;
                            if (!localsToBailOut.Contains(variable))
                            {
                                context.ReportDiagnostic(variableNameAndLocation.Value.CreateDiagnostic(Rule));
                            }
                        }
                        variableNameToOperationsMap.Free(context.CancellationToken);
                        localsToBailOut.Free(context.CancellationToken);
                    }

                    bool IsDesiredTargetMethod(IMethodSymbol targetMethod) =>
                    targetMethod.Equals(stringArgumentIndexOfMethod) ||
                    targetMethod.Equals(charArgumentIndexOfMethod) ||
                    targetMethod.Equals(stringAndComparisonTypeArgumentIndexOfMethod) ||
                    targetMethod.Equals(charAndComparisonTypeArgumentIndexOfMethod);
                }
            });
Esempio n. 26
0
 /// <summary>
 /// コンストラクタ
 /// </summary>
 /// <param name="operation">IOperationインスタンス</param>
 /// <param name="container">イベントコンテナ</param>
 public LocalReference(ILocalReferenceOperation operation, EventContainer container) : base(container)
 {
     Expressions.Add(new Expression(operation.Local.Name, Expression.GetSymbolTypeName(operation.Local)));
 }
Esempio n. 27
0
 public override void VisitLocalReference([NotNull] ILocalReferenceOperation operation)
 {
     Result = owner.AnalyzeLocalReference(operation);
 }