private static SyntaxList <StatementSyntax> AddBreakStatementIfNecessary(StatementSyntax statement) { if (statement.IsKind(SyntaxKind.Block)) { var block = (BlockSyntax)statement; SyntaxList <StatementSyntax> statements = block.Statements; if (statements.Any() && IsJumpStatement(statements.Last())) { return(SingletonList <StatementSyntax>(block)); } else { return(SingletonList <StatementSyntax>(block.AddStatements(BreakStatement()))); } } else { if (IsJumpStatement(statement)) { return(SingletonList(statement)); } else { return(SingletonList <StatementSyntax>(Block(statement, BreakStatement()))); } } }
private static void AnalyzeNamespaceDeclaration(SyntaxNodeAnalysisContext context) { var namespaceDeclaration = (NamespaceDeclarationSyntax)context.Node; SyntaxList <MemberDeclarationSyntax> members = namespaceDeclaration.Members; SyntaxList <ExternAliasDirectiveSyntax> externs = namespaceDeclaration.Externs; if (externs.Any()) { AnalyzeStart(context, externs[0], namespaceDeclaration.OpenBraceToken); } else { SyntaxList <UsingDirectiveSyntax> usings = namespaceDeclaration.Usings; if (usings.Any()) { AnalyzeStart(context, usings[0], namespaceDeclaration.OpenBraceToken); } else if (members.Any()) { AnalyzeStart(context, members[0], namespaceDeclaration.OpenBraceToken); } } if (members.Any()) { AnalyzeEnd(context, members.Last(), namespaceDeclaration.CloseBraceToken); } }
private static void Analyze( SyntaxNodeAnalysisContext context, SyntaxList <StatementSyntax> statements, SingleLocalDeclarationStatement localDeclaration, ExpressionSyntax expression) { if (expression?.IsKind(SyntaxKind.IdentifierName) == true) { var identifierName = (IdentifierNameSyntax)expression; string name = localDeclaration.IdentifierText; if (string.Equals(name, identifierName.Identifier.ValueText, StringComparison.Ordinal)) { TextSpan span = TextSpan.FromBounds(expression.Span.End, statements.Last().Span.End); SyntaxNode parent = localDeclaration.Statement.Parent; if (!IsLocalVariableReferenced(localDeclaration.Declarator, name, parent, span, context.SemanticModel, context.CancellationToken) && !parent.ContainsDirectives(TextSpan.FromBounds(localDeclaration.Statement.SpanStart, expression.Span.End))) { ReportDiagnostic(context, localDeclaration, expression); } } } }
public static void AnalyzeSwitchStatement(SyntaxNodeAnalysisContext context) { var switchStatement = (SwitchStatementSyntax)context.Node; SyntaxList <SwitchSectionSyntax> sections = switchStatement.Sections; if (sections.Any()) { AnalyzeStart(context, sections.First(), switchStatement.OpenBraceToken); AnalyzeEnd(context, sections.Last(), switchStatement.CloseBraceToken); if (sections.Count > 1) { SwitchSectionSyntax prevSection = sections.First(); for (int i = 1; i < sections.Count; i++) { if (prevSection.Statements.LastOrDefault()?.IsKind(SyntaxKind.Block) == true) { Analyze(context, prevSection, sections[i]); } prevSection = sections[i]; } } } }
private static void AnalyzeSwitchStatement(SyntaxNodeAnalysisContext context) { var switchStatement = (SwitchStatementSyntax)context.Node; SyntaxList <SwitchSectionSyntax> sections = switchStatement.Sections; if (sections.Any()) { AnalyzeStart(context, sections[0], switchStatement.OpenBraceToken); AnalyzeEnd(context, sections.Last(), switchStatement.CloseBraceToken); if (sections.Count > 1 && !context.IsAnalyzerSuppressed(AnalyzerOptions.RemoveEmptyLineBetweenClosingBraceAndSwitchSection)) { SwitchSectionSyntax prevSection = sections[0]; for (int i = 1; i < sections.Count; i++) { SwitchSectionSyntax section = sections[i]; if (prevSection.Statements.LastOrDefault() is BlockSyntax block) { Analyze(context, block.CloseBraceToken, section); } prevSection = section; } } } }
private static void AnalyzeSwitchSection(SyntaxNodeAnalysisContext context) { var switchSection = (SwitchSectionSyntax)context.Node; SyntaxList <SwitchLabelSyntax> labels = switchSection.Labels; int count = labels.Count; if (count <= 1) { return; } SwitchLabelSyntax lastLabel = labels.Last(); for (int i = 0; i < count - 1; i++) { SwitchLabelSyntax label = labels[i]; if (label.Kind() == SyntaxKind.DefaultSwitchLabel) { TextSpan span = TextSpan.FromBounds(label.Span.End, lastLabel.SpanStart); if (!switchSection.ContainsDirectives(span)) { DiagnosticHelpers.ReportDiagnostic(context, DiagnosticDescriptors.DefaultLabelShouldBeLastLabelInSwitchSection, label); break; } } } }
private static async Task <Document> MoveDefaultLabelToLastPositionAsync( Document document, SwitchSectionSyntax switchSection, CancellationToken cancellationToken = default(CancellationToken)) { SyntaxNode root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); SyntaxList <SwitchLabelSyntax> labels = switchSection.Labels; SwitchLabelSyntax defaultLabel = labels.First(f => f.IsKind(SyntaxKind.DefaultSwitchLabel)); int index = labels.IndexOf(defaultLabel); SwitchLabelSyntax lastLabel = labels.Last(); labels = labels.Replace(lastLabel, defaultLabel.WithTriviaFrom(lastLabel)); labels = labels.Replace(labels[index], lastLabel.WithTriviaFrom(defaultLabel)); SwitchSectionSyntax newSwitchSection = switchSection.WithLabels(labels); SyntaxNode newRoot = root.ReplaceNode(switchSection, newSwitchSection); return(document.WithSyntaxRoot(newRoot)); }
private static AwaitExpressionSyntax GetLastReturnAwaitExpressionOfDefault(StatementSyntax statement) { if (statement != null) { SyntaxKind kind = statement.Kind(); if (kind == SyntaxKind.Block) { var block = (BlockSyntax)statement; SyntaxList <StatementSyntax> statements = block.Statements; if (statements.Any()) { for (int i = 0; i < statements.Count - 1; i++) { if (!statements[i].IsKind(SyntaxKind.LocalFunctionStatement) && ContainsAwaitExpression(statements[i])) { return(null); } } return(GetAwaitExpressionOrDefault(statements.Last())); } } else if (kind == SyntaxKind.ReturnStatement) { return(GetAwaitExpressionOrDefault((ReturnStatementSyntax)statement)); } } return(null); }
internal static bool IsFixableRecursively(IfStatementSyntax ifStatement, SyntaxKind jumpKind) { if (ifStatement.Statement is not BlockSyntax block) { return(false); } SyntaxList <StatementSyntax> statements = block.Statements; if (!statements.Any()) { return(false); } StatementSyntax statement = statements.Last(); if (statement is IfStatementSyntax ifStatement2) { return(IsFixable(ifStatement2)); } return(jumpKind == GetJumpKind(statement) && (statements.LastButOneOrDefault() is IfStatementSyntax ifStatement3) && IsFixable(ifStatement3)); }
public static void AnalyzeSwitchSection(SyntaxNodeAnalysisContext context) { var switchSection = (SwitchSectionSyntax)context.Node; SyntaxList <StatementSyntax> statements = switchSection.Statements; if (!statements.Any()) { return; } SyntaxList <SwitchLabelSyntax> labels = switchSection.Labels; if (!labels.Any()) { return; } StatementSyntax statement = statements.First(); if (!switchSection.SyntaxTree.IsSingleLineSpan(TextSpan.FromBounds(labels.Last().Span.End, statement.SpanStart))) { return; } context.ReportDiagnostic(DiagnosticDescriptors.FormatSwitchSectionStatementOnSeparateLine, statement); }
private static Task <Document> AddCasesAsync( Document document, SwitchStatementSyntax switchStatement, IEnumerable <IFieldSymbol> fieldSymbols, CancellationToken cancellationToken) { SyntaxList <SwitchSectionSyntax> sections = switchStatement.Sections; TypeSyntax enumType = fieldSymbols.First().ContainingType.ToTypeSyntax().WithSimplifierAnnotation(); SyntaxList <StatementSyntax> statements = SingletonList <StatementSyntax>(BreakStatement()); cancellationToken.ThrowIfCancellationRequested(); SyntaxList <SwitchSectionSyntax> newSections = fieldSymbols .Select(fieldSymbol => CreateSwitchSection(fieldSymbol, enumType, statements)) .ToSyntaxList(); int insertIndex = sections.Count; if (sections.Last().ContainsDefaultLabel()) { insertIndex--; } SwitchStatementSyntax newSwitchStatement = switchStatement .WithSections(sections.InsertRange(insertIndex, newSections)) .WithFormatterAnnotation(); return(document.ReplaceNodeAsync(switchStatement, newSwitchStatement, cancellationToken)); }
private static void Analyze( SyntaxNodeAnalysisContext context, SyntaxList <StatementSyntax> statements, SingleLocalDeclarationStatementInfo localDeclarationInfo, int index, ExpressionStatementSyntax expressionStatement) { SimpleAssignmentExpressionInfo assignment = SyntaxInfo.SimpleAssignmentExpressionInfo(expressionStatement.Expression); if (!assignment.Success) { return; } if (assignment.Right.Kind() != SyntaxKind.IdentifierName) { return; } var identifierName = (IdentifierNameSyntax)assignment.Right; string name = localDeclarationInfo.IdentifierText; if (!string.Equals(name, identifierName.Identifier.ValueText, StringComparison.Ordinal)) { return; } VariableDeclaratorSyntax declarator = localDeclarationInfo.Declarator; ISymbol localSymbol = context.SemanticModel.GetDeclaredSymbol(declarator, context.CancellationToken); if (localSymbol?.IsErrorType() != false) { return; } bool isReferenced = IsLocalVariableReferenced(localSymbol, name, assignment.Left, assignment.Left.Span, context.SemanticModel, context.CancellationToken); if (!isReferenced && index < statements.Count - 2) { TextSpan span = TextSpan.FromBounds(statements[index + 2].SpanStart, statements.Last().Span.End); isReferenced = IsLocalVariableReferenced(localSymbol, name, localDeclarationInfo.Statement.Parent, span, context.SemanticModel, context.CancellationToken); } if (isReferenced) { return; } if (expressionStatement.SpanOrLeadingTriviaContainsDirectives()) { return; } ReportDiagnostic(context, localDeclarationInfo, assignment.Right); }
private static void ProcessNodeList <T>( SyntaxList <T> children, List <TextSpan> spans, CancellationToken cancellationToken ) where T : SyntaxNode { Contract.ThrowIfNull(spans); if (children.Count == 0) { // nothing to separate return; } // first child needs no separator var seenSeparator = true; for (var i = 0; i < children.Count - 1; i++) { cancellationToken.ThrowIfCancellationRequested(); var cur = children[i]; if (!IsSeparableBlock(cur)) { seenSeparator = false; } else { if (!seenSeparator) { var prev = children[i - 1]; AddLineSeparatorSpanForNode(prev, spans, cancellationToken); } AddLineSeparatorSpanForNode(cur, spans, cancellationToken); seenSeparator = true; } } // last child may need separator only before it var lastChild = children.Last(); if (IsSeparableBlock(lastChild)) { if (!seenSeparator) { var nextToLast = children[children.Count - 2]; AddLineSeparatorSpanForNode(nextToLast, spans, cancellationToken); } if (lastChild.IsParentKind(SyntaxKind.CompilationUnit)) { AddLineSeparatorSpanForNode(lastChild, spans, cancellationToken); } } }
private static void ProcessUsings(SyntaxList <UsingDirectiveSyntax> usings, List <TextSpan> spans, CancellationToken cancellationToken) { Contract.ThrowIfNull(spans); if (usings.Any()) { AddLineSeparatorSpanForNode(usings.Last(), spans, cancellationToken); } }
public static void Analyze(SyntaxNodeAnalysisContext context, AccessorListSyntax accessorList) { SyntaxList <AccessorDeclarationSyntax> accessors = accessorList.Accessors; if (accessors.Any()) { AnalyzeStart(context, accessors.First(), accessorList.OpenBraceToken); AnalyzeEnd(context, accessors.Last(), accessorList.CloseBraceToken); } }
public static void Analyze(SyntaxNodeAnalysisContext context, BlockSyntax block) { SyntaxList <StatementSyntax> statements = block.Statements; if (statements.Any()) { AnalyzeStart(context, statements.First(), block.OpenBraceToken); AnalyzeEnd(context, statements.Last(), block.CloseBraceToken); } }
private static void AnalyzeDeclaration( SyntaxNodeAnalysisContext context, SyntaxList <MemberDeclarationSyntax> members, SyntaxToken openBrace, SyntaxToken closeBrace) { if (members.Any()) { AnalyzeStart(context, members.First(), openBrace); AnalyzeEnd(context, members.Last(), closeBrace); } }
private static void AnalyzeAccessorList(SyntaxNodeAnalysisContext context) { var accessorList = (AccessorListSyntax)context.Node; SyntaxList <AccessorDeclarationSyntax> accessors = accessorList.Accessors; if (accessors.Any()) { AnalyzeStart(context, accessors[0], accessorList.OpenBraceToken); AnalyzeEnd(context, accessors.Last(), accessorList.CloseBraceToken); } }
private static StatementSyntax GetLastStatementBeforeBreakStatementOrDefault(SwitchSectionSyntax switchSection) { SyntaxList <StatementSyntax> statements = GetStatements(switchSection); if (statements.Count > 1 && statements.Last().IsKind(SyntaxKind.BreakStatement)) { return(statements[statements.Count - 2]); } return(null); }
private static void AnalyzeSwitchStatement(SyntaxNodeAnalysisContext context) { var switchStatement = (SwitchStatementSyntax)context.Node; SyntaxList <SwitchSectionSyntax> sections = switchStatement.Sections; if (sections.Any()) { AnalyzeStart(context, sections[0], switchStatement.OpenBraceToken); AnalyzeEnd(context, sections.Last(), switchStatement.CloseBraceToken); } }
private static async Task <Document> RefactorAsync( Document document, StatementSyntax statement, CancellationToken cancellationToken) { StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(statement); var methodDeclaration = (MethodDeclarationSyntax)statementsInfo.Parent.Parent; SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); string name = methodDeclaration.Identifier.ValueText; if (!name.EndsWith("Iterator", StringComparison.Ordinal)) { name += "Iterator"; } name = NameGenerator.Default.EnsureUniqueLocalName(name, semanticModel, statement.SpanStart, cancellationToken: cancellationToken); SyntaxList <StatementSyntax> statements = statementsInfo.Statements; int index = statements.IndexOf(statement); List <StatementSyntax> localFunctionStatements = statements.Skip(index).ToList(); int lastIndex = localFunctionStatements.Count - 1; localFunctionStatements[lastIndex] = localFunctionStatements[lastIndex].WithoutTrailingTrivia(); LocalFunctionStatementSyntax localFunction = LocalFunctionStatement( default(SyntaxTokenList), methodDeclaration.ReturnType.WithoutTrivia(), Identifier(name).WithRenameAnnotation(), ParameterList(), Block(localFunctionStatements).WithTrailingTrivia(statements.Last().GetTrailingTrivia())); localFunction = localFunction.WithFormatterAnnotation(); ReturnStatementSyntax returnStatement = ReturnStatement( Token(SyntaxKind.ReturnKeyword).WithLeadingTrivia(statement.GetLeadingTrivia()), InvocationExpression(IdentifierName(name)), SemicolonToken()); SyntaxList <StatementSyntax> newStatements = statements.ReplaceRange( index, statements.Count - index, new StatementSyntax[] { returnStatement, localFunction }); return(await document.ReplaceStatementsAsync(statementsInfo, newStatements, cancellationToken).ConfigureAwait(false)); }
private static async Task <Document> ChangeArrayTypeToImplicitAsync( Document document, ArrayCreationExpressionSyntax arrayCreation, CancellationToken cancellationToken) { SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); ArrayTypeSyntax arrayType = arrayCreation.Type; SyntaxList <ArrayRankSpecifierSyntax> rankSpecifiers = arrayType.RankSpecifiers; InitializerExpressionSyntax initializer = arrayCreation.Initializer; ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(arrayType.ElementType, cancellationToken); TypeSyntax castType; if (rankSpecifiers.Count > 1) { castType = ParseTypeName(arrayType.ToString().Remove(rankSpecifiers.Last().SpanStart - arrayType.SpanStart)); } else { castType = arrayType.ElementType; } InitializerExpressionSyntax newInitializer = initializer.ReplaceNodes( initializer.Expressions, (node, _) => CastExpression(castType, node.WithoutTrivia()) .WithTriviaFrom(node) .WithSimplifierAnnotation()); ImplicitArrayCreationExpressionSyntax implicitArrayCreation = ImplicitArrayCreationExpression( arrayCreation.NewKeyword.WithTrailingTrivia(arrayCreation.NewKeyword.TrailingTrivia.EmptyIfWhitespace()), rankSpecifiers[0].OpenBracketToken, default(SyntaxTokenList), rankSpecifiers.Last().CloseBracketToken, newInitializer); return(await document.ReplaceNodeAsync(arrayCreation, implicitArrayCreation, cancellationToken).ConfigureAwait(false)); }
private static SyntaxList <T> WithSourceMappingFrom <T>(this SyntaxList <T> converted, SyntaxNode node) where T : SyntaxNode { if (!converted.Any()) { return(converted); } var origLinespan = node.SyntaxTree.GetLineSpan(node.Span); var first = converted.First(); converted = converted.Replace(first, node.CopyAnnotationsTo(first).WithSourceStartLineAnnotation(origLinespan)); var last = converted.Last(); return(converted.Replace(last, last.WithSourceEndLineAnnotation(origLinespan))); }
private static void Analyze( SyntaxNodeAnalysisContext context, SyntaxList <StatementSyntax> statements, SingleLocalDeclarationStatementInfo localDeclarationInfo, int index, LocalDeclarationStatementSyntax localDeclaration2) { ExpressionSyntax value2 = localDeclaration2 .Declaration? .Variables .SingleOrDefault(shouldThrow: false)? .Initializer? .Value; if (value2?.Kind() != SyntaxKind.IdentifierName) { return; } var identifierName = (IdentifierNameSyntax)value2; string name = localDeclarationInfo.IdentifierText; if (!string.Equals(name, identifierName.Identifier.ValueText, StringComparison.Ordinal)) { return; } bool isReferenced = false; if (index < statements.Count - 2) { TextSpan span = TextSpan.FromBounds(statements[index + 2].SpanStart, statements.Last().Span.End); isReferenced = IsLocalVariableReferenced(localDeclarationInfo.Declarator, name, localDeclarationInfo.Statement.Parent, span, context.SemanticModel, context.CancellationToken); } if (isReferenced) { return; } if (localDeclaration2.SpanOrLeadingTriviaContainsDirectives()) { return; } ReportDiagnostic(context, localDeclarationInfo, value2); }
private static void ReportIssue(SyntaxList <StatementSyntax> statementsToReport, SyntaxList <StatementSyntax> locationProvider, SyntaxNodeAnalysisContext context, string constructType) { var firstStatement = statementsToReport.FirstOrDefault(); if (firstStatement == null) { return; } var lastStatement = statementsToReport.Last(); context.ReportDiagnosticWhenActive(Diagnostic.Create(rule, firstStatement.CreateLocation(lastStatement), locationProvider.First().GetLineNumberToReport(), constructType)); }
private static Task <Document> RemoveBracesAsync( Document document, BlockSyntax block, CancellationToken cancellationToken) { var switchSection = (SwitchSectionSyntax)block.Parent; SyntaxList <StatementSyntax> statements = block.Statements; SyntaxTriviaList leadingTrivia = block.OpenBraceToken.LeadingTrivia; leadingTrivia = AddTriviaIfNecessary(leadingTrivia, block.OpenBraceToken.TrailingTrivia); leadingTrivia = AddTriviaIfNecessary(leadingTrivia, statements[0].GetLeadingTrivia()); SyntaxTriviaList trailingTrivia = statements.Last().GetTrailingTrivia(); trailingTrivia = AddTriviaIfNecessary(trailingTrivia, block.CloseBraceToken.LeadingTrivia); trailingTrivia = AddTriviaIfNecessary(trailingTrivia, block.CloseBraceToken.TrailingTrivia); trailingTrivia = trailingTrivia.TrimEnd().Add(CSharpFactory.NewLine()); var switchStatement = (SwitchStatementSyntax)switchSection.Parent; if (!switchStatement.Sections.IsLast(switchSection)) { trailingTrivia = trailingTrivia.Add(CSharpFactory.NewLine()); } SyntaxList <StatementSyntax> newStatements = statements.ReplaceAt(0, statements[0].WithLeadingTrivia(leadingTrivia)); newStatements = newStatements.ReplaceAt(newStatements.Count - 1, newStatements.Last().WithTrailingTrivia(trailingTrivia)); SwitchSectionSyntax newSwitchSection = switchSection .WithStatements(newStatements) .WithFormatterAnnotation(); return(document.ReplaceNodeAsync(switchSection, newSwitchSection, cancellationToken)); SyntaxTriviaList AddTriviaIfNecessary(SyntaxTriviaList trivia, SyntaxTriviaList triviaToAdd) { if (triviaToAdd.Any(f => f.IsKind(SyntaxKind.SingleLineCommentTrivia))) { trivia = trivia.AddRange(triviaToAdd); } return(trivia); } }
public static void Analyze(SyntaxNodeAnalysisContext context, SwitchStatementSyntax switchStatement) { SyntaxList <SwitchSectionSyntax> sections = switchStatement.Sections; if (sections.Any()) { AnalyzeStart(context, sections.First(), switchStatement.OpenBraceToken); AnalyzeEnd(context, sections.Last(), switchStatement.CloseBraceToken); if (sections.Count > 1) { SwitchSectionSyntax prevSection = sections.First(); for (int i = 1; i < sections.Count; i++) { if (prevSection.Statements.LastOrDefault()?.IsKind(SyntaxKind.Block) == true) { SwitchSectionSyntax section = sections[i]; SyntaxTriviaList trailingTrivia = prevSection.GetTrailingTrivia(); SyntaxTriviaList leadingTrivia = section.GetLeadingTrivia(); if (!IsStandardTriviaBetweenSections(trailingTrivia, leadingTrivia) && switchStatement .SyntaxTree .GetLineSpan(TextSpan.FromBounds(prevSection.Span.End, section.Span.Start), context.CancellationToken) .GetLineCount() == 3) { SyntaxTrivia trivia = leadingTrivia .SkipWhile(f => f.IsWhitespaceTrivia()) .FirstOrDefault(); if (trivia.IsEndOfLineTrivia() && trailingTrivia.All(f => f.IsWhitespaceOrEndOfLineTrivia()) && leadingTrivia.All(f => f.IsWhitespaceOrEndOfLineTrivia())) { context.ReportDiagnostic( DiagnosticDescriptors.RemoveRedundantEmptyLine, Location.Create(switchStatement.SyntaxTree, TextSpan.FromBounds(section.FullSpan.Start, trivia.Span.End))); } } } prevSection = sections[i]; } } } }
private static void AnalyzeBlock(SyntaxNodeAnalysisContext context) { var block = (BlockSyntax)context.Node; SyntaxList <StatementSyntax> statements = block.Statements; if (statements.Any()) { AnalyzeStart(context, statements[0], block.OpenBraceToken); AnalyzeEnd(context, statements.Last(), block.CloseBraceToken); } else { AnalyzeEmptyBraces(context, block.OpenBraceToken, block.CloseBraceToken); } }
private static void AnalyzeDeclaration<TMember>( SyntaxNodeAnalysisContext context, SyntaxList<TMember> members, SyntaxToken openBrace, SyntaxToken closeBrace) where TMember : MemberDeclarationSyntax { if (members.Any()) { AnalyzeStart(context, members[0], openBrace); AnalyzeEnd(context, members.Last(), closeBrace); } else { AnalyzeEmptyBraces(context, openBrace, closeBrace); } }
public static void Analyze(SyntaxNodeAnalysisContext context, DoStatementSyntax doStatement) { StatementSyntax statement = doStatement.Statement; if (statement?.IsKind(SyntaxKind.Block) == true) { var block = (BlockSyntax)statement; SyntaxList <StatementSyntax> statements = block.Statements; if (statements.Any()) { SyntaxToken closeBrace = block.CloseBraceToken; if (!closeBrace.IsMissing) { SyntaxToken whileKeyword = doStatement.WhileKeyword; if (!whileKeyword.IsMissing) { int closeBraceLine = closeBrace.GetSpanEndLine(); if (closeBraceLine == whileKeyword.GetSpanStartLine()) { StatementSyntax last = statements.Last(); int line = last.GetSpanEndLine(context.CancellationToken); if (closeBraceLine - line == 1) { SyntaxTrivia trivia = last .GetTrailingTrivia() .FirstOrDefault(f => f.IsEndOfLineTrivia()); if (trivia.IsKind(SyntaxKind.EndOfLineTrivia)) { context.ReportDiagnostic( DiagnosticDescriptors.AddEmptyLineAfterLastStatementInDoStatement, Location.Create(doStatement.SyntaxTree, trivia.Span)); } } } } } } } }