186 lines
4.3 KiB
C#
186 lines
4.3 KiB
C#
using System;
|
|
using System.Threading;
|
|
using Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax;
|
|
using Microsoft.CodeAnalysis.Text;
|
|
|
|
namespace Microsoft.CodeAnalysis.CSharp;
|
|
|
|
internal struct SyntaxTreeDiagnosticEnumerator
|
|
{
|
|
private struct NodeIteration
|
|
{
|
|
internal readonly GreenNode Node;
|
|
|
|
internal int DiagnosticIndex;
|
|
|
|
internal int SlotIndex;
|
|
|
|
internal NodeIteration(GreenNode node)
|
|
{
|
|
Node = node;
|
|
SlotIndex = -1;
|
|
DiagnosticIndex = -1;
|
|
}
|
|
}
|
|
|
|
private struct NodeIterationStack
|
|
{
|
|
private NodeIteration[] _stack;
|
|
|
|
private int _count;
|
|
|
|
internal NodeIteration Top => this[_count - 1];
|
|
|
|
internal NodeIteration this[int index] => _stack[index];
|
|
|
|
internal NodeIterationStack(int capacity)
|
|
{
|
|
_stack = new NodeIteration[capacity];
|
|
_count = 0;
|
|
}
|
|
|
|
internal void PushNodeOrToken(GreenNode node)
|
|
{
|
|
if (node is SyntaxToken token)
|
|
{
|
|
PushToken(token);
|
|
}
|
|
else
|
|
{
|
|
Push(node);
|
|
}
|
|
}
|
|
|
|
private void PushToken(SyntaxToken token)
|
|
{
|
|
GreenNode trailingTrivia = token.GetTrailingTrivia();
|
|
if (trailingTrivia != null)
|
|
{
|
|
Push(trailingTrivia);
|
|
}
|
|
Push((GreenNode)(object)token);
|
|
GreenNode leadingTrivia = token.GetLeadingTrivia();
|
|
if (leadingTrivia != null)
|
|
{
|
|
Push(leadingTrivia);
|
|
}
|
|
}
|
|
|
|
private void Push(GreenNode node)
|
|
{
|
|
if (_count >= _stack.Length)
|
|
{
|
|
NodeIteration[] array = new NodeIteration[_stack.Length * 2];
|
|
Array.Copy(_stack, array, _stack.Length);
|
|
_stack = array;
|
|
}
|
|
_stack[_count] = new NodeIteration(node);
|
|
_count++;
|
|
}
|
|
|
|
internal void Pop()
|
|
{
|
|
_count--;
|
|
}
|
|
|
|
internal bool Any()
|
|
{
|
|
return _count > 0;
|
|
}
|
|
|
|
internal void UpdateSlotIndexForStackTop(int slotIndex)
|
|
{
|
|
_stack[_count - 1].SlotIndex = slotIndex;
|
|
}
|
|
|
|
internal void UpdateDiagnosticIndexForStackTop(int diagnosticIndex)
|
|
{
|
|
_stack[_count - 1].DiagnosticIndex = diagnosticIndex;
|
|
}
|
|
}
|
|
|
|
private readonly SyntaxTree? _syntaxTree;
|
|
|
|
private NodeIterationStack _stack;
|
|
|
|
private Diagnostic? _current;
|
|
|
|
private int _position;
|
|
|
|
private const int DefaultStackCapacity = 8;
|
|
|
|
public Diagnostic Current => _current;
|
|
|
|
internal SyntaxTreeDiagnosticEnumerator(SyntaxTree syntaxTree, GreenNode? node, int position)
|
|
{
|
|
_syntaxTree = null;
|
|
_current = null;
|
|
_position = position;
|
|
if (node != null && node.ContainsDiagnostics)
|
|
{
|
|
_syntaxTree = syntaxTree;
|
|
_stack = new NodeIterationStack(8);
|
|
_stack.PushNodeOrToken(node);
|
|
}
|
|
else
|
|
{
|
|
_stack = default(NodeIterationStack);
|
|
}
|
|
}
|
|
|
|
public bool MoveNext()
|
|
{
|
|
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00cc: Expected O, but got Unknown
|
|
while (_stack.Any())
|
|
{
|
|
int diagnosticIndex = _stack.Top.DiagnosticIndex;
|
|
GreenNode node = _stack.Top.Node;
|
|
DiagnosticInfo[] diagnostics = node.GetDiagnostics();
|
|
if (diagnosticIndex < diagnostics.Length - 1)
|
|
{
|
|
diagnosticIndex++;
|
|
SyntaxDiagnosticInfo syntaxDiagnosticInfo = (SyntaxDiagnosticInfo)(object)diagnostics[diagnosticIndex];
|
|
int num = (node.IsToken ? node.GetLeadingTriviaWidth() : 0);
|
|
TextSpan fullSpan = _syntaxTree.GetRoot(default(CancellationToken)).FullSpan;
|
|
int length = ((TextSpan)(ref fullSpan)).Length;
|
|
int num2 = Math.Min(_position - num + syntaxDiagnosticInfo.Offset, length);
|
|
int num3 = Math.Min(num2 + syntaxDiagnosticInfo.Width, length) - num2;
|
|
_current = (Diagnostic?)(object)new CSDiagnostic((DiagnosticInfo)(object)syntaxDiagnosticInfo, (Location)new SourceLocation(_syntaxTree, new TextSpan(num2, num3)));
|
|
_stack.UpdateDiagnosticIndexForStackTop(diagnosticIndex);
|
|
return true;
|
|
}
|
|
int num4 = _stack.Top.SlotIndex;
|
|
while (true)
|
|
{
|
|
if (num4 < node.SlotCount - 1)
|
|
{
|
|
num4++;
|
|
GreenNode slot = node.GetSlot(num4);
|
|
if (slot != null)
|
|
{
|
|
if (slot.ContainsDiagnostics)
|
|
{
|
|
_stack.UpdateSlotIndexForStackTop(num4);
|
|
_stack.PushNodeOrToken(slot);
|
|
break;
|
|
}
|
|
_position += slot.FullWidth;
|
|
}
|
|
continue;
|
|
}
|
|
if (node.SlotCount == 0)
|
|
{
|
|
_position += node.Width;
|
|
}
|
|
_stack.Pop();
|
|
break;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|