/// <summary> /// Analyzes class declaration. /// </summary> /// <param name="context">Syntax node analysis context.</param> private static void AnalyzeClassDeclaration(SyntaxNodeAnalysisContext context) { if (BTAnalyzer.IsGenerated(context)) { return; } BTAnalyzer.AnalyzeSummaryComments(context); }
/// <summary> /// Analyzes items inside methods. /// </summary> /// <param name="context">Code block analysis context.</param> private static void AnalyzeInsideMethod(SyntaxNodeAnalysisContext context) { if (BTAnalyzer.IsGenerated(context)) { return; } // Analyze comments inside methods BTAnalyzer.AnalyzeInsideMethodComment(context); BTAnalyzer.AnalyzeLogicalExpressions(context); }
/// <summary> /// Analyzes empty lines inside blocks. /// </summary> /// <param name="context">Context.</param> private static void AnalyzeBlockEmptyLines(SyntaxNodeAnalysisContext context) { // Return early if (BTAnalyzer.IsGenerated(context)) { return; } // Get the block ClassDeclarationSyntax classDeclarationSyntax = context.Node as ClassDeclarationSyntax; // Check method spacing SyntaxNode[] nodes = classDeclarationSyntax.ChildNodes().Where(node => SyntaxKind.BaseList != node.Kind() && SyntaxKind.AttributeList != node.Kind()).ToArray(); Location location = default(Location); for (int i = 0; i < nodes.Length; i++) { SyntaxNode method = nodes[i]; IEnumerable <SyntaxTrivia> trivias = method.GetFirstToken().LeadingTrivia; int count = 0; int j = 0; foreach (SyntaxTrivia trivia in trivias) { if (j == 0) { location = BTAnalyzer.GetLocation(trivia.SyntaxTree, trivia.GetLocation(), Position.Origin); j++; } if (SyntaxKind.EndOfLineTrivia == trivia.Kind()) { count++; } else if (!(SyntaxKind.WhitespaceTrivia == trivia.Kind())) { break; } } if ((i == 0 && count > 0) || (i > 0 && count > 1)) { context.ReportDiagnostic(Diagnostic.Create(BTAnalyzer.Rule, location, ErrorCode.ExtraLine)); } if (i > 0 && count < 1) { context.ReportDiagnostic(Diagnostic.Create(BTAnalyzer.Rule, location, ErrorCode.MissingEmptyLine)); } } // Check blocks IEnumerable <BlockSyntax> blocks = classDeclarationSyntax.DescendantNodes().Where(node => SyntaxKind.Block == node.Kind()).OfType <BlockSyntax>(); // Iterate through each block foreach (BlockSyntax block in blocks) { // Get a list of node, single line comment and end of line List <Tuple <object, SyntaxKind> > blockObjectList = new List <Tuple <object, SyntaxKind> >(); foreach (SyntaxNode node in block.ChildNodes()) { // Check whether the node is a block node bool isBlockNode = node.ChildNodes().Any(nodee => SyntaxKind.Block == nodee.Kind()); // Get all trivias SyntaxTrivia[] allTrivias = node.DescendantTrivia().Where(trivia => (SyntaxKind.SingleLineCommentTrivia == trivia.Kind()) || (SyntaxKind.EndOfLineTrivia == trivia.Kind())).ToArray(); // Add trivias before the node foreach (SyntaxTrivia trivia in allTrivias) { if (trivia.Span.End <= node.SpanStart) { blockObjectList.Add(Tuple.Create <object, SyntaxKind>(trivia, trivia.Kind())); } } // Add the node blockObjectList.Add(Tuple.Create <object, SyntaxKind>(node, SyntaxKind.None)); // Add trivia after the node foreach (SyntaxTrivia trivia in allTrivias) { if ((trivia.SpanStart >= node.Span.End) && !isBlockNode) { blockObjectList.Add(Tuple.Create <object, SyntaxKind>(trivia, trivia.Kind())); } } // Add an additional end of line trivia for block node if (isBlockNode) { blockObjectList.Add(Tuple.Create <object, SyntaxKind>(null, SyntaxKind.EndOfLineTrivia)); } } // Trim the block object list // Remove end of line after a statement List <Tuple <object, SyntaxKind> > trimmedBlockObjectList = new List <Tuple <object, SyntaxKind> >(); for (int i = 0; i < blockObjectList.Count(); i++) { if (SyntaxKind.EndOfLineTrivia != blockObjectList[i].Item2) { if ((i + 1 < blockObjectList.Count()) && (SyntaxKind.EndOfLineTrivia == blockObjectList[i + 1].Item2)) { trimmedBlockObjectList.Add(blockObjectList[i]); i++; continue; } } trimmedBlockObjectList.Add(blockObjectList[i]); } // Cannot start with empty lines for (int i = 0; i < trimmedBlockObjectList.Count(); i++) { if (SyntaxKind.EndOfLineTrivia == blockObjectList[i].Item2) { SyntaxTrivia trivia = (SyntaxTrivia)trimmedBlockObjectList[i].Item1; context.ReportDiagnostic(Diagnostic.Create(BTAnalyzer.Rule, trivia.GetLocation(), ErrorCode.ExtraLine)); } else { break; } } // Check if there is only syntax node inside the block bool isOnlySyntaxNode = trimmedBlockObjectList.All(tuple => SyntaxKind.None == tuple.Item2); // Statement should have comments before for (int i = 0; i < trimmedBlockObjectList.Count(); i++) { // Skip nodes while ((i < trimmedBlockObjectList.Count()) && (SyntaxKind.None != trimmedBlockObjectList[i].Item2)) { i++; } // Check for missing comment if (i < trimmedBlockObjectList.Count()) { if ((((0 < i - 1) && (SyntaxKind.SingleLineCommentTrivia != trimmedBlockObjectList[i - 1].Item2)) || i == 0) && !isOnlySyntaxNode) { SyntaxNode node = (SyntaxNode)trimmedBlockObjectList[i].Item1; context.ReportDiagnostic(Diagnostic.Create(BTAnalyzer.Rule, Location.Create(node.SyntaxTree, new TextSpan(node.SpanStart, 10)), ErrorCode.MissingComment)); } } while ((i < trimmedBlockObjectList.Count()) && (SyntaxKind.None == trimmedBlockObjectList[i].Item2)) { i++; } // Check for missing empty line if ((i < trimmedBlockObjectList.Count()) && (SyntaxKind.EndOfLineTrivia != trimmedBlockObjectList[i].Item2)) { context.ReportDiagnostic(Diagnostic.Create(BTAnalyzer.Rule, ((SyntaxTrivia)trimmedBlockObjectList[i].Item1).GetLocation(), ErrorCode.MissingEmptyLine)); } } // Cannot end with empty lines IEnumerable <SyntaxTrivia> triviaBeforeClosingBrackets = block.CloseBraceToken.LeadingTrivia; if (1 < triviaBeforeClosingBrackets.Count()) { context.ReportDiagnostic(Diagnostic.Create(BTAnalyzer.Rule, block.CloseBraceToken.GetLocation(), ErrorCode.UnexpectedComponentsBeforeClosingBracket)); } } }