/// <summary> /// Gets diagnostics for this <see cref="SyntaxNode"/> an all child elements. /// </summary> public IReadOnlyList <Diagnostic> GetContainedDiagnostics(DiagnosticsInclude include = DiagnosticsInclude.Syntactic | DiagnosticsInclude.Semantic, CancellationToken cancellationToken = default(CancellationToken)) { var list = new List <Diagnostic>(); GatherDiagnostics(this, list, include, cancellationToken: cancellationToken); return(list.AsReadOnly()); }
protected static void GatherDiagnostics( SyntaxElement root, List <Diagnostic> diagnostics, DiagnosticsInclude include, CancellationToken cancellationToken = default(CancellationToken)) { cancellationToken.ThrowIfCancellationRequested(); bool includeSyntax = (include & DiagnosticsInclude.Syntactic) != 0; bool includeSemantic = (include & DiagnosticsInclude.Semantic) != 0; bool includeExpansion = (include & DiagnosticsInclude.Expansion) != 0; var fnDescend = (include == DiagnosticsInclude.Syntactic) ? (Func <SyntaxElement, bool>)((SyntaxElement e) => e.ContainsSyntaxDiagnostics) : null; SyntaxElement.WalkElements(root, fnBefore: element => { if (element.HasSyntaxDiagnostics && includeSyntax) { // each syntax diagnostic is located at the element that carries it. diagnostics.AddRange(element.SyntaxDiagnostics.Select(d => d.HasLocation ? d : SetLocation(d, element))); } if (includeSemantic && element is SyntaxNode node && node.SemanticDiagnostics.Count > 0) { diagnostics.AddRange(node.SemanticDiagnostics); } },
protected static void GatherDiagnostics( SyntaxElement element, List <Diagnostic> diagnostics, DiagnosticsInclude include, CancellationToken cancellationToken = default(CancellationToken)) { cancellationToken.ThrowIfCancellationRequested(); bool includeSyntax = (include & DiagnosticsInclude.Syntactic) != 0; bool includeSemantic = (include & DiagnosticsInclude.Semantic) != 0; bool includeExpansion = (include & DiagnosticsInclude.Expansion) != 0; if (element.HasSyntaxDiagnostics && includeSyntax) { // each syntax diagnostic is located at the element that carries it. diagnostics.AddRange(element.SyntaxDiagnostics.Select(d => d.HasLocation ? d : SetLocation(d, element))); } if (includeSemantic && element is SyntaxNode node && node.SemanticDiagnostics.Count > 0) { diagnostics.AddRange(node.SemanticDiagnostics); } if (includeSemantic || (includeSyntax && element.ContainsSyntaxDiagnostics)) { for (int i = 0, n = element.ChildCount; i < n; i++) { var child = element.GetChild(i); if (child != null) { GatherDiagnostics(child, diagnostics, include, cancellationToken); } } } if (includeExpansion && element is Expression expr && expr.GetExpansion() is SyntaxNode expansion) { var originalCount = diagnostics.Count; GatherDiagnostics(expansion, diagnostics, include, cancellationToken); if (diagnostics.Count > originalCount) { var name = expr.ReferencedSymbol?.Name ?? "<unknown>"; var location = expr is FunctionCallExpression fc ? fc.Name : expr; var errors = diagnostics[originalCount].Message; var dx = DiagnosticFacts.GetErrorInExpansion(name, errors).WithLocation(location); diagnostics.SetCount(originalCount); diagnostics.Add(dx); } } }