// This is kinda duplicated in CodeBlockAnalyzer.GetAssignmentStatus private void CheckExpressionForNull(ISymbol symbol, ExpressionSyntax expression, MethodFlowAnalysis analysis = null) { var expressionValueType = expression.GetTypeOfValue(context.SemanticModel); if (expressionValueType == ValueType.NotNull) { // Argument cannot be null, so move to the next return; } if (expressionValueType == ValueType.Null) { context.ReportDiagnostic(MainAnalyzer.CreateReturnNull(expression.GetLocation(), symbol.ToString())); return; } if (analysis == null) { context.ReportDiagnostic(MainAnalyzer.CreateReturnNull(expression.GetLocation(), symbol.ToString())); return; } ExpressionStatus status = analysis.IsAlwaysAssigned(expression, expression); if (!status.IsAssigned()) { context.ReportDiagnostic(MainAnalyzer.CreateReturnNull(expression.GetLocation(), symbol.ToString())); } if (status == ExpressionStatus.AssignedWithUnneededConstraint) { context.ReportDiagnostic(MainAnalyzer.CreateUnneededConstraint(expression.GetLocation(), symbol.ToString())); } }
private void ReportIssue(ExpressionStatus status, Location location, string errorContext) { switch (status) { case ExpressionStatus.NotAssigned: context.ReportDiagnostic(MainAnalyzer.CreateNullAssignmentError(location, errorContext)); break; case ExpressionStatus.ReassignedAfterCondition: context.ReportDiagnostic(MainAnalyzer.CreateAssignmentAfterCondition(location, errorContext)); break; case ExpressionStatus.AssignedWithUnneededConstraint: context.ReportDiagnostic(MainAnalyzer.CreateUnneededConstraint(location, errorContext)); break; } }
public override void VisitAssignmentExpression(AssignmentExpressionSyntax node) { base.VisitAssignmentExpression(node); var valueType = node.Right.GetTypeOfValue(context.SemanticModel); if (valueType == ValueType.NotNull) { return; } var target = node.Left.FindUnderlyingMember(); if (target == null) { return; } var symbol = context.SemanticModel.GetSymbolInfo(target).Symbol; if (!symbol.HasNotNullOrCheckNull()) { return; } switch (GetAssignmentStatus(node.Right, node, valueType)) { case ExpressionStatus.NotAssigned: context.ReportDiagnostic(MainAnalyzer.CreateNullAssignmentError(node.GetLocation(), symbol)); break; case ExpressionStatus.ReassignedAfterCondition: context.ReportDiagnostic(MainAnalyzer.CreateAssignmentAfterCondition(node.GetLocation(), node.ToString())); break; case ExpressionStatus.AssignedWithUnneededConstraint: context.ReportDiagnostic(MainAnalyzer.CreateUnneededConstraint(node.GetLocation(), node.ToString())); break; } }
public override void VisitInvocationExpression(InvocationExpressionSyntax node) { base.VisitInvocationExpression(node); var methodDefinition = context.SemanticModel.GetSymbolInfo(node).Symbol as IMethodSymbol; if (methodDefinition == null) { return; } if (node.IsCheckAgainstNull(methodDefinition, out var target, out var valueType)) { ReportIfIsNotNullSymbol(target); } if (methodDefinition.IsConstraintMethod()) { if (node.IsConstraint(context.SemanticModel, out var expression)) { var symbol = context.SemanticModel.GetSymbolInfo(expression).Symbol; if (symbol.HasNotNullOrCheckNull()) { context.ReportDiagnostic(MainAnalyzer.CreateUnneededConstraint(node.GetLocation(), symbol.ToString())); } } else { context.ReportDiagnostic(MainAnalyzer.CreateInvalidConstraintError(node.GetLocation())); } } CheckMethodInvocation( node, methodDefinition, node.ArgumentList, (status, location, error) => ReportIssue(status, location, error)); }