| File: Syntax\SyntaxNodeOrTokenListBuilder.cs | Web Access |
| Project: src\roslyn\src\Compilers\Core\Portable\Microsoft.CodeAnalysis.csproj (Microsoft.CodeAnalysis) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System; using System.Collections.Generic; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.Syntax { internal class SyntaxNodeOrTokenListBuilder { private GreenNode?[] _nodes; private int _count; public SyntaxNodeOrTokenListBuilder(int size) { _nodes = new GreenNode?[size]; _count = 0; } public static SyntaxNodeOrTokenListBuilder Create() { return new SyntaxNodeOrTokenListBuilder(8); } public int Count { get { return _count; } } public void Clear() { _count = 0; } public SyntaxNodeOrToken this[int index] { get { var innerNode = _nodes[index]; RoslynDebug.Assert(innerNode is object); if (innerNode.IsToken == true) { // getting internal token so we do not know the position return new SyntaxNodeOrToken(null, innerNode, 0, 0); } else { return innerNode.CreateRed(); } } set { _nodes[index] = value.UnderlyingNode; } } internal void Add(GreenNode item) { if (_count >= _nodes.Length) { this.Grow(_count == 0 ? 8 : _nodes.Length * 2); } _nodes[_count++] = item; } public void Add(SyntaxNode item) { this.Add(item.Green); } public void Add(in SyntaxToken item) { RoslynDebug.Assert(item.Node is object); this.Add(item.Node); } public void Add(in SyntaxNodeOrToken item) { RoslynDebug.Assert(item.UnderlyingNode is object); this.Add(item.UnderlyingNode); } public void Add(SyntaxNodeOrTokenList list) { this.Add(list, 0, list.Count); } public void Add(SyntaxNodeOrTokenList list, int offset, int length) { if (_count + length > _nodes.Length) { this.Grow(_count + length); } list.CopyTo(offset, _nodes, _count, length); _count += length; } public void Add(IEnumerable<SyntaxNodeOrToken> nodeOrTokens) { foreach (var n in nodeOrTokens) { this.Add(n); } } public void Add(ReadOnlySpan<SyntaxNodeOrToken> nodeOrTokens) { foreach (var n in nodeOrTokens) this.Add(n); } internal void RemoveLast() { _count--; _nodes[_count] = null; } private void Grow(int size) { var tmp = new GreenNode[size]; Array.Copy(_nodes, tmp, _nodes.Length); _nodes = tmp; } public SyntaxNodeOrTokenList ToList() { if (_count > 0) { switch (_count) { case 1: if (_nodes[0]!.IsToken) { return new SyntaxNodeOrTokenList( InternalSyntax.SyntaxList.List(new[] { _nodes[0]! }).CreateRed(), index: 0); } else { return new SyntaxNodeOrTokenList(_nodes[0]!.CreateRed(), index: 0); } case 2: return new SyntaxNodeOrTokenList( InternalSyntax.SyntaxList.List(_nodes[0]!, _nodes[1]!).CreateRed(), index: 0); case 3: return new SyntaxNodeOrTokenList( InternalSyntax.SyntaxList.List(_nodes[0]!, _nodes[1]!, _nodes[2]!).CreateRed(), index: 0); default: var tmp = new ArrayElement<GreenNode>[_count]; for (int i = 0; i < _count; i++) { tmp[i].Value = _nodes[i]!; } return new SyntaxNodeOrTokenList(InternalSyntax.SyntaxList.List(tmp).CreateRed(), index: 0); } } else { return default(SyntaxNodeOrTokenList); } } } }