Syntax trivia
As mentioned in the note about syntax trees, syntax trivia includes elements such as comments, preprocessor directives, and various formatting elements (spaces, newlines). Syntax trivia elements will not get into the IL code. However, they are represented in the syntax tree. The SyntaxTree object has the full fidelity property. This means we can get code that is completely identical to the source code from the existing tree. Besides, we get all the elements in all instances of the SyntaxTrivia structure.
The elements of syntax trivia always refer to some token. There are Leading trivia and Trailing trivia. Leading trivia – additional syntax information preceding the token. Trailing trivia – additional syntax information following the token. All the elements of additional syntactic information have the type SyntaxTrivia. To define what exactly the element is (a space, single-line, multiline comment or something else) we use the SyntaxKind enumeration and the Kind and IsKind methods.
#if NETCOREAPP3_1 b = 10; #endif //Comment1 a = b;
Example of comment analysis using syntax trivia
public static StringBuilder Warnings = new StringBuilder(); public const int MaxCommentLength = 130;
public static void ApplyRule(SyntaxTrivia commentTrivia) { switch (commentTrivia.Kind()) { case SyntaxKind.SingleLineCommentTrivia: { if (commentTrivia.ToString().Length > MaxCommentLength) { int line = commentTrivia.GetLocation().GetLineSpan() .StartLinePosition.Line + 1; string filePath = commentTrivia.SyntaxTree.FilePath; Warnings.AppendLine($"Length of a comment at line " + $"{line} in file {filePath} " + $"exceeds {MaxCommentLength} " + $"characters, please, " + $"break up it on several lines"); } break; } case SyntaxKind.MultiLineCommentTrivia: case SyntaxKind.SingleLineDocumentationCommentTrivia: { var listStr = commentTrivia.ToString() .Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries ); foreach (string str in listStr) { if (str.Length > MaxCommentLength) { int line = commentTrivia.GetLocation().GetLineSpan() .StartLinePosition.Line + 1; string filePath = commentTrivia.SyntaxTree.FilePath; Warnings.AppendLine($"Multiline comment or XML comment at line " + $"{line} in file {filePath} " + $"contains individual lines that " + $"exceeds {MaxCommentLength} " + $"characters. Please, break up " + $"them on several lines."); return; } } break; } } }
public static Project GetProjectFromSolution(String solutionPath) { MSBuildLocator.RegisterDefaults(); MSBuildWorkspace workspace = MSBuildWorkspace.Create(); Solution currSolution = workspace.OpenSolutionAsync(solutionPath) .Result; return currSolution.Projects.Single(); }
static void Main(string[] args) { string solutionPath = @"D:\Test\TestForTrivia.sln"; string logPath = @"D:\Test\warnings.txt"; Project project = GetProjectFromSolution(solutionPath); foreach (var document in project.Documents) { var tree = document.GetSyntaxTreeAsync().Result; var comTriv = tree.GetRoot() .DescendantTrivia() .Where(n => n.IsKind(SyntaxKind.SingleLineCommentTrivia) || n.IsKind(SyntaxKind .SingleLineDocumentationCommentTrivia) || n.IsKind(SyntaxKind.MultiLineCommentTrivia)); foreach (var commentTrivia in comTriv) ApplyRule(commentTrivia); } if (Warnings.Length != 0) File.AppendAllText(logPath, Warnings.ToString()); }
methodDeclaration.DescendantTrivia()
.Any(trivia => trivia.IsKind(SyntaxKind.IfDirectiveTrivia))
Summary
Author Credit
Article Type : | Guest Article |
Author : | Ilya Gainulin |
Tags : | CSharp, Knowledge |
Article Date : | 26-03-2021 |
Article Publish Date : | 20-04-2021 |
Note : All content of this article are copyright of their author. |