Пример #1
0
 /// <summary>
 /// Returns a new <see cref="RegionTree"/> with the specified child added at the end.
 /// </summary>
 /// <param name="child">The child to add.</param>
 /// <returns>The updated <see cref="RegionTree"/>.</returns>
 private RegionTree AddChild(RegionTree child)
 {
     return(new RegionTree(
                this.Name,
                this.SpanStart,
                this.SpanEnd,
                this.Children.Add(child),
                this.IsRoot,
                this.ItemCollection));
 }
Пример #2
0
 /// <summary>
 /// Returns a new <see cref="RegionTree"/> with the specified child removed.
 /// </summary>
 /// <param name="childToRemove">The child to remove.</param>
 /// <returns>The updated <see cref="RegionTree"/>.</returns>
 private RegionTree RemoveChild(RegionTree childToRemove)
 {
     return(new RegionTree(
                this.Name,
                this.SpanStart,
                this.SpanEnd,
                this.Children.Remove(childToRemove),
                this.IsRoot,
                this.ItemCollection));
 }
Пример #3
0
 /// <summary>
 /// Returns a new <see cref="RegionTree"/> with <paramref name="oldChild"/> replaced with
 /// <paramref name="newChild"/>.
 /// </summary>
 /// <param name="oldChild">The child to be replaced.</param>
 /// <param name="newChild">The replacemend child.</param>
 /// <returns>The updated <see cref="RegionTree"/>.</returns>
 private RegionTree UpdateChild(RegionTree oldChild, RegionTree newChild)
 {
     return(new RegionTree(
                this.Name,
                this.SpanStart,
                this.SpanEnd,
                this.Children.Replace(oldChild, newChild),
                this.IsRoot,
                this.ItemCollection));
 }
Пример #4
0
        /// <summary>
        /// Builds a region tree from a list of <see cref="RegionDirectiveTriviaSyntax"/> and
        /// <see cref="EndRegionDirectiveTriviaSyntax"/> elements. Builds up the item collections with only regions.
        /// </summary>
        /// <param name="directives">The directives to build the region tree from.</param>
        /// <returns>The built region tree.</returns>
        public RegionTree Create(IEnumerator <DirectiveTriviaSyntax> directives)
        {
            var result = this;

            while (directives.MoveNext())
            {
                if (directives.Current is RegionDirectiveTriviaSyntax start)
                {
                    // A new region is started, so try finding sub-regions inside it.
                    // Note that if there are more start-regions than end-regions, this will result the outermost
                    // region being ended at the same time as the last region that was ended.
                    var item = new TreeViewItem {
                        IsExpanded = true
                    };
                    var child = new RegionTree(start.ToString(), start.FullSpan, item.Items).Create(directives);
                    result      = result.AddChild(child);
                    item.Header = new TreeElement(
                        child.Name.Substring("#region ".Length),
                        new TextSpan(child.SpanStart, child.SpanEnd - child.SpanStart),
                        TreeImages.GetImage(ElementType.Region),
                        regionId: child.Id)
                    {
                        TextColor = "#666"
                    };

                    this.ItemCollection.Add(item);
                }
                else if (directives.Current is EndRegionDirectiveTriviaSyntax end)
                {
                    // We return the region currently being built up with its span-end filled in.
                    // Note that an additional endregion syntax will exit this method early, resulting in fewer regions
                    // being returned. But that is okay, since the syntax is not correct anyway.
                    return(result.SetSpanEnd(end.FullSpan.End));
                }
            }

            // For the root, don't update the span end, it was set when creating the region.
            // Otherwise, there are end-region directives missing, so end the current region at the end of its
            // child regions (if it has any).
            var lastChild = result.Children.LastOrDefault();

            if (result.IsRoot || lastChild == null)
            {
                return(result);
            }
            else
            {
                return(result.SetSpanEnd(lastChild.SpanEnd));
            }
        }
Пример #5
0
        /// <summary>
        /// Handles nesting child nodes within regions. While regions are allowed in multiple levels,
        /// we only use this on second level nodes.
        /// </summary>
        private static void HandleChildrenWithRegions(SyntaxNode node, ItemCollection itemCollection)
        {
            // Determine regions, so we know whether to put nodes inside the regions, or not.
            var startRegionDirectives = node.DescendantNodes(descendIntoTrivia: true)
                                        .OfType <RegionDirectiveTriviaSyntax>().Cast <DirectiveTriviaSyntax>()
                                        .Where(s => node.Span.Contains(s.Span));
            var endRegionDirectives = node.DescendantNodes(descendIntoTrivia: true).OfType <EndRegionDirectiveTriviaSyntax>()
                                      .Where(s => node.Span.Contains(s.Span));
            var regionDirectives = startRegionDirectives.Union(endRegionDirectives).OrderBy(x => x.FullSpan.Start);

            var regionTree = new RegionTree(node.Span, itemCollection).Create(regionDirectives.GetEnumerator());

            // Insert all nodes in the region tree, this will update itemCollection.
            // Note that this uses an immutable structure to easily recurse over the region structure, while mutating
            // the mutable itemCollection as the intended side-effect. Hence the return value is not used.
            node.ChildNodes().Aggregate(regionTree, (current, child) => current.InsertNode(child));
        }