private async Task<Document> FixSpacingAsync(Document document, IfStatementSyntax ifStatement, CancellationToken c) { // This method will generate a new if-statement node with a single space between the if-keyword and the opening parenthesis. var generator = SyntaxGenerator.GetGenerator(document); // The new if-statement will need to retain the same statements as the old if-statement. var ifBlock = ifStatement.Statement as BlockSyntax; var ifBlockStatements = ifBlock.Statements; // The new if-statement should retain the formatting of the trivia before and after the if-statement. // The following statements extract the original trivia. var ifKeyword = ifStatement.IfKeyword; var leadingTrivia = ifKeyword.LeadingTrivia; var closeBrace = ifBlock.CloseBraceToken; var trailingTrivia = closeBrace.TrailingTrivia; // If-statements generated using SyntaxGenerator are formatted with the desired spacing by default so this is not specified explicitly. var newIfStatement = generator.IfStatement(ifStatement.Condition, ifBlockStatements).WithLeadingTrivia(leadingTrivia).WithTrailingTrivia(trailingTrivia); // This statement gets the top of the syntax tree so that the old if-statement node can be replaced with the new one. var root = await document.GetSyntaxRootAsync(); // A new root is created with the old if-statement replaced by the new one. var newRoot = root.ReplaceNode(ifStatement, newIfStatement); // A new document with the new root is returned. var newDocument = document.WithSyntaxRoot(newRoot); return newDocument; }
static bool GetMatch(IfStatementSyntax node, out ExpressionSyntax c, out ReturnStatementSyntax e1, out ReturnStatementSyntax e2, out ReturnStatementSyntax rs) { rs = e1 = e2 = null; c = node.Condition; //attempt to match if(condition) return else return e1 = ConvertIfStatementToNullCoalescingExpressionAction.GetSimpleStatement(node.Statement) as ReturnStatementSyntax; if (e1 == null) return false; e2 = node.Else != null ? ConvertIfStatementToNullCoalescingExpressionAction.GetSimpleStatement(node.Else.Statement) as ReturnStatementSyntax : null; //match if (e1 != null && e2 != null) { return true; } //attempt to match if(condition) return if (e1 != null) { rs = node.Parent.ChildThatContainsPosition(node.GetTrailingTrivia().Max(t => t.FullSpan.End) + 1).AsNode() as ReturnStatementSyntax; if (rs != null) { e2 = rs; return true; } } return false; }
static bool HasConflictingNames(SyntaxNodeAnalysisContext nodeContext, IfStatementSyntax ifElseStatement) { var block = ifElseStatement.Else.Statement as BlockSyntax; if (block == null || block.Statements.Count == 0) return false; var member = ifElseStatement.Ancestors().FirstOrDefault(a => a is MemberDeclarationSyntax); var priorLocalDeclarations = new List<string>(); foreach (var localDecl in member.DescendantNodes().Where(n => n.SpanStart < ifElseStatement.Else.SpanStart).OfType<LocalDeclarationStatementSyntax>()) { foreach (var v in localDecl.Declaration.Variables) priorLocalDeclarations.Add(v.Identifier.ValueText); } foreach (var sym in block.Statements) { var decl = sym as LocalDeclarationStatementSyntax; if (decl == null) continue; if (priorLocalDeclarations.Contains(s => decl.Declaration.Variables.Any(v => v.Identifier.ValueText == s))) return true; } return false; }
static bool GetMatch(IfStatementSyntax node, out ExpressionSyntax c, out ReturnStatementSyntax e1, out ReturnStatementSyntax e2, out ReturnStatementSyntax rs) { rs = e1 = e2 = null; c = node.Condition; //attempt to match if(condition) return else return e1 = ConvertIfStatementToNullCoalescingExpressionAction.GetSimpleStatement(node.Statement) as ReturnStatementSyntax; if (e1 == null) return false; e2 = node.Else != null ? ConvertIfStatementToNullCoalescingExpressionAction.GetSimpleStatement(node.Else.Statement) as ReturnStatementSyntax : null; //match if (e1 != null && e2 != null) { return true; } //attempt to match if(condition) return; return if (e1 != null) { var parentBlock = node.Parent as BlockSyntax; if (parentBlock == null) return false; var index = parentBlock.Statements.IndexOf(node); if (index + 1 < parentBlock.Statements.Count) { rs = parentBlock.Statements[index + 1] as ReturnStatementSyntax; } if (rs != null) { e2 = rs; return true; } } return false; }
public static IEnumerable<StatementSyntax> LopsidedTerminalBranchesToGuardedBranches(IfStatementSyntax syntax) { Contract.Requires(syntax != null); Contract.Requires(syntax.Parent is BlockSyntax); if (syntax.Statement.IsGuaranteedToJumpOut()) return new[] { syntax }; if (syntax.Else != null && syntax.Else.Statement.IsGuaranteedToJumpOut()) return new[] { syntax }; var allowedJump = syntax.TryGetEquivalentJumpAfterStatement(); if (allowedJump == null) return new[] { syntax }; var trueBloat = syntax.Statement.Bloat(); var falseBloat = syntax.Else == null ? 0 : syntax.Else.Statement.Bloat(); if (trueBloat < falseBloat * 2 - 10) { // inline the false branch, guard with the true branch return syntax.Else.Statement.Statements().Prepend( syntax.WithStatement(syntax.Statement.BracedTo(syntax.Statement.Statements().Concat(new[] {allowedJump}))) .WithElse(null)); } if (falseBloat < trueBloat * 2 - 10) { // inline the true branch, guard with the false branch return syntax.Statement.Statements().Prepend( syntax.WithCondition(syntax.Condition.Inverted()) .WithStatement(syntax.Else == null ? allowedJump : syntax.Else.Statement.BracedTo(syntax.Else.Statement.Statements().Concat(new[] {allowedJump}))) .WithElse(null)); } return new[] { syntax }; }
public BoundIfStatement(IfStatementSyntax syntax, BoundExpression condition, BoundStatement consequence, BoundStatement alternativeOpt) : base(BoundNodeKind.IfStatement, syntax) { Condition = condition; Consequence = consequence; AlternativeOpt = alternativeOpt; }
protected override SyntaxNode VisitIfStatement(IfStatementSyntax node) { if (!node.DescendentNodes().OfType<BlockSyntax>().Any()) { node = node.Update (node.IfKeyword, node.OpenParenToken, node.Condition, node.CloseParenToken, Syntax.Block (statements: node.Statement), node.ElseOpt); } if (node.ElseOpt != null) { ElseClauseSyntax elseOpt = node.ElseOpt; IfStatementSyntax ifSyntax = elseOpt.Statement as IfStatementSyntax; if (ifSyntax != null) { if (!ifSyntax.DescendentNodes().OfType<BlockSyntax>().Any()) { ifSyntax = ifSyntax.Update (ifSyntax.IfKeyword, ifSyntax.OpenParenToken, ifSyntax.Condition, ifSyntax.CloseParenToken, Syntax.Block (statements: ifSyntax.Statement), ifSyntax.ElseOpt); elseOpt = elseOpt.Update (elseOpt.ElseKeyword, ifSyntax); } } else if (!elseOpt.DescendentNodes().OfType<BlockSyntax>().Any()) elseOpt = node.ElseOpt.Update (node.ElseOpt.ElseKeyword, Syntax.Block (statements: node.ElseOpt.Statement)); if (elseOpt != node.ElseOpt) node = node.Update (node.IfKeyword, node.OpenParenToken, node.Condition, node.CloseParenToken, node.Statement, elseOpt); } return base.VisitIfStatement (node); }
private static SyntaxNode CalculateNewRoot(SyntaxNode root, IfStatementSyntax ifStatement) { SyntaxNode newRoot; var isTrue = ifStatement.Condition.IsKind(SyntaxKind.TrueLiteralExpression); if (isTrue) { var block = ifStatement.Statement as BlockSyntax; newRoot = block == null ? root.ReplaceNode(ifStatement, ifStatement.Statement) : root.ReplaceNode(ifStatement, block.Statements); } else { if (ifStatement.Else == null) { newRoot = root.RemoveNode(ifStatement, SyntaxRemoveOptions.KeepNoTrivia); } else { var block = ifStatement.Else.Statement as BlockSyntax; newRoot = block == null ? root.ReplaceNode(ifStatement, ifStatement.Else.Statement) : root.ReplaceNode(ifStatement, block.Statements); } } return newRoot.WithAdditionalAnnotations(Formatter.Annotation); }
public static IfStatementSyntax AddBraces(IfStatementSyntax ifStatement) { Debug.Assert(ifStatement != null && NeedsBraces(ifStatement)); return ifStatement .WithStatement(SyntaxFactory.Block(ifStatement.Statement)) .WithAdditionalAnnotations(Formatter.Annotation); }
private Document ConvertToConditional(Document document, SemanticModel semanticModel, IfStatementSyntax ifStatement, StatementSyntax replacementStatement, CancellationToken cancellationToken) { var oldRoot = semanticModel.SyntaxTree.GetRoot(); var newRoot = oldRoot.ReplaceNode( oldNode: ifStatement, newNode: replacementStatement.WithAdditionalAnnotations(Formatter.Annotation)); return document.WithSyntaxRoot(newRoot); }
private void HandleIf(SyntaxNodeAnalysisContext context, IfStatementSyntax ifStatement) { if (ifStatement.Statement is BlockSyntax) { return; } context.ReportDiagnostic(Diagnostic.Create(Rule, ifStatement.IfKeyword.GetLocation())); }
public BoundIfStatement( BoundExpression boundExpression, BoundScopeStatement boundStatements, IfStatementSyntax statementSyntax) : base(statementSyntax) { BoundExpression = boundExpression; BoundStatements = boundStatements; }
private async Task<Document> AddBracesAsync(Document document, IfStatementSyntax ifStatement, CancellationToken cancellationToken) { var nonBlockedStatement = ifStatement.Statement as ExpressionStatementSyntax; var newBlockedStatement = SyntaxFactory.Block(statements: nonBlockedStatement).WithAdditionalAnnotations(annotations: Formatter.Annotation); var newIfStatement = ifStatement.ReplaceNode(oldNode: nonBlockedStatement, newNode: newBlockedStatement); var root = await document.GetSyntaxRootAsync(); var newRoot = root.ReplaceNode(oldNode: ifStatement, newNode: newIfStatement); var newDocument = document.WithSyntaxRoot(newRoot); return newDocument; }
public static string IfStatement(IfStatementSyntax statement) { var output = statement.IfKeyword.Text + " ("; output += SyntaxNode(statement.Condition); output += ")" + NewLine + SyntaxNode(statement.Statement); if (statement.Else != null) { output += SyntaxNode(statement.Else); } return output; }
internal static bool ParseIfStatement(IfStatementSyntax node, out ExpressionSyntax condition, out ExpressionSyntax target, out AssignmentExpressionSyntax whenTrue, out AssignmentExpressionSyntax whenFalse) { condition = null; target = null; whenTrue = null; whenFalse = null; if (node == null || node.Else == null || node.Parent is IfStatementSyntax || node.Else.Statement is IfStatementSyntax) return false; condition = node.Condition; //make sure to check for multiple statements ExpressionStatementSyntax whenTrueExprStatement, whenFalseExprStatement; var embeddedBlock = node.Statement as BlockSyntax; if (embeddedBlock != null) { if (embeddedBlock.Statements.Count > 1) return false; var childNodes = embeddedBlock.ChildNodes(); if (childNodes.Count() > 1) return false; whenTrueExprStatement = childNodes.OfType<ExpressionStatementSyntax>().FirstOrDefault(); } else { whenTrueExprStatement = node.Statement as ExpressionStatementSyntax; } var elseBlock = node.Else.Statement as BlockSyntax; if (elseBlock != null) { if (elseBlock.Statements.Count > 1) return false; var childNodes = elseBlock.ChildNodes(); if (childNodes.Count() > 1) return false; whenFalseExprStatement = childNodes.OfType<ExpressionStatementSyntax>().FirstOrDefault(); } else { whenFalseExprStatement = node.Else.Statement as ExpressionStatementSyntax; } if (whenTrueExprStatement == null || whenFalseExprStatement == null) return false; whenTrue = whenTrueExprStatement.Expression as AssignmentExpressionSyntax; whenFalse = whenFalseExprStatement.Expression as AssignmentExpressionSyntax; if (whenTrue == null || whenFalse == null || whenTrue.Kind() != whenFalse.Kind() || !SyntaxFactory.AreEquivalent(whenTrue.Left, whenFalse.Left)) return false; return true; }
static bool ElseIsRedundantControlFlow(IfStatementSyntax ifElseStatement, SyntaxNodeAnalysisContext syntaxNode) { if (ifElseStatement.Else == null || ifElseStatement.Parent is ElseClauseSyntax) return false; var blockSyntax = ifElseStatement.Else.Statement as BlockSyntax; if (blockSyntax != null && blockSyntax.Statements.Count == 0) return true; var result = syntaxNode.SemanticModel.AnalyzeControlFlow(ifElseStatement.Statement); return !result.EndPointIsReachable; }
private static async Task<Document> UseExistenceOperatorAsyncWithReturnAsync(Document document, IfStatementSyntax ifStatement, CancellationToken cancellationToken, ReturnStatementSyntax returnIf) { var newMemberAccess = ((MemberAccessExpressionSyntax)returnIf.Expression).ToConditionalAccessExpression(); var newReturn = SyntaxFactory.ReturnStatement(newMemberAccess) .WithLeadingTrivia(ifStatement.GetLeadingTrivia()) .WithTrailingTrivia(ifStatement.GetTrailingTrivia()) .WithAdditionalAnnotations(Formatter.Annotation); var root = await document.GetSyntaxRootAsync(cancellationToken); var newRoot = root.ReplaceNode(ifStatement, newReturn); var newDocument = document.WithSyntaxRoot(newRoot); return newDocument; }
private static async Task<Document> UseExistenceOperatorAsyncWithAssignmentAsync(Document document, IfStatementSyntax ifStatement, CancellationToken cancellationToken, ExpressionStatementSyntax expressionIf) { var memberAccessAssignment = (AssignmentExpressionSyntax)expressionIf.Expression; var newMemberAccess = ((MemberAccessExpressionSyntax)memberAccessAssignment.Right).ToConditionalAccessExpression(); var newExpressionStatement = SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, memberAccessAssignment.Left, newMemberAccess)) .WithLeadingTrivia(ifStatement.GetLeadingTrivia()) .WithTrailingTrivia(ifStatement.GetTrailingTrivia()) .WithAdditionalAnnotations(Formatter.Annotation); var root = await document.GetSyntaxRootAsync(cancellationToken); var newRoot = root.ReplaceNode(ifStatement, newExpressionStatement); var newDocument = document.WithSyntaxRoot(newRoot); return newDocument; }
private BoundIfStatement BindIfStatement(IfStatementSyntax node) { Debug.Assert(node != null); var condition = BindBooleanExpression(node.Condition); var consequence = BindStatement(node.Statement); if (node.ElseOpt == null) { return new BoundIfStatement(node, condition, consequence, null); } var alternative = BindStatement(node.ElseOpt.Statement); return new BoundIfStatement(node, condition, consequence, alternative); }
private static SyntaxNode MergeIfs(IfStatementSyntax ifStatement, SyntaxNode root) { var nestedIf = (IfStatementSyntax)ifStatement.Statement.GetSingleStatementFromPossibleBlock(); var newIf = ifStatement .WithCondition(SyntaxFactory.BinaryExpression(SyntaxKind.LogicalAndExpression, ifStatement.Condition, nestedIf.Condition)) .WithStatement(nestedIf.Statement) .WithLeadingTrivia(ifStatement.GetLeadingTrivia().AddRange(nestedIf.GetLeadingTrivia())) .WithAdditionalAnnotations(Formatter.Annotation); if (ifStatement.HasTrailingTrivia && nestedIf.HasTrailingTrivia && !ifStatement.GetTrailingTrivia().Equals(nestedIf.GetTrailingTrivia())) newIf = newIf.WithTrailingTrivia(ifStatement.GetTrailingTrivia().AddRange(nestedIf.GetTrailingTrivia())); var newRoot = root.ReplaceNode(ifStatement, newIf); return newRoot; }
public static bool TryGetNewReturnStatement(IfStatementSyntax ifStatement, SemanticModel semanticModel, out ReturnStatementSyntax returnStatement) { returnStatement = null; var conditional = new ReturnConditionalAnalyzer(ifStatement, semanticModel).CreateConditional(); if (conditional == null) { return false; } returnStatement = SyntaxFactory.ReturnStatement(conditional); return true; }
private async Task<Document> MakeBlockAsync(Document document, IfStatementSyntax ifStatement, CancellationToken cancellationToken) { var nodes = new List<Tuple<SyntaxNode, SyntaxNode>>(); StatementSyntax thenClause = ifStatement.Statement; if (thenClause != null && !(thenClause is BlockSyntax)) { nodes.Add(new Tuple<SyntaxNode, SyntaxNode>(thenClause, SyntaxFactory.Block(thenClause))); } StatementSyntax elseClause = ifStatement.Else?.Statement; if (elseClause != null) { if (elseClause is BlockSyntax == false && elseClause is IfStatementSyntax == false) { nodes.Add(new Tuple<SyntaxNode, SyntaxNode>(elseClause, SyntaxFactory.Block(elseClause))); } } return await this.ReplaceNodesInDocumentAsync(document, cancellationToken, nodes.ToArray()); }
private static void CheckIf(SyntaxNodeAnalysisContext context, IfStatementSyntax ifStatement) { if (ifStatement.GetPrecedingIfsInConditionChain().Any()) { return; } var lastStatementInIfChain = GetLastStatementInIfChain(ifStatement); if (IsStatementCandidateLoop(lastStatementInIfChain)) { return; } CheckStatement(context, lastStatementInIfChain, "conditionally", "unconditionally"); }
private static IEnumerable<StatementSyntax> InlineLargeGuardedBranches2(IfStatementSyntax syntax) { Contract.Requires(syntax != null); var trueIsAGuard = syntax.Statement.IsGuaranteedToJumpOut(); var falseIsAGuard = syntax.Else != null && syntax.Statement.IsGuaranteedToJumpOut(); var preferTrue = trueIsAGuard; if (trueIsAGuard == falseIsAGuard && syntax.Else != null) { preferTrue = 2 * syntax.Statement.Bloat() >= syntax.Else.Bloat(); } if (trueIsAGuard && preferTrue) return syntax.WithUnguardedElse(); if (falseIsAGuard && !preferTrue) return syntax.Inverted().WithUnguardedElse(); return new[] { syntax }; }
public override SyntaxNode VisitIfStatement(IfStatementSyntax node) { node = (IfStatementSyntax)base.VisitIfStatement(node); if (node.Statement.Kind == SyntaxKind.Block) { return node; } var block = Syntax.Block(statements: Syntax.List(node.Statement)); return Syntax.IfStatement( node.IfKeyword, node.OpenParenToken, node.Condition, node.CloseParenToken, block, node.Else); }
private async Task<Document> FixSpacingAsync(Document document, IfStatementSyntax ifStatement, CancellationToken c) { var generator = SyntaxGenerator.GetGenerator(document); var ifKeyword = ifStatement.IfKeyword; var ifBlock = ifStatement.Statement as BlockSyntax; var closeBrace = ifBlock.CloseBraceToken; var ifBlockStatements = ifBlock.Statements; var leadingTrivia = ifKeyword.LeadingTrivia; var trailingTrivia = closeBrace.TrailingTrivia; var newIfStatement = generator.IfStatement(ifStatement.Condition, ifBlockStatements).WithLeadingTrivia(leadingTrivia).WithTrailingTrivia(trailingTrivia); var root = await document.GetSyntaxRootAsync(); var newRoot = root.ReplaceNode(ifStatement, newIfStatement); var newDocument = document.WithSyntaxRoot(newRoot); return newDocument; }
private static IfStatementSyntax GetParentIfStatement(IfStatementSyntax ifStatement) { var parent = ifStatement.Parent; while (parent is BlockSyntax) { var block = (BlockSyntax) parent; if (block.Statements.Count != 1) { return null; } parent = parent.Parent; } var parentIfStatement = parent as IfStatementSyntax; return parentIfStatement; }
public IEnumerable<string> Inspect(IfStatementSyntax ifElseStatement) { bool trueStatementIsReturnBoolLiteral = (ifElseStatement.Statement as ReturnStatementSyntax) .Call(r => r.Expression as LiteralExpressionSyntax) .Call(IsBoolLiteral, false); bool? falseStatementIsReturnBoolLiteral = ifElseStatement.Else .Call(e => e.Statement as ReturnStatementSyntax) .Call(r => r.Expression as LiteralExpressionSyntax) .Call(e => (bool?)IsBoolLiteral(e), null); var nextSibling = ifElseStatement.Parent.ChildNodes().SkipWhile(n => n != ifElseStatement).Skip(1).FirstOrDefault(); falseStatementIsReturnBoolLiteral = falseStatementIsReturnBoolLiteral ?? (nextSibling as ReturnStatementSyntax) .Call(r => r.Expression as LiteralExpressionSyntax) .Call(IsBoolLiteral, false); if (trueStatementIsReturnBoolLiteral && falseStatementIsReturnBoolLiteral == true) yield return Report(ifElseStatement, "Используйте return вместо if"); }
static ExpressionSyntax CheckNode(IfStatementSyntax node, out ExpressionSyntax rightSide) { rightSide = null; var condition = node.Condition as BinaryExpressionSyntax; if (condition == null || !(condition.IsKind(SyntaxKind.EqualsExpression) || condition.IsKind(SyntaxKind.NotEqualsExpression))) return null; var nullSide = condition.Right as LiteralExpressionSyntax; bool nullIsRight = true; if (nullSide == null || !nullSide.IsKind(SyntaxKind.NullLiteralExpression)) { nullSide = condition.Left as LiteralExpressionSyntax; nullIsRight = false; if (nullSide == null || !nullSide.IsKind(SyntaxKind.NullLiteralExpression)) return null; } bool isEquality = condition.IsKind(SyntaxKind.EqualsExpression); StatementSyntax contentStatement; if (isEquality) { contentStatement = node.Statement; if (node.Else != null && !IsEmpty(node.Else.Statement)) return null; } else { contentStatement = node.Else != null ? node.Else.Statement : null; if (!IsEmpty(node.Statement)) return null; } contentStatement = GetSimpleStatement(contentStatement); if (contentStatement == null) return null; var assignExpr = (contentStatement as ExpressionStatementSyntax)?.Expression as AssignmentExpressionSyntax; if (assignExpr == null || !assignExpr.Left.IsEquivalentTo(nullIsRight ? condition.Left : condition.Right, true)) return null; rightSide = assignExpr.Right; return nullIsRight ? condition.Left : condition.Right; }
private static bool TrySearchForIfThenContinueStatement(ForEachStatementSyntax fe, out IfStatementSyntax ifStatement, out string ifType) { if (fe.Statement is BlockSyntax) { var block = ((BlockSyntax)fe.Statement); if ((block.Statements.Count > 1 && block.Statements.First() is IfStatementSyntax) || (block.Statements.Count > 0 && block.Statements.First() is IfStatementSyntax && ((IfStatementSyntax)block.Statements.First()).Else != null) ) { ifStatement = (block.Statements.FirstOrDefault() as IfStatementSyntax); if (ifStatement?.Statement is ContinueStatementSyntax || ((ifStatement?.Statement as BlockSyntax)?.Statements)?.FirstOrDefault() is ContinueStatementSyntax) { ifType = IfWithContinueToWhere; return true; } } } ifStatement = null; ifType = null; return false; }
public bool TryGetPatternPieces( BinaryExpressionSyntax isExpression, out IfStatementSyntax ifStatement, out LocalDeclarationStatementSyntax localDeclarationStatement, out VariableDeclaratorSyntax declarator, out CastExpressionSyntax castExpression) { ifStatement = null; localDeclarationStatement = null; declarator = null; castExpression = null; // The is check has to be in an if check: "if (x is Type) if (!isExpression.Parent.IsKind(SyntaxKind.IfStatement)) { return(false); } ifStatement = (IfStatementSyntax)isExpression.Parent; if (!ifStatement.Statement.IsKind(SyntaxKind.Block)) { return(false); } var ifBlock = (BlockSyntax)ifStatement.Statement; if (ifBlock.Statements.Count == 0) { return(false); } var firstStatement = ifBlock.Statements[0]; if (!firstStatement.IsKind(SyntaxKind.LocalDeclarationStatement)) { return(false); } localDeclarationStatement = (LocalDeclarationStatementSyntax)firstStatement; if (localDeclarationStatement.Declaration.Variables.Count != 1) { return(false); } declarator = localDeclarationStatement.Declaration.Variables[0]; if (declarator.Initializer == null) { return(false); } var declaratorValue = declarator.Initializer.Value.WalkDownParentheses(); if (!declaratorValue.IsKind(SyntaxKind.CastExpression)) { return(false); } castExpression = (CastExpressionSyntax)declaratorValue; if (!SyntaxFactory.AreEquivalent(isExpression.Left.WalkDownParentheses(), castExpression.Expression.WalkDownParentheses(), topLevel: false) || !SyntaxFactory.AreEquivalent(isExpression.Right.WalkDownParentheses(), castExpression.Type, topLevel: false)) { return(false); } return(true); }
private static bool TryGetNotEqualsCondition(IfStatementSyntax ifStatement, out BinaryExpressionSyntax condition) { condition = ifStatement.Condition?.RemoveParentheses() as BinaryExpressionSyntax; return(condition != null && condition.IsKind(SyntaxKind.NotEqualsExpression)); }
public override void VisitIfStatement(IfStatementSyntax node) { AddExpressionTerms(node.Condition, _expressions); }
public static BracesAnalysis AnalyzeBraces(IfStatementSyntax ifStatement) { bool anyHasEmbedded = false; bool anyHasBlock = false; bool allSupportsEmbedded = true; int cnt = 0; foreach (IfStatementOrElseClause ifOrElse in ifStatement.AsCascade()) { cnt++; StatementSyntax statement = ifOrElse.Statement; if (!anyHasEmbedded && statement.Kind() != SyntaxKind.Block) { anyHasEmbedded = true; } if (!anyHasBlock && statement.Kind() == SyntaxKind.Block) { anyHasBlock = true; } if (allSupportsEmbedded && !SupportsEmbedded(statement)) { allSupportsEmbedded = false; } if (cnt > 1 && anyHasEmbedded && !allSupportsEmbedded) { return(BracesAnalysisFlags.AddBraces); } } if (cnt > 1 && allSupportsEmbedded && anyHasBlock) { if (anyHasEmbedded) { return(BracesAnalysisFlags.AddBraces | BracesAnalysisFlags.RemoveBraces); } else { return(BracesAnalysisFlags.RemoveBraces); } } return(BracesAnalysisFlags.None); bool SupportsEmbedded(StatementSyntax statement) { if (statement.IsParentKind(SyntaxKind.IfStatement) && ((IfStatementSyntax)statement.Parent).Condition?.IsMultiLine() == true) { return(false); } if (statement.Kind() == SyntaxKind.Block) { var block = (BlockSyntax)statement; statement = block.Statements.SingleOrDefault(shouldThrow: false); if (statement == null) { return(false); } } return(!statement.IsKind(SyntaxKind.LocalDeclarationStatement, SyntaxKind.LabeledStatement) && statement.IsSingleLine()); } }
public override void VisitIfStatement(IfStatementSyntax node) { base.VisitIfStatement(node); _counter++; }
internal static void Analyze(SyntaxNodeAnalysisContext context, IfStatementSyntax ifStatement) { Analyze(context, ifStatement, ifStatement.CloseParenToken, ifStatement.Statement); }
internal static SyntaxToken GetFirstExcludedToken(StatementSyntax statement) { Debug.Assert(statement != null); switch (statement.Kind()) { case SyntaxKind.Block: return(((BlockSyntax)statement).CloseBraceToken); case SyntaxKind.BreakStatement: return(((BreakStatementSyntax)statement).EosToken); case SyntaxKind.CheckedStatement: case SyntaxKind.UncheckedStatement: return(((CheckedStatementSyntax)statement).Block.CloseBraceToken); case SyntaxKind.ContinueStatement: return(((ContinueStatementSyntax)statement).EosToken); case SyntaxKind.LocalDeclarationStatement: return(((LocalDeclarationStatementSyntax)statement).EosToken); case SyntaxKind.DoStatement: return(((DoStatementSyntax)statement).EosToken); case SyntaxKind.EmptyStatement: return(((EmptyStatementSyntax)statement).EosToken); case SyntaxKind.ExpressionStatement: return(((ExpressionStatementSyntax)statement).EosToken); case SyntaxKind.FixedStatement: return(GetFirstExcludedToken(((FixedStatementSyntax)statement).Statement)); case SyntaxKind.ForStatement: return(GetFirstExcludedToken(((ForStatementSyntax)statement).Statement)); case SyntaxKind.GotoDefaultStatement: case SyntaxKind.GotoCaseStatement: case SyntaxKind.GotoStatement: return(((GotoStatementSyntax)statement).EosToken); case SyntaxKind.IfStatement: IfStatementSyntax ifStmt = (IfStatementSyntax)statement; ElseClauseSyntax elseOpt = ifStmt.Else; return(GetFirstExcludedToken(elseOpt == null ? ifStmt.Statement : elseOpt.Statement)); case SyntaxKind.LabeledStatement: return(GetFirstExcludedToken(((LabeledStatementSyntax)statement).Statement)); case SyntaxKind.LockStatement: return(GetFirstExcludedToken(((LockStatementSyntax)statement).Statement)); case SyntaxKind.ReturnStatement: return(((ReturnStatementSyntax)statement).EosToken); case SyntaxKind.SwitchStatement: return(((SwitchStatementSyntax)statement).CloseBraceToken); case SyntaxKind.ThrowStatement: return(((ThrowStatementSyntax)statement).EosToken); case SyntaxKind.TryStatement: TryStatementSyntax tryStmt = (TryStatementSyntax)statement; FinallyClauseSyntax finallyClause = tryStmt.Finally; if (finallyClause != null) { return(finallyClause.Block.CloseBraceToken); } CatchClauseSyntax lastCatch = tryStmt.Catches.LastOrDefault(); if (lastCatch != null) { return(lastCatch.Block.CloseBraceToken); } return(tryStmt.Block.CloseBraceToken); case SyntaxKind.UnsafeStatement: return(((UnsafeStatementSyntax)statement).Block.CloseBraceToken); case SyntaxKind.UsingStatement: return(GetFirstExcludedToken(((UsingStatementSyntax)statement).Statement)); case SyntaxKind.WhileStatement: return(GetFirstExcludedToken(((WhileStatementSyntax)statement).Statement)); case SyntaxKind.YieldReturnStatement: case SyntaxKind.YieldBreakStatement: return(((YieldStatementSyntax)statement).EosToken); case SyntaxKind.LocalFunctionStatement: LocalFunctionStatementSyntax localFunctionStmt = (LocalFunctionStatementSyntax)statement; if (localFunctionStmt.Body != null) { return(GetFirstExcludedToken(localFunctionStmt.Body)); } if (localFunctionStmt.EosToken != default(SyntaxToken)) { return(localFunctionStmt.EosToken); } return(localFunctionStmt.ParameterList.GetLastToken()); default: throw ExceptionUtilities.UnexpectedValue(statement.Kind()); } }
private static async Task <Document> RefactorAsync( Document document, IfStatementSyntax ifStatement, CancellationToken cancellationToken) { ExpressionSyntax condition = ifStatement.Condition; ElseClauseSyntax elseClause = ifStatement.Else; if ((ifStatement.Statement as BlockSyntax)?.Statements.Any() == false) { SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); ExpressionSyntax newCondition = Negator.LogicallyNegate(condition, semanticModel, cancellationToken); StatementSyntax statement = elseClause.Statement; if (statement is IfStatementSyntax nestedIf) { newCondition = LogicalAndExpression(newCondition.Parenthesize(), nestedIf.Condition.Parenthesize()); statement = nestedIf.Statement; } cancellationToken.ThrowIfCancellationRequested(); IfStatementSyntax newNode = ifStatement.Update( ifStatement.IfKeyword, ifStatement.OpenParenToken, newCondition, ifStatement.CloseParenToken, statement, default(ElseClauseSyntax)); newNode = newNode.WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(ifStatement, newNode, cancellationToken).ConfigureAwait(false)); } else if (elseClause != null) { WhileStatementSyntax whileStatement; if (ifStatement.Parent is BlockSyntax block) { whileStatement = (WhileStatementSyntax)block.Parent; } else { block = Block(); whileStatement = (WhileStatementSyntax)ifStatement.Parent; } cancellationToken.ThrowIfCancellationRequested(); BlockSyntax newBlock = (ifStatement.Statement is BlockSyntax ifBlock) ? block.WithStatements(ifBlock.Statements) : block.WithStatements(SingletonList(ifStatement.Statement)); SyntaxNode newNode = whileStatement.Update( whileStatement.WhileKeyword, whileStatement.OpenParenToken, ifStatement.Condition, whileStatement.CloseParenToken, newBlock); newNode = newNode.WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(whileStatement, newNode, cancellationToken).ConfigureAwait(false)); } else { var block = (BlockSyntax)ifStatement.Parent; SyntaxList <StatementSyntax> statements = block.Statements; BlockSyntax newBlock = block.WithStatements(statements.Remove(ifStatement)); SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); ExpressionSyntax newCondition = Negator.LogicallyNegate(condition, semanticModel, cancellationToken); SyntaxNode newNode = block.Parent; switch (block.Parent) { case WhileStatementSyntax whileStatement: { cancellationToken.ThrowIfCancellationRequested(); if (statements.IsFirst(ifStatement)) { newNode = whileStatement.Update( whileStatement.WhileKeyword, whileStatement.OpenParenToken, newCondition, whileStatement.CloseParenToken, newBlock); } else { newNode = DoStatement( Token(whileStatement.WhileKeyword.LeadingTrivia, SyntaxKind.DoKeyword, whileStatement.CloseParenToken.TrailingTrivia), newBlock.WithoutTrailingTrivia(), WhileKeyword(), OpenParenToken(), newCondition, CloseParenToken(), SemicolonToken().WithTrailingTrivia(newBlock.GetTrailingTrivia())); } break; } case DoStatementSyntax doStatement: { cancellationToken.ThrowIfCancellationRequested(); if (statements.IsLast(ifStatement)) { newNode = doStatement.Update( doStatement.DoKeyword, newBlock, doStatement.WhileKeyword, doStatement.OpenParenToken, newCondition, doStatement.CloseParenToken, doStatement.SemicolonToken); } else { newNode = WhileStatement( Token(doStatement.DoKeyword.LeadingTrivia, SyntaxKind.WhileKeyword, SyntaxTriviaList.Empty), OpenParenToken(), newCondition, Token(SyntaxTriviaList.Empty, SyntaxKind.CloseParenToken, doStatement.DoKeyword.TrailingTrivia), newBlock.WithTrailingTrivia(doStatement.GetTrailingTrivia())); } break; } default: { Debug.Fail(block.Parent.Kind().ToString()); break; } } newNode = newNode.WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(block.Parent, newNode, cancellationToken).ConfigureAwait(false)); } }
private static bool IsPartOfLazyInitialization(IfStatementSyntax ifStatement, SyntaxList <StatementSyntax> statements) { return(statements.Count == 2 && statements.IndexOf(ifStatement) == 0 && statements[1].IsKind(SyntaxKind.ReturnStatement)); }
private static Task <Document> RefactorAsync( Document document, StatementSyntax statement, IfStatementSyntax ifStatement, int statementIndex, in StatementListInfo statementsInfo,
public static async Task ComputeRefactoringsAsync(RefactoringContext context, IfStatementSyntax ifStatement) { SyntaxToken ifKeyword = ifStatement.IfKeyword; bool isTopmostIf = ifStatement.IsTopmostIf(); if (context.Span.IsEmptyAndContainedInSpan(ifKeyword) || context.Span.IsBetweenSpans(ifStatement)) { if (isTopmostIf && context.IsAnyRefactoringEnabled( RefactoringIdentifiers.UseCoalesceExpressionInsteadOfIf, RefactoringIdentifiers.UseConditionalExpressionInsteadOfIf, RefactoringIdentifiers.SimplifyIf)) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); IfAnalysisOptions options = GetIfAnalysisOptions(context); foreach (IfAnalysis analysis in IfAnalysis.Analyze(ifStatement, options, semanticModel, context.CancellationToken)) { string refactoringId = GetRefactoringIdentifier(analysis); if (context.IsRefactoringEnabled(refactoringId)) { context.RegisterRefactoring( analysis.Title, ct => IfRefactoring.RefactorAsync(context.Document, analysis, ct), refactoringId); } } } if (context.IsAnyRefactoringEnabled(RefactoringIdentifiers.InvertIf, RefactoringIdentifiers.InvertIfElse) && isTopmostIf && context.Span.IsEmptyAndContainedInSpan(ifKeyword)) { InvertIfRefactoring.ComputeRefactoring(context, ifStatement); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.ReplaceIfWithSwitch) && isTopmostIf) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ReplaceIfWithSwitchRefactoring.ComputeRefactoring(context, ifStatement, semanticModel); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.SplitIfStatement)) { SplitIfStatementRefactoring.ComputeRefactoring(context, ifStatement); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.MergeIfWithParentIf) && isTopmostIf && context.Span.IsEmptyAndContainedInSpan(ifKeyword)) { MergeIfWithParentIfRefactoring.ComputeRefactoring(context, ifStatement); } } if (context.IsRefactoringEnabled(RefactoringIdentifiers.InvertIf) && context.Span.IsEmptyAndContainedInSpan(ifKeyword)) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ReduceIfNestingAnalysisResult analysis = ReduceIfNestingAnalysis.Analyze( ifStatement, semanticModel, options: ReduceIfNestingOptions.AllowNestedFix | ReduceIfNestingOptions.AllowIfInsideIfElse | ReduceIfNestingOptions.AllowLoop | ReduceIfNestingOptions.AllowSwitchSection, cancellationToken: context.CancellationToken); if (analysis.Success) { context.RegisterRefactoring( "Invert if", ct => ReduceIfNestingRefactoring.RefactorAsync(context.Document, ifStatement, analysis.JumpKind, false, ct), RefactoringIdentifiers.InvertIf); if (ReduceIfNestingAnalysis.IsFixableRecursively(ifStatement, analysis.JumpKind)) { context.RegisterRefactoring( "Invert if (recursively)", ct => ReduceIfNestingRefactoring.RefactorAsync(context.Document, ifStatement, analysis.JumpKind, true, ct), EquivalenceKey.Join(RefactoringIdentifiers.InvertIf, "Recursive")); } } } if (context.IsRefactoringEnabled(RefactoringIdentifiers.SplitIfElse) && context.Span.IsEmptyAndContainedInSpan(ifKeyword)) { SplitIfElseRefactoring.ComputeRefactoring(context, ifStatement); } }
private static IfStatementSyntax GetNewIfStatement(IfStatementSyntax ifStatement, IfStatementSyntax ifStatement2) { if (ifStatement.Statement.IsKind(SyntaxKind.Block)) { if (ifStatement2.Statement.IsKind(SyntaxKind.Block)) { return(ifStatement.ReplaceNode(ifStatement2, ((BlockSyntax)ifStatement2.Statement).Statements)); } else { return(ifStatement.ReplaceNode(ifStatement2, ifStatement2.Statement)); } } else { return(ifStatement.ReplaceNode(ifStatement.Statement, ifStatement2.Statement)); } }
private async Task <Document> UseExistenceOperatorAsyncWithAssignment(Document document, IfStatementSyntax ifStatement, CancellationToken cancellationToken, ExpressionStatementSyntax expressionIf, ExpressionStatementSyntax expressionElse) { var memberAccessAssignment = (AssignmentExpressionSyntax)expressionIf.Expression; var newMemberAccess = ((MemberAccessExpressionSyntax)memberAccessAssignment.Right).ToConditionalAccessExpression(); var newExpressionStatement = SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, memberAccessAssignment.Left, newMemberAccess)) .WithLeadingTrivia(ifStatement.GetLeadingTrivia()) .WithTrailingTrivia(ifStatement.GetTrailingTrivia()) .WithAdditionalAnnotations(Formatter.Annotation); var root = await document.GetSyntaxRootAsync(); var newRoot = root.ReplaceNode <SyntaxNode, StatementSyntax>(ifStatement, newExpressionStatement); var newDocument = document.WithSyntaxRoot(newRoot); return(newDocument); }
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false); if (!TryFindNode(root, context.Span, out ExpressionSyntax expression)) { return; } foreach (Diagnostic diagnostic in context.Diagnostics) { switch (diagnostic.Id) { case CompilerDiagnosticIdentifiers.CannotImplicitlyConvertTypeExplicitConversionExists: { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); TypeInfo typeInfo = semanticModel.GetTypeInfo(expression, context.CancellationToken); ITypeSymbol type = typeInfo.Type; ITypeSymbol convertedType = typeInfo.ConvertedType; if ((type is INamedTypeSymbol namedType) && namedType.IsNullableType()) { if (convertedType?.SpecialType == SpecialType.System_Boolean || AddComparisonWithBooleanLiteralRefactoring.IsCondition(expression)) { if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddComparisonWithBooleanLiteral)) { CodeAction codeAction = CodeAction.Create( AddComparisonWithBooleanLiteralRefactoring.GetTitle(expression), cancellationToken => AddComparisonWithBooleanLiteralRefactoring.RefactorAsync(context.Document, expression, cancellationToken), GetEquivalenceKey(diagnostic, CodeFixIdentifiers.AddComparisonWithBooleanLiteral)); context.RegisterCodeFix(codeAction, diagnostic); } } else if (namedType.TypeArguments[0].Equals(convertedType)) { if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.UseCoalesceExpression)) { CodeAction codeAction = CodeAction.Create( "Use coalesce expression", cancellationToken => { ExpressionSyntax defaultValue = convertedType.GetDefaultValueSyntax(context.Document.GetDefaultSyntaxOptions()); ExpressionSyntax newNode = CoalesceExpression(expression.WithoutTrivia(), defaultValue) .WithTriviaFrom(expression) .Parenthesize() .WithFormatterAnnotation(); return(context.Document.ReplaceNodeAsync(expression, newNode, cancellationToken)); }, GetEquivalenceKey(diagnostic, CodeFixIdentifiers.UseCoalesceExpression)); context.RegisterCodeFix(codeAction, diagnostic); } } } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ChangeMemberTypeAccordingToReturnExpression) && expression.IsParentKind(SyntaxKind.ReturnStatement, SyntaxKind.YieldReturnStatement)) { ChangeMemberTypeRefactoring.ComputeCodeFix(context, diagnostic, expression, semanticModel); } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddCastExpression)) { CodeFixRegistrator.AddCastExpression(context, diagnostic, expression, convertedType, semanticModel); } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ChangeTypeAccordingToInitializer)) { ChangeTypeAccordingToInitializerRefactoring.ComputeCodeFix(context, diagnostic, expression, semanticModel); } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.CreateSingletonArray) && type?.IsErrorType() == false && !type.Equals(convertedType) && (convertedType is IArrayTypeSymbol arrayType) && semanticModel.IsImplicitConversion(expression, arrayType.ElementType)) { CodeAction codeAction = CodeAction.Create( "Create singleton array", cancellationToken => CreateSingletonArrayRefactoring.RefactorAsync(context.Document, expression, arrayType.ElementType, semanticModel, cancellationToken), GetEquivalenceKey(diagnostic, CodeFixIdentifiers.CreateSingletonArray)); context.RegisterCodeFix(codeAction, diagnostic); } break; } case CompilerDiagnosticIdentifiers.ConstantValueCannotBeConverted: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.UseUncheckedExpression)) { break; } CodeAction codeAction = CodeAction.Create( "Use 'unchecked'", cancellationToken => { CheckedExpressionSyntax newNode = CSharpFactory.UncheckedExpression(expression.WithoutTrivia()); newNode = newNode.WithTriviaFrom(expression); return(context.Document.ReplaceNodeAsync(expression, newNode, cancellationToken)); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.ExpressionBeingAssignedMustBeConstant: { SyntaxNode parent = expression.Parent; if (parent?.IsKind(SyntaxKind.EqualsValueClause) != true) { break; } parent = parent.Parent; if (parent?.IsKind(SyntaxKind.VariableDeclarator) != true) { break; } parent = parent.Parent; if (!(parent is VariableDeclarationSyntax variableDeclaration)) { break; } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveConstModifier) && variableDeclaration.Parent is LocalDeclarationStatementSyntax localDeclarationStatement) { SyntaxTokenList modifiers = localDeclarationStatement.Modifiers; if (!modifiers.Contains(SyntaxKind.ConstKeyword)) { break; } ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, localDeclarationStatement, SyntaxKind.ConstKeyword); } else if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ReplaceConstantWithField) && variableDeclaration.Variables.Count == 1 && (variableDeclaration.Parent is FieldDeclarationSyntax fieldDeclaration) && fieldDeclaration.Modifiers.Contains(SyntaxKind.ConstKeyword)) { CodeAction codeAction = CodeAction.Create( ReplaceConstantWithFieldRefactoring.Title, cancellationToken => ReplaceConstantWithFieldRefactoring.RefactorAsync(context.Document, fieldDeclaration, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } break; } case CompilerDiagnosticIdentifiers.CannotConvertNullToTypeBecauseItIsNonNullableValueType: case CompilerDiagnosticIdentifiers.CannotConvertNullToTypeParameterBecauseItCouldBeNonNullableValueType: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ReplaceNullLiteralExpressionWithDefaultValue)) { break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); CodeFixRegistrator.ReplaceNullWithDefaultValue(context, diagnostic, expression, semanticModel); break; } case CompilerDiagnosticIdentifiers.ResultOfExpressionIsAlwaysConstantSinceValueIsNeverEqualToNull: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveConditionThatIsAlwaysEqualToTrueOrFalse)) { break; } NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(expression, allowedStyles: NullCheckStyles.ComparisonToNull); if (!nullCheck.Success) { break; } CodeAction codeAction = CodeAction.Create( "Remove condition", cancellationToken => { cancellationToken.ThrowIfCancellationRequested(); SyntaxNode newRoot = RemoveCondition(root, expression, nullCheck.Style == NullCheckStyles.NotEqualsToNull); cancellationToken.ThrowIfCancellationRequested(); return(Task.FromResult(context.Document.WithSyntaxRoot(newRoot))); }, GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } case CompilerDiagnosticIdentifiers.OnlyAssignmentCallIncrementDecrementAndNewObjectExpressionsCanBeUsedAsStatement: { if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveParentheses) && expression is ParenthesizedExpressionSyntax parenthesizedExpression && parenthesizedExpression?.IsMissing == false) { CodeAction codeAction = CodeAction.Create( "Remove parentheses", cancellationToken => RemoveRedundantParenthesesRefactoring.RefactorAsync(context.Document, parenthesizedExpression, cancellationToken), GetEquivalenceKey(diagnostic)); context.RegisterCodeFix(codeAction, diagnostic); break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); if (expression.Parent is ArrowExpressionClauseSyntax arrowExpresssionClause) { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ChangeMemberTypeAccordingToReturnExpression)) { break; } ChangeMemberTypeRefactoring.ComputeCodeFix(context, diagnostic, expression, semanticModel); } else if (expression.Parent is ExpressionStatementSyntax expressionStatement) { if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddArgumentList) && expression.IsKind( SyntaxKind.IdentifierName, SyntaxKind.SimpleMemberAccessExpression)) { SyntaxNode invocationExpression = InvocationExpression(expression); if (semanticModel.GetSpeculativeMethodSymbol(expression.SpanStart, invocationExpression) != null) { CodeAction codeAction = CodeAction.Create( "Add argument list", cancellationToken => context.Document.ReplaceNodeAsync(expression, invocationExpression, cancellationToken), GetEquivalenceKey(diagnostic, CodeFixIdentifiers.AddArgumentList)); context.RegisterCodeFix(codeAction, diagnostic); } } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ReplaceComparisonWithAssignment) && expression.IsKind(SyntaxKind.EqualsExpression)) { BinaryExpressionInfo info = SyntaxInfo.BinaryExpressionInfo(expression); if (!info.Success) { break; } ITypeSymbol leftTypeSymbol = semanticModel.GetTypeSymbol(info.Left, context.CancellationToken); if (leftTypeSymbol?.IsErrorType() != false) { break; } if (!semanticModel.IsImplicitConversion(info.Right, leftTypeSymbol)) { break; } CodeAction codeAction = CodeAction.Create( "Replace comparison with assignment", cancellationToken => { AssignmentExpressionSyntax simpleAssignment = SimpleAssignmentExpression(info.Left, info.Right).WithTriviaFrom(expression); return(context.Document.ReplaceNodeAsync(expression, simpleAssignment, cancellationToken)); }, GetEquivalenceKey(diagnostic, CodeFixIdentifiers.ReplaceComparisonWithAssignment)); context.RegisterCodeFix(codeAction, diagnostic); } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ReplaceConditionalExpressionWithIfElse) && (expression is ConditionalExpressionSyntax conditionalExpression) && conditionalExpression.Condition != null) { ExpressionSyntax whenTrue = conditionalExpression.WhenTrue; ExpressionSyntax whenFalse = conditionalExpression.WhenFalse; if (whenTrue != null && whenFalse != null && semanticModel.GetTypeSymbol(whenTrue, context.CancellationToken)?.SpecialType == SpecialType.System_Void && semanticModel.GetTypeSymbol(whenFalse, context.CancellationToken)?.SpecialType == SpecialType.System_Void) { CodeAction codeAction = CodeAction.Create( "Replace ?: with if-else", cancellationToken => { IfStatementSyntax newNode = IfStatement( conditionalExpression.Condition.WalkDownParentheses(), Block(ExpressionStatement(whenTrue)), ElseClause(Block(ExpressionStatement(whenFalse)))); newNode = newNode .WithTriviaFrom(expressionStatement) .WithFormatterAnnotation(); return(context.Document.ReplaceNodeAsync(expressionStatement, newNode, cancellationToken)); }, GetEquivalenceKey(diagnostic, CodeFixIdentifiers.ReplaceConditionalExpressionWithIfElse)); context.RegisterCodeFix(codeAction, diagnostic); } } if (semanticModel.GetSymbol(expression, context.CancellationToken)?.IsErrorType() != false) { break; } ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(expression, context.CancellationToken); if (typeSymbol?.IsErrorType() != false) { break; } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.IntroduceLocalVariable) && !expressionStatement.IsEmbedded()) { bool addAwait = typeSymbol.OriginalDefinition.EqualsOrInheritsFromTaskOfT() && semanticModel.GetEnclosingSymbol(expressionStatement.SpanStart, context.CancellationToken).IsAsyncMethod(); CodeAction codeAction = CodeAction.Create( IntroduceLocalVariableRefactoring.GetTitle(expression), cancellationToken => IntroduceLocalVariableRefactoring.RefactorAsync(context.Document, expressionStatement, typeSymbol, addAwait, semanticModel, cancellationToken), GetEquivalenceKey(diagnostic, CodeFixIdentifiers.IntroduceLocalVariable)); context.RegisterCodeFix(codeAction, diagnostic); } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.IntroduceField)) { CodeAction codeAction = CodeAction.Create( $"Introduce field for '{expression}'", cancellationToken => IntroduceFieldRefactoring.RefactorAsync(context.Document, expressionStatement, typeSymbol, semanticModel, cancellationToken), GetEquivalenceKey(diagnostic, CodeFixIdentifiers.IntroduceField)); context.RegisterCodeFix(codeAction, diagnostic); } } break; } case CompilerDiagnosticIdentifiers.CannotImplicitlyConvertType: { if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ReplaceYieldReturnWithForEach) && expression.IsParentKind(SyntaxKind.YieldReturnStatement)) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ReplaceYieldReturnWithForEachRefactoring.ComputeCodeFix(context, diagnostic, expression, semanticModel); break; } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ChangeMemberTypeAccordingToReturnExpression) && expression.IsParentKind(SyntaxKind.ReturnStatement, SyntaxKind.YieldReturnStatement)) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ChangeMemberTypeRefactoring.ComputeCodeFix(context, diagnostic, expression, semanticModel); break; } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ChangeTypeAccordingToInitializer)) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); CodeFixRegistrationResult result = ChangeTypeAccordingToInitializerRefactoring.ComputeCodeFix(context, diagnostic, expression, semanticModel); if (!result.Success) { RemoveAssignmentOfVoidExpression(context, diagnostic, expression, semanticModel); } break; } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ReplaceStringLiteralWithCharacterLiteral) && expression?.Kind() == SyntaxKind.StringLiteralExpression) { var literalExpression = (LiteralExpressionSyntax)expression; if (literalExpression.Token.ValueText.Length == 1) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); if (semanticModel.GetTypeInfo(expression, context.CancellationToken).ConvertedType?.SpecialType == SpecialType.System_Char) { CodeAction codeAction = CodeAction.Create( "Replace string literal with character literal", cancellationToken => ReplaceStringLiteralWithCharacterLiteralRefactoring.RefactorAsync(context.Document, literalExpression, cancellationToken), GetEquivalenceKey(diagnostic, CodeFixIdentifiers.ReplaceStringLiteralWithCharacterLiteral)); context.RegisterCodeFix(codeAction, diagnostic); } } } if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.UseYieldReturnInsteadOfReturn) && expression.IsParentKind(SyntaxKind.ReturnStatement)) { var returnStatement = (ReturnStatementSyntax)expression.Parent; SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ISymbol containingSymbol = semanticModel.GetEnclosingSymbol(returnStatement.SpanStart, context.CancellationToken); if (containingSymbol?.Kind == SymbolKind.Method && ((IMethodSymbol)containingSymbol).ReturnType.OriginalDefinition.IsIEnumerableOrIEnumerableOfT()) { CodeAction codeAction = CodeAction.Create( "Use yield return instead of return", cancellationToken => UseYieldReturnInsteadOfReturnRefactoring.RefactorAsync(context.Document, returnStatement, SyntaxKind.YieldReturnStatement, semanticModel, cancellationToken), GetEquivalenceKey(diagnostic, CodeFixIdentifiers.UseYieldReturnInsteadOfReturn)); context.RegisterCodeFix(codeAction, diagnostic); } } break; } case CompilerDiagnosticIdentifiers.LeftHandSideOfAssignmentMustBeVariablePropertyOrIndexer: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveConstModifier)) { return; } if (!expression.IsKind(SyntaxKind.IdentifierName)) { return; } if (!expression.IsParentKind(SyntaxKind.SimpleAssignmentExpression)) { return; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); SymbolInfo symbolInfo = semanticModel.GetSymbolInfo(expression, context.CancellationToken); if (symbolInfo.CandidateReason != CandidateReason.NotAVariable) { return; } if (!(symbolInfo.CandidateSymbols.SingleOrDefault(shouldThrow: false) is ILocalSymbol localSymbol)) { return; } if (!localSymbol.IsConst) { return; } SyntaxNode node = localSymbol.GetSyntaxOrDefault(context.CancellationToken); if (!node.IsKind(SyntaxKind.VariableDeclarator)) { return; } node = node.Parent; if (!node.IsKind(SyntaxKind.VariableDeclaration)) { return; } node = node.Parent; if (!(node is LocalDeclarationStatementSyntax localDeclaration)) { return; } SyntaxToken constModifier = localDeclaration.Modifiers.Find(SyntaxKind.ConstKeyword); if (!constModifier.IsKind(SyntaxKind.ConstKeyword)) { return; } ModifiersCodeFixRegistrator.RemoveModifier(context, diagnostic, localDeclaration, constModifier); break; } case CompilerDiagnosticIdentifiers.ReadOnlyFieldCannotBeAssignedTo: { if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.MakeFieldWritable)) { break; } SimpleAssignmentExpressionInfo simpleAssignment = SyntaxInfo.SimpleAssignmentExpressionInfo(expression.Parent); if (!simpleAssignment.Success) { return; } if (simpleAssignment.Left != expression) { return; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); SymbolInfo symbolInfo = semanticModel.GetSymbolInfo(expression, context.CancellationToken); if (symbolInfo.CandidateReason != CandidateReason.NotAVariable) { return; } if (!(symbolInfo.CandidateSymbols.SingleOrDefault(shouldThrow: false) is IFieldSymbol fieldSymbol)) { return; } if (fieldSymbol.DeclaredAccessibility != Accessibility.Private) { return; } if (!(fieldSymbol.GetSyntax().Parent.Parent is FieldDeclarationSyntax fieldDeclaration)) { return; } TypeDeclarationSyntax containingTypeDeclaration = fieldDeclaration.FirstAncestor <TypeDeclarationSyntax>(); if (!expression.Ancestors().Any(f => f == containingTypeDeclaration)) { return; } ModifiersCodeFixRegistrator.RemoveModifier( context, diagnostic, fieldDeclaration, SyntaxKind.ReadOnlyKeyword, title: $"Make '{fieldSymbol.Name}' writable"); break; } } } }
public override void VisitIfStatement(IfStatementSyntax node) => CheckToken(node.IfKeyword);
public override void VisitIfStatement(IfStatementSyntax node) { VisitPossibleEmbeddedStatement(node.Statement, enclosing); Visit(node.Else, enclosing); }
public override void VisitIfStatement(IfStatementSyntax node) { return; }
private static bool IsElseIfWithoutElse(IfStatementSyntax node) { return(node.Parent.IsKind(SyntaxKind.ElseClause) && node.Else == null); }
public override void VisitIfStatement(IfStatementSyntax node) { AddLocation(node.IfKeyword); base.VisitIfStatement(node); }
private bool TryCheckVariableAndIfStatementForm( SyntaxNodeAnalysisContext syntaxContext, IfStatementSyntax ifStatement, BinaryExpressionSyntax condition, ExpressionStatementSyntax expressionStatement, InvocationExpressionSyntax invocationExpression, ReportDiagnostic severity) { var cancellationToken = syntaxContext.CancellationToken; cancellationToken.ThrowIfCancellationRequested(); // look for the form "if (a != null)" or "if (null != a)" if (!ifStatement.Parent.IsKind(SyntaxKind.Block)) { return(false); } if (!IsNullCheckExpression(condition.Left, condition.Right) && !IsNullCheckExpression(condition.Right, condition.Left)) { return(false); } var expression = invocationExpression.Expression; if (!expression.IsKind(SyntaxKind.IdentifierName)) { return(false); } var conditionName = condition.Left is IdentifierNameSyntax ? (IdentifierNameSyntax)condition.Left : (IdentifierNameSyntax)condition.Right; var invocationName = (IdentifierNameSyntax)expression; if (!Equals(conditionName.Identifier.ValueText, invocationName.Identifier.ValueText)) { return(false); } // Now make sure the previous statement is "var a = ..." var parentBlock = (BlockSyntax)ifStatement.Parent; var ifIndex = parentBlock.Statements.IndexOf(ifStatement); if (ifIndex == 0) { return(false); } var previousStatement = parentBlock.Statements[ifIndex - 1]; if (!previousStatement.IsKind(SyntaxKind.LocalDeclarationStatement)) { return(false); } var localDeclarationStatement = (LocalDeclarationStatementSyntax)previousStatement; var variableDeclaration = localDeclarationStatement.Declaration; var declarator = variableDeclaration; if (declarator.Initializer == null) { return(false); } cancellationToken.ThrowIfCancellationRequested(); if (!Equals(declarator.Identifier.ValueText, conditionName.Identifier.ValueText)) { return(false); } // Syntactically this looks good. Now make sure that the local is a delegate type. var semanticModel = syntaxContext.SemanticModel; var localSymbol = (ILocalSymbol)semanticModel.GetDeclaredSymbol(declarator, cancellationToken); // Ok, we made a local just to check it for null and invoke it. Looks like something // we can suggest an improvement for! // But first make sure we're only using the local only within the body of this if statement. var analysis = semanticModel.AnalyzeDataFlow(localDeclarationStatement, ifStatement); if (analysis.ReadOutside.Contains(localSymbol) || analysis.WrittenOutside.Contains(localSymbol)) { return(false); } // Looks good! var tree = semanticModel.SyntaxTree; var additionalLocations = new List <Location> { Location.Create(tree, localDeclarationStatement.Span), Location.Create(tree, ifStatement.Span), Location.Create(tree, expressionStatement.Span) }; ReportDiagnostics(syntaxContext, localDeclarationStatement, ifStatement, expressionStatement, severity, additionalLocations, Constants.VariableAndIfStatementForm); return(true); }
public static async Task ComputeRefactoringsAsync(RefactoringContext context, IfStatementSyntax ifStatement) { if (ifStatement.IsTopmostIf() && (context.Span.IsEmptyAndContainedInSpan(ifStatement.IfKeyword) || context.Span.IsBetweenSpans(ifStatement))) { if (context.IsAnyRefactoringEnabled( RefactoringIdentifiers.UseCoalesceExpressionInsteadOfIf, RefactoringIdentifiers.UseConditionalExpressionInsteadOfIf, RefactoringIdentifiers.SimplifyIf)) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); var options = new IfAnalysisOptions( useCoalesceExpression: context.IsRefactoringEnabled(RefactoringIdentifiers.UseCoalesceExpressionInsteadOfIf), useConditionalExpression: context.IsRefactoringEnabled(RefactoringIdentifiers.UseConditionalExpressionInsteadOfIf), useBooleanExpression: context.IsRefactoringEnabled(RefactoringIdentifiers.SimplifyIf), useExpression: false); foreach (IfAnalysis analysis in IfAnalysis.Analyze(ifStatement, options, semanticModel, context.CancellationToken)) { context.RegisterRefactoring( analysis.Title, cancellationToken => IfRefactoring.RefactorAsync(context.Document, analysis, cancellationToken)); } } if (context.IsRefactoringEnabled(RefactoringIdentifiers.SwapIfElse)) { SwapIfElseRefactoring.ComputeRefactoring(context, ifStatement); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.ReplaceIfWithSwitch)) { await ReplaceIfWithSwitchRefactoring.ComputeRefactoringAsync(context, ifStatement).ConfigureAwait(false); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.SplitIfStatement)) { SplitIfStatementRefactoring.ComputeRefactoring(context, ifStatement); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.MergeIfWithParentIf) && context.Span.IsEmptyAndContainedInSpan(ifStatement.IfKeyword)) { MergeIfWithParentIfRefactoring.ComputeRefactoring(context, ifStatement); } } if (context.IsRefactoringEnabled(RefactoringIdentifiers.ReduceIfNesting) && context.Span.IsEmptyAndContainedInSpanOrBetweenSpans(ifStatement.IfKeyword)) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ReduceIfNestingAnalysisResult analysis = ReduceIfNestingAnalysis.Analyze( ifStatement, semanticModel, options: ReduceIfNestingOptions.AllowNestedFix | ReduceIfNestingOptions.AllowIfInsideIfElse | ReduceIfNestingOptions.AllowLoop | ReduceIfNestingOptions.AllowSwitchSection, taskSymbol: semanticModel.GetTypeByMetadataName(MetadataNames.System_Threading_Tasks_Task), cancellationToken: context.CancellationToken); if (analysis.Success) { context.RegisterRefactoring( "Reduce if nesting", cancellationToken => ReduceIfNestingRefactoring.RefactorAsync(context.Document, ifStatement, analysis.JumpKind, false, cancellationToken)); if (ReduceIfNestingAnalysis.IsFixableRecursively(ifStatement, analysis.JumpKind)) { context.RegisterRefactoring( "Reduce if nesting (recursively)", cancellationToken => ReduceIfNestingRefactoring.RefactorAsync(context.Document, ifStatement, analysis.JumpKind, true, cancellationToken)); } } } if (context.IsRefactoringEnabled(RefactoringIdentifiers.SplitIfElse) && context.Span.IsEmptyAndContainedInSpanOrBetweenSpans(ifStatement.IfKeyword)) { SplitIfElseRefactoring.ComputeRefactoring(context, ifStatement); } }
internal Enumerator(IfStatementSyntax ifStatement) { _ifOrElse = ifStatement; _count = -1; }
public IfReturnToReturnWithBooleanExpression( IfStatementSyntax ifStatement, ExpressionSyntax expression1, ExpressionSyntax expression2) : base(ifStatement, expression1, expression2) { }
internal IfStatementCascade(IfStatementSyntax ifStatement) { IfStatement = ifStatement; }
public IfReturnToReturnWithConditionalExpression( IfStatementSyntax ifStatement, ExpressionSyntax expression1, ExpressionSyntax expression2) : base(ifStatement, expression1, expression2) { }
internal EnumeratorImpl(IfStatementSyntax ifStatement) { _en = new Enumerator(ifStatement); }
private static void ReportDiagnostic(SyntaxNodeAnalysisContext context, IfStatementSyntax ifStatement, IfStatementSyntax nestedIf) { context.ReportDiagnostic(DiagnosticDescriptors.MergeIfStatementWithNestedIfStatement, ifStatement); context.ReportToken(DiagnosticDescriptors.MergeIfStatementWithNestedIfStatementFadeOut, nestedIf.IfKeyword); context.ReportToken(DiagnosticDescriptors.MergeIfStatementWithNestedIfStatementFadeOut, nestedIf.OpenParenToken); context.ReportToken(DiagnosticDescriptors.MergeIfStatementWithNestedIfStatementFadeOut, nestedIf.CloseParenToken); if (ifStatement.Statement.IsKind(SyntaxKind.Block) && nestedIf.Statement.IsKind(SyntaxKind.Block)) { context.ReportBraces(DiagnosticDescriptors.MergeIfStatementWithNestedIfStatementFadeOut, (BlockSyntax)nestedIf.Statement); } }
public IfReturnToReturnWithCoalesceExpression( IfStatementSyntax ifStatement, ExpressionSyntax left, ExpressionSyntax right) : base(ifStatement, left, right) { }
/// <inheritdoc /> public override void VisitIfStatement(IfStatementSyntax node) { this.ifStatements.Add(node); base.VisitIfStatement(node); }
private async Task <Document> UseExistenceOperatorAsyncWithReturn(Document document, IfStatementSyntax ifStatement, CancellationToken cancellationToken, ReturnStatementSyntax returnIf, ReturnStatementSyntax returnElse) { var newMemberAccess = ((MemberAccessExpressionSyntax)returnIf.Expression).ToConditionalAccessExpression(); var newReturn = SyntaxFactory.ReturnStatement(newMemberAccess) .WithLeadingTrivia(ifStatement.GetLeadingTrivia()) .WithTrailingTrivia(ifStatement.GetTrailingTrivia()) .WithAdditionalAnnotations(Formatter.Annotation); var root = await document.GetSyntaxRootAsync(); var newRoot = root.ReplaceNode <SyntaxNode, StatementSyntax>(ifStatement, newReturn); var newDocument = document.WithSyntaxRoot(newRoot); return(newDocument); }