internal static IEnumerable <ICollapsible> GetInnermostCollapsibles(ITextSnapshot snapshot, IEnumerable <ICollapsible> collapsibles)
        {
            if (snapshot == null)
            {
                throw new ArgumentNullException(nameof(snapshot));
            }

            List <ICollapsible> innermostCollapsibles = null;

            if (collapsibles != null)
            {
                // OutliningManager returns collapsibles "sorted" such that contained follow containing and preceed not contained
                // Include collapsibles which have no following collapsibles which are contained within them
                ICollapsible previousCollapsible = null;
                foreach (ICollapsible collapsible in collapsibles)
                {
                    if (previousCollapsible != null)
                    {
                        if (!previousCollapsible.Extent.GetSpan(snapshot).Contains(collapsible.Extent.GetSpan(snapshot)))
                        {
                            AddCollapsible(ref innermostCollapsibles, previousCollapsible);
                        }
                    }
                    previousCollapsible = collapsible;
                }
                if (previousCollapsible != null)
                {
                    AddCollapsible(ref innermostCollapsibles, previousCollapsible);
                }
            }

            return(innermostCollapsibles);
        }
        // Returns true when the collapsible should be collapsed.
        private bool Match(ICollapsible collapsible)
        {
            try
            {
                //Get region text
                string regionText = collapsible?.Extent?.GetText(wpfTextView.TextSnapshot);

                //Check if collapsing is wanted
                bool collapse = CheckToCollapse(regionText, collapsible.Tag.IsImplementation);

                //Collapse if wanted
                if (collapse)
                {
                    return true;
                }

                return false;
            }
            catch (Exception ex)
            {
                ActivityLog.LogError("AutoCollapseToDefinitions", ex.ToString());

                return false;
            }
        }
            internal bool Match(ICollapsible givenCollapsible)
            {
                if (givenCollapsible != null)
                {
                    while (_currentTrackingSpan != null)
                    {
                        SnapshotSpan currentSnapshotSpan = _currentTrackingSpan.GetSpan(_textSnapshot);
                        SnapshotSpan givenSnapshotSpan   = givenCollapsible.Extent.GetSpan(_textSnapshot);
                        int          comparison          = ((currentSnapshotSpan.Start != givenSnapshotSpan.Start) ?
                                                            currentSnapshotSpan.Start.CompareTo(givenSnapshotSpan.Start) :
                                                            -currentSnapshotSpan.Length.CompareTo(givenSnapshotSpan.Length));
                        if (comparison <= 0)
                        {
                            // Advance current
                            _currentTrackingSpan = (_trackingSpanEnum.MoveNext() ? _trackingSpanEnum.Current : null);

                            if (comparison == 0)
                            {
                                // Match
                                return(MatchReturn);
                            }

                            // Continue loop to try updated current
                        }
                        else
                        {
                            // Break loop to advance given
                            break;
                        }
                    }
                }
                return(!MatchReturn);
            }
Exemple #4
0
        /// <summary>
        /// Gets the start line for the specified collapsible.
        /// </summary>
        /// <remarks>
        /// The +1 offset is to accomdate for the 0-based code indexing vs. 1-based code item indexing.
        /// </remarks>
        /// <param name="collapsible">The collapsible region.</param>
        /// <returns>The starting line.</returns>
        private static int GetStartLineForCollapsible(ICollapsible collapsible)
        {
            var startPoint = collapsible.Extent.GetStartPoint(collapsible.Extent.TextBuffer.CurrentSnapshot);
            var line       = startPoint.Snapshot.GetLineNumberFromPosition(startPoint.Position) + 1;

            return(line);
        }
Exemple #5
0
        bool IsRegionExposed(ICollapsible region, ITextSnapshot current)
        {
            var regionSpan = region.Extent.GetSpan(current);

            // Filter out regions that don't have both end points exposed.
            return(!collapsedRegionTree.IsPointContainedInANode(regionSpan.Start) &&
                   !collapsedRegionTree.IsPointContainedInANode(regionSpan.End));
        }
 internal static void AddCollapsible(ref List <ICollapsible> collapsibles, ICollapsible collapsible)
 {
     if (collapsibles == null)
     {
         collapsibles = new List <ICollapsible>();
     }
     collapsibles.Add(collapsible);
 }
        private async Task AssertFoldableBlocksAsync(params string[] blockTexts)
        {
            var textView = await TestServices.Editor.GetActiveTextViewAsync(HangMitigatingCancellationToken);

            var text = textView.TextBuffer.CurrentSnapshot.GetText();

            var foldableSpans = blockTexts.Select(blockText =>
            {
                Assert.Contains(blockText, text);
                var start = text.IndexOf(blockText);
                return(new Span(start, blockText.Length));
            }).ToImmutableArray();

            var foldableLines = foldableSpans.Select(s => ConvertToLineNumbers(s, textView)).ToImmutableArray();

            //
            // Built in retry logic because getting spans can take time.
            //
            var       tries    = 0;
            const int MaxTries = 1;
            ImmutableArray <CollapsibleBlock> missingLines;
            var outlines = new ICollapsible[0];

            while (tries++ < MaxTries)
            {
                textView = await TestServices.Editor.GetActiveTextViewAsync(HangMitigatingCancellationToken);

                outlines = await TestServices.Editor.GetOutlineRegionsAsync(textView, HangMitigatingCancellationToken);

                (missingLines, var extraLines) = GetOutlineDiff(outlines, foldableSpans, textView);
                if (missingLines.Length == 0)
                {
                    if (extraLines.Length > 0)
                    {
                        var extraLineText = PrintLines(extraLines, textView);
                        var lineText      = PrintLines(foldableLines, textView);

                        Assert.False(true, $"Extra Lines: {extraLineText}Expected Lines: {lineText}");
                    }

                    return;
                }

                await Task.Delay(500);
            }

            if (missingLines.Length > 0)
            {
                var missingSpanText = PrintLines(missingLines, textView);
                var spans           = outlines.Select(o => o.Extent.GetSpan(textView.TextSnapshot).Span).ToImmutableArray();
                var lines           = spans.Select(s => ConvertToLineNumbers(s, textView)).ToImmutableArray();
                var linesText       = PrintLines(lines, textView);

                Assert.False(true, $"Missing Lines: {missingSpanText}Actual Lines: {linesText}");
            }

            Assert.Empty(missingLines);
Exemple #8
0
        public ICollapsible Expand(ICollapsed collapsed)
        {
            ICollapsible newCollapsible = ExpandInternal(collapsed);

            // Send out change event
            var handler = RegionsExpanded;

            if (handler != null)
            {
                handler(this, new RegionsExpandedEventArgs(Enumerable.Repeat(newCollapsible, 1)));
            }

            return(newCollapsible);
        }
Exemple #9
0
        private static void SetRegionIsExpanded(IEnumerable <CodeItem> document, ICollapsible region, bool isExpanded)
        {
            if (!document.Any())
            {
                return;
            }

            var startLine = GetStartLineForCollapsible(region);

            document.ToList().ForEach(
                root => root.Descendants().Where(i => i.StartLine == startLine && i.Kind == CodeItemKindEnum.Region).ToList()
                .ForEach(ci => (ci as IMembers).IsExpanded = isExpanded)
                );
        }
Exemple #10
0
        public ICollapsed TryCollapse(ICollapsible collapsible)
        {
            ICollapsed newCollapsed = CollapseInternal(collapsible);

            if (newCollapsed == null)
            {
                return(newCollapsed);
            }

            // Raise event.
            var handler = RegionsCollapsed;

            if (handler != null)
            {
                handler(this, new RegionsCollapsedEventArgs(Enumerable.Repeat(newCollapsed, 1)));
            }

            return(newCollapsed);
        }
Exemple #11
0
        private ICollapsed CollapseInternal(ICollapsible collapsible)
        {
            EnsureValid();

            if (collapsible.IsCollapsed)
            {
                return(null);
            }

            Collapsed newCollapsed = new Collapsed(collapsible.Extent, collapsible.Tag);

            newCollapsed.Node = collapsedRegionTree.TryAddItem(newCollapsed, newCollapsed.Extent);

            if (newCollapsed.Node == null)
            {
                return(null);
            }

            return(newCollapsed);
        }
Exemple #12
0
        private static void SetRegionIsExpanded(IEnumerable <CodeItem> document, ICollapsible region, bool isExpanded)
        {
            var startLine = GetStartLineForCollapsible(region);

            var found = new List <CodeItem>();

            FindHelper.Find(found, document, startLine);
            if (!found.Any())
            {
                return;
            }

            var item = found.Last();

            if (!(item is IMembers))
            {
                return;
            }
            (item as IMembers).IsExpanded = isExpanded;
        }
Exemple #13
0
        private void ToggleCurrent()
        {
            var caretPosition = _textView.Caret.Position.BufferPosition;
            var snapshot      = _textView.TextBuffer.CurrentSnapshot;
            var span          = new SnapshotSpan(snapshot, new Span(caretPosition, 0));

            var regions = OutliningManager.GetAllRegions(span);

            // Find innermost one
            ICollapsible region = null;

            int regionStart = 0;
            int regionEnd   = snapshot.Length;

            foreach (ICollapsible c in regions)
            {
                int start = c.Extent.GetStartPoint(snapshot);
                int end   = c.Extent.GetEndPoint(snapshot);

                if (start >= regionStart && end < regionEnd)
                {
                    regionStart = start;
                    regionEnd   = end;

                    region = c;
                }
            }

            if (region != null)
            {
                if (region.IsCollapsed)
                {
                    OutliningManager.Expand(region as ICollapsed);
                }
                else
                {
                    OutliningManager.TryCollapse(region);
                }
            }
        }
        internal static bool ShouldExpandToggledCollapsibles(IEnumerable <ICollapsible> collapsibles)
        {
            if (collapsibles != null)
            {
                // Determine whether homogenous collapse state for given collapsibles
                bool         homogenousCollapseState = true;
                ICollapsible previousCollapsible     = null;
                foreach (ICollapsible collapsible in collapsibles)
                {
                    if (previousCollapsible != null)
                    {
                        if (previousCollapsible.IsCollapsed != collapsible.IsCollapsed)
                        {
                            homogenousCollapseState = false;
                            break;
                        }
                    }
                    previousCollapsible = collapsible;
                }

                // Check whether non empty collection of collapsibles
                if (previousCollapsible != null)
                {
                    // Check whether homogenous collapse state and collapsed
                    if (homogenousCollapseState && previousCollapsible.IsCollapsed)
                    {
                        // Should expand collapsibles
                        return(true);
                    }
                    else
                    {
                        // Should collapse collapsibles
                        return(false);
                    }
                }
            }

            return(false);
        }
        internal bool AreCollapsible(IEnumerable <ICollapsible> collapsibles, ITextSnapshot snapshot)
        {
            if (collapsibles != null)
            {
                // OutliningManager returns collapsibles "sorted" such that contained follow containing and preceed not contained
                // Return true if find uncollapsed not nested within collapsed
                ICollapsible previousCollapsed = null;
                foreach (ICollapsible collapsible in collapsibles)
                {
                    bool nestedInPreviousCollapsed = ((previousCollapsed != null) && previousCollapsed.Extent.GetSpan(snapshot).Contains(collapsible.Extent.GetSpan(snapshot)));
                    if (!nestedInPreviousCollapsed)
                    {
                        if (!collapsible.IsCollapsed)
                        {
                            return(true);
                        }
                        previousCollapsed = collapsible;
                    }
                }
            }

            return(false);
        }
        /// <summary>
        /// Gets the start line for the specified collapsible.
        /// </summary>
        /// <remarks>
        /// The +1 offset is to accomdate for the 0-based code indexing vs. 1-based code item indexing.
        /// </remarks>
        /// <param name="collapsible">The collapsible region.</param>
        /// <returns>The starting line.</returns>
        private static int GetStartLineForCollapsible(ICollapsible collapsible)
        {
            var startPoint = collapsible.Extent.GetStartPoint(collapsible.Extent.TextBuffer.CurrentSnapshot);
            var line = startPoint.Snapshot.GetLineNumberFromPosition(startPoint.Position) + 1;

            return line;
        }
Exemple #17
0
        /// <summary>
        /// Attempts to find a <see cref="ICodeItemParent" /> associated with the specified <see
        /// cref="ICollapsible" />.
        /// </summary>
        /// <param name="collapsible">The collapsible region.</param>
        /// <returns>
        /// The <see cref="ICodeItemParent" /> on the same starting line, otherwise null.
        /// </returns>
        private ICodeItemParent FindCodeItemParentFromCollapsible(ICollapsible collapsible)
        {
            var startLine = GetStartLineForCollapsible(collapsible);

            return(_codeItemParents.FirstOrDefault(x => x.StartLine == startLine));
        }
        private static bool IsRegion(ICollapsible collapsible)
        {
            var text = collapsible.Extent.GetText(collapsible.Extent.TextBuffer.CurrentSnapshot);

            return(text.TrimStart().ToLowerInvariant().StartsWith("#region"));
        }
Exemple #19
0
        private IEnumerable <ICollapsible> MergeRegions(IEnumerable <ICollapsed> currentCollapsed, IEnumerable <ICollapsible> newCollapsibles,
                                                        out IEnumerable <ICollapsed> removedRegions)
        {
            List <ICollapsed> toRemove = new List <ICollapsed>();

            List <ICollapsed>   oldRegions = new List <ICollapsed>(currentCollapsed);
            List <ICollapsible> newRegions = new List <ICollapsible>(newCollapsibles);

            List <ICollapsible> merged = new List <ICollapsible>(oldRegions.Count + newRegions.Count);

            int oldIndex = 0;
            int newIndex = 0;

            CollapsibleSorter sorter = new CollapsibleSorter(this.editBuffer);

            while (oldIndex < oldRegions.Count || newIndex < newRegions.Count)
            {
                if (oldIndex < oldRegions.Count && newIndex < newRegions.Count)
                {
                    Collapsed    oldRegion = oldRegions[oldIndex] as Collapsed;
                    ICollapsible newRegion = newRegions[newIndex];

                    int compareVal = sorter.Compare(oldRegion, newRegion);

                    // Same region
                    if (compareVal == 0)
                    {
                        // might be the same region, but content could be new
                        oldRegion.Tag = newRegion.Tag;
                        merged.Add(oldRegion);

                        oldIndex++;
                        newIndex++;
                    }
                    // old region comes first
                    else if (compareVal < 0)
                    {
                        toRemove.Add(oldRegion);
                        oldIndex++;
                    }
                    // new region comes first
                    else if (compareVal > 0)
                    {
                        merged.Add(newRegion);
                        newIndex++;
                    }
                }
                else if (oldIndex < oldRegions.Count)
                {
                    toRemove.AddRange(oldRegions.GetRange(oldIndex, oldRegions.Count - oldIndex));
                    break;
                }
                else if (newIndex < newRegions.Count)
                {
                    merged.AddRange(newRegions.GetRange(newIndex, newRegions.Count - newIndex));
                    break;
                }
            }

            removedRegions = toRemove;

            return(merged);
        }
        /// <summary>
        /// Attempts to find a <see cref="ICodeItemParent" /> associated with the specified <see
        /// cref="ICollapsible" />.
        /// </summary>
        /// <param name="collapsible">The collapsible region.</param>
        /// <returns>
        /// The <see cref="ICodeItemParent" /> on the same starting line, otherwise null.
        /// </returns>
        private ICodeItemParent FindCodeItemParentFromCollapsible(ICollapsible collapsible)
        {
            var startLine = GetStartLineForCollapsible(collapsible);

            return _codeItemParents.FirstOrDefault(x => x.StartLine == startLine);
        }