/// <summary> /// Gets the descendants of the specified element that match the specified type and predicate. /// </summary> private static List <TElement> GetDescendants <TElement>(SyntaxElement element, Func <TElement, bool> predicate, List <TElement> list) where TElement : SyntaxElement { for (int i = 0; i < element.ChildCount; i++) { var child = element.GetChild(i); if (child != null) { if (child is TElement ce && (predicate == null || predicate(ce))) { if (list == null) { list = new List <TElement>(); } list.Add(ce); } if (child is SyntaxNode cn) { list = GetDescendants(child, predicate, list); } } } return(list); }
/// <summary> /// Gets the descendants of the specified element that match the specified type and predicate. /// </summary> private static IReadOnlyList <TElement> GetDescendants <TElement>( SyntaxElement element, Func <TElement, bool> predicate, bool includeSelf) where TElement : SyntaxElement { List <TElement> list = null; if (includeSelf && element is TElement telem && (predicate == null || predicate(telem))) { list = list ?? new List <TElement>(); list.Add(telem); } var root = element; var childIndex = 0; while (element != null) { if (childIndex < element.ChildCount && childIndex >= 0) { // walk down var child = element.GetChild(childIndex); if (child != null) { element = child; childIndex = 0; if (element is TElement telem2 && (predicate == null || predicate(telem2))) { list = list ?? new List <TElement>(); list.Add(telem2); } } else { childIndex++; } } else if (element == root) { break; } else { // walk up childIndex = element.IndexInParent + 1; element = element.Parent; } } return(list != null?list.ToReadOnly() : EmptyReadOnlyList <TElement> .Instance); }
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); } } }
private static TElement GetFirstDescendant <TElement>(SyntaxElement element, Func <TElement, bool> predicate, bool includeSelf) where TElement : SyntaxElement { if (includeSelf && element is TElement telem && (predicate == null || predicate(telem))) { return(telem); } var root = element; var childIndex = 0; while (element != null) { if (childIndex < element.ChildCount && childIndex >= 0) { // walk down var child = element.GetChild(childIndex); if (child != null) { element = child; childIndex = 0; if (element is TElement telem2 && (predicate == null || predicate(telem2))) { return(telem2); } } else { childIndex++; } } else if (element == root) { break; } else { // walk up childIndex = element.IndexInParent + 1; element = element.Parent; } } return(null); }