public void AddCommentTrivia(SyntaxTrivia trivia, LocationStore commentLocationstore, ClassStore classStore, string fileName) { if (trivia.Kind() == SyntaxKind.SingleLineCommentTrivia) { Comment comment = new SingleLineComment(trivia.ToString(), trivia.GetLocation().GetLineSpan().EndLinePosition.Line + 1) { FileName = fileName, }; comment.Initialize(commentLocationstore, classStore); Comments.Add(comment); } else if (trivia.Kind() == SyntaxKind.MultiLineCommentTrivia) { Comment comment = new MultiLineComment(trivia.ToString(), trivia.GetLocation().GetLineSpan().StartLinePosition.Line + 1, trivia.GetLocation().GetLineSpan().EndLinePosition.Line + 1) { FileName = fileName, }; comment.Initialize(commentLocationstore, classStore); Comments.Add(comment); } }
private void HandleWhitespaceTrivia(SyntaxTreeAnalysisContext context, SyntaxTrivia trivia) { if (trivia.Span.Length <= 1) { return; } if (trivia.GetLocation()?.GetMappedLineSpan().StartLinePosition.Character == 0) { return; } // Code must not contain multiple whitespace characters in a row. context.ReportDiagnostic(Diagnostic.Create(Descriptor, trivia.GetLocation())); }
private static void ReportDiagnostic(SyntaxNodeAnalysisContext context, SyntaxToken token, SyntaxTrivia tokenLeadingTrivia, string indentation, string expectedIndentation) { Location location = (indentation.Length == 0) ? token.GetLocation() : tokenLeadingTrivia.GetLocation(); ImmutableDictionary <string, string> properties = ImmutableDictionary.Create <string, string>().SetItem(ExpectedIndentationKey, expectedIndentation); context.ReportDiagnostic(Diagnostic.Create(Descriptor, location, properties)); }
private void HandleSingleLineCommentTrivia(SyntaxTreeAnalysisContext context, SyntaxTrivia trivia) { string text = trivia.ToFullString(); if (text.Equals("//")) { return; } // special case: commented code if (text.StartsWith("////")) { return; } int spaceCount = 0; for (int i = 2; (i < text.Length) && (text[i] == ' '); i++) { spaceCount++; } if (spaceCount == 1) { return; } // Single line comment must begin with a space. context.ReportDiagnostic(Diagnostic.Create(Descriptor, trivia.GetLocation())); }
public override SyntaxTrivia VisitTrivia(SyntaxTrivia trivia) { if (!trivia.IsKind(SyntaxKind.SingleLineCommentTrivia) && !trivia.IsKind(SyntaxKind.MultiLineCommentTrivia)) { return(trivia); } var lineSpan = trivia.GetLocation().GetLineSpan(); while (lineCount < lineSpan.StartLinePosition.Line) { allComments.AppendLine(); lineCount++; } string comment = trivia.ToString(); if (trivia.IsKind(SyntaxKind.SingleLineCommentTrivia)) { comment = comment.Substring(2); } else if (trivia.IsKind(SyntaxKind.MultiLineCommentTrivia)) { comment = comment.Substring(2, comment.Length - 4); } allComments.Append(comment); lineCount = lineSpan.EndLinePosition.Line; return(trivia); }
static int GetLine(SyntaxTrivia trivia) { return(trivia.GetLocation() .GetLineSpan() .StartLinePosition .Line); }
public EvaluationResult Evaluate(SyntaxTrivia node) { var result = EvaluateImpl(node); if (result != null) { var sourceTree = node.GetLocation().SourceTree; var filePath = sourceTree.FilePath; var typeDefinition = GetNodeType(node.Token.Parent); var unitNamespace = GetNamespace(node.Token.Parent); if (result.ErrorCount == 0) { result.ErrorCount = 1; } result.LinesOfCodeAffected = 0; result.Namespace = unitNamespace; result.TypeKind = typeDefinition.Item1; result.TypeName = typeDefinition.Item2; result.Title = Title; result.Suggestion = Suggestion; result.Quality = Quality; result.QualityAttribute = QualityAttribute; result.ImpactLevel = ImpactLevel; result.FilePath = filePath; } return(result); }
private static void HandleSingleLineComment(SyntaxTreeAnalysisContext context, SyntaxTrivia singleLineComment) { int index = 0; // PERF: Explicitly cast to IReadOnlyList so we only box once. IReadOnlyList <SyntaxTrivia> list = TriviaHelper.GetContainingTriviaList(singleLineComment, out index); var firstNonWhiteSpace = TriviaHelper.IndexOfFirstNonWhitespaceTrivia(list); // When we encounter a block of single line comments, we only want to raise this diagnostic // on the first or last line. This ensures that whitespace in code commented out using // the Comment Selection option in Visual Studio will not raise the diagnostic for every // blank line in the code which is commented out. bool isFirst = index == firstNonWhiteSpace; if (!isFirst) { // This is -2 because we need to go back past the end of line trivia as well. var lastNonWhiteSpace = TriviaHelper.IndexOfTrailingWhitespace(list) - 2; if (index != lastNonWhiteSpace) { return; } } if (IsNullOrWhiteSpace(singleLineComment.ToString(), 2)) { var diagnostic = Diagnostic.Create(Descriptor, singleLineComment.GetLocation()); context.ReportDiagnostic(diagnostic); } }
internal static GetFullCommentedCodeResult GetFullCommentedCode(SyntaxNode root, SyntaxTrivia firstComment) { var result = new StringBuilder(); var current = firstComment; var numberOfComments = 1; var start = firstComment.GetLocation().SourceSpan.Start; int end; do { end = current.GetLocation().SourceSpan.End; result.Append(current.ToString().Substring(2)); var eol = root.FindTrivia(current.GetLocation().SourceSpan.End + 1); if (!eol.IsKind(SyntaxKind.EndOfLineTrivia)) { break; } var whitespace = root.FindTrivia(eol.GetLocation().SourceSpan.End + 1); if (!whitespace.IsKind(SyntaxKind.WhitespaceTrivia)) { break; } current = root.FindTrivia(whitespace.GetLocation().SourceSpan.End + 1); if (!current.IsKind(SyntaxKind.SingleLineCommentTrivia)) { break; } numberOfComments++; } while (true); return(new GetFullCommentedCodeResult(result.ToString(), numberOfComments, start, end)); }
SyntaxTrivia ReplaceTrivia(SyntaxTrivia triv) { if (!triv.IsKind(SyntaxKind.WhitespaceTrivia)) { return(triv); } //return triv; var loc = triv.GetLocation(); var ls = loc.GetLineSpan(); if (ls.StartLinePosition.Character != 0) { return(triv); } var triviaString = triv.ToFullString(); if (triviaString.Equals(_tabs) || triviaString.Equals(_spaces)) { return(triv.CopyAnnotationsTo(SyntaxFactory.Whitespace(""))); } if (triviaString.StartsWith(_tabs)) { return(triv.CopyAnnotationsTo(SyntaxFactory.Whitespace(triviaString.Substring(_tabs.Length)))); } if (triviaString.StartsWith(_spaces)) { return(triv.CopyAnnotationsTo(SyntaxFactory.Whitespace(triviaString.Substring(_spaces.Length)))); } return(triv); }
public override void VisitTrivia(SyntaxTrivia trivia) { base.VisitTrivia(trivia); if (trivia.IsKind(SyntaxKind.RegionDirectiveTrivia)) { regionStack.Push(trivia); } else if (trivia.IsKind(SyntaxKind.EndRegionDirectiveTrivia)) { if (regionStack.Count == 0) { return; } var regionStart = regionStack.Pop(); try { var first = regionStart.GetLocation().GetLineSpan(); var last = trivia.GetLocation().GetLineSpan(); var v = regionStart.ToString(); v = v.Substring("#region".Length).Trim(); if (v.Length == 0) { v = "..."; } Foldings.Add(new FoldingRegion(v, new DocumentRegion(first.StartLinePosition, last.EndLinePosition), FoldType.UserRegion, true)); } catch (ArgumentOutOfRangeException) { } } }
public EvaluationResult Evaluate(SyntaxTrivia node) { var result = EvaluateImpl(node); if (result != null) { var sourceTree = node.GetLocation().SourceTree; var filePath = sourceTree.FilePath; var typeDefinition = GetNodeType(node.Token.Parent); var unitNamespace = GetNamespace(node.Token.Parent); if (result.ErrorCount == 0) { result.ErrorCount = 1; } result.LinesOfCodeAffected = 0; result.Namespace = unitNamespace; result.TypeKind = typeDefinition.Item1; result.TypeName = typeDefinition.Item2; result.Title = Title; result.Suggestion = Suggestion; result.Quality = Quality; result.QualityAttribute = QualityAttribute; result.ImpactLevel = ImpactLevel; result.FilePath = filePath; } return result; }
public override SyntaxTrivia VisitTrivia(SyntaxTrivia trivia) { if (trivia.IsKind(SyntaxKind.NullableDirectiveTrivia)) { reporter.ReportDiagnostic( DiagnosticDescriptors.EMBED0008_NullableDirective(trivia.GetLocation())); } return(SyntaxFactory.ElasticMarker); }
public static void ReportDiagnostic( this SyntaxTreeAnalysisContext context, DiagnosticDescriptor descriptor, SyntaxTrivia trivia, params object[] messageArgs) { context.ReportDiagnostic( Diagnostic.Create(descriptor, trivia.GetLocation(), messageArgs)); }
private void HandleWhitespaceTrivia(SyntaxTreeAnalysisContext context, SyntaxTrivia trivia) { if (trivia.ToFullString().IndexOf('\t') < 0) { return; } // Tabs must not be used. context.ReportDiagnostic(Diagnostic.Create(Descriptor, trivia.GetLocation())); }
public static void ReportDiagnostic( SymbolAnalysisContext context, DiagnosticDescriptor descriptor, SyntaxTrivia trivia, params object[] messageArgs) { ReportDiagnostic( context: context, descriptor: descriptor, location: trivia.GetLocation(), messageArgs: messageArgs); }
private void HandleRegionDirectiveTrivia(SyntaxTreeAnalysisContext context, SyntaxTrivia trivia) { BlockSyntax blockSyntax = trivia.Token.Parent.AncestorsAndSelf().OfType <BlockSyntax>().FirstOrDefault(); if (blockSyntax == null) { return; } // Region must not be located within a code element. context.ReportDiagnostic(Diagnostic.Create(Descriptor, trivia.GetLocation())); }
private void HandleWhitespaceTrivia(SyntaxTreeAnalysisContext context, SyntaxTrivia trivia) { if (trivia.Span.Length <= 1) { return; } if (trivia.GetLocation()?.GetMappedLineSpan().StartLinePosition.Character == 0) { return; } SyntaxToken token = trivia.Token; SyntaxToken precedingToken; SyntaxToken followingToken; if (token.LeadingTrivia.Contains(trivia)) { precedingToken = token.GetPreviousToken(); followingToken = token; } else if (token.TrailingTrivia.Contains(trivia)) { precedingToken = token; followingToken = precedingToken.GetNextToken(); } else { // shouldn't be reachable, but either way can't proceed return; } if (precedingToken.IsKind(SyntaxKind.CommaToken) || precedingToken.IsKind(SyntaxKind.SemicolonToken)) { return; } // Code must not contain multiple whitespace characters in a row. context.ReportDiagnostic(Diagnostic.Create(Descriptor, trivia.GetLocation())); }
private void HandleSingleLineCommentTrivia(SyntaxTreeAnalysisContext context, SyntaxTrivia trivia, bool isFirstSingleLineTrivia) { string text = trivia.ToFullString(); if (text.Equals(@"//")) { return; } // special case: commented code if (text.StartsWith(@"////", StringComparison.Ordinal)) { return; } // Special case: multiple dashes at start of comment if (text.StartsWith(@"//--", StringComparison.Ordinal)) { return; } // Special case: //\ negates spacing requirements if (text.StartsWith(@"//\", StringComparison.Ordinal)) { return; } // No need to handle documentation comments ("///") because they're not // reported as SingleLineCommentTrivia. int spaceCount = 0; for (int i = 2; (i < text.Length) && (text[i] == ' '); i++) { spaceCount++; } if (spaceCount == 1) { return; } // Special case: follow-on comment lines may be indented with more than // one space. if (spaceCount > 1 && !isFirstSingleLineTrivia) { return; } // Single line comment must begin with a space. context.ReportDiagnostic(Diagnostic.Create(Descriptor, trivia.GetLocation())); }
private static void HandleMultiLineComment(SyntaxTreeAnalysisContext context, SyntaxTrivia multiLineComment) { var nodeText = multiLineComment.ToString(); // We remove the /* and the */ and determine if the comment has any content. var commentText = nodeText.Substring(2, nodeText.Length - 4); if (string.IsNullOrWhiteSpace(commentText)) { var diagnostic = Diagnostic.Create(Descriptor, multiLineComment.GetLocation()); context.ReportDiagnostic(diagnostic); } }
private static void CheckMultilineComment(SyntaxTreeAnalysisContext c, SyntaxTrivia comment) { var triviaContent = GetTriviaContent(comment); var triviaLines = triviaContent.Split(MetricsBase.LineTerminators, StringSplitOptions.None); for (var triviaLineNumber = 0; triviaLineNumber < triviaLines.Length; triviaLineNumber++) { if (!IsCode(triviaLines[triviaLineNumber])) { continue; } var triviaStartingLineNumber = comment.GetLocation().GetLineSpan().StartLinePosition.Line; var lineNumber = triviaStartingLineNumber + triviaLineNumber; var lineSpan = c.Tree.GetText().Lines[lineNumber].Span; var commentLineSpan = lineSpan.Intersection(comment.GetLocation().SourceSpan); var location = Location.Create(c.Tree, commentLineSpan ?? lineSpan); c.ReportDiagnostic(Diagnostic.Create(Rule, location)); return; } }
private void HandleWhitespaceTrivia(SyntaxTreeAnalysisContext context, SyntaxTrivia trivia) { if (trivia.Span.Length <= 1) { return; } if (trivia.SyntaxTree.GetMappedLineSpan(trivia.Span).StartLinePosition.Character == 0) { return; } SyntaxToken token = trivia.Token; SyntaxToken precedingToken; SyntaxToken followingToken; int index; SyntaxTriviaList list; if ((index = token.LeadingTrivia.IndexOf(trivia)) >= 0) { precedingToken = token.GetPreviousToken(); followingToken = token; list = token.LeadingTrivia; } else if ((index = token.TrailingTrivia.IndexOf(trivia)) >= 0) { precedingToken = token; followingToken = precedingToken.GetNextToken(); list = token.TrailingTrivia; } else { // shouldn't be reachable, but either way can't proceed return; } var followingTrivia = index + 1 < list.Count ? list[index + 1] : default(SyntaxTrivia); if (precedingToken.IsKind(SyntaxKind.CommaToken) || precedingToken.IsKind(SyntaxKind.SemicolonToken) || followingTrivia.IsKind(SyntaxKind.EndOfLineTrivia) || followingToken.IsKind(SyntaxKind.EndOfFileToken)) { return; } // Code must not contain multiple whitespace characters in a row. context.ReportDiagnostic(Diagnostic.Create(Descriptor, trivia.GetLocation())); }
private void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext context) { if (GeneratedCodeAnalyzer?.IsGeneratedCode(context) == true) { return; } var declaration = (MemberDeclarationSyntax)context.Node; if (declaration.Parent?.IsKind(SyntaxKind.CompilationUnit) == false) { TokenPair tokenPair = GetTokenPair(declaration); if (!tokenPair.OpenToken.IsKind(SyntaxKind.None) && !tokenPair.OpenToken.IsMissing && !tokenPair.CloseToken.IsKind(SyntaxKind.None) && !tokenPair.CloseToken.IsMissing) { int closeTokenLine = tokenPair.CloseToken.GetSpanEndLine(); if (tokenPair.OpenToken.GetSpanEndLine() != closeTokenLine) { MemberDeclarationSyntax nextDeclaration = GetNextDeclaration(declaration); if (nextDeclaration != null) { int diff = nextDeclaration.GetSpanStartLine() - closeTokenLine; if (diff < 2) { SyntaxTrivia trivia = declaration.GetTrailingTrivia().LastOrDefault(); if (trivia.IsKind(SyntaxKind.EndOfLineTrivia)) { context.ReportDiagnostic( DiagnosticDescriptors.AddEmptyLineBetweenDeclarations, trivia.GetLocation()); } else { context.ReportDiagnostic( DiagnosticDescriptors.AddEmptyLineBetweenDeclarations, tokenPair.CloseToken.GetLocation()); } } } } } } }
private static void HandleWhitespaceTrivia(SyntaxTreeAnalysisContext context, SyntaxTrivia trivia) { // We can ignore structured trivia like directives (e.g., #region, #pragma) and XML comments. if (!trivia.HasStructure) { // We only need to look at leading trivia. It's ok to use spaces between keywords (e.g., private void Method()), // and those usually show up as trailing trivia. However, sometimes spaces between identifiers show up as leading // trivia (e.g., in <param name="X">). So we have to make sure the leading trivia is really at the beginning of a line. SyntaxToken token = trivia.Token; if (token.LeadingTrivia.IndexOf(trivia) >= 0 && trivia.ToFullString().IndexOf(' ') >= 0 && trivia.GetLineSpan().StartLinePosition.Character == 0) { context.ReportDiagnostic(Diagnostic.Create(Rule, trivia.GetLocation())); } } }
public static void Analyze(SyntaxNodeAnalysisContext context, MemberDeclarationSyntax declaration) { if (!declaration.IsParentKind(SyntaxKind.CompilationUnit)) { TokenPair tokenPair = GetTokenPair(declaration); SyntaxToken openToken = tokenPair.OpenToken; SyntaxToken closeToken = tokenPair.CloseToken; if (!openToken.IsKind(SyntaxKind.None) && !openToken.IsMissing && !closeToken.IsKind(SyntaxKind.None) && !closeToken.IsMissing) { int closeTokenLine = closeToken.GetSpanEndLine(); if (openToken.GetSpanEndLine() != closeTokenLine) { MemberDeclarationSyntax nextDeclaration = GetNextDeclaration(declaration); if (nextDeclaration != null) { int diff = nextDeclaration.GetSpanStartLine() - closeTokenLine; if (diff < 2) { SyntaxTrivia trivia = declaration.GetTrailingTrivia().LastOrDefault(); if (trivia.IsKind(SyntaxKind.EndOfLineTrivia)) { context.ReportDiagnostic( DiagnosticDescriptors.AddEmptyLineBetweenDeclarations, trivia.GetLocation()); } else { context.ReportDiagnostic( DiagnosticDescriptors.AddEmptyLineBetweenDeclarations, closeToken.GetLocation()); } } } } } } }
private void HandleSingleLineCommentTrivia(SyntaxTreeAnalysisContext context, SyntaxTrivia trivia) { string text = trivia.ToFullString(); if (text.Equals("//") || text.StartsWith("// ")) { return; } // special case: commented code if (text.StartsWith("////")) { return; } // Single line comment must begin with a space. context.ReportDiagnostic(Diagnostic.Create(Descriptor, trivia.GetLocation())); }
internal static MyToken Create(int index, SyntaxTrivia trivia) { var loc = trivia.GetLocation(); var lineInfo = loc.GetLineSpan(); var genericTokenType = GetGenericType(trivia.Kind(), false); var t = new MyToken { Index = index, LineNumber = lineInfo.StartLinePosition.Line, RawType = trivia.Kind().ToString(), GenericType = genericTokenType, Text = trivia.ToString(), StartPos = loc.SourceSpan.Start, EndPos = loc.SourceSpan.End, IsTrivia = true }; return(t); }
private static void HandleWhitespaceTrivia(SyntaxTreeAnalysisContext context, SyntaxTrivia trivia) { string fullString = trivia.ToFullString(); if (fullString.StartsWith("////")) { // This is a line of commented code. return; } if (fullString.IndexOf('\t') < 0) { // No hard tabs were found. return; } // Tabs must not be used. context.ReportDiagnostic(Diagnostic.Create(Descriptor, trivia.GetLocation())); }
private static void Analyze(SyntaxNodeAnalysisContext context) { CompilationUnitSyntax node = (CompilationUnitSyntax)context.Node; if (Helper.IsGeneratedCode(context) || Helper.IsAssemblyInfo(context) || Helper.HasAutoGeneratedComment(node)) { return; } if (node.FindToken(0).IsKind(SyntaxKind.EndOfFileToken)) { return; } var first = node.GetLeadingTrivia(); if (!first.Any()) { CreateDiagnostic(context, node.GetLocation()); return; } SyntaxTrivia copyrightSyntax = first[0]; if (first[0].IsKind(SyntaxKind.RegionDirectiveTrivia)) { if (first.Count < 2 || !first[1].IsKind(SyntaxKind.SingleLineCommentTrivia)) { CreateDiagnostic(context, context.Node.GetLocation()); return; } copyrightSyntax = first[1]; } bool isCorrectStatement = CheckCopyrightStatement(context, copyrightSyntax); if (!isCorrectStatement) { CreateDiagnostic(context, copyrightSyntax.GetLocation()); return; } }
public override void VisitTrivia(SyntaxTrivia trivia) { cancellationToken.ThrowIfCancellationRequested(); if (trivia.IsKind(SyntaxKind.SingleLineCommentTrivia) || trivia.IsKind(SyntaxKind.MultiLineCommentTrivia) || trivia.IsKind(SyntaxKind.SingleLineDocumentationCommentTrivia)) { var trimmedContent = trivia.ToString().TrimStart('/', ' ', '*'); foreach (string tag in tagComments) { if (!trimmedContent.StartsWith(tag, StringComparison.Ordinal)) { continue; } var loc = trivia.GetLocation().GetLineSpan(); Tags.Add(new Tag(tag, trimmedContent, new DocumentRegion(loc.StartLinePosition, loc.EndLinePosition))); break; } } }
void Mark(SyntaxTrivia trivia, string type, JObject props = null) { var location = trivia.GetLocation().GetLineSpan(); var startLine = location.StartLinePosition.Line; var endLine = location.EndLinePosition.Line; for (var i = startLine; i <= endLine; i++) { var start = i == startLine ? location.StartLinePosition.Character : 0; var end = i == endLine ? location.EndLinePosition.Character : int.MaxValue; _regions.Add(new Region { Line = i, Start = start, End = end, Style = type, Props = props }); } }
public override void VisitTrivia (SyntaxTrivia trivia) { base.VisitTrivia (trivia); if (trivia.IsKind (SyntaxKind.RegionDirectiveTrivia)) { regionStack.Push (trivia); } else if (trivia.IsKind (SyntaxKind.EndRegionDirectiveTrivia)) { if (regionStack.Count == 0) return; var regionStart = regionStack.Pop (); try { var first = regionStart.GetLocation ().GetLineSpan (); var last = trivia.GetLocation ().GetLineSpan (); var v = regionStart.ToString (); v = v.Substring ("#region".Length).Trim (); if (v.Length == 0) v = "..."; Foldings.Add (new FoldingRegion(v, new DocumentRegion(first.StartLinePosition, last.EndLinePosition), FoldType.UserRegion, true)); } catch (ArgumentOutOfRangeException) { } } }
public override void VisitTrivia (SyntaxTrivia trivia) { cancellationToken.ThrowIfCancellationRequested (); if (trivia.IsKind (SyntaxKind.SingleLineCommentTrivia) || trivia.IsKind (SyntaxKind.MultiLineCommentTrivia) || trivia.IsKind (SyntaxKind.SingleLineDocumentationCommentTrivia)) { var trimmedContent = trivia.ToString ().TrimStart ('/', ' ', '*'); foreach (string tag in tagComments) { if (!trimmedContent.StartsWith (tag, StringComparison.Ordinal)) continue; var loc = trivia.GetLocation ().GetLineSpan (); Tags.Add (new Tag (tag, trimmedContent, new DocumentRegion (loc.StartLinePosition, loc.EndLinePosition))); break; } } }
private void HandleWhitespaceTrivia(SyntaxTreeAnalysisContext context, SyntaxTrivia trivia) { if (trivia.Span.Length <= 1) { return; } if (trivia.SyntaxTree.GetMappedLineSpan(trivia.Span).StartLinePosition.Character == 0) { return; } SyntaxToken token = trivia.Token; SyntaxToken precedingToken; SyntaxToken followingToken; if (token.LeadingTrivia.Contains(trivia)) { precedingToken = token.GetPreviousToken(); followingToken = token; } else if (token.TrailingTrivia.Contains(trivia)) { precedingToken = token; followingToken = precedingToken.GetNextToken(); } else { // shouldn't be reachable, but either way can't proceed return; } if (precedingToken.IsKind(SyntaxKind.CommaToken) || precedingToken.IsKind(SyntaxKind.SemicolonToken)) { return; } // Code must not contain multiple whitespace characters in a row. context.ReportDiagnostic(Diagnostic.Create(Descriptor, trivia.GetLocation())); }
private static void HandleWhitespaceTrivia(SyntaxTreeAnalysisContext context, SyntaxTrivia trivia) { if (trivia.Span.Length <= 1) { return; } if (trivia.SyntaxTree.GetMappedLineSpan(trivia.Span).StartLinePosition.Character == 0) { return; } SyntaxToken token = trivia.Token; SyntaxToken precedingToken; SyntaxToken followingToken; int index; SyntaxTriviaList list; if ((index = token.LeadingTrivia.IndexOf(trivia)) >= 0) { precedingToken = token.GetPreviousToken(); followingToken = token; list = token.LeadingTrivia; } else if ((index = token.TrailingTrivia.IndexOf(trivia)) >= 0) { precedingToken = token; followingToken = precedingToken.GetNextToken(); list = token.TrailingTrivia; } else { // shouldn't be reachable, but either way can't proceed return; } var followingTrivia = index + 1 < list.Count ? list[index + 1] : default(SyntaxTrivia); if (precedingToken.IsKind(SyntaxKind.CommaToken) || precedingToken.IsKind(SyntaxKind.SemicolonToken) || followingTrivia.IsKind(SyntaxKind.EndOfLineTrivia) || followingToken.IsKind(SyntaxKind.EndOfFileToken)) { return; } // Code must not contain multiple whitespace characters in a row. context.ReportDiagnostic(Diagnostic.Create(Descriptor, trivia.GetLocation())); }
internal static GetFullCommentedCodeResult GetFullCommentedCode(SyntaxNode root, SyntaxTrivia firstComment) { var result = new StringBuilder(); var current = firstComment; var numberOfComments = 1; var start = firstComment.GetLocation().SourceSpan.Start; int end; do { end = current.GetLocation().SourceSpan.End; result.Append(current.ToString().Substring(2)); var eol = root.FindTrivia(current.GetLocation().SourceSpan.End + 1); if (!eol.IsKind(SyntaxKind.EndOfLineTrivia)) break; var whitespace = root.FindTrivia(eol.GetLocation().SourceSpan.End + 1); if (!whitespace.IsKind(SyntaxKind.WhitespaceTrivia)) break; current = root.FindTrivia(whitespace.GetLocation().SourceSpan.End + 1); if (!current.IsKind(SyntaxKind.SingleLineCommentTrivia)) break; numberOfComments ++; } while (true); return new GetFullCommentedCodeResult(result.ToString(), numberOfComments, start, end); }
private static void HandleSingleLineComment(SyntaxTreeAnalysisContext context, SyntaxTrivia singleLineComment) { int index = 0; // PERF: Explicitly cast to IReadOnlyList so we only box once. IReadOnlyList<SyntaxTrivia> list = TriviaHelper.GetContainingTriviaList(singleLineComment, out index); var firstNonWhiteSpace = TriviaHelper.IndexOfFirstNonWhitespaceTrivia(list); // When we encounter a block of single line comments, we only want to raise this diagnostic // on the first or last line. This ensures that whitespace in code commented out using // the Comment Selection option in Visual Studio will not raise the diagnostic for every // blank line in the code which is commented out. bool isFirst = index == firstNonWhiteSpace; if (!isFirst) { // This is -2 because we need to go back past the end of line trivia as well. var lastNonWhiteSpace = TriviaHelper.IndexOfTrailingWhitespace(list) - 2; if (index != lastNonWhiteSpace) { return; } } if (IsNullOrWhiteSpace(singleLineComment.ToString(), 2)) { var diagnostic = Diagnostic.Create(Descriptor, singleLineComment.GetLocation()); context.ReportDiagnostic(diagnostic); } }
private static void HandleSingleLineCommentTrivia(SyntaxTreeAnalysisContext context, SyntaxTrivia trivia, bool isFirstSingleLineTrivia) { string text = trivia.ToFullString(); if (text.Equals(@"//")) { return; } // special case: commented code or documentation if the parsers documentation mode is DocumentationMode.None if (text.StartsWith(@"///", StringComparison.Ordinal)) { return; } // Special case: multiple dashes at start of comment if (text.StartsWith(@"//--", StringComparison.Ordinal)) { return; } // Special case: //\ negates spacing requirements if (text.StartsWith(@"//\", StringComparison.Ordinal)) { return; } // No need to handle documentation comments ("///") because they're not // reported as SingleLineCommentTrivia. int spaceCount = 0; for (int i = 2; (i < text.Length) && (text[i] == ' '); i++) { spaceCount++; } if (spaceCount == 1) { return; } // Special case: follow-on comment lines may be indented with more than // one space. if (spaceCount > 1 && !isFirstSingleLineTrivia) { return; } // Single line comment must begin with a space. context.ReportDiagnostic(Diagnostic.Create(Descriptor, trivia.GetLocation())); }