private static void CheckConditionalExpression(SyntaxNodeAnalysisContext c) { var conditional = (ConditionalExpressionSyntax)c.Node; var condition = TernaryOperatorPointless.RemoveParentheses(conditional.Condition); var whenTrue = TernaryOperatorPointless.RemoveParentheses(conditional.WhenTrue); var whenFalse = TernaryOperatorPointless.RemoveParentheses(conditional.WhenFalse); if (EquivalenceChecker.AreEquivalent(whenTrue, whenFalse)) { /// handled by S2758, <see cref="TernaryOperatorPointless"/> return; } ExpressionSyntax comparedToNull; bool comparedIsNullInTrue; if (!TryGetExpressionComparedToNull(condition, out comparedToNull, out comparedIsNullInTrue) || !ExpressionCanBeNull(comparedToNull, c.SemanticModel)) { // expression not compared to null, or can't be null return; } if (CanExpressionBeNullCoalescing(whenTrue, whenFalse, comparedToNull, comparedIsNullInTrue, c.SemanticModel)) { c.ReportDiagnostic(Diagnostic.Create(Rule, conditional.GetLocation(), "??")); } }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); var diagnostic = context.Diagnostics.First(); var diagnosticSpan = diagnostic.Location.SourceSpan; var conditional = root.FindNode(diagnosticSpan, getInnermostNodeForTie: true) as ConditionalExpressionSyntax; if (conditional == null) { return; } context.RegisterCodeFix( CodeAction.Create( Title, c => { var newRoot = root.ReplaceNode( conditional, TernaryOperatorPointless.RemoveParentheses(conditional.WhenTrue) .WithAdditionalAnnotations(Formatter.Annotation)); return(Task.FromResult(context.Document.WithSyntaxRoot(newRoot))); }), context.Diagnostics); }
private static bool CanBeSimplified(StatementSyntax statement1, StatementSyntax statement2, ExpressionSyntax comparedToNull, bool comparedIsNullInTrue, SemanticModel semanticModel, out bool isNullCoalescing) { isNullCoalescing = false; var return1 = statement1 as ReturnStatementSyntax; var return2 = statement2 as ReturnStatementSyntax; if (return1 != null && return2 != null) { var retExpr1 = TernaryOperatorPointless.RemoveParentheses(return1.Expression); var retExpr2 = TernaryOperatorPointless.RemoveParentheses(return2.Expression); if (!AreTypesCompatible(return1.Expression, return2.Expression, semanticModel)) { return(false); } if (comparedToNull != null && CanExpressionBeNullCoalescing(retExpr1, retExpr2, comparedToNull, comparedIsNullInTrue, semanticModel)) { isNullCoalescing = true; } return(true); } var expressionStatement1 = statement1 as ExpressionStatementSyntax; var expressionStatement2 = statement2 as ExpressionStatementSyntax; if (expressionStatement1 == null || expressionStatement2 == null) { return(false); } var expression1 = TernaryOperatorPointless.RemoveParentheses(expressionStatement1.Expression); var expression2 = TernaryOperatorPointless.RemoveParentheses(expressionStatement2.Expression); if (AreCandidateAssignments(expression1, expression2, comparedToNull, comparedIsNullInTrue, semanticModel, out isNullCoalescing)) { return(true); } if (comparedToNull != null && CanExpressionBeNullCoalescing(expression1, expression2, comparedToNull, comparedIsNullInTrue, semanticModel)) { isNullCoalescing = true; return(true); } if (AreCandidateInvocationsForTernary(expression1, expression2, semanticModel)) { return(true); } return(false); }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); var diagnostic = context.Diagnostics.First(); var diagnosticSpan = diagnostic.Location.SourceSpan; var syntax = root.FindNode(diagnosticSpan); var semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false); var conditional = syntax as ConditionalExpressionSyntax; if (conditional != null) { var condition = TernaryOperatorPointless.RemoveParentheses(conditional.Condition); var whenTrue = TernaryOperatorPointless.RemoveParentheses(conditional.WhenTrue); var whenFalse = TernaryOperatorPointless.RemoveParentheses(conditional.WhenFalse); ExpressionSyntax compared; bool comparedIsNullInTrue; ConditionalSimplification.TryGetExpressionComparedToNull(condition, out compared, out comparedIsNullInTrue); var annotation = new SyntaxAnnotation(); var coalescing = GetNullCoalescing(whenTrue, whenFalse, compared, semanticModel, annotation); context.RegisterCodeFix( GetActionToExecute(context, root, conditional, coalescing, annotation), context.Diagnostics); } var ifStatement = syntax as IfStatementSyntax; if (ifStatement != null) { var whenTrue = ConditionalSimplification.ExtractSingleStatement(ifStatement.Statement); var whenFalse = ConditionalSimplification.ExtractSingleStatement(ifStatement.Else.Statement); ExpressionSyntax compared; bool comparedIsNullInTrue; ConditionalSimplification.TryGetExpressionComparedToNull(ifStatement.Condition, out compared, out comparedIsNullInTrue); var isNullCoalescing = bool.Parse(diagnostic.Properties[ConditionalSimplification.IsNullCoalescingKey]); var annotation = new SyntaxAnnotation(); var simplified = GetSimplified(whenTrue, whenFalse, ifStatement.Condition, compared, isNullCoalescing, semanticModel, annotation); context.RegisterCodeFix( GetActionToExecute(context, root, ifStatement, simplified, annotation), context.Diagnostics); } }
private static StatementSyntax GetSimplified(StatementSyntax statement1, StatementSyntax statement2, ExpressionSyntax condition, ExpressionSyntax compared, bool isNullCoalescing, SemanticModel semanticModel, SyntaxAnnotation annotation) { var return1 = statement1 as ReturnStatementSyntax; var return2 = statement2 as ReturnStatementSyntax; if (return1 != null && return2 != null) { var retExpr1 = TernaryOperatorPointless.RemoveParentheses(return1.Expression); var retExpr2 = TernaryOperatorPointless.RemoveParentheses(return2.Expression); var createdExpression = isNullCoalescing ? GetNullCoalescing(retExpr1, retExpr2, compared, semanticModel, annotation) : SyntaxFactory.ConditionalExpression( condition, return1.Expression, return2.Expression) .WithAdditionalAnnotations(annotation); return(SyntaxFactory.ReturnStatement(createdExpression)); } var expressionStatement1 = statement1 as ExpressionStatementSyntax; var expressionStatement2 = statement2 as ExpressionStatementSyntax; var expression1 = TernaryOperatorPointless.RemoveParentheses(expressionStatement1.Expression); var expression2 = TernaryOperatorPointless.RemoveParentheses(expressionStatement2.Expression); var assignment = GetSimplifiedAssignment(expression1, expression2, condition, compared, isNullCoalescing, semanticModel, annotation); if (assignment != null) { return(SyntaxFactory.ExpressionStatement(assignment)); } var expression = GetSimplificationFromInvocations(expression1, expression2, condition, compared, isNullCoalescing, semanticModel, annotation); if (expression != null) { return(SyntaxFactory.ExpressionStatement(expression)); } return(null); }