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); }
/// <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); }
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);
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); }
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) ); }
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); }
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); }
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; }
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; }
/// <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")); }
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); }