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); }
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)); }
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); }
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 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)))); }
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)))); }
public bool IsNull(ExpressionKey key) { return(value == ValueType.Null && this.Key.Contains(key)); }
public Part(ExpressionKey key, ExpressionSyntax expression, ValueType value) { this.Key = key; this.Expression = expression; this.value = value; }
public bool IsNull(ExpressionKey key) { return(hasNotPrefix && this.Key.Contains(key)); }
public Condition(ConditionType kind, ExpressionKey key, ExpressionSyntax expression, ValueType value) { this.Kind = kind; parts = ImmutableArray.Create <IPart>(new Part(key, expression, value)); }
public IsPart(ExpressionKey key, ExpressionSyntax expression, bool hasNotPrefix) { this.Key = key; this.Expression = expression; this.hasNotPrefix = hasNotPrefix; }