private void AddEmbeddedStatementsIndentationOperation(List <IndentBlockOperation> list, StatementSyntax statement) { var firstToken = statement.GetFirstToken(includeZeroWidth: true); var lastToken = statement.GetLastToken(includeZeroWidth: true); if (lastToken.IsMissing) { // embedded statement is not done, consider following as part of embedded statement AddIndentBlockOperation(list, firstToken, lastToken); } else { // embedded statement is done AddIndentBlockOperation(list, firstToken, lastToken, TextSpan.FromBounds(firstToken.FullSpan.Start, lastToken.FullSpan.End)); } }
public static bool StatementNeedsWrapping(StatementSyntax statement) { // Statement has to be parented by another statement (or an else-clause) to count. var parent = statement.Parent; var parentIsElseClause = parent.IsKind(SyntaxKind.ElseClause); if (!(parent is StatementSyntax || parentIsElseClause)) { return(false); } // `else if` is always allowed. if (statement.IsKind(SyntaxKind.IfStatement) && parentIsElseClause) { return(false); } var statementStartToken = statement.GetFirstToken(); // we have to have a newline between the start of this statement and the previous statement. if (ContainsEndOfLineBetween(statementStartToken.GetPreviousToken(), statementStartToken)) { return(false); } // Looks like a statement that might need wrapping. However, we do suppress wrapping for a few well known // acceptable cases. if (parent.IsKind(SyntaxKind.Block)) { // Blocks can be on a single line if parented by a member/accessor/lambda. // And if they only contain a single statement at most within them. var blockParent = parent.Parent; if (blockParent is MemberDeclarationSyntax or AccessorDeclarationSyntax or AnonymousFunctionExpressionSyntax) { if (parent.DescendantNodes().OfType <StatementSyntax>().Count() <= 1) { return(false); } } } return(true); }
private bool CheckStatementSyntax(SyntaxTreeAnalysisContext context, ReportDiagnostic severity, StatementSyntax statement) { if (!StatementNeedsWrapping(statement)) { return(false); } var additionalLocations = ImmutableArray.Create(statement.GetLocation()); context.ReportDiagnostic(DiagnosticHelper.Create( this.Descriptor, statement.GetFirstToken().GetLocation(), severity, additionalLocations, properties: null)); return(true); }
public static bool StatementNeedsWrapping(StatementSyntax statement) { // Statement has to be parented by another statement (or an else-clause) to count. var parent = statement.Parent; var parentIsElseClause = parent.IsKind(SyntaxKind.ElseClause); if (!(parent is StatementSyntax || parentIsElseClause)) { return(false); } // `else if` is always allowed. if (statement.IsKind(SyntaxKind.IfStatement) && parentIsElseClause) { return(false); } if (parent.IsKind(SyntaxKind.Block)) { // Blocks can be on a single line if parented by a member/accessor/lambda. var blockParent = parent.Parent; if (blockParent is MemberDeclarationSyntax or AccessorDeclarationSyntax or AnonymousFunctionExpressionSyntax) { return(false); } } var statementStartToken = statement.GetFirstToken(); var previousToken = statementStartToken.GetPreviousToken(); // we have to have a newline between the start of this statement and the previous statement. if (ContainsEndOfLine(previousToken.TrailingTrivia) || ContainsEndOfLine(statementStartToken.LeadingTrivia)) { return(false); } return(true); }
private static void CheckChildStatement(SyntaxNodeAnalysisContext context, SyntaxNode node, StatementSyntax childStatement) { if (childStatement == null || childStatement.IsMissing) { return; } if (childStatement is BlockSyntax) { // BlockSyntax child statements are handled by HandleBlock return; } // We are only interested in the first instance of this violation on a line. if (!node.GetFirstToken().IsFirstInLine()) { return; } // We are only interested in the case where statement and childStatement start on the same line. Use // IsFirstInLine to detect this condition easily. SyntaxToken firstChildToken = childStatement.GetFirstToken(); if (firstChildToken.IsMissingOrDefault() || firstChildToken.IsFirstInLine()) { return; } if (!context.IsAnalyzerSuppressed(SA1519CurlyBracketsMustNotBeOmittedFromMultiLineChildStatement.DiagnosticId)) { // diagnostics for multi-line statements is handled by SA1519, as long as it's not suppressed FileLinePositionSpan lineSpan = childStatement.GetLineSpan(); if (lineSpan.StartLinePosition.Line != lineSpan.EndLinePosition.Line) { return; } } context.ReportDiagnostic(Diagnostic.Create(Descriptor, childStatement.GetLocation())); }
private static void CheckChildStatement(SyntaxNodeAnalysisContext context, StatementSyntax childStatement) { bool reportAsHidden = false; if (childStatement == null || childStatement.IsMissing) { return; } if (childStatement is BlockSyntax) { // BlockSyntax child statements are handled by HandleBlock return; } // We are only interested in the case where statement and childStatement start on the same line. Use // IsFirstInLine to detect this condition easily. SyntaxToken firstChildToken = childStatement.GetFirstToken(); if (firstChildToken.IsMissingOrDefault() || firstChildToken.IsFirstInLine()) { return; } if (!context.IsAnalyzerSuppressed(SA1519BracesMustNotBeOmittedFromMultiLineChildStatement.Descriptor)) { // diagnostics for multi-line statements is handled by SA1519, as long as it's not suppressed FileLinePositionSpan lineSpan = childStatement.GetLineSpan(); if (lineSpan.StartLinePosition.Line != lineSpan.EndLinePosition.Line) { reportAsHidden = true; } } ReportDiagnostic(context, childStatement.GetLocation(), reportAsHidden); }
private static SyntaxToken GetFirstIncludedToken(StatementSyntax statement) { Debug.Assert(statement != null); switch (statement.Kind()) { case SyntaxKind.Block: return(((BlockSyntax)statement).OpenBraceToken); case SyntaxKind.BreakStatement: return(((BreakStatementSyntax)statement).BreakKeyword); case SyntaxKind.CheckedStatement: case SyntaxKind.UncheckedStatement: return(((CheckedStatementSyntax)statement).Keyword); case SyntaxKind.ContinueStatement: return(((ContinueStatementSyntax)statement).ContinueKeyword); case SyntaxKind.ExpressionStatement: case SyntaxKind.LocalDeclarationStatement: return(statement.GetFirstToken()); case SyntaxKind.DoStatement: return(((DoStatementSyntax)statement).DoKeyword); case SyntaxKind.EmptyStatement: return(default(SyntaxToken)); //The caller will have to check for this. case SyntaxKind.FixedStatement: return(((FixedStatementSyntax)statement).FixedKeyword); case SyntaxKind.ForEachStatement: case SyntaxKind.ForEachVariableStatement: return(((CommonForEachStatementSyntax)statement).OpenParenToken.GetNextToken()); case SyntaxKind.ForStatement: return(((ForStatementSyntax)statement).OpenParenToken.GetNextToken()); case SyntaxKind.GotoDefaultStatement: case SyntaxKind.GotoCaseStatement: case SyntaxKind.GotoStatement: return(((GotoStatementSyntax)statement).GotoKeyword); case SyntaxKind.IfStatement: return(((IfStatementSyntax)statement).IfKeyword); case SyntaxKind.LabeledStatement: return(((LabeledStatementSyntax)statement).Identifier); case SyntaxKind.LockStatement: return(((LockStatementSyntax)statement).LockKeyword); case SyntaxKind.ReturnStatement: return(((ReturnStatementSyntax)statement).ReturnKeyword); case SyntaxKind.SwitchStatement: return(((SwitchStatementSyntax)statement).Expression.GetFirstToken()); case SyntaxKind.ThrowStatement: return(((ThrowStatementSyntax)statement).ThrowKeyword); case SyntaxKind.TryStatement: return(((TryStatementSyntax)statement).TryKeyword); case SyntaxKind.UnsafeStatement: return(((UnsafeStatementSyntax)statement).UnsafeKeyword); case SyntaxKind.UsingStatement: return(((UsingStatementSyntax)statement).UsingKeyword); case SyntaxKind.WhileStatement: return(((WhileStatementSyntax)statement).WhileKeyword); case SyntaxKind.YieldReturnStatement: case SyntaxKind.YieldBreakStatement: return(((YieldStatementSyntax)statement).YieldKeyword); case SyntaxKind.LocalFunctionStatement: return(statement.GetFirstToken()); default: throw ExceptionUtilities.UnexpectedValue(statement.Kind()); } }
private static SyntaxToken GetFirstIncludedToken(StatementSyntax statement, bool inRecursiveCall = false) { Debug.Assert(statement != null); switch (statement.Kind()) { case SyntaxKind.Block: return(((BlockSyntax)statement).OpenBraceToken); case SyntaxKind.BreakStatement: return(((BreakStatementSyntax)statement).BreakKeyword); case SyntaxKind.CheckedStatement: case SyntaxKind.UncheckedStatement: return(((CheckedStatementSyntax)statement).Keyword); case SyntaxKind.ContinueStatement: return(((ContinueStatementSyntax)statement).ContinueKeyword); case SyntaxKind.ExpressionStatement: case SyntaxKind.LocalDeclarationStatement: return(statement.GetFirstToken()); case SyntaxKind.DoStatement: return(((DoStatementSyntax)statement).DoKeyword); case SyntaxKind.EmptyStatement: return(default(SyntaxToken)); //The caller will have to check for this. case SyntaxKind.FixedStatement: return(((FixedStatementSyntax)statement).FixedKeyword); case SyntaxKind.ForEachStatement: // NB: iteration variable is only in scope in body. ForEachStatementSyntax forEachSyntax = (ForEachStatementSyntax)statement; if (inRecursiveCall) { return(forEachSyntax.ForEachKeyword); } return(GetFirstIncludedToken(forEachSyntax.Statement, inRecursiveCall: true)); case SyntaxKind.ForStatement: // Section 8.8.3 of the spec says that the scope of the loop variable starts at // its declaration. If it's not there, then the scope we are interested in is // the loop body. ForStatementSyntax forSyntax = (ForStatementSyntax)statement; if (inRecursiveCall) { return(forSyntax.ForKeyword); } VariableDeclarationSyntax declOpt = forSyntax.Declaration; return(declOpt == null?GetFirstIncludedToken(forSyntax.Statement, inRecursiveCall : true) : declOpt.GetFirstToken()); case SyntaxKind.GotoDefaultStatement: case SyntaxKind.GotoCaseStatement: case SyntaxKind.GotoStatement: return(((GotoStatementSyntax)statement).GotoKeyword); case SyntaxKind.IfStatement: return(((IfStatementSyntax)statement).IfKeyword); case SyntaxKind.LabeledStatement: return(((LabeledStatementSyntax)statement).Identifier); case SyntaxKind.LockStatement: return(((LockStatementSyntax)statement).LockKeyword); case SyntaxKind.ReturnStatement: return(((ReturnStatementSyntax)statement).ReturnKeyword); case SyntaxKind.SwitchStatement: return(((SwitchStatementSyntax)statement).OpenBraceToken); case SyntaxKind.ThrowStatement: return(((ThrowStatementSyntax)statement).ThrowKeyword); case SyntaxKind.TryStatement: return(((TryStatementSyntax)statement).TryKeyword); case SyntaxKind.UnsafeStatement: return(((UnsafeStatementSyntax)statement).UnsafeKeyword); case SyntaxKind.UsingStatement: return(((UsingStatementSyntax)statement).UsingKeyword); case SyntaxKind.WhileStatement: return(((WhileStatementSyntax)statement).WhileKeyword); case SyntaxKind.YieldReturnStatement: case SyntaxKind.YieldBreakStatement: return(((YieldStatementSyntax)statement).YieldKeyword); default: throw ExceptionUtilities.UnexpectedValue(statement.Kind()); } }
private void AddEmbeddedStatementsIndentationOperation(List<IndentBlockOperation> list, StatementSyntax statement) { var firstToken = statement.GetFirstToken(includeZeroWidth: true); var lastToken = statement.GetLastToken(includeZeroWidth: true); if (lastToken.IsMissing) { // embedded statement is not done, consider following as part of embedded statement AddIndentBlockOperation(list, firstToken, lastToken); } else { // embedded statement is done AddIndentBlockOperation(list, firstToken, lastToken, TextSpan.FromBounds(firstToken.FullSpan.Start, lastToken.FullSpan.End)); } }
private static void CheckChildStatement(SyntaxNodeAnalysisContext context, SyntaxNode node, StatementSyntax childStatement) { if (childStatement == null || childStatement.IsMissing) { return; } if (childStatement is BlockSyntax) { // BlockSyntax child statements are handled by HandleBlock return; } // We are only interested in the first instance of this violation on a line. if (!node.GetFirstToken().IsFirstInLine()) { return; } // We are only interested in the case where statement and childStatement start on the same line. Use // IsFirstInLine to detect this condition easily. SyntaxToken firstChildToken = childStatement.GetFirstToken(); if (firstChildToken.IsMissingOrDefault() || firstChildToken.IsFirstInLine()) { return; } if (!context.IsAnalyzerSuppressed(SA1519CurlyBracketsMustNotBeOmittedFromMultiLineChildStatement.DiagnosticId)) { // diagnostics for multi-line statements is handled by SA1519, as long as it's not suppressed FileLinePositionSpan lineSpan = childStatement.GetLineSpan(); if (lineSpan.StartLinePosition.Line != lineSpan.EndLinePosition.Line) { return; } } context.ReportDiagnostic(Diagnostic.Create(Descriptor, childStatement.GetLocation())); }
private static SyntaxToken GetFirstIncludedToken(StatementSyntax statement, bool inRecursiveCall = false) { Debug.Assert(statement != null); switch (statement.Kind) { case SyntaxKind.Block: return ((BlockSyntax)statement).OpenBraceToken; case SyntaxKind.BreakStatement: return ((BreakStatementSyntax)statement).BreakKeyword; case SyntaxKind.CheckedStatement: case SyntaxKind.UncheckedStatement: return ((CheckedStatementSyntax)statement).Keyword; case SyntaxKind.ContinueStatement: return ((ContinueStatementSyntax)statement).ContinueKeyword; case SyntaxKind.ExpressionStatement: case SyntaxKind.LocalDeclarationStatement: return statement.GetFirstToken(); case SyntaxKind.DoStatement: return ((DoStatementSyntax)statement).DoKeyword; case SyntaxKind.EmptyStatement: return default(SyntaxToken); //The caller will have to check for this. case SyntaxKind.FixedStatement: return ((FixedStatementSyntax)statement).FixedKeyword; case SyntaxKind.ForEachStatement: // NB: iteration variable is only in scope in body. ForEachStatementSyntax forEachSyntax = (ForEachStatementSyntax)statement; if (inRecursiveCall) { return forEachSyntax.ForEachKeyword; } return GetFirstIncludedToken(forEachSyntax.Statement, inRecursiveCall: true); case SyntaxKind.ForStatement: // Section 8.8.3 of the spec says that the scope of the loop variable starts at // its declaration. If it's not there, then the scope we are interested in is // the loop body. ForStatementSyntax forSyntax = (ForStatementSyntax)statement; if (inRecursiveCall) { return forSyntax.ForKeyword; } VariableDeclarationSyntax declOpt = forSyntax.Declaration; return declOpt == null ? GetFirstIncludedToken(forSyntax.Statement, inRecursiveCall: true) : declOpt.GetFirstToken(); case SyntaxKind.GotoDefaultStatement: case SyntaxKind.GotoCaseStatement: case SyntaxKind.GotoStatement: return ((GotoStatementSyntax)statement).GotoKeyword; case SyntaxKind.IfStatement: return ((IfStatementSyntax)statement).IfKeyword; case SyntaxKind.LabeledStatement: return ((LabeledStatementSyntax)statement).Identifier; case SyntaxKind.LockStatement: return ((LockStatementSyntax)statement).LockKeyword; case SyntaxKind.ReturnStatement: return ((ReturnStatementSyntax)statement).ReturnKeyword; case SyntaxKind.SwitchStatement: return ((SwitchStatementSyntax)statement).OpenBraceToken; case SyntaxKind.ThrowStatement: return ((ThrowStatementSyntax)statement).ThrowKeyword; case SyntaxKind.TryStatement: return ((TryStatementSyntax)statement).TryKeyword; case SyntaxKind.UnsafeStatement: return ((UnsafeStatementSyntax)statement).UnsafeKeyword; case SyntaxKind.UsingStatement: return ((UsingStatementSyntax)statement).UsingKeyword; case SyntaxKind.WhileStatement: return ((WhileStatementSyntax)statement).WhileKeyword; case SyntaxKind.YieldReturnStatement: case SyntaxKind.YieldBreakStatement: return ((YieldStatementSyntax)statement).YieldKeyword; default: throw ExceptionUtilities.UnexpectedValue(statement.Kind); } }
private static SyntaxToken GetFirstIncludedToken(StatementSyntax statement) { Debug.Assert(statement != null); switch (statement.Kind()) { case SyntaxKind.Block: return ((BlockSyntax)statement).OpenBraceToken; case SyntaxKind.BreakStatement: return ((BreakStatementSyntax)statement).BreakKeyword; case SyntaxKind.CheckedStatement: case SyntaxKind.UncheckedStatement: return ((CheckedStatementSyntax)statement).Keyword; case SyntaxKind.ContinueStatement: return ((ContinueStatementSyntax)statement).ContinueKeyword; case SyntaxKind.ExpressionStatement: case SyntaxKind.LocalDeclarationStatement: case SyntaxKind.DeconstructionDeclarationStatement: return statement.GetFirstToken(); case SyntaxKind.DoStatement: return ((DoStatementSyntax)statement).DoKeyword; case SyntaxKind.EmptyStatement: return default(SyntaxToken); //The caller will have to check for this. case SyntaxKind.FixedStatement: return ((FixedStatementSyntax)statement).FixedKeyword; case SyntaxKind.ForEachStatement: case SyntaxKind.ForEachComponentStatement: return ((CommonForEachStatementSyntax)statement).OpenParenToken.GetNextToken(); case SyntaxKind.ForStatement: return ((ForStatementSyntax)statement).OpenParenToken.GetNextToken(); case SyntaxKind.GotoDefaultStatement: case SyntaxKind.GotoCaseStatement: case SyntaxKind.GotoStatement: return ((GotoStatementSyntax)statement).GotoKeyword; case SyntaxKind.IfStatement: return ((IfStatementSyntax)statement).IfKeyword; case SyntaxKind.LabeledStatement: return ((LabeledStatementSyntax)statement).Identifier; case SyntaxKind.LockStatement: return ((LockStatementSyntax)statement).LockKeyword; case SyntaxKind.ReturnStatement: return ((ReturnStatementSyntax)statement).ReturnKeyword; case SyntaxKind.SwitchStatement: return ((SwitchStatementSyntax)statement).Expression.GetFirstToken(); case SyntaxKind.ThrowStatement: return ((ThrowStatementSyntax)statement).ThrowKeyword; case SyntaxKind.TryStatement: return ((TryStatementSyntax)statement).TryKeyword; case SyntaxKind.UnsafeStatement: return ((UnsafeStatementSyntax)statement).UnsafeKeyword; case SyntaxKind.UsingStatement: return ((UsingStatementSyntax)statement).UsingKeyword; case SyntaxKind.WhileStatement: return ((WhileStatementSyntax)statement).WhileKeyword; case SyntaxKind.YieldReturnStatement: case SyntaxKind.YieldBreakStatement: return ((YieldStatementSyntax)statement).YieldKeyword; case SyntaxKind.LocalFunctionStatement: return statement.GetFirstToken(); default: throw ExceptionUtilities.UnexpectedValue(statement.Kind()); } }
private static StatementSyntax ReformatStatement(Document document, StatementSyntax statement) { var indentationOptions = IndentationOptions.FromDocument(document); var parentIndentationLevel = IndentationHelper.GetIndentationSteps(indentationOptions, GetStatementParent(statement.Parent)); // use one additional step of indentation for lambdas / anonymous methods switch (statement.Parent.Kind()) { case SyntaxKind.AnonymousMethodExpression: case SyntaxKind.SimpleLambdaExpression: case SyntaxKind.ParenthesizedLambdaExpression: parentIndentationLevel++; break; } var statementIndentationString = IndentationHelper.GenerateIndentationString(indentationOptions, parentIndentationLevel + 1); var newFirstTokenLeadingTrivia = statement.GetFirstToken().LeadingTrivia .WithoutTrailingWhitespace() .Add(SyntaxFactory.Whitespace(statementIndentationString)); var newLastTokenTrailingTrivia = statement.GetLastToken().TrailingTrivia .WithoutTrailingWhitespace() .Add(SyntaxFactory.CarriageReturnLineFeed); var firstToken = statement.GetFirstToken().WithLeadingTrivia(newFirstTokenLeadingTrivia); var lastToken = statement.GetLastToken().WithTrailingTrivia(newLastTokenTrailingTrivia); return statement.ReplaceTokens( new[] { statement.GetFirstToken(), statement.GetLastToken() }, (originalToken, rewrittenToken) => { if (originalToken == statement.GetFirstToken()) { return firstToken; } else if (originalToken == statement.GetLastToken()) { return lastToken; } else { return rewrittenToken; } }); }
private static SyntaxNode ReformatStatementAndParent(Document document, SyntaxNode syntaxRoot, StatementSyntax statement) { var parentLastToken = statement.GetFirstToken().GetPreviousToken(); var parentEndLine = parentLastToken.GetEndLine(); var statementStartLine = statement.GetFirstToken().GetLine(); var newParentLastToken = parentLastToken; if (parentEndLine == statementStartLine) { var newTrailingTrivia = parentLastToken.TrailingTrivia .WithoutTrailingWhitespace() .Add(SyntaxFactory.CarriageReturnLineFeed); newParentLastToken = newParentLastToken.WithTrailingTrivia(newTrailingTrivia); } var parentNextToken = statement.GetLastToken().GetNextToken(); var nextTokenLine = parentNextToken.GetLine(); var statementCloseLine = statement.GetLastToken().GetEndLine(); var newParentNextToken = parentNextToken; if (nextTokenLine == statementCloseLine) { var indentationOptions = IndentationOptions.FromDocument(document); var parentIndentationLevel = IndentationHelper.GetIndentationSteps(indentationOptions, GetStatementParent(statement.Parent)); var indentationString = IndentationHelper.GenerateIndentationString(indentationOptions, parentIndentationLevel); newParentNextToken = newParentNextToken.WithLeadingTrivia(SyntaxFactory.Whitespace(indentationString)); } var newStatement = ReformatStatement(document, statement); var newSyntaxRoot = syntaxRoot.ReplaceSyntax( new[] { statement }, (originalNode, rewrittenNode) => originalNode == statement ? newStatement : rewrittenNode, new[] { parentLastToken, parentNextToken }, (originalToken, rewrittenToken) => { if (originalToken == parentLastToken) { return newParentLastToken; } else if (originalToken == parentNextToken) { return newParentNextToken; } else { return rewrittenToken; } }, Enumerable.Empty<SyntaxTrivia>(), (originalTrivia, rewrittenTrivia) => rewrittenTrivia); return newSyntaxRoot.WithoutFormatting(); }