Skip to content

Commit

Permalink
Merge pull request #73714 from CyrusNajmabadi/intervalTreeSpan
Browse files Browse the repository at this point in the history
  • Loading branch information
CyrusNajmabadi authored May 25, 2024
2 parents 386b920 + 4e4eb96 commit 6350341
Show file tree
Hide file tree
Showing 14 changed files with 83 additions and 102 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Collections;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.Text.Shared.Extensions;
using Microsoft.CodeAnalysis.Utilities;
using Microsoft.CodeAnalysis.Workspaces;
Expand Down Expand Up @@ -275,10 +276,7 @@ async Task AddEmbeddedClassificationsAsync()

private readonly struct ClassificationTagSpanIntervalIntrospector : IIntervalIntrospector<TagSpan<IClassificationTag>>
{
public int GetStart(TagSpan<IClassificationTag> value)
=> value.Span.Start;

public int GetLength(TagSpan<IClassificationTag> value)
=> value.Span.Length;
public TextSpan GetSpan(TagSpan<IClassificationTag> value)
=> value.Span.Span.ToTextSpan();
}
}
13 changes: 4 additions & 9 deletions src/EditorFeatures/Core/InlineRename/TrackingSpanIntrospector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,15 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#nullable disable

using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Collections;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.Text;

namespace Microsoft.CodeAnalysis.Editor.Implementation.InlineRename;

internal sealed class TrackingSpanIntrospector(ITextSnapshot snapshot) : IIntervalIntrospector<ITrackingSpan>
{
private readonly ITextSnapshot _snapshot = snapshot;

public int GetStart(ITrackingSpan value)
=> value.GetStartPoint(_snapshot);

public int GetLength(ITrackingSpan value)
=> value.GetSpan(_snapshot).Length;
public TextSpan GetSpan(ITrackingSpan value)
=> value.GetSpan(snapshot).Span.ToTextSpan();
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Collections;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Tagging;

Expand All @@ -15,10 +17,7 @@ private readonly struct IntervalIntrospector(
SpanTrackingMode trackingMode)
: IIntervalIntrospector<ITagSpan<TTag>>
{
public int GetStart(ITagSpan<TTag> value)
=> GetTranslatedSpan(value, snapshot, trackingMode).Start;

public int GetLength(ITagSpan<TTag> value)
=> GetTranslatedSpan(value, snapshot, trackingMode).Length;
public TextSpan GetSpan(ITagSpan<TTag> value)
=> GetTranslatedSpan(value, snapshot, trackingMode).Span.ToTextSpan();
}
}
17 changes: 6 additions & 11 deletions src/EditorFeatures/Test/Collections/IntervalTreeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,18 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis.Shared.Collections;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.Text;
using Xunit;

namespace Microsoft.CodeAnalysis.Editor.UnitTests.Collections;

public class IntervalTreeTests
public sealed class IntervalTreeTests
{
private readonly struct TupleIntrospector<T> : IIntervalIntrospector<Tuple<int, int, T>>
{
public int GetStart(Tuple<int, int, T> value)
=> value.Item1;

public int GetLength(Tuple<int, int, T> value)
=> value.Item2;
public TextSpan GetSpan(Tuple<int, int, T> value)
=> new(value.Item1, value.Item2);
}

private static IEnumerable<SimpleIntervalTree<Tuple<int, int, string>, TupleIntrospector<string>>> CreateTrees(params Tuple<int, int, string>[] values)
Expand Down Expand Up @@ -260,11 +258,8 @@ public void TestEmptySpanAtStart()

private readonly struct Int32Introspector : IIntervalIntrospector<int>
{
public int GetLength(int value)
=> 0;

public int GetStart(int value)
=> value;
public TextSpan GetSpan(int value)
=> new(value, 0);
}

private static IntervalTree<int> CreateIntTree(params int[] values)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Collections;
using Microsoft.CodeAnalysis.Text;

namespace Microsoft.VisualStudio.LanguageServices.DocumentOutline;

Expand All @@ -14,10 +16,7 @@ internal sealed partial class DocumentOutlineViewModel
/// </summary>
private readonly struct IntervalIntrospector : IIntervalIntrospector<DocumentSymbolDataViewModel>
{
public int GetStart(DocumentSymbolDataViewModel value)
=> value.Data.RangeSpan.Start;

public int GetLength(DocumentSymbolDataViewModel value)
=> value.Data.RangeSpan.Length;
public TextSpan GetSpan(DocumentSymbolDataViewModel value)
=> value.Data.RangeSpan.Span.ToTextSpan();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.CodeAnalysis.Editor.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Collections;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.LanguageServices.Implementation.InheritanceMargin.MarginGlyph;
using Microsoft.VisualStudio.Text;

namespace Microsoft.VisualStudio.LanguageServices.Implementation.InheritanceMargin;

internal partial class InheritanceGlyphManager
{
private record GlyphData
private sealed record GlyphData
{
public SnapshotSpan SnapshotSpan { get; }
public InheritanceMarginGlyph Glyph { get; }
Expand All @@ -30,10 +32,7 @@ public void Deconstruct(out SnapshotSpan span, out InheritanceMarginGlyph glyph)

private readonly struct GlyphDataIntrospector : IIntervalIntrospector<GlyphData>
{
public int GetStart(GlyphData data)
=> data.SnapshotSpan.Start;

public int GetLength(GlyphData data)
=> data.SnapshotSpan.Length;
public TextSpan GetSpan(GlyphData data)
=> data.SnapshotSpan.Span.ToTextSpan();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,17 @@
// See the LICENSE file in the project root for more information.

using Microsoft.CodeAnalysis.Shared.Collections;
using Microsoft.CodeAnalysis.Text;

namespace Microsoft.CodeAnalysis.Classification;

internal static partial class ClassifierHelper
{
private readonly struct ClassifiedSpanIntervalIntrospector : IIntervalIntrospector<ClassifiedSpan>
{
public static readonly ClassifiedSpanIntervalIntrospector Instance = new ClassifiedSpanIntervalIntrospector();
public static readonly ClassifiedSpanIntervalIntrospector Instance = new();

public int GetLength(ClassifiedSpan value)
=> value.TextSpan.Length;

public int GetStart(ClassifiedSpan value)
=> value.TextSpan.Start;
public TextSpan GetSpan(ClassifiedSpan value)
=> value.TextSpan;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ internal class TextChangeMerger
{
private readonly struct IntervalIntrospector : IIntervalIntrospector<TextChange>
{
int IIntervalIntrospector<TextChange>.GetStart(TextChange value) => value.Span.Start;
int IIntervalIntrospector<TextChange>.GetLength(TextChange value) => value.Span.Length;
public TextSpan GetSpan(TextChange value)
=> value.Span;
}

private readonly Document _oldDocument;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.CodeAnalysis.Text;

namespace Microsoft.CodeAnalysis.Shared.Collections;

internal interface IIntervalIntrospector<T>
{
int GetStart(T value);
int GetLength(T value);
TextSpan GetSpan(T value);
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,9 @@ protected static bool Contains<TIntrospector>(T value, int start, int length, in
var otherStart = start;
var otherEnd = start + length;

var thisStart = introspector.GetStart(value);
var thisEnd = thisStart + introspector.GetLength(value);
var thisSpan = introspector.GetSpan(value);
var thisStart = thisSpan.Start;
var thisEnd = thisSpan.End;

// TODO(cyrusn): This doesn't actually seem to match what TextSpan.Contains does. It doesn't specialize empty
// length in any way. Preserving this behavior for now, but we should consider changing this.
Expand All @@ -82,8 +83,9 @@ private static bool IntersectsWith<TIntrospector>(T value, int start, int length
var otherStart = start;
var otherEnd = start + length;

var thisStart = introspector.GetStart(value);
var thisEnd = thisStart + introspector.GetLength(value);
var thisSpan = introspector.GetSpan(value);
var thisStart = thisSpan.Start;
var thisEnd = thisSpan.End;

return otherStart <= thisEnd && otherEnd >= thisStart;
}
Expand All @@ -94,8 +96,9 @@ private static bool OverlapsWith<TIntrospector>(T value, int start, int length,
var otherStart = start;
var otherEnd = start + length;

var thisStart = introspector.GetStart(value);
var thisEnd = thisStart + introspector.GetLength(value);
var thisSpan = introspector.GetSpan(value);
var thisStart = thisSpan.Start;
var thisEnd = thisSpan.End;

// TODO(cyrusn): This doesn't actually seem to match what TextSpan.OverlapsWith does. It doesn't specialize empty
// length in any way. Preserving this behavior for now, but we should consider changing this.
Expand Down Expand Up @@ -251,7 +254,7 @@ private static bool ShouldExamineRight<TIntrospector>(
{
// right children's starts will never be to the left of the parent's start so we should consider right
// subtree only if root's start overlaps with interval's End,
if (introspector.GetStart(currentNode.Value) <= end)
if (introspector.GetSpan(currentNode.Value).Start <= end)
{
right = currentNode.Right;
if (right != null && GetEnd(right.MaxEndNode.Value, in introspector) >= start)
Expand Down Expand Up @@ -282,7 +285,7 @@ private static bool ShouldExamineLeft<TIntrospector>(
protected static Node Insert<TIntrospector>(Node? root, Node newNode, in TIntrospector introspector)
where TIntrospector : struct, IIntervalIntrospector<T>
{
var newNodeStart = introspector.GetStart(newNode.Value);
var newNodeStart = introspector.GetSpan(newNode.Value).Start;
return Insert(root, newNode, newNodeStart, in introspector);
}

Expand All @@ -296,7 +299,7 @@ private static Node Insert<TIntrospector>(Node? root, Node newNode, int newNodeS

Node? newLeft, newRight;

if (newNodeStart < introspector.GetStart(root.Value))
if (newNodeStart < introspector.GetSpan(root.Value).Start)
{
newLeft = Insert(root.Left, newNode, newNodeStart, in introspector);
newRight = root.Right;
Expand Down Expand Up @@ -383,7 +386,7 @@ IEnumerator IEnumerable.GetEnumerator()

protected static int GetEnd<TIntrospector>(T value, in TIntrospector introspector)
where TIntrospector : struct, IIntervalIntrospector<T>
=> introspector.GetStart(value) + introspector.GetLength(value);
=> introspector.GetSpan(value).End;

protected static int MaxEndValue<TIntrospector>(Node? node, in TIntrospector introspector)
where TIntrospector : struct, IIntervalIntrospector<T>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,8 @@ namespace Microsoft.CodeAnalysis.Shared.Collections;

internal readonly struct TextSpanIntervalIntrospector : IIntervalIntrospector<TextSpan>
{
public int GetStart(TextSpan value)
=> value.Start;

public int GetLength(TextSpan value)
=> value.Length;
public TextSpan GetSpan(TextSpan value)
=> value;
}

internal sealed class TextSpanIntervalTree(IEnumerable<TextSpan>? values)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,18 @@ private class AnchorData(AnchorIndentationOperation operation, SyntaxToken ancho
public int OriginalColumn { get; } = originalColumn;
}

private readonly struct FormattingContextIntervalIntrospector
: IIntervalIntrospector<AnchorData>,
private readonly struct FormattingContextIntervalIntrospector :
IIntervalIntrospector<AnchorData>,
IIntervalIntrospector<IndentationData>,
IIntervalIntrospector<RelativeIndentationData>
{
int IIntervalIntrospector<AnchorData>.GetStart(AnchorData value)
=> value.TextSpan.Start;
TextSpan IIntervalIntrospector<AnchorData>.GetSpan(AnchorData value)
=> value.TextSpan;

int IIntervalIntrospector<AnchorData>.GetLength(AnchorData value)
=> value.TextSpan.Length;
TextSpan IIntervalIntrospector<IndentationData>.GetSpan(IndentationData value)
=> value.TextSpan;

int IIntervalIntrospector<IndentationData>.GetStart(IndentationData value)
=> value.TextSpan.Start;

int IIntervalIntrospector<IndentationData>.GetLength(IndentationData value)
=> value.TextSpan.Length;

int IIntervalIntrospector<RelativeIndentationData>.GetStart(RelativeIndentationData value)
=> value.InseparableRegionSpan.Start;

int IIntervalIntrospector<RelativeIndentationData>.GetLength(RelativeIndentationData value)
=> value.InseparableRegionSpan.Length;
TextSpan IIntervalIntrospector<RelativeIndentationData>.GetSpan(RelativeIndentationData value)
=> value.InseparableRegionSpan;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,17 @@
// See the LICENSE file in the project root for more information.

using Microsoft.CodeAnalysis.Shared.Collections;
using Microsoft.CodeAnalysis.Text;

namespace Microsoft.CodeAnalysis.Formatting;

internal readonly struct SuppressIntervalIntrospector :
IIntervalIntrospector<SuppressSpacingData>,
IIntervalIntrospector<SuppressWrappingData>
{
int IIntervalIntrospector<SuppressSpacingData>.GetStart(SuppressSpacingData value)
=> value.TextSpan.Start;
TextSpan IIntervalIntrospector<SuppressSpacingData>.GetSpan(SuppressSpacingData value)
=> value.TextSpan;

int IIntervalIntrospector<SuppressSpacingData>.GetLength(SuppressSpacingData value)
=> value.TextSpan.Length;

int IIntervalIntrospector<SuppressWrappingData>.GetStart(SuppressWrappingData value)
=> value.TextSpan.Start;

int IIntervalIntrospector<SuppressWrappingData>.GetLength(SuppressWrappingData value)
=> value.TextSpan.Length;
TextSpan IIntervalIntrospector<SuppressWrappingData>.GetSpan(SuppressWrappingData value)
=> value.TextSpan;
}
Loading

0 comments on commit 6350341

Please sign in to comment.