private static void AnalyzeSwitchStatement(SyntaxNodeAnalysisContext context) { var switchStatement = (SwitchStatementSyntax)context.Node; SyntaxList <SwitchSectionSyntax> sections = switchStatement.Sections; SyntaxList <SwitchSectionSyntax> .Enumerator en = sections.GetEnumerator(); if (!en.MoveNext()) { return; } SwitchSectionSyntax previousSection = en.Current; while (en.MoveNext()) { SyntaxTriviaList leadingTrivia = en.Current.Labels[0].GetLeadingTrivia(); if (SyntaxTriviaAnalysis.IsEmptyOrSingleWhitespaceTrivia(leadingTrivia)) { SyntaxTriviaList trailingTrivia = previousSection.GetTrailingTrivia(); if (SyntaxTriviaAnalysis.IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(trailingTrivia)) { DiagnosticHelpers.ReportDiagnostic( context, DiagnosticDescriptors.AddEmptyLineBetweenSwitchSections, Location.Create(switchStatement.SyntaxTree, trailingTrivia.Last().Span.WithLength(0))); } } previousSection = en.Current; } }
private static void AnalyzeCompilationUnit(SyntaxNodeAnalysisContext context) { var compilationUnit = (CompilationUnitSyntax)context.Node; MemberDeclarationSyntax declaration = compilationUnit.Members.FirstOrDefault(); if (declaration == null) { return; } if (!SyntaxTriviaAnalysis.IsEmptyOrSingleWhitespaceTrivia(declaration.GetLeadingTrivia())) { return; } SyntaxNode node = compilationUnit.AttributeLists.LastOrDefault() ?? (SyntaxNode)compilationUnit.Usings.LastOrDefault() ?? compilationUnit.Externs.LastOrDefault(); if (node == null) { return; } if (!SyntaxTriviaAnalysis.IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(node.GetTrailingTrivia())) { return; } DiagnosticHelpers.ReportDiagnostic( context, DiagnosticDescriptors.AddEmptyLineBeforeTopDeclaration, Location.Create(compilationUnit.SyntaxTree, new TextSpan(node.GetTrailingTrivia().Last().SpanStart, 0))); }
private static void AnalyzeAccessorList(SyntaxNodeAnalysisContext context) { var accessorList = (AccessorListSyntax)context.Node; SyntaxList <AccessorDeclarationSyntax> accessors = accessorList.Accessors; if (accessors.Count <= 1) { return; } Debug.Assert(accessors.Count == 2, accessors.Count.ToString()); AccessorDeclarationSyntax accessor1 = accessors[0]; if (accessor1.BodyOrExpressionBody() == null) { return; } AccessorDeclarationSyntax accessor2 = accessors[1]; if (accessor2.BodyOrExpressionBody() == null) { return; } SyntaxTriviaList trailingTrivia = accessor1.GetTrailingTrivia(); if (!SyntaxTriviaAnalysis.IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(trailingTrivia)) { return; } SyntaxTriviaList leadingTrivia = accessor2.GetLeadingTrivia(); bool isEmptyLine = SyntaxTriviaAnalysis.StartsWithOptionalWhitespaceThenEndOfLineTrivia(leadingTrivia); if (accessorList.SyntaxTree.IsSingleLineSpan(accessor1.Span, context.CancellationToken) && accessorList.SyntaxTree.IsSingleLineSpan(accessor2.Span, context.CancellationToken)) { if (isEmptyLine) { ReportDiagnostic(context, DiagnosticDescriptors.RemoveEmptyLineBetweenSingleLineAccessors, leadingTrivia[0]); } else { ReportDiagnostic(context, DiagnosticDescriptors.AddEmptyLineBetweenSingleLineAccessors, trailingTrivia.Last()); } } else if (!isEmptyLine) { ReportDiagnostic(context, DiagnosticDescriptors.AddEmptyLineBetweenAccessors, trailingTrivia.Last()); } }
private static void AnalyzeCompilationUnit(SyntaxNodeAnalysisContext context) { var compilationUnit = (CompilationUnitSyntax)context.Node; UsingDirectiveSyntax usingDirective = compilationUnit.Usings.FirstOrDefault(); if (usingDirective == null) { return; } SyntaxTriviaList.Reversed.Enumerator en = usingDirective.GetLeadingTrivia().Reverse().GetEnumerator(); if (en.MoveNext()) { if (en.Current.IsWhitespaceTrivia() && !en.MoveNext()) { if (IsPrecededWithExternAliasDirective()) { ReportDiagnostic(usingDirective.SpanStart); } } else if (en.Current.IsEndOfLineTrivia() && en.MoveNext() && en.Current.IsKind(SyntaxKind.SingleLineCommentTrivia)) { ReportDiagnostic(usingDirective.SpanStart); } } else if (IsPrecededWithExternAliasDirective()) { ReportDiagnostic(usingDirective.SpanStart); } bool IsPrecededWithExternAliasDirective() { ExternAliasDirectiveSyntax externAliasDirective = compilationUnit.Externs.LastOrDefault(); return(externAliasDirective?.FullSpan.End == usingDirective.FullSpan.Start && SyntaxTriviaAnalysis.IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(externAliasDirective.GetTrailingTrivia())); } void ReportDiagnostic(int position) { DiagnosticHelpers.ReportDiagnostic( context, DiagnosticDescriptors.AddEmptyLineBeforeUsingDirectiveList, Location.Create(compilationUnit.SyntaxTree, new TextSpan(position, 0))); } }
private static void Analyze( SyntaxNodeAnalysisContext context, UsingDirectiveSyntax usingDirective, SyntaxToken nextToken) { SyntaxTriviaList trailingTrivia = usingDirective.GetTrailingTrivia(); if (!SyntaxTriviaAnalysis.IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(triviaList: trailingTrivia)) { return; } SyntaxTriviaList.Enumerator en = nextToken.LeadingTrivia.GetEnumerator(); if (en.MoveNext()) { if (en.Current.IsWhitespaceTrivia() && !en.MoveNext()) { ReportDiagnostic(trailingTrivia.Last().SpanStart); } else { switch (en.Current.Kind()) { case SyntaxKind.SingleLineCommentTrivia: case SyntaxKind.SingleLineDocumentationCommentTrivia: case SyntaxKind.MultiLineDocumentationCommentTrivia: { ReportDiagnostic(trailingTrivia.Last().SpanStart); break; } } } } else { ReportDiagnostic(trailingTrivia.Last().SpanStart); } void ReportDiagnostic(int position) { DiagnosticHelpers.ReportDiagnostic( context, DiagnosticRules.AddBlankLineAfterUsingDirectiveList, Location.Create(usingDirective.SyntaxTree, new TextSpan(position, 0))); } }
private static void AnalyzeSwitchStatement(SyntaxNodeAnalysisContext context) { var switchStatement = (SwitchStatementSyntax)context.Node; SyntaxList <SwitchSectionSyntax> sections = switchStatement.Sections; SyntaxList <SwitchSectionSyntax> .Enumerator en = sections.GetEnumerator(); if (!en.MoveNext()) { return; } SwitchSectionSyntax previousSection = en.Current; var previousBlock = previousSection.Statements.SingleOrDefault(shouldThrow: false) as BlockSyntax; while (en.MoveNext()) { SyntaxTriviaList leadingTrivia = en.Current.Labels[0].GetLeadingTrivia(); if (SyntaxTriviaAnalysis.IsEmptyOrSingleWhitespaceTrivia(leadingTrivia)) { SyntaxTriviaList trailingTrivia = previousSection.GetTrailingTrivia(); if (SyntaxTriviaAnalysis.IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(trailingTrivia) && (context.GetBlankLineBetweenClosingBraceAndSwitchSection() != false || previousBlock == null)) { DiagnosticHelpers.ReportDiagnostic( context, DiagnosticRules.AddBlankLineBetweenSwitchSections, Location.Create(switchStatement.SyntaxTree, trailingTrivia.Last().Span.WithLength(0))); } } previousSection = en.Current; previousBlock = en.Current.Statements.SingleOrDefault(shouldThrow: false) as BlockSyntax; } }
private static void AnalyzeUsings(SyntaxNodeAnalysisContext context, SyntaxList <UsingDirectiveSyntax> usings) { int count = usings.Count; if (count <= 1) { return; } UsingDirectiveSyntax usingDirective1 = usings[0]; for (int i = 1; i < count; i++, usingDirective1 = usings[i - 1]) { if (usingDirective1.StaticKeyword.IsKind(SyntaxKind.StaticKeyword)) { return; } if (usingDirective1.Alias != null) { return; } UsingDirectiveSyntax usingDirective2 = usings[i]; if (usingDirective2.StaticKeyword.IsKind(SyntaxKind.StaticKeyword)) { return; } if (usingDirective2.Alias != null) { return; } SyntaxTriviaList trailingTrivia = usingDirective1.GetTrailingTrivia(); if (!SyntaxTriviaAnalysis.IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(trailingTrivia)) { continue; } IdentifierNameSyntax rootNamespace1 = usingDirective1.GetRootNamespace(); if (rootNamespace1 == null) { continue; } IdentifierNameSyntax rootNamespace2 = usingDirective2.GetRootNamespace(); if (rootNamespace2 == null) { continue; } SyntaxTriviaList leadingTrivia = usingDirective2.GetLeadingTrivia(); bool isEmptyLine = SyntaxTriviaAnalysis.StartsWithOptionalWhitespaceThenEndOfLineTrivia(leadingTrivia); if (string.Equals(rootNamespace1.Identifier.ValueText, rootNamespace2.Identifier.ValueText, StringComparison.Ordinal)) { if (isEmptyLine) { DiagnosticHelpers.ReportDiagnosticIfNotSuppressed( context, DiagnosticDescriptors.RemoveEmptyLineBetweenUsingDirectivesWithSameRootNamespace, Location.Create(context.Node.SyntaxTree, leadingTrivia[0].Span.WithLength(0))); } } else if (!context.IsAnalyzerSuppressed(DiagnosticDescriptors.AddEmptyLineBetweenUsingDirectivesWithDifferentRootNamespaceOrViceVersa)) { if (isEmptyLine) { if (!context.IsAnalyzerSuppressed(AnalyzerOptions.RemoveEmptyLineBetweenUsingDirectivesWithDifferentRootNamespace)) { DiagnosticHelpers.ReportDiagnostic( context, DiagnosticDescriptors.ReportOnly.RemoveEmptyLineBetweenUsingDirectivesWithDifferentRootNamespace, Location.Create(context.Node.SyntaxTree, leadingTrivia[0].Span.WithLength(0)), properties: DiagnosticProperties.AnalyzerOption_Invert); } } else if (context.IsAnalyzerSuppressed(AnalyzerOptions.RemoveEmptyLineBetweenUsingDirectivesWithDifferentRootNamespace)) { DiagnosticHelpers.ReportDiagnostic( context, DiagnosticDescriptors.AddEmptyLineBetweenUsingDirectivesWithDifferentRootNamespaceOrViceVersa, Location.Create(context.Node.SyntaxTree, trailingTrivia.Last().Span.WithLength(0))); } } } }
private static void Analyze(SyntaxNodeAnalysisContext context, SyntaxList <MemberDeclarationSyntax> members) { int count = members.Count; if (count <= 1) { return; } SyntaxTree tree = context.Node.SyntaxTree; CancellationToken cancellationToken = context.CancellationToken; MemberDeclarationSyntax member; MemberDeclarationSyntax previousMember = members[0]; bool?isSingleLine; bool?isPreviousSingleLine = null; for (int i = 1; i < count; i++, previousMember = member, isPreviousSingleLine = isSingleLine) { member = members[i]; isSingleLine = null; SyntaxTriviaList trailingTrivia = previousMember.GetTrailingTrivia(); if (!SyntaxTriviaAnalysis.IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(trailingTrivia)) { continue; } SyntaxTriviaList leadingTrivia = member.GetLeadingTrivia(); (bool emptyOrWhitespaceTrivia, bool documentationComment, bool emptyLine) = AnalyzeLeadingTrivia(leadingTrivia); if (documentationComment) { ReportDiagnostic(context, DiagnosticDescriptors.AddEmptyLineBetweenDeclarationAndDocumentationComment, trailingTrivia.Last()); continue; } if (!emptyOrWhitespaceTrivia && !emptyLine) { continue; } if ((isSingleLine ?? (isSingleLine = tree.IsSingleLineSpan(member.Span, cancellationToken)).Value) && (isPreviousSingleLine ?? tree.IsSingleLineSpan(members[i - 1].Span, cancellationToken))) { if (emptyLine) { if (MemberKindEquals(previousMember, member)) { ReportDiagnostic(context, DiagnosticDescriptors.RemoveEmptyLineBetweenSingleLineDeclarationsOfSameKind, leadingTrivia[0]); } } else if (emptyOrWhitespaceTrivia) { ReportDiagnostic(context, DiagnosticDescriptors.AddEmptyLineBetweenSingleLineDeclarations, trailingTrivia.Last()); if (!MemberKindEquals(previousMember, member)) { ReportDiagnostic(context, DiagnosticDescriptors.AddEmptyLineBetweenSingleLineDeclarationsOfDifferentKind, trailingTrivia.Last()); } } } else if (emptyOrWhitespaceTrivia) { ReportDiagnostic(context, DiagnosticDescriptors.AddEmptyLineBetweenDeclarations, trailingTrivia.Last()); } } }
private static void AnalyzeEnumDeclaration(SyntaxNodeAnalysisContext context) { var enumDeclaration = (EnumDeclarationSyntax)context.Node; SeparatedSyntaxList <EnumMemberDeclarationSyntax> members = enumDeclaration.Members; int count = members.Count; if (count <= 1) { return; } SyntaxTree tree = enumDeclaration.SyntaxTree; CancellationToken cancellationToken = context.CancellationToken; EnumMemberDeclarationSyntax member; bool?isSingleLine; bool?isPreviousSingleLine = null; for (int i = 1; i < count; i++, isPreviousSingleLine = isSingleLine) { member = members[i]; isSingleLine = null; SyntaxToken commaToken = members.GetSeparator(i - 1); SyntaxTriviaList trailingTrivia = commaToken.TrailingTrivia; if (!SyntaxTriviaAnalysis.IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(trailingTrivia)) { continue; } SyntaxTriviaList leadingTrivia = member.GetLeadingTrivia(); (bool emptyOrWhitespaceTrivia, bool documentationComment, bool emptyLine) = AnalyzeLeadingTrivia(leadingTrivia); if (documentationComment) { ReportDiagnostic(context, DiagnosticDescriptors.AddEmptyLineBetweenDeclarationAndDocumentationComment, trailingTrivia.Last()); continue; } if (!emptyOrWhitespaceTrivia && !emptyLine) { continue; } if ((isSingleLine ?? (isSingleLine = tree.IsSingleLineSpan(member.Span, cancellationToken)).Value) && (isPreviousSingleLine ?? tree.IsSingleLineSpan(members[i - 1].Span, cancellationToken))) { if (emptyLine) { ReportDiagnostic(context, DiagnosticDescriptors.RemoveEmptyLineBetweenSingleLineDeclarationsOfSameKind, leadingTrivia[0]); } else if (emptyOrWhitespaceTrivia) { ReportDiagnostic(context, DiagnosticDescriptors.AddEmptyLineBetweenSingleLineDeclarations, trailingTrivia.Last()); } } else if (emptyOrWhitespaceTrivia) { ReportDiagnostic(context, DiagnosticDescriptors.AddEmptyLineBetweenDeclarations, trailingTrivia.Last()); } } }
private static void AnalyzeUsings(SyntaxNodeAnalysisContext context, SyntaxList <UsingDirectiveSyntax> usings) { int count = usings.Count; if (count <= 1) { return; } UsingDirectiveSyntax usingDirective1 = usings[0]; for (int i = 1; i < count; i++, usingDirective1 = usings[i - 1]) { if (usingDirective1.StaticKeyword.IsKind(SyntaxKind.StaticKeyword)) { return; } if (usingDirective1.Alias != null) { return; } UsingDirectiveSyntax usingDirective2 = usings[i]; if (usingDirective2.StaticKeyword.IsKind(SyntaxKind.StaticKeyword)) { return; } if (usingDirective2.Alias != null) { return; } SyntaxTriviaList trailingTrivia = usingDirective1.GetTrailingTrivia(); if (!SyntaxTriviaAnalysis.IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(trailingTrivia)) { continue; } IdentifierNameSyntax rootNamespace1 = usingDirective1.GetRootNamespace(); if (rootNamespace1 == null) { continue; } IdentifierNameSyntax rootNamespace2 = usingDirective2.GetRootNamespace(); if (rootNamespace2 == null) { continue; } SyntaxTriviaList leadingTrivia = usingDirective2.GetLeadingTrivia(); bool isEmptyLine = SyntaxTriviaAnalysis.StartsWithOptionalWhitespaceThenEndOfLineTrivia(leadingTrivia); if (string.Equals(rootNamespace1.Identifier.ValueText, rootNamespace2.Identifier.ValueText, StringComparison.Ordinal)) { if (isEmptyLine) { if (DiagnosticRules.RemoveBlankLineBetweenUsingDirectivesWithSameRootNamespace.IsEffective(context)) { DiagnosticHelpers.ReportDiagnostic( context, DiagnosticRules.RemoveBlankLineBetweenUsingDirectivesWithSameRootNamespace, Location.Create(context.Node.SyntaxTree, leadingTrivia[0].Span.WithLength(0))); } if (DiagnosticRules.BlankLineBetweenUsingDirectives.IsEffective(context) && context.GetBlankLineBetweenUsingDirectives() == UsingDirectiveBlankLineStyle.Never) { DiagnosticHelpers.ReportDiagnostic( context, DiagnosticRules.BlankLineBetweenUsingDirectives, Location.Create(context.Node.SyntaxTree, leadingTrivia[0].Span.WithLength(0)), properties: DiagnosticProperties.AnalyzerOption_Invert, "Remove"); } } } else if (DiagnosticRules.BlankLineBetweenUsingDirectives.IsEffective(context)) { UsingDirectiveBlankLineStyle style = context.GetBlankLineBetweenUsingDirectives(); if (isEmptyLine) { if (style == UsingDirectiveBlankLineStyle.Never) { DiagnosticHelpers.ReportDiagnostic( context, DiagnosticRules.BlankLineBetweenUsingDirectives, Location.Create(context.Node.SyntaxTree, leadingTrivia[0].Span.WithLength(0)), properties: DiagnosticProperties.AnalyzerOption_Invert, "Remove"); } } else if (style == UsingDirectiveBlankLineStyle.SeparateGroups) { DiagnosticHelpers.ReportDiagnostic( context, DiagnosticRules.BlankLineBetweenUsingDirectives, Location.Create(context.Node.SyntaxTree, trailingTrivia.Last().Span.WithLength(0)), "Add"); } } } }
private static void AnalyzeUsings(SyntaxNodeAnalysisContext context, SyntaxList <UsingDirectiveSyntax> usings) { int count = usings.Count; if (count <= 1) { return; } UsingDirectiveSyntax usingDirective1 = usings[0]; for (int i = 1; i < count; i++, usingDirective1 = usings[i - 1]) { if (usingDirective1.StaticKeyword.IsKind(SyntaxKind.StaticKeyword)) { return; } if (usingDirective1.Alias != null) { return; } UsingDirectiveSyntax usingDirective2 = usings[i]; if (usingDirective2.StaticKeyword.IsKind(SyntaxKind.StaticKeyword)) { return; } if (usingDirective2.Alias != null) { return; } SyntaxTriviaList trailingTrivia = usingDirective1.GetTrailingTrivia(); if (!SyntaxTriviaAnalysis.IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(trailingTrivia)) { continue; } IdentifierNameSyntax rootNamespace1 = usingDirective1.GetRootNamespace(); if (rootNamespace1 == null) { continue; } IdentifierNameSyntax rootNamespace2 = usingDirective2.GetRootNamespace(); if (rootNamespace2 == null) { continue; } SyntaxTriviaList leadingTrivia = usingDirective2.GetLeadingTrivia(); bool isEmptyLine = SyntaxTriviaAnalysis.StartsWithOptionalWhitespaceThenEndOfLineTrivia(leadingTrivia); if (string.Equals(rootNamespace1.Identifier.ValueText, rootNamespace2.Identifier.ValueText, StringComparison.Ordinal)) { if (isEmptyLine) { ReportDiagnostic( context, DiagnosticDescriptors.RemoveEmptyLineBetweenUsingDirectivesWithSameRootNamespace, leadingTrivia[0]); } } else if (isEmptyLine) { ReportDiagnostic( context, DiagnosticDescriptors.RemoveEmptyLineBetweenUsingDirectivesWithDifferentRootNamespace, leadingTrivia[0]); } else { ReportDiagnostic( context, DiagnosticDescriptors.AddEmptyLineBetweenUsingDirectivesWithDifferentRootNamespace, trailingTrivia.Last()); } } }
private static void AnalyzeAccessorList(SyntaxNodeAnalysisContext context) { var accessorList = (AccessorListSyntax)context.Node; SyntaxList <AccessorDeclarationSyntax> accessors = accessorList.Accessors; if (accessors.Count <= 1) { return; } Debug.Assert(accessors.Count == 2, accessors.Count.ToString()); AccessorDeclarationSyntax accessor1 = accessors[0]; if (accessor1.BodyOrExpressionBody() == null) { return; } AccessorDeclarationSyntax accessor2 = accessors[1]; if (accessor2.BodyOrExpressionBody() == null) { return; } SyntaxTriviaList trailingTrivia = accessor1.GetTrailingTrivia(); if (!SyntaxTriviaAnalysis.IsOptionalWhitespaceThenOptionalSingleLineCommentThenEndOfLineTrivia(trailingTrivia)) { return; } SyntaxTriviaList leadingTrivia = accessor2.GetLeadingTrivia(); bool isEmptyLine = SyntaxTriviaAnalysis.StartsWithOptionalWhitespaceThenEndOfLineTrivia(leadingTrivia); if (accessorList.SyntaxTree.IsSingleLineSpan(accessor1.Span, context.CancellationToken) && accessorList.SyntaxTree.IsSingleLineSpan(accessor2.Span, context.CancellationToken)) { if (DiagnosticRules.BlankLineBetweenSingleLineAccessors.IsEffective(context)) { BlankLineStyle style = context.GetBlankLineBetweenSingleLineAccessors(); if (isEmptyLine) { if (style == BlankLineStyle.Remove) { DiagnosticHelpers.ReportDiagnostic( context, DiagnosticRules.BlankLineBetweenSingleLineAccessors, Location.Create(context.Node.SyntaxTree, leadingTrivia[0].Span.WithLength(0)), properties: DiagnosticProperties.AnalyzerOption_Invert, "Remove"); } } else if (style == BlankLineStyle.Add) { DiagnosticHelpers.ReportDiagnostic( context, DiagnosticRules.BlankLineBetweenSingleLineAccessors, Location.Create(context.Node.SyntaxTree, trailingTrivia.Last().Span.WithLength(0)), "Add"); } } } else if (!isEmptyLine) { DiagnosticHelpers.ReportDiagnosticIfEffective( context, DiagnosticRules.AddBlankLineBetweenAccessors, Location.Create(context.Node.SyntaxTree, trailingTrivia.Last().Span.WithLength(0))); } }