private void TryPerformEntryOperation(MenuEntry entry)
        {
            if (entry.ShouldQuit)
            {
                exitRequested = true;
                return;
            }

            try
            {
                Console.WriteLine();
                IOperation?operation = entry.CreateNewOperation(new ConsoleUserInterface());
                if (operation == null)
                {
                    return;
                }

                operation.Run();
                Console.Write("\nDone! ");
            }
            catch (Exception exc)
            {
                ConsoleHelpers.WriteLine($"Operation failed: {exc.Message}", ConsoleColor.Red);
                #if DEBUG
                ConsoleHelpers.WriteLine(exc.StackTrace, ConsoleColor.Red);
                #endif
                Console.WriteLine();
            }

            ConsoleHelpers.FlushStandardInput();
            Console.WriteLine("Press a key to return to the main menu");
            Console.ReadKey();
        }
            protected override void SetAbstractValueForAssignment(
                AnalysisEntity targetAnalysisEntity, IOperation?assignedValueOperation, GlobalFlowStateDictionaryAnalysisValue assignedValue)
            {
                if (assignedValueOperation is null || !IsDeferredType(assignedValueOperation.Type?.OriginalDefinition, _wellKnownSymbolsInfo.AdditionalDeferredTypes))
                {
                    return;
                }

                var deferredTypeCreationEntity = new DeferredTypeCreationEntity(assignedValueOperation);

                if (GlobalState.TrackedEntities.ContainsKey(deferredTypeCreationEntity))
                {
                    // An operation create an 'IEnumerable' entity is visited again in an AssignmentOperation, this could happens in cases like
                    // foreach (var x in collection)
                    // {
                    //     var a = CreateIEnumerable();
                    //     a.Count();
                    // }
                    // where the 'CreateIEnumerable()' is visited again in the loop.
                    // In this case, reset the linked 'IEnumerable' entity.
                    SetAbstractValue(GlobalEntity, GlobalState.RemoveTrackedDeferredTypeEntity(deferredTypeCreationEntity));
                }

                base.SetAbstractValueForAssignment(targetAnalysisEntity, assignedValueOperation, assignedValue);
            }
Beispiel #3
0
        private static bool TryGetAssignmentOrThrow(
            [NotNullWhen(true)] IOperation?statement,
            out ISimpleAssignmentOperation?assignment,
            out IThrowOperation?throwOperation
            )
        {
            assignment     = null;
            throwOperation = null;

            if (statement is IThrowOperation throwOp)
            {
                throwOperation = throwOp;

                // We can only convert a `throw expr` to a throw expression, not `throw;`
                return(throwOperation.Exception != null);
            }

            // Both the WhenTrue and WhenFalse statements must be of the form:
            //      target = value;
            if (
                statement is IExpressionStatementOperation exprStatement &&
                exprStatement.Operation is ISimpleAssignmentOperation assignmentOp &&
                assignmentOp.Target != null
                )
            {
                assignment = assignmentOp;
                return(true);
            }

            return(false);
        }
        private void AnalyzeInvokedMember(
            OperationAnalysisContext context,
            InfoCache infoCache,
            IOperation?instance,
            IMethodSymbol?targetMethod,
            IOperation argumentValue,
            IPropertySymbol?lengthLikeProperty,
            CancellationToken cancellationToken)
        {
            // look for `s[s.Length - value]` or `s.Get(s.Length- value)`.

            // Needs to have the one arg for `s.Length - value`, and that arg needs to be
            // a subtraction.
            if (instance is null ||
                !IsSubtraction(argumentValue, out var subtraction))
            {
                return;
            }

            if (subtraction.Syntax is not BinaryExpressionSyntax binaryExpression)
            {
                return;
            }

            // Don't bother analyzing if the user doesn't like using Index/Range operators.
            var option = context.Options.GetOption(CSharpCodeStyleOptions.PreferIndexOperator, binaryExpression.SyntaxTree, cancellationToken);

            if (!option.Value)
            {
                return;
            }

            // Ok, looks promising.  We're indexing in with some subtraction expression. Examine the
            // type this indexer is in to see if there's another member that takes a System.Index
            // that we can convert to.
            //
            // Also ensure that the left side of the subtraction : `s.Length - value` is actually
            // getting the length off the same instance we're indexing into.

            lengthLikeProperty ??= TryGetLengthLikeProperty(infoCache, targetMethod);
            if (lengthLikeProperty == null ||
                !IsInstanceLengthCheck(lengthLikeProperty, instance, subtraction.LeftOperand))
            {
                return;
            }

            if (CSharpSemanticFacts.Instance.IsInExpressionTree(instance.SemanticModel, instance.Syntax, infoCache.ExpressionOfTType, cancellationToken))
            {
                return;
            }

            // Everything looks good.  We can update this to use the System.Index member instead.
            context.ReportDiagnostic(
                DiagnosticHelper.Create(
                    Descriptor,
                    binaryExpression.GetLocation(),
                    option.Notification.Severity,
                    ImmutableArray <Location> .Empty,
                    ImmutableDictionary <string, string?> .Empty));
        }
Beispiel #5
0
        private static AbstractLocation Create(IOperation?creation, ImmutableStack <IOperation>?creationCallStack, AnalysisEntity?analysisEntity, ISymbol?symbol, InterproceduralCaptureId?captureId, ITypeSymbol?locationType)
        {
            Debug.Assert(creation != null ^ symbol != null ^ analysisEntity != null ^ captureId != null);
            Debug.Assert(locationType != null);

            return(new AbstractLocation(creation, creationCallStack, analysisEntity, symbol, captureId, locationType, isSpecialSingleton: false));
        }
        public static AccessPath?FromOperation(IOperation?operation)
        {
            var list = ImmutableArray.CreateBuilder <ISymbol>();

            list.Reverse();
            while (operation is IMemberReferenceOperation mro && (mro.Kind == OperationKind.PropertyReference || mro.Kind == OperationKind.FieldReference))
            {
                if (mro.Member is IPropertySymbol prop && !prop.Parameters.IsEmpty)
                {
                    return(null); // indexers are not supported
                }
                list.Add(mro.Member);
                operation = mro.Instance;
            }
            AccessPathRoot root;

            switch (operation)
            {
            case ILocalReferenceOperation localOp:
                list.Add(localOp.Local);
                root = AccessPathRoot.Local;
                break;

            case IParameterReferenceOperation paramOp:
                list.Add(paramOp.Parameter);
                root = AccessPathRoot.Local;
                break;

            case IInstanceReferenceOperation {
                    ReferenceKind: InstanceReferenceKind.ContainingTypeInstance
            } :
                root = AccessPathRoot.This;
                break;
Beispiel #7
0
            public override void Visit(IOperation?operation)
            {
                _cancellationToken.ThrowIfCancellationRequested();
                if (operation == null)
                {
                    return;
                }

                if (operation is IVariableDeclaratorOperation variableDeclarationOperation)
                {
                    _allSymbols.Add(variableDeclarationOperation.Symbol);
                }

                if (
                    operation is ILocalReferenceOperation localReferenceOperation &&
                    localReferenceOperation.IsDeclaration
                    )
                {
                    _allSymbols.Add(localReferenceOperation.Local);
                }

                // Stop when meet lambda or local function
                if (
                    operation.Kind == OperationKind.AnonymousFunction ||
                    operation.Kind == OperationKind.LocalFunction
                    )
                {
                    return;
                }

                base.Visit(operation);
            }
            public override GlobalFlowStateAnalysisValueSet VisitInvocation_NonLambdaOrDelegateOrLocalFunction(
                IMethodSymbol method,
                IOperation?visitedInstance,
                ImmutableArray <IArgumentOperation> visitedArguments,
                bool invokedAsDelegate,
                IOperation originalOperation,
                GlobalFlowStateAnalysisValueSet defaultValue)
            {
                var value = base.VisitInvocation_NonLambdaOrDelegateOrLocalFunction(method, visitedInstance, visitedArguments, invokedAsDelegate, originalOperation, defaultValue);

                if (_platformCheckMethods.Contains(method.OriginalDefinition))
                {
                    using var infosBuilder = ArrayBuilder <PlatformMethodValue> .GetInstance();

                    if (PlatformMethodValue.TryDecode(method, visitedArguments, DataFlowAnalysisContext.ValueContentAnalysisResult, _osPlatformType, infosBuilder))
                    {
                        for (var i = 0; i < infosBuilder.Count; i++)
                        {
                            var newValue = new GlobalFlowStateAnalysisValueSet(infosBuilder[i]);
                            value = i == 0 ? newValue : new GlobalFlowStateAnalysisValueSet(value, newValue);
                        }

                        return(value);
                    }

                    return(GlobalFlowStateAnalysisValueSet.Unknown);
                }

                return(GetValueOrDefault(value));
            }
                        // Determine if we should warn for the stackalloc we found in a loop.  In general
                        // if a stackalloc is in a loop, it should be moved out.  However, there's a pattern
                        // where a loop will search for something and then, once it finds it, it stackallocs
                        // as part of processing the thing it found, and exits the loop.  We want to avoid
                        // warning on such cases if possible.  So, as a heuristic, we walk up all the blocks
                        // we find until we reach the first containing loop, and for each block look at all
                        // operations it contains after the target one to see if any is a break or a return.
                        static bool ShouldWarn(IOperation? op, SyntaxNode node)
                        {
                            // Walk up the operation tree, looking at all blocks until we find a loop.
                            for (; op is not null and not ILoopOperation; op = op.Parent)
                            {
                                // If we hit a block, iterate through all operations in the block
                                // after the node's position, and see if it's something that will
                                // execute the loop.
                                if (op is IBlockOperation block)
                                {
                                    foreach (IOperation child in block.Operations)
                                    {
                                        if (child.Syntax.SpanStart > node.SpanStart &&
                                            (child is IReturnOperation || (child is IBranchOperation branch && branch.BranchKind == BranchKind.Break)))
                                        {
                                            // Err on the side of false negatives / caution and say this stackalloc is ok.
                                            // Note, too, it's possible we're breaking out of a nested loop, and the outer loop
                                            // will still cause the stackalloc to be invoked an unbounded number of times,
                                            // but that's difficult to analyze well.
                                            return(false);
                                        }
                                    }
                                }
                            }

                            // Warn.
                            return(true);
                        }
        // Override visitor methods to create tracked values when visiting operations
        // which reference possibly annotated source locations:
        // - parameters
        // - 'this' parameter (for annotated methods)
        // - field reference

        public override MultiValue Visit(IOperation?operation, StateValue argument)
        {
            var returnValue = base.Visit(operation, argument);

            // If the return value is empty (TopValue basically) and the Operation tree
            // reports it as having a constant value, use that as it will automatically cover
            // cases we don't need/want to handle.
            if (operation != null && returnValue.IsEmpty() && operation.ConstantValue.HasValue)
            {
                object?constantValue = operation.ConstantValue.Value;
                if (constantValue == null)
                {
                    return(NullValue.Instance);
                }
                else if (operation.Type?.SpecialType == SpecialType.System_String && constantValue is string stringConstantValue)
                {
                    return(new KnownStringValue(stringConstantValue));
                }
                else if (operation.Type?.TypeKind == TypeKind.Enum && constantValue is int enumConstantValue)
                {
                    return(new ConstIntValue(enumConstantValue));
                }
                else if (operation.Type?.SpecialType == SpecialType.System_Int32 && constantValue is int intConstantValue)
                {
                    return(new ConstIntValue(intConstantValue));
                }
            }

            return(returnValue);
        }
        private static IOperation?Unwrap(IOperation?expression, bool towardsParent = false)
        {
            while (true)
            {
                if (towardsParent && expression?.Parent is null)
                {
                    return(expression);
                }

                switch (expression)
                {
                case IParenthesizedOperation parenthesized:
                    expression = towardsParent ? expression.Parent : parenthesized.Operand;
                    continue;

                case IConversionOperation {
                        IsImplicit: true
                } conversion:
                    expression = towardsParent ? expression.Parent : conversion.Operand;
                    continue;

                default:
                    return(expression);
                }
            }
        }
Beispiel #12
0
 internal Context(IOperation?implicitInstance, INamedTypeSymbol?anonymousType, ImmutableArray <KeyValuePair <IPropertySymbol, IOperation> > anonymousTypePropertyValues)
 {
     Debug.Assert(!anonymousTypePropertyValues.IsDefault);
     Debug.Assert(implicitInstance == null || anonymousType == null);
     ImplicitInstance            = implicitInstance;
     AnonymousType               = anonymousType;
     AnonymousTypePropertyValues = anonymousTypePropertyValues;
 }
 protected override void SetAbstractValueForAssignment(IOperation target, IOperation?assignedValueOperation, ParameterValidationAbstractValue assignedValue, bool mayBeAssignment = false)
 {
     // If we are assigning to parameter, mark it as validated on this path.
     if (target is IParameterReferenceOperation)
     {
         MarkValidatedLocations(target);
     }
 }
 internal BranchWithInfo With(
     IOperation?branchValue,
     ControlFlowConditionKind controlFlowConditionKind)
 {
     return(new BranchWithInfo(Destination, EnteringRegions, LeavingRegions,
                               FinallyRegions, Kind, branchValue, controlFlowConditionKind,
                               LeavingRegionLocals, LeavingRegionFlowCaptures));
 }
Beispiel #15
0
 private static bool IsPrefixNotOperation(IOperation operation, [NotNullWhen(true)] out IOperation?operand)
 {
     if (operation is IUnaryOperation unaryOperation &&
         unaryOperation.OperatorKind == UnaryOperatorKind.Not)
     {
         operand = unaryOperation.Operand;
         return(true);
     }
Beispiel #16
0
 /// <summary>
 /// Analyzes the containing <c>GetHashCode</c> method to determine which fields and
 /// properties were combined to form a hash code for this type.
 /// </summary>
 public (bool accessesBase, ImmutableArray <ISymbol> members, ImmutableArray <IOperation> statements) GetHashedMembers(
     ISymbol?owningSymbol,
     IOperation?operation
     )
 {
     if (!(operation is IBlockOperation blockOperation))
     {
         return(default);
Beispiel #17
0
        public void KeyCodeEnterred(System.Windows.Input.Key key)
        {
            IOperation?newOperation = _KeyMapping.ContainsKey(key) ? _KeyMapping[key]() : null;

            if (newOperation != null)
            {
                AddOperation(newOperation);
            }
        }
        public static bool IsExpressionEqualsIntZero([NotNullWhen(returnValue: true)] IOperation?operation)
        {
            if (operation is not ILiteralOperation literal || !literal.ConstantValue.HasValue)
            {
                return(false);
            }

            return(literal.HasConstantValue(0));
        }
Beispiel #19
0
 internal static ISymbol?GetUnderlyingSymbol(IOperation?operation)
 {
     return(operation switch
     {
         IParameterReferenceOperation paramRef => paramRef.Parameter,
         ILocalReferenceOperation localRef => localRef.Local,
         IMemberReferenceOperation memberRef => memberRef.Member,
         _ => null,
     });
Beispiel #20
0
        private static bool IsReturnExprOrThrow(IOperation?statement)
        {
            // We can only convert a `throw expr` to a throw expression, not `throw;`
            if (statement is IThrowOperation throwOperation)
            {
                return(throwOperation.Exception != null);
            }

            return(statement is IReturnOperation returnOp && returnOp.ReturnedValue != null);
        }
Beispiel #21
0
        protected override void SetAbstractValueForAssignment(IOperation target, IOperation?assignedValueOperation, TAbstractAnalysisValue assignedValue, bool mayBeAssignment = false)
        {
            if (AnalysisEntityFactory.TryCreate(target, out var targetAnalysisEntity))
            {
                if (mayBeAssignment)
                {
                    assignedValue = ValueDomain.Merge(GetAbstractValue(targetAnalysisEntity), assignedValue);
                }

                SetAbstractValueForAssignment(targetAnalysisEntity, assignedValueOperation, assignedValue);
            }
        }
Beispiel #22
0
        private AbstractLocation(IOperation?creation, ImmutableStack <IOperation>?creationCallStack, AnalysisEntity?analysisEntity, ISymbol?symbol, InterproceduralCaptureId?captureId, ITypeSymbol?locationType, bool isSpecialSingleton)
        {
            Debug.Assert(isSpecialSingleton ^ (locationType != null));

            CreationOpt         = creation;
            CreationCallStack   = creationCallStack ?? ImmutableStack <IOperation> .Empty;
            AnalysisEntityOpt   = analysisEntity;
            SymbolOpt           = symbol;
            CaptureIdOpt        = captureId;
            LocationTypeOpt     = locationType;
            _isSpecialSingleton = isSpecialSingleton;
        }
        public bool TryCreateForSymbolDeclaration(ISymbol symbol, [NotNullWhen(returnValue: true)] out AnalysisEntity?analysisEntity)
        {
            Debug.Assert(symbol.Kind is SymbolKind.Local or SymbolKind.Parameter or SymbolKind.Field or SymbolKind.Property);

            var        indices  = ImmutableArray <AbstractIndex> .Empty;
            IOperation?instance = null;
            var        type     = symbol.GetMemberOrLocalOrParameterType();

            RoslynDebug.Assert(type != null);

            return(TryCreate(symbol, indices, type, instance, out analysisEntity));
        }
Beispiel #24
0
        private string?TryGetFormatText(IOperation?argumentExpression)
        {
            if (argumentExpression is null)
            {
                return(null);
            }

            switch (argumentExpression)
            {
            case IOperation {
                    ConstantValue: { HasValue : true, Value : string constantValue }
            } :
                return(constantValue);
Beispiel #25
0
 public override TResult?Visit(IOperation?operation, TArgument argument)
 {
     if (operation != null)
     {
         _recursionDepth++;
         try {
             StackGuard.EnsureSufficientExecutionStack(_recursionDepth);
             return(operation.Accept(this, argument));
         } finally {
             _recursionDepth--;
         }
     }
     return(default);
Beispiel #26
0
        // Override visitor methods to create tracked values when visiting operations
        // which reference possibly annotated source locations:
        // - parameters
        // - 'this' parameter (for annotated methods)
        // - field reference

        public override MultiValue Visit(IOperation?operation, StateValue argument)
        {
            var returnValue = base.Visit(operation, argument);

            // If the return value is empty (TopValue basically) and the Operation tree
            // reports it as having a constant value, use that as it will automatically cover
            // cases we don't need/want to handle.
            if (operation != null && returnValue.IsEmpty() && TryGetConstantValue(operation, out var constValue))
            {
                return(constValue);
            }

            return(returnValue);
        }
 public Result(
     ResultKind kind, CodeStyleOption2 <bool> option,
     IInvocationOperation invocationOperation, InvocationExpressionSyntax invocation,
     IMethodSymbol sliceLikeMethod, MemberInfo memberInfo,
     IOperation op1, IOperation?op2)
 {
     Kind   = kind;
     Option = option;
     InvocationOperation = invocationOperation;
     Invocation          = invocation;
     SliceLikeMethod     = sliceLikeMethod;
     MemberInfo          = memberInfo;
     Op1 = op1;
     Op2 = op2;
 }
        private static void AnalyzeOperation(SyntaxNodeAnalysisContext context, IOperation?operation)
        {
            if (operation == null)
            {
                return;
            }

            foreach (var op in DescendantsAndSelf(operation, o => !(o is IAnonymousFunctionOperation) && !(o is ILocalFunctionOperation)))
            {
                if (op is IReturnOperation returnOperation && IsNullValue(returnOperation.ReturnedValue))
                {
                    context.ReportDiagnostic(Diagnostic.Create(s_rule, op.Syntax.GetLocation()));
                }
            }
        }
        private AnalysisContextInfo(
            Compilation?compilation,
            IOperation?operation,
            ISymbol?symbol,
            SourceOrAdditionalFile?file,
            SyntaxNode?node)
        {
            Debug.Assert(node == null || file?.SourceTree != null);
            Debug.Assert(operation == null || file?.SourceTree != null);

            _compilation = compilation;
            _operation   = operation;
            _symbol      = symbol;
            _file        = file;
            _node        = node;
        }
Beispiel #30
0
        internal static ISymbol GetContainingFunction(IOperation operation, ISymbol operationBlockContainingSymbol)
        {
            for (IOperation?current = operation; current is object; current = current.Parent)
            {
                if (current.Kind == OperationKind.AnonymousFunction)
                {
                    return(((IAnonymousFunctionOperation)current).Symbol);
                }
                else if (current.Kind == OperationKind.LocalFunction)
                {
                    return(((ILocalFunctionOperation)current).Symbol);
                }
            }

            return(operationBlockContainingSymbol);
        }