示例#1
0
 public Branch FindBranch(SyntaxNode expression, out Condition inlineCondition)
 {
     using (new OperationTimer(i => Timings.Update(TimingOperation.FindBranch, i)))
     {
         return(InnerFindBranch(this, expression, out inlineCondition));
     }
 }
示例#2
0
        public MethodFlowAnalysis Analyze(BlockSyntax body, IEnumerable <SyntaxNode> statements)
        {
            hasConstraints = false;
            assignments.Clear();
            lambdas.Clear();
            using (new OperationTimer(i => Timings.Update(TimingOperation.MethodAnlyzer, i)))
            {
                var tree        = BuildTree(null, null, statements, false);
                var lambdaTrees = new List <Branch>();
                while (lambdas.Count > 0)
                {
                    var lambda = lambdas.Dequeue();
                    if (lambda.Item2.Body is BlockSyntax block)
                    {
                        lambdaTrees.Add(BuildTree(lambda.Item1, null, lambda.Item2.Body.ChildNodes(), true));
                    }
                    else
                    {
                        lambdaTrees.Add(BuildTree(lambda.Item1, null, new[] { lambda.Item2.Body }, true));
                    }
                }
                // This is kinda a hack. The idea is that we probably wanna search the inner most lambda first.
                // But since each lambda contains all the statements of the inner lambdas, we'd match on the outer one first.
                // So reverse the list and start at the bottom.
                lambdaTrees.Reverse();

                var nullAssignments = assignments
                                      .Where(i => i.Value != ValueType.NotNull)
                                      .Select(i => i.Symbol)
                                      .ToList();

                if (body != null)
                {
                    var data = model.AnalyzeDataFlow(body);

                    var variablesThatAreAlwaysNotNull = data.AlwaysAssigned.RemoveAll(i => i is IParameterSymbol || nullAssignments.Any(j => j.Equals(i)));

                    var safeParameters = data.WrittenOutside.Where(i => i.HasNotNullOrCheckNull());

                    return(new MethodFlowAnalysis(
                               mode,
                               model,
                               assignments,
                               variablesThatAreAlwaysNotNull.AddRange(safeParameters),
                               tree,
                               lambdaTrees,
                               hasConstraints,
                               returnStatements));
                }
                return(new MethodFlowAnalysis(
                           mode,
                           model,
                           assignments,
                           ImmutableArray.Create <ISymbol>(),
                           tree,
                           lambdaTrees,
                           hasConstraints,
                           returnStatements));
            }
        }
示例#3
0
        public Condition Parse(ConditionType kind, ExpressionSyntax expression)
        {
            using (new OperationTimer(i => Timings.Update(TimingOperation.ExpressionToCondition, i)))
            {
                var list = new LinkedList <BooleanExpression>();
                list.AddFirst(new BooleanExpression(expression));
                Queue <LinkedListNode <BooleanExpression> > queue = new Queue <LinkedListNode <BooleanExpression> >();
                ExplodeExpression(list, list.First, queue);

                while (queue.Count > 0)
                {
                    ExplodeExpression(list, queue.Dequeue(), queue);
                }

                var condition = new Condition(kind);
                var lastOp    = Operator.None;
                foreach (var item in list)
                {
                    LogicalType conditionType;
                    switch (lastOp)
                    {
                    case Operator.Or:
                        conditionType = LogicalType.Or;
                        break;

                    case Operator.And:
                        conditionType = LogicalType.And;
                        break;

                    default:
                        conditionType = LogicalType.Mixed;
                        break;
                    }
                    if (item.IsIsExpression)
                    {
                        condition = condition.WithIs(conditionType, new ExpressionKey(item.Expression, item.IsType), item.Expression, item.HasNotPrefix);
                    }
                    else
                    {
                        condition = condition.With(conditionType, new ExpressionKey(item.Expression, model), item.Expression, item.Value);
                    }
                    lastOp = item.Operator;
                }

                return(condition);
            }
        }
        public ExpressionStatus IsAlwaysAssigned(SyntaxNode expression, SyntaxNode parent, bool searchAssignments = true)
        {
            using (new OperationTimer(i => Timings.Update(TimingOperation.IsAlwaysAssigned, i)))
            {
                var argSymbol = model.GetSymbolInfo(expression).Symbol;
                if (AlwaysAssignedToNotNull.Contains(argSymbol))
                {
                    // Agument might have been null, but it was assigned to a NotNull in all execution paths
                    return(ExpressionStatus.Assigned);
                }

                var assignmentsForExpression = assignments.Where(i => i.Symbol.Equals(argSymbol)).ToList();
                // Fields/properties might be unassigned. We can really only look at locals
                if (argSymbol is ILocalSymbol)
                {
                    if (assignmentsForExpression.Count > 0)
                    {
                        if (assignmentsForExpression.All(i => i.Value == ValueType.NotNull))
                        {
                            return(ExpressionStatus.Assigned);
                        }
                    }
                }

                // TODO: cache this?
                var path = GetListOfParents(parent, out var inlineCondition);
                var key  = new ExpressionKey(expression, model);
                if (inlineCondition != null && inlineCondition.IsNotNullShortCircuit(key))
                {
                    // Short circuiting expression
                    return(ExpressionStatus.Assigned);
                }

                // Find the condition that checks for NotNull
                Branch branchWithNullCheck = GetBranchWithNullCheck(path, key, out var unneededConstraint);

                if (branchWithNullCheck == null)
                {
                    if (searchAssignments && argSymbol is ILocalSymbol)
                    {
                        var questionableAssignments = assignmentsForExpression.Where(i => i.Value != ValueType.NotNull).ToList();
                        if (questionableAssignments.Count > 0)
                        {
                            if (questionableAssignments.Any(i => !IsAlwaysAssigned(i.Expression, parent, false).IsAssigned()))
                            {
                                return(ExpressionStatus.NotAssigned);
                            }
                            return(ExpressionStatus.Assigned);
                        }
                    }
                    return(ExpressionStatus.NotAssigned);
                }

                if (NullAssignmentsAreInPath(expression, assignmentsForExpression, branchWithNullCheck))
                {
                    return(ExpressionStatus.ReassignedAfterCondition);
                }

                return(unneededConstraint ? ExpressionStatus.AssignedWithUnneededConstraint : ExpressionStatus.Assigned);
            }
        }
 public void Update()
 {
     // DO WORK
     Timings.Update();
 }