コード例 #1
0
 protected SeparatedElement(SyntaxElement element, SyntaxToken separator = null)
     : base(null)
 {
     this.Element   = Attach(element);
     this.Separator = Attach(separator, optional: true);
     this.Init();
 }
コード例 #2
0
        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);
                }
            },
コード例 #3
0
        /// <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);
        }
コード例 #4
0
 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;
     });
 }
コード例 #5
0
        /// <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);
        }
コード例 #6
0
        /// <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;
                }
            }
        }
コード例 #7
0
        /// <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);
        }
コード例 #8
0
        /// <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));
        }
コード例 #9
0
        /// <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);
        }
コード例 #10
0
        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);
                }
            }
        }
コード例 #11
0
        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);
        }
コード例 #12
0
        /// <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);
        }
コード例 #13
0
        /// <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);
        }
コード例 #14
0
        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));
        }
コード例 #15
0
        /// <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);
        }
コード例 #16
0
        /// <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);
        }
コード例 #17
0
        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);
        }