提交 14a02817 编写于 作者: C Cyrus Najmabadi

Remove the addInterval method from interval trees.

上级 827a65d5
......@@ -33,14 +33,6 @@ public int GetLength(Tuple<int, int, T> value)
private static IEnumerable<SimpleIntervalTree<Tuple<int, int, string>>> CreateTrees(IEnumerable<Tuple<int, int, string>> values)
{
yield return SimpleIntervalTree.Create(new TupleIntrospector<string>(), values);
var tree1 = SimpleIntervalTree.Create(new TupleIntrospector<string>());
foreach (var v in values)
{
tree1 = tree1.AddInterval(v);
}
yield return tree1;
}
[Fact]
......
......@@ -17,7 +17,7 @@ private class DirectiveInfo
public IDictionary<DirectiveTriviaSyntax, DirectiveTriviaSyntax> DirectiveMap { get; }
// Maps a #If/#elif/#else/#endIf directive to its list of matching #If/#elif/#else/#endIf directives
public IDictionary<DirectiveTriviaSyntax, IEnumerable<DirectiveTriviaSyntax>> ConditionalMap { get; }
public IDictionary<DirectiveTriviaSyntax, IReadOnlyList<DirectiveTriviaSyntax>> ConditionalMap { get; }
// A set of inactive regions spans. The items in the tuple are the start and end line
// *both inclusive* of the inactive region. Actual PP lines are not contined within.
......@@ -28,7 +28,7 @@ private class DirectiveInfo
public DirectiveInfo(
IDictionary<DirectiveTriviaSyntax, DirectiveTriviaSyntax> directiveMap,
IDictionary<DirectiveTriviaSyntax, IEnumerable<DirectiveTriviaSyntax>> conditionalMap,
IDictionary<DirectiveTriviaSyntax, IReadOnlyList<DirectiveTriviaSyntax>> conditionalMap,
ISet<Tuple<int, int>> inactiveRegionLines)
{
this.DirectiveMap = directiveMap;
......
......@@ -16,7 +16,7 @@ internal partial class DirectiveSyntaxExtensions
private class DirectiveWalker : CSharpSyntaxWalker
{
private readonly IDictionary<DirectiveTriviaSyntax, DirectiveTriviaSyntax> _directiveMap;
private readonly IDictionary<DirectiveTriviaSyntax, IEnumerable<DirectiveTriviaSyntax>> _conditionalMap;
private readonly IDictionary<DirectiveTriviaSyntax, IReadOnlyList<DirectiveTriviaSyntax>> _conditionalMap;
private readonly CancellationToken _cancellationToken;
private readonly Stack<DirectiveTriviaSyntax> _regionStack = new Stack<DirectiveTriviaSyntax>();
......@@ -24,7 +24,7 @@ private class DirectiveWalker : CSharpSyntaxWalker
public DirectiveWalker(
IDictionary<DirectiveTriviaSyntax, DirectiveTriviaSyntax> directiveMap,
IDictionary<DirectiveTriviaSyntax, IEnumerable<DirectiveTriviaSyntax>> conditionalMap,
IDictionary<DirectiveTriviaSyntax, IReadOnlyList<DirectiveTriviaSyntax>> conditionalMap,
CancellationToken cancellationToken) :
base(SyntaxWalkerDepth.Token)
{
......@@ -105,8 +105,16 @@ private void HandleEndIfDirective(DirectiveTriviaSyntax directive)
return;
}
FinishIf(directive);
}
private void FinishIf(DirectiveTriviaSyntax directiveOpt)
{
var condDirectives = new List<DirectiveTriviaSyntax>();
condDirectives.Add(directive);
if (directiveOpt != null)
{
condDirectives.Add(directiveOpt);
}
while (!_ifStack.IsEmpty())
{
......@@ -132,8 +140,11 @@ private void HandleEndIfDirective(DirectiveTriviaSyntax directive)
ifDirective.Kind() == SyntaxKind.ElifDirectiveTrivia ||
ifDirective.Kind() == SyntaxKind.ElseDirectiveTrivia);
_directiveMap.Add(directive, ifDirective);
_directiveMap.Add(ifDirective, directive);
if (directiveOpt != null)
{
_directiveMap.Add(directiveOpt, ifDirective);
_directiveMap.Add(ifDirective, directiveOpt);
}
}
private void HandleEndRegionDirective(DirectiveTriviaSyntax directive)
......@@ -148,6 +159,16 @@ private void HandleEndRegionDirective(DirectiveTriviaSyntax directive)
_directiveMap.Add(directive, previousDirective);
_directiveMap.Add(previousDirective, directive);
}
internal void Finish() {
while (_regionStack.Count > 0) {
_directiveMap.Add(_regionStack.Pop(), null);
}
while (_ifStack.Count > 0) {
FinishIf(directiveOpt: null);
}
}
}
}
}
......@@ -40,11 +40,12 @@ private static DirectiveInfo GetDirectiveInfo(SyntaxNode node, CancellationToken
{
var directiveMap = new Dictionary<DirectiveTriviaSyntax, DirectiveTriviaSyntax>(
DirectiveSyntaxEqualityComparer.Instance);
var conditionalMap = new Dictionary<DirectiveTriviaSyntax, IEnumerable<DirectiveTriviaSyntax>>(
var conditionalMap = new Dictionary<DirectiveTriviaSyntax, IReadOnlyList<DirectiveTriviaSyntax>>(
DirectiveSyntaxEqualityComparer.Instance);
var walker = new DirectiveWalker(directiveMap, conditionalMap, cancellationToken);
walker.Visit(r);
walker.Finish();
return new DirectiveInfo(directiveMap, conditionalMap, inactiveRegionLines: null);
});
......@@ -67,7 +68,7 @@ internal static DirectiveTriviaSyntax GetMatchingDirective(this DirectiveTriviaS
return result;
}
internal static IEnumerable<DirectiveTriviaSyntax> GetMatchingConditionalDirectives(this DirectiveTriviaSyntax directive, CancellationToken cancellationToken)
internal static IReadOnlyList<DirectiveTriviaSyntax> GetMatchingConditionalDirectives(this DirectiveTriviaSyntax directive, CancellationToken cancellationToken)
{
if (directive == null)
{
......@@ -76,7 +77,7 @@ internal static IEnumerable<DirectiveTriviaSyntax> GetMatchingConditionalDirecti
var directiveConditionalMap = GetDirectiveInfo(directive, cancellationToken).ConditionalMap;
IEnumerable<DirectiveTriviaSyntax> result;
IReadOnlyList<DirectiveTriviaSyntax> result;
directiveConditionalMap.TryGetValue(directive, out result);
return result;
......
......@@ -420,17 +420,13 @@ public static bool IsAnyLambdaOrAnonymousMethod(this SyntaxNode node)
this SyntaxNode syntaxNode,
CancellationToken cancellationToken)
{
// Check if this node contains a start or end pp construct whose matching construct is
// Check if this node contains a start, middle or end pp construct whose matching construct is
// not contained within this node. If so, this node must be pinned and cannot move.
//
// Also, keep track of those spans so that if we see #else/#elif we can tell if they
// belong to a pp span that is entirely within the node.
var ifEndIfSpans = SimpleIntervalTree.Create(TextSpanIntervalIntrospector.Instance);
var span = syntaxNode.Span;
foreach (var token in syntaxNode.DescendantTokens())
{
if (ContainsInterleavedDirective(span, token, ref ifEndIfSpans, cancellationToken))
if (ContainsInterleavedDirective(span, token, cancellationToken))
{
return true;
}
......@@ -442,25 +438,23 @@ public static bool IsAnyLambdaOrAnonymousMethod(this SyntaxNode node)
private static bool ContainsInterleavedDirective(
TextSpan textSpan,
SyntaxToken token,
ref SimpleIntervalTree<TextSpan> ifEndIfSpans,
CancellationToken cancellationToken)
{
return
ContainsInterleavedDirective(textSpan, token.LeadingTrivia, ref ifEndIfSpans, cancellationToken) ||
ContainsInterleavedDirective(textSpan, token.TrailingTrivia, ref ifEndIfSpans, cancellationToken);
ContainsInterleavedDirective(textSpan, token.LeadingTrivia, cancellationToken) ||
ContainsInterleavedDirective(textSpan, token.TrailingTrivia, cancellationToken);
}
private static bool ContainsInterleavedDirective(
TextSpan textSpan,
SyntaxTriviaList list,
ref SimpleIntervalTree<TextSpan> ifEndIfSpans,
CancellationToken cancellationToken)
{
foreach (var trivia in list)
{
if (textSpan.Contains(trivia.Span))
{
if (ContainsInterleavedDirective(textSpan, trivia, ref ifEndIfSpans, cancellationToken))
if (ContainsInterleavedDirective(textSpan, trivia, cancellationToken))
{
return true;
}
......@@ -473,18 +467,18 @@ public static bool IsAnyLambdaOrAnonymousMethod(this SyntaxNode node)
private static bool ContainsInterleavedDirective(
TextSpan textSpan,
SyntaxTrivia trivia,
ref SimpleIntervalTree<TextSpan> ifEndIfSpans,
CancellationToken cancellationToken)
{
if (trivia.HasStructure)
{
var parentSpan = trivia.GetStructure().Span;
var structure = trivia.GetStructure();
var parentSpan = structure.Span;
if (trivia.GetStructure().IsKind(SyntaxKind.RegionDirectiveTrivia,
SyntaxKind.EndRegionDirectiveTrivia,
SyntaxKind.IfDirectiveTrivia,
SyntaxKind.EndIfDirectiveTrivia))
{
var match = ((DirectiveTriviaSyntax)trivia.GetStructure()).GetMatchingDirective(cancellationToken);
var match = ((DirectiveTriviaSyntax)structure).GetMatchingDirective(cancellationToken);
if (match != null)
{
var matchSpan = match.Span;
......@@ -494,25 +488,20 @@ public static bool IsAnyLambdaOrAnonymousMethod(this SyntaxNode node)
// this node.
return true;
}
if (trivia.GetStructure().IsKind(SyntaxKind.IfDirectiveTrivia, SyntaxKind.EndIfDirectiveTrivia))
{
var ppSpan = TextSpan.FromBounds(
Math.Min(parentSpan.Start, matchSpan.Start),
Math.Max(parentSpan.End, matchSpan.End));
ifEndIfSpans = ifEndIfSpans.AddInterval(ppSpan);
}
}
}
else if (
trivia.GetStructure().IsKind(SyntaxKind.ElseDirectiveTrivia, SyntaxKind.ElifDirectiveTrivia))
else if (trivia.GetStructure().IsKind(SyntaxKind.ElseDirectiveTrivia, SyntaxKind.ElifDirectiveTrivia))
{
if (!ifEndIfSpans.IntersectsWith(parentSpan.Start))
var directives = ((DirectiveTriviaSyntax)structure).GetMatchingConditionalDirectives(cancellationToken);
if (directives != null && directives.Count > 0)
{
// This else/elif belongs to a pp span that isn't
// entirely within this node.
return true;
if (!textSpan.Contains(directives[0].SpanStart) ||
!textSpan.Contains(directives[directives.Count - 1].SpanStart))
{
// This else/elif belongs to a pp span that isn't
// entirely within this node.
return true;
}
}
}
}
......
......@@ -218,12 +218,6 @@ private IEnumerable<T> GetPreOrderIntervals(int start, int length, TestInterval
}
}
public IntervalTree<T> AddInterval(T value, IIntervalIntrospector<T> introspector)
{
var newNode = new Node(introspector, value);
return new IntervalTree<T>(Insert(root, newNode, introspector, inPlace: false));
}
public bool IsEmpty()
{
return this.root == null;
......
......@@ -62,12 +62,6 @@ public bool IntersectsWith(int position)
return GetIntersectingIntervals(position, 0).Any();
}
public SimpleIntervalTree<T> AddInterval(T value)
{
var newNode = new Node(_introspector, value);
return new SimpleIntervalTree<T>(_introspector, Insert(root, newNode, _introspector, inPlace: false));
}
protected int MaxEndValue(Node node)
{
return GetEnd(node.MaxEndNode.Value, _introspector);
......
......@@ -26,12 +26,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
End Get
End Property
Private ReadOnly _conditionalMap As IDictionary(Of DirectiveTriviaSyntax, IEnumerable(Of DirectiveTriviaSyntax))
Private ReadOnly _conditionalMap As IDictionary(Of DirectiveTriviaSyntax, IReadOnlyList(Of DirectiveTriviaSyntax))
''' <summary>
''' Maps a #If/#ElseIf/#Else/#EndIf directive to its list of matching #If/#ElseIf/#Else/#End directives.
''' </summary>
Public ReadOnly Property ConditionalMap As IDictionary(Of DirectiveTriviaSyntax, IEnumerable(Of DirectiveTriviaSyntax))
Public ReadOnly Property ConditionalMap As IDictionary(Of DirectiveTriviaSyntax, IReadOnlyList(Of DirectiveTriviaSyntax))
Get
Return _conditionalMap
End Get
......@@ -51,7 +51,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
End Property
Public Sub New(startEndMap As IDictionary(Of DirectiveTriviaSyntax, DirectiveTriviaSyntax),
conditionalMap As IDictionary(Of DirectiveTriviaSyntax, IEnumerable(Of DirectiveTriviaSyntax)),
conditionalMap As IDictionary(Of DirectiveTriviaSyntax, IReadOnlyList(Of DirectiveTriviaSyntax)),
inactiveRegionLines As ISet(Of Tuple(Of Integer, Integer)))
_startEndMap = startEndMap
_conditionalMap = conditionalMap
......@@ -66,7 +66,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
Dim info = s_rootToDirectiveInfo.GetValue(root,
Function(r)
Dim startEndMap = New Dictionary(Of DirectiveTriviaSyntax, DirectiveTriviaSyntax)(DirectiveSyntaxEqualityComparer.Instance)
Dim conditionalMap = New Dictionary(Of DirectiveTriviaSyntax, IEnumerable(Of DirectiveTriviaSyntax))(DirectiveSyntaxEqualityComparer.Instance)
Dim conditionalMap = New Dictionary(Of DirectiveTriviaSyntax, IReadOnlyList(Of DirectiveTriviaSyntax))(DirectiveSyntaxEqualityComparer.Instance)
Dim walker = New DirectiveWalker(startEndMap, conditionalMap, cancellationToken)
walker.Visit(r)
walker.Finish()
......@@ -120,14 +120,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
''' </summary>
<Extension()>
Public Function GetMatchingConditionalDirectives(directive As DirectiveTriviaSyntax,
cancellationToken As CancellationToken) As IEnumerable(Of DirectiveTriviaSyntax)
cancellationToken As CancellationToken) As IReadOnlyList(Of DirectiveTriviaSyntax)
If directive Is Nothing Then
Throw New ArgumentNullException(NameOf(directive))
End If
Dim result As IEnumerable(Of DirectiveTriviaSyntax) = Nothing
Dim result As IReadOnlyList(Of DirectiveTriviaSyntax) = Nothing
If Not GetDirectiveInfo(directive, cancellationToken).ConditionalMap.TryGetValue(directive, result) Then
Return SpecializedCollections.EmptyEnumerable(Of DirectiveTriviaSyntax)()
Return SpecializedCollections.EmptyReadOnlyList(Of DirectiveTriviaSyntax)()
End If
Return result
End Function
......
......@@ -394,31 +394,27 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
' Also, keep track of those spans so that if we see #else/#elif we
' can tell if they belong to a pp span that is entirely within the
' node.
Dim ifEndIfSpans = SimpleIntervalTree.Create(TextSpanIntervalIntrospector.Instance)
Dim span = node.Span
Return node.DescendantTokens().Any(Function(token) ContainsInterleavedDirective(span, token, cancellationToken, ifEndIfSpans))
Return node.DescendantTokens().Any(Function(token) ContainsInterleavedDirective(span, token, cancellationToken))
End Function
Private Function ContainsInterleavedDirective(
textSpan As TextSpan,
token As SyntaxToken,
cancellationToken As CancellationToken,
ByRef ifEndIfSpans As SimpleIntervalTree(Of TextSpan)) As Boolean
cancellationToken As CancellationToken) As Boolean
Return ContainsInterleavedDirective(textSpan, token.LeadingTrivia, cancellationToken, ifEndIfSpans) OrElse
ContainsInterleavedDirective(textSpan, token.TrailingTrivia, cancellationToken, ifEndIfSpans)
Return ContainsInterleavedDirective(textSpan, token.LeadingTrivia, cancellationToken) OrElse
ContainsInterleavedDirective(textSpan, token.TrailingTrivia, cancellationToken)
End Function
Private Function ContainsInterleavedDirective(
textSpan As TextSpan,
list As SyntaxTriviaList,
cancellationToken As CancellationToken,
ByRef ifEndIfSpans As SimpleIntervalTree(Of TextSpan)) As Boolean
cancellationToken As CancellationToken) As Boolean
For Each trivia In list
If textSpan.Contains(trivia.Span) Then
If ContainsInterleavedDirective(textSpan, trivia, cancellationToken, ifEndIfSpans) Then
If ContainsInterleavedDirective(textSpan, trivia, cancellationToken) Then
Return True
End If
End If
......@@ -430,8 +426,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
Private Function ContainsInterleavedDirective(
textSpan As TextSpan,
trivia As SyntaxTrivia,
cancellationToken As CancellationToken,
ByRef ifEndIfSpans As SimpleIntervalTree(Of TextSpan)) As Boolean
cancellationToken As CancellationToken) As Boolean
If trivia.HasStructure AndAlso TypeOf trivia.GetStructure() Is DirectiveTriviaSyntax Then
Dim parentSpan = trivia.GetStructure().Span
......@@ -445,18 +440,16 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
' this node.
Return True
End If
If directiveSyntax.IsKind(SyntaxKind.IfDirectiveTrivia, SyntaxKind.EndIfDirectiveTrivia) Then
Dim ppSpan = TextSpan.FromBounds(Math.Min(parentSpan.Start, matchSpan.Start), Math.Max(parentSpan.End, matchSpan.End))
ifEndIfSpans = ifEndIfSpans.AddInterval(ppSpan)
End If
End If
ElseIf directiveSyntax.IsKind(SyntaxKind.ElseDirectiveTrivia, SyntaxKind.ElseIfDirectiveTrivia) Then
If Not ifEndIfSpans.IntersectsWith(parentSpan.Start) Then
' This else/elif belongs to a pp span that isn't
' entirely within this node.
Return True
Dim directives = directiveSyntax.GetMatchingConditionalDirectives(cancellationToken)
If directives IsNot Nothing AndAlso directives.Count > 0 Then
If Not textSpan.Contains(directives(0).SpanStart) OrElse
Not textSpan.Contains(directives(directives.Count - 1).SpanStart) Then
' This else/elif belongs to a pp span that isn't
' entirely within this node.
Return True
End If
End If
End If
End If
......
......@@ -18,14 +18,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Utilities
Inherits VisualBasicSyntaxWalker
Private ReadOnly _startEndMap As Dictionary(Of DirectiveTriviaSyntax, DirectiveTriviaSyntax)
Private ReadOnly _conditionalMap As Dictionary(Of DirectiveTriviaSyntax, IEnumerable(Of DirectiveTriviaSyntax))
Private ReadOnly _conditionalMap As Dictionary(Of DirectiveTriviaSyntax, IReadOnlyList(Of DirectiveTriviaSyntax))
Private ReadOnly _cancellationToken As CancellationToken
Private ReadOnly _regionStack As New Stack(Of DirectiveTriviaSyntax)()
Private ReadOnly _ifStack As New Stack(Of DirectiveTriviaSyntax)()
Public Sub New(startEndMap As Dictionary(Of DirectiveTriviaSyntax, DirectiveTriviaSyntax),
conditionalMap As Dictionary(Of DirectiveTriviaSyntax, IEnumerable(Of DirectiveTriviaSyntax)),
conditionalMap As Dictionary(Of DirectiveTriviaSyntax, IReadOnlyList(Of DirectiveTriviaSyntax)),
cancellationToken As CancellationToken)
MyBase.New(SyntaxWalkerDepth.StructuredTrivia)
......@@ -68,35 +68,45 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Utilities
End Sub
Public Overrides Sub VisitEndIfDirectiveTrivia(directive As EndIfDirectiveTriviaSyntax)
If Not _ifStack.IsEmpty() Then
Dim condDirectives As New List(Of DirectiveTriviaSyntax)
condDirectives.Add(directive)
Do
Dim poppedDirective = _ifStack.Pop()
condDirectives.Add(poppedDirective)
If poppedDirective.Kind = SyntaxKind.IfDirectiveTrivia Then
Exit Do
End If
Loop Until _ifStack.IsEmpty()
condDirectives.Sort(Function(n1, n2) n1.SpanStart.CompareTo(n2.SpanStart))
For Each cond In condDirectives
_conditionalMap.Add(cond, condDirectives)
Next
' #If should be the first one in sorted order
Dim ifDirective = condDirectives.First()
Contract.Assert(ifDirective.Kind = SyntaxKind.IfDirectiveTrivia OrElse
FinishIf(directive)
MyBase.VisitEndIfDirectiveTrivia(directive)
End Sub
Private Sub FinishIf(directiveOpt As EndIfDirectiveTriviaSyntax)
If _ifStack.IsEmpty() Then
Return
End If
Dim condDirectives As New List(Of DirectiveTriviaSyntax)
If directiveOpt IsNot Nothing Then
condDirectives.Add(directiveOpt)
End If
Do
Dim poppedDirective = _ifStack.Pop()
condDirectives.Add(poppedDirective)
If poppedDirective.Kind = SyntaxKind.IfDirectiveTrivia Then
Exit Do
End If
Loop Until _ifStack.IsEmpty()
condDirectives.Sort(Function(n1, n2) n1.SpanStart.CompareTo(n2.SpanStart))
For Each cond In condDirectives
_conditionalMap.Add(cond, condDirectives)
Next
' #If should be the first one in sorted order
Dim ifDirective = condDirectives.First()
Contract.Assert(ifDirective.Kind = SyntaxKind.IfDirectiveTrivia OrElse
ifDirective.Kind = SyntaxKind.ElseIfDirectiveTrivia OrElse
ifDirective.Kind = SyntaxKind.ElseDirectiveTrivia)
_startEndMap.Add(directive, ifDirective)
_startEndMap.Add(ifDirective, directive)
If directiveOpt IsNot Nothing Then
_startEndMap.Add(directiveOpt, ifDirective)
_startEndMap.Add(ifDirective, directiveOpt)
End If
MyBase.VisitEndIfDirectiveTrivia(directive)
End Sub
Public Overrides Sub VisitEndRegionDirectiveTrivia(directive As EndRegionDirectiveTriviaSyntax)
......@@ -114,6 +124,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Utilities
While _regionStack.Count > 0
_startEndMap.Add(_regionStack.Pop(), Nothing)
End While
While _ifStack.Count > 0
FinishIf(directiveOpt:=Nothing)
End While
End Sub
End Class
End Namespace
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册