private static void AddNode(ItemCollection items, SyntaxNode node, string prefix) { var tooltip = string.Join(Environment.NewLine, node.GetDiagnostics().Select(x => x.ToString())); var treeViewItem = new TreeViewItem { Background = (node.ContainsDiagnostics) ? Brushes.Pink : Brushes.Transparent, Foreground = (node.IsToken) ? Brushes.DarkGreen : (node.Ancestors().Any(a => a.IsToken) ? Brushes.DarkRed : Brushes.Blue), Header = $"{prefix}{node.Kind} [{node.SourceRange.Start}..{node.SourceRange.End})", ToolTip = string.IsNullOrEmpty(tooltip) ? null : tooltip, Tag = node }; foreach (var childNode in node.ChildNodes) { AddNode(treeViewItem.Items, childNode, string.Empty); } if (node.IsToken) { var token = (SyntaxToken)node; foreach (var childNode in token.LeadingTrivia) { AddNode(treeViewItem.Items, childNode, "Lead: "); } foreach (var childNode in token.TrailingTrivia) { AddNode(treeViewItem.Items, childNode, "Trail: "); } } items.Add(treeViewItem); }
private Result getResult(out IEnumerable <MemberDeclarationSyntax> members) { members = members_; if (all_ == 0) { bool codeFound = node_.GetDiagnostics(). Where(error => { return(error.Id == "CS1022"); }).Any(); if (codeFound) { return(Result.Code); } return(Result.Empty); } if (members_.Count == 0) { return(Result.Empty); } if (all_ == members_.Count) { return(Result.Class); } return(Result.Error); }
private void Recurse( SyntaxTreeAnalysisContext context, ReportDiagnostic severity, SyntaxNode node, CancellationToken cancellationToken ) { if ( node.ContainsDiagnostics && node.GetDiagnostics().Any(d => d.Severity == DiagnosticSeverity.Error) ) { return; } if (IsBlockLikeStatement(node)) { ProcessBlockLikeStatement(context, severity, node); } foreach (var child in node.ChildNodesAndTokens()) { if (child.IsNode) { Recurse(context, severity, child.AsNode() !, cancellationToken); } } }
private void VerifyErrorCode(SyntaxNode node, params DiagnosticId[] expected) { var actual = node.GetDiagnostics().Select(e => e.DiagnosticId).ToList(); // no error if ((expected.Length == 0) && (actual.Count == 0)) { return; } // Parser might give more errors than expected & that's fine Assert.That(actual.Count, Is.GreaterThanOrEqualTo(expected.Length)); Assert.That(actual.Count, Is.LessThanOrEqualTo(int.MaxValue)); // necessary? if (actual.Count < expected.Length) { return; } foreach (var i in expected) { Assert.Contains(i, actual); // no order } }
public static bool HasErrors(this SyntaxNode node) { if (!node.ContainsDiagnostics) //fast path { return(false); } return(node.GetDiagnostics().Any(d => d.Severity == DiagnosticSeverity.Error)); }
/// <summary> /// check whether node contains error for itself but not from its child node /// </summary> public static bool HasDiagnostics(this SyntaxNode node) { var set = new HashSet <Diagnostic>(node.GetDiagnostics()); foreach (var child in node.ChildNodes()) { set.ExceptWith(child.GetDiagnostics()); } return(set.Count > 0); }
public ParseTree Parse(SourceCodeFile sourceCodeFile) { CSharpRoslynParseTree result = null; var filePath = Path.Combine(sourceCodeFile.RelativePath, sourceCodeFile.Name); if (sourceCodeFile.Code != null) { SyntaxNode root = null; try { SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(sourceCodeFile.Code, null, filePath); result = new CSharpRoslynParseTree(syntaxTree); root = syntaxTree.GetRoot(); result.Comments = root.DescendantTrivia().Where(node => { SyntaxKind kind = node.Kind(); return(kind == SyntaxKind.SingleLineCommentTrivia || kind == SyntaxKind.MultiLineCommentTrivia || kind == SyntaxKind.SingleLineDocumentationCommentTrivia || kind == SyntaxKind.MultiLineDocumentationCommentTrivia || kind == SyntaxKind.DocumentationCommentExteriorTrivia || kind == SyntaxKind.XmlComment); }).ToArray(); IEnumerable <Diagnostic> diagnostics = root.GetDiagnostics(); foreach (var diagnostic in diagnostics) { if (diagnostic.Severity == DiagnosticSeverity.Error && diagnostic.Id != "CS1029") { var textSpan = RoslynHelper.ConvertTextSpan(diagnostic.Location); Logger.LogError(new ParsingException(filePath, message: diagnostic.ToString()) { TextSpan = textSpan }); } } } catch (Exception ex) { Logger.LogError(new ParsingException(filePath, ex)); result = new CSharpRoslynParseTree(); } } else { result = new CSharpRoslynParseTree(); } result.FileName = filePath; result.FileData = sourceCodeFile.Code; return(result); }
public override void Visit(SyntaxNode node) { if (node?.ContainsDiagnostics == true) { var diagnostics = node.GetDiagnostics(); _diagnostics.AddRange(diagnostics); base.Visit(node); } }
public static void Deconstruct( this string text, out SyntaxTree tree, out string formatter, out IEnumerable <Diagnostic> errors) { tree = CSharpSyntaxTree.ParseText(text.Trim(), _options); SyntaxNode root = Formatter.Format(tree.GetCompilationUnitRoot(), _workSpace); tree = root.SyntaxTree; formatter = root.ToString(); errors = root.GetDiagnostics(); }
public ParseTree Parse(TextFile sourceFile, out TimeSpan parserTimeSpan) { if (sourceFile.Data == null) { return(null); } try { var stopwatch = Stopwatch.StartNew(); var filePath = Path.Combine(sourceFile.RelativePath, sourceFile.Name); SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(sourceFile.Data, null, filePath); var result = new CSharpRoslynParseTree(syntaxTree); SyntaxNode root = syntaxTree.GetRoot(); result.Comments = root.DescendantTrivia().Where(node => { SyntaxKind kind = node.Kind(); return(kind == SyntaxKind.SingleLineCommentTrivia || kind == SyntaxKind.MultiLineCommentTrivia || kind == SyntaxKind.SingleLineDocumentationCommentTrivia || kind == SyntaxKind.MultiLineDocumentationCommentTrivia || kind == SyntaxKind.DocumentationCommentExteriorTrivia || kind == SyntaxKind.XmlComment); }).ToArray(); IEnumerable <Diagnostic> diagnostics = root.GetDiagnostics(); foreach (Diagnostic diagnostic in diagnostics) { if (diagnostic.Severity == DiagnosticSeverity.Error && diagnostic.Id != "CS1029") { var textSpan = diagnostic.Location.ToTextSpan(); Logger.LogError(new ParsingException(sourceFile, message: diagnostic.ToString()) { TextSpan = textSpan }); } } stopwatch.Stop(); parserTimeSpan = stopwatch.Elapsed; result.SourceFile = sourceFile; return(result); } catch (Exception ex) when(!(ex is ThreadAbortException)) { Logger.LogError(new ParsingException(sourceFile, ex)); return(null); } }
protected override EvaluationResult EvaluateImpl(SyntaxNode node) { // Roslyn does not handle async await keywords. var diagnostics = node.GetDiagnostics(); if (diagnostics.Any(d => d.Severity != DiagnosticSeverity.Info)) { return(new EvaluationResult { Snippet = node.ToFullString() }); } return(null); }
/// <summary> /// Reads in a <see cref="SyntaxNode"/> and returns a <see cref="XmlSyntaxData"/> /// </summary> /// <param name="node">Parsed Xml Node</param> /// <param name="withChildren">Include children in this new node.</param> /// <returns>UI ready data.</returns> public static XmlSyntaxData FromNode(SyntaxNode node, bool withChildren = true) { return(new XmlSyntaxData() { HashId = node.GetHashCode(), Type = node.IsList ? "SyntaxList" : node.GetType().Name, TypeClass = node.IsList ? "list" : (node.IsToken ? "token" : "syntax"), Text = node.IsToken ? (node as SyntaxToken).Text : string.Empty, Errors = node.ContainsDiagnostics ? node.GetDiagnostics().Select(d => new XmlSyntaxError() { Id = d.ErrorID, Description = d.GetDescription() }).ToList() : Array.Empty <XmlSyntaxError>().ToList(), SpanStart = node.FullSpan.Start, SpanEnd = node.FullSpan.End, Children = withChildren ? node.ChildNodes.Select(child => XmlSyntaxData.FromNode(child)).ToList() : Array.Empty <XmlSyntaxData>().ToList() }); }
private void VerifyErrorCode(SyntaxNode node, params DiagnosticId[] expected) { var actual = node.GetDiagnostics().Select(e => e.DiagnosticId).ToList(); // no error if ((expected.Length == 0) && (actual.Count == 0)) { return; } // Parser might give more errors than expected & that's fine Assert.That(actual.Count, Is.GreaterThanOrEqualTo(expected.Length)); Assert.That(actual.Count, Is.LessThanOrEqualTo(int.MaxValue)); // necessary? if (actual.Count < expected.Length) return; foreach (var i in expected) Assert.Contains(i, actual); // no order }
public static SyntaxNode GenerateViewModel(SyntaxNode node) { // Find the first class in the syntax node var classNode = node.DescendantNodes().OfType <ClassDeclarationSyntax>().FirstOrDefault(); if (classNode != null) { var codeIssues = node.GetDiagnostics(); if (!codeIssues.Any()) { // Get the name of the model class var modelClassName = classNode.Identifier.Text; // The name of the ViewModel class var viewModelClassName = $"{modelClassName}ViewModel"; // Only for demo purposes, pluralizing an object is done by // simply adding the "s" letter. Consider proper algorithms string newImplementation = $@"public class {viewModelClassName} : INotifyPropertyChanged {{ public event PropertyChangedEventHandler PropertyChanged; // Raise a property change notification protected virtual void OnPropertyChanged(string propname) {{ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propname)); }} private ObservableCollection<{modelClassName}> _{modelClassName}s; public ObservableCollection<{modelClassName}> {modelClassName}s {{ get {{ return _{modelClassName}s; }} set {{ _{modelClassName}s = value; OnPropertyChanged(nameof({modelClassName}s)); }} }} public {viewModelClassName}() {{ // Implement your logic to load a collection of items }} }} "; var newClassNode = SyntaxFactory.ParseSyntaxTree(newImplementation).GetRoot() .DescendantNodes().OfType <ClassDeclarationSyntax>() .FirstOrDefault(); // Retrieve the parent namespace declaration if (!(classNode.Parent is NamespaceDeclarationSyntax)) { return(null); } var parentNamespace = (NamespaceDeclarationSyntax)classNode.Parent; // Add the new class to the namespace var newParentNamespace = parentNamespace.AddMembers(newClassNode).NormalizeWhitespace(); return(newParentNamespace); } else { foreach (Diagnostic codeIssue in codeIssues) { string issue = $"ID: {codeIssue.Id}, Message: {codeIssue.GetMessage()}, " + $"Location: {codeIssue.Location.GetLineSpan()}," + $"Severity: {codeIssue.Severity}"; Console.WriteLine(issue); } return(null); } } else { return(null); } }
private static void AddNode(ItemCollection items, SyntaxNode node, string prefix) { var tooltip = string.Join(Environment.NewLine, node.GetDiagnostics().Select(x => x.ToString())); var treeViewItem = new TreeViewItem { Background = (node.ContainsDiagnostics) ? Brushes.Pink : Brushes.Transparent, Foreground = (node.IsToken) ? Brushes.DarkGreen : (node.Ancestors().Any(a => a.IsToken) ? Brushes.DarkRed : Brushes.Blue), Header = $"{prefix}{node.Kind} [{node.SourceRange.Start}..{node.SourceRange.End})", ToolTip = string.IsNullOrEmpty(tooltip) ? null : tooltip, Tag = node }; foreach (var childNode in node.ChildNodes) AddNode(treeViewItem.Items, childNode, string.Empty); if (node.IsToken) { var token = (SyntaxToken) node; foreach (var childNode in token.LeadingTrivia) AddNode(treeViewItem.Items, childNode, "Lead: "); foreach (var childNode in token.TrailingTrivia) AddNode(treeViewItem.Items, childNode, "Trail: "); } items.Add(treeViewItem); }
private static async Task <(ImmutableArray <Diagnostic> reportedDiagnostics, ImmutableArray <string> unhandledIds)> GetReportedDiagnosticsForIdsAsync( ImmutableHashSet <string> idsToAnalyze, SyntaxNode root, SemanticModel semanticModel, CompilationWithAnalyzers compilationWithAnalyzers, Func <DiagnosticAnalyzer, ImmutableArray <DiagnosticDescriptor> > getSupportedDiagnostics, Func <DiagnosticAnalyzer, bool> getIsCompilationEndAnalyzer, PooledHashSet <string> compilerDiagnosticIds, CancellationToken cancellationToken) { using var _1 = ArrayBuilder <DiagnosticAnalyzer> .GetInstance(out var analyzersBuilder); using var _2 = ArrayBuilder <string> .GetInstance(out var unhandledIds); // First, we compute the relevant analyzers whose reported diagnostics need to be computed. var addedCompilerAnalyzer = false; var hasNonCompilerAnalyzers = idsToAnalyze.Count > compilerDiagnosticIds.Count; foreach (var analyzer in compilationWithAnalyzers.Analyzers) { if (!addedCompilerAnalyzer && analyzer.IsCompilerAnalyzer()) { addedCompilerAnalyzer = true; analyzersBuilder.Add(analyzer); if (!hasNonCompilerAnalyzers) { break; } continue; } if (hasNonCompilerAnalyzers) { Debug.Assert(!analyzer.IsCompilerAnalyzer()); bool?lazyIsUnhandledAnalyzer = null; foreach (var descriptor in getSupportedDiagnostics(analyzer)) { if (!idsToAnalyze.Contains(descriptor.Id)) { continue; } lazyIsUnhandledAnalyzer ??= getIsCompilationEndAnalyzer(analyzer) || analyzer is IPragmaSuppressionsAnalyzer; if (lazyIsUnhandledAnalyzer.Value) { unhandledIds.Add(descriptor.Id); } } if (lazyIsUnhandledAnalyzer.HasValue && !lazyIsUnhandledAnalyzer.Value) { analyzersBuilder.Add(analyzer); } } } // Then, we execute these analyzers on the current file to fetch these diagnostics. // Note that if an analyzer has already executed, then this will be just a cache access // as computed analyzer diagnostics are cached on CompilationWithAnalyzers instance. using var _3 = ArrayBuilder <Diagnostic> .GetInstance(out var reportedDiagnostics); if (!addedCompilerAnalyzer && compilerDiagnosticIds.Count > 0) { // Special case when compiler analyzer could not be found. Debug.Assert(semanticModel.Compilation.Options.ReportSuppressedDiagnostics); reportedDiagnostics.AddRange(root.GetDiagnostics()); reportedDiagnostics.AddRange(semanticModel.GetDiagnostics(cancellationToken: cancellationToken)); cancellationToken.ThrowIfCancellationRequested(); } if (analyzersBuilder.Count > 0) { var analyzers = analyzersBuilder.ToImmutable(); var syntaxDiagnostics = await compilationWithAnalyzers.GetAnalyzerSyntaxDiagnosticsAsync(semanticModel.SyntaxTree, analyzers, cancellationToken).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); reportedDiagnostics.AddRange(syntaxDiagnostics); var semanticDiagnostics = await compilationWithAnalyzers.GetAnalyzerSemanticDiagnosticsAsync(semanticModel, filterSpan : null, analyzers, cancellationToken).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); reportedDiagnostics.AddRange(semanticDiagnostics); } return(reportedDiagnostics.ToImmutable(), unhandledIds.ToImmutable()); }