예제 #1
0
 public bool IsNotNullShortCircuit(ExpressionKey key)
 {
     if (type.GetValueOrDefault(LogicalType.And) == LogicalType.And)
     {
         return(parts.Any(i => i.IsNotNull(key)));
     }
     if (type.GetValueOrDefault(LogicalType.Or) == LogicalType.Or)
     {
         return(parts.Any(i => i.IsNull(key)));
     }
     return(false);
 }
예제 #2
0
        public bool IsConstraintFor(SyntaxNode node, SemanticModel model)
        {
            ExpressionKey key;

            switch (node)
            {
            case AssignmentExpressionSyntax assignment:
                key = new ExpressionKey(assignment.Left, model);
                break;

            default:
                key = new ExpressionKey(node, model);
                break;
            }

            return(Kind == ConditionType.Constraint && parts.Any(i => i.Key == key));
        }
예제 #3
0
        private Branch GetBranchWithNullCheck(List <Branch> parents, ExpressionKey key, out bool unneededConstraint)
        {
            Branch constraintBranch            = null;
            Branch branchWithMatchingCondition = null;

            foreach (var parent in parents)
            {
                if (parent.Condition.IsNotNull(key))
                {
                    branchWithMatchingCondition = parent;
                    if (parent.Condition.Kind != ConditionType.Constraint)
                    {
                        break;
                    }
                    else
                    {
                        constraintBranch = parent;
                    }
                }
            }
            unneededConstraint = constraintBranch != null && constraintBranch != branchWithMatchingCondition;
            return(branchWithMatchingCondition);
        }
예제 #4
0
        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);
            }
        }
예제 #5
0
        public Condition With(LogicalType op, ExpressionKey key, ExpressionSyntax expression, ValueType value)
        {
            var newType = CombineType(type, op);

            return(new Condition(Kind, newType, parts.Add(new Part(key, expression, value))));
        }
예제 #6
0
        public Condition WithIs(LogicalType op, ExpressionKey key, ExpressionSyntax expression, bool hasNotPrefix)
        {
            var newType = CombineType(type, op);

            return(new Condition(Kind, newType, parts.Add(new IsPart(key, expression, hasNotPrefix))));
        }
예제 #7
0
 public bool IsNull(ExpressionKey key)
 {
     return(value == ValueType.Null && this.Key.Contains(key));
 }
예제 #8
0
 public Part(ExpressionKey key, ExpressionSyntax expression, ValueType value)
 {
     this.Key        = key;
     this.Expression = expression;
     this.value      = value;
 }
예제 #9
0
 public bool IsNull(ExpressionKey key)
 {
     return(hasNotPrefix && this.Key.Contains(key));
 }
예제 #10
0
 public Condition(ConditionType kind, ExpressionKey key, ExpressionSyntax expression, ValueType value)
 {
     this.Kind = kind;
     parts     = ImmutableArray.Create <IPart>(new Part(key, expression, value));
 }
예제 #11
0
 public IsPart(ExpressionKey key, ExpressionSyntax expression, bool hasNotPrefix)
 {
     this.Key          = key;
     this.Expression   = expression;
     this.hasNotPrefix = hasNotPrefix;
 }