protected SeparatedElement(SyntaxElement element, SyntaxToken separator = null) : base(null) { this.Element = Attach(element); this.Separator = Attach(separator, optional: true); this.Init(); }
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); } },
/// <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); }
internal void InitializeTriviaStarts() { SyntaxElement.WalkElements( this.Root, fnBefore: element => { System.Diagnostics.Debug.Assert(element.Parent == null || element.Parent._triviaStart >= 0); element._triviaStart = (element.Parent?._triviaStart ?? 0) + element.OffsetInParent; }); }
/// <summary> /// Gets the index of the child node, or -1 if the node is not a child. /// </summary> public int GetChildIndex(SyntaxElement child) { for (int i = 0, n = this.ChildCount; i < n; i++) { if (this.GetChild(i) == child) { return(i); } } return(-1); }
/// <summary> /// Walks this element and its descendants in lexical order, invoking the actions for each <see cref="SyntaxElement"/> including the root element. /// </summary> /// <param name="root">The root element of the walk. The walk includes this element and any descendant elements.</param> /// <param name="fnBefore">An optional function that is invoked for each element before any child elements are visited.</param> /// <param name="fnAfter">An optional function that is invoked for each element after any child elements have been visited.</param> /// <param name="fnDescend">An optional function that determines whether the children of an element are visited.</param> public static void WalkElements( SyntaxElement root, Action <SyntaxElement> fnBefore = null, Action <SyntaxElement> fnAfter = null, Func <SyntaxElement, bool> fnDescend = null) { if (root == null) { throw new ArgumentNullException(nameof(root)); } var node = root; var childIndex = 0; // the root before walking children fnBefore?.Invoke(root); while (node != null) { if (childIndex < node.ChildCount && childIndex >= 0 && (fnDescend == null || fnDescend(node))) { // walk down var child = node.GetChild(childIndex); if (child != null) { node = child; childIndex = 0; // before walking children fnBefore?.Invoke(node); } else { childIndex++; } } else { // after walking children fnAfter?.Invoke(node); // stop if we are done with root node if (node == root) { break; } // walk up childIndex = node.IndexInParent + 1; node = node.Parent; } } }
/// <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); }
/// <summary> /// Gets the first ancestor of this element that matches the specified type and predicate. /// </summary> public TElement GetFirstAncestor <TElement>(Func <TElement, bool> predicate = null) where TElement : SyntaxElement { for (SyntaxElement elem = this.Parent; elem != null; elem = elem.Parent) { if (elem is TElement e && (predicate == null || predicate(e))) { return(e); } } return(default(TElement)); }
/// <summary> /// Returns true if this element is the ancestor of the specified element. /// </summary> public bool IsAncestorOf(SyntaxElement element) { while (element != null) { if (element.Parent == this) { return(true); } element = element.Parent; } return(false); }
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); }
/// <summary> /// Walks the entire syntax tree and evaluates the maximum depth of all the nodes. /// </summary> private static int ComputeMaxDepth(SyntaxNode root) { var maxDepth = 0; var depth = 0; SyntaxElement.WalkNodes( root, fnBefore: e => { depth++; if (depth > maxDepth) { maxDepth = depth; } }, fnAfter: e => depth--); return(maxDepth); }
/// <summary> /// Gets the all ancestors of this element (including itself) that match the specified type and predicate. /// </summary> public IReadOnlyList <TElement> GetAncestors <TElement>(Func <TElement, bool> predicate = null) where TElement : SyntaxElement { List <TElement> list = null; for (SyntaxElement elem = this.Parent; elem != null; elem = elem.Parent) { if (elem is TElement e && (predicate == null || predicate(e))) { if (list == null) { list = new List <TElement>(); } list.Add(e); } } return(list != null?list.ToReadOnly() : EmptyReadOnlyList <TElement> .Instance); }
private static Diagnostic SetLocation(Diagnostic d, SyntaxElement location) { if (location.Width == 0) { if (location is SyntaxToken token) { // move location to next token if it is // lest than two spaces away and not separated by line breaks var next = token.GetNextToken(); if (next != null && (next.TextStart - token.End) < 2 && !TextFacts.HasLineBreaks(next.Trivia)) { location = next; } } } return(d.WithLocation(location)); }
/// <summary> /// Gets the next <see cref="SyntaxToken"/> in lexical order. /// </summary> public SyntaxToken GetNextToken(bool includeZeroWidthTokens = false) { for (SyntaxElement node = this; node != null; node = node.Parent) { var sibling = node.GetNextSibling(includeZeroWidthTokens); if (sibling != null) { if (sibling.IsToken) { return((SyntaxToken)sibling); } var first = sibling.GetFirstToken(includeZeroWidthTokens); if (first != null) { return(first); } } } return(null); }
/// <summary> /// Gets the previous <see cref="SyntaxToken"/> in lexical orer. /// </summary> public SyntaxToken GetPreviousToken(bool includeZeroWidthTokens = false) { for (SyntaxElement node = this; node != null; node = node.Parent) { var sibling = node.GetPreviousSibling(); if (sibling != null) { if (sibling.IsToken) { return((SyntaxToken)sibling); } var last = sibling.GetLastToken(includeZeroWidthTokens); if (last != null) { return(last); } } } return(null); }
protected static SyntaxToken GetPreviousToken(SyntaxElement root, SyntaxToken token, bool includeZeroWidthTokens) { var node = token != null ? token.Parent : root; var childIndex = token != null ? token.IndexInParent - 1 : root.ChildCount - 1; while (node != null) { if (childIndex < node.ChildCount && childIndex >= 0) { var child = node.GetChild(childIndex); if (child != null) { node = child; childIndex = node.ChildCount - 1; if (node is SyntaxToken t && (includeZeroWidthTokens || t.FullWidth > 0)) { return(t); } } else { childIndex--; } } else if (node == root) { return(null); } else { childIndex = node.IndexInParent - 1; node = node.Parent; } } return(null); }