diff --git a/src/Compilers/Core/Portable/Syntax/SyntaxNode.cs b/src/Compilers/Core/Portable/Syntax/SyntaxNode.cs
index ba5ab7ed1b3d..dc8bddd5e1dc 100644
--- a/src/Compilers/Core/Portable/Syntax/SyntaxNode.cs
+++ b/src/Compilers/Core/Portable/Syntax/SyntaxNode.cs
@@ -325,9 +325,9 @@ public virtual void WriteTo(TextWriter writer)
/// is not supported.
public SourceText GetText(Encoding? encoding = null, SourceHashAlgorithm checksumAlgorithm = SourceHashAlgorithm.Sha1)
{
- var builder = new StringBuilder(this.Green.FullWidth);
- this.WriteTo(new StringWriter(builder));
- return new StringBuilderText(builder, encoding, checksumAlgorithm);
+ var writer = SourceTextWriter.Create(encoding, checksumAlgorithm, this.Green.FullWidth);
+ this.WriteTo(writer);
+ return writer.ToSourceText();
}
///
diff --git a/src/Workspaces/CSharp/Portable/Workspace/LanguageServices/CSharpSyntaxTreeFactoryService.ParsedSyntaxTree.cs b/src/Workspaces/CSharp/Portable/Workspace/LanguageServices/CSharpSyntaxTreeFactoryService.ParsedSyntaxTree.cs
index 8a64e2ff7157..814853036893 100644
--- a/src/Workspaces/CSharp/Portable/Workspace/LanguageServices/CSharpSyntaxTreeFactoryService.ParsedSyntaxTree.cs
+++ b/src/Workspaces/CSharp/Portable/Workspace/LanguageServices/CSharpSyntaxTreeFactoryService.ParsedSyntaxTree.cs
@@ -48,8 +48,7 @@ public override SourceText GetText(CancellationToken cancellationToken)
{
if (_lazyText == null)
{
- var sourceText = SourceTextExtensions.CreateSourceText(GetRoot(cancellationToken), Encoding, _checksumAlgorithm, cancellationToken);
- Interlocked.CompareExchange(ref _lazyText, sourceText, null);
+ Interlocked.CompareExchange(ref _lazyText, GetRoot(cancellationToken).GetText(Encoding, _checksumAlgorithm), null);
}
return _lazyText;
diff --git a/src/Workspaces/Core/Portable/Shared/Extensions/SourceTextExtensions.cs b/src/Workspaces/Core/Portable/Shared/Extensions/SourceTextExtensions.cs
index 5b8433ec1ccc..1eef6e5b28e9 100644
--- a/src/Workspaces/Core/Portable/Shared/Extensions/SourceTextExtensions.cs
+++ b/src/Workspaces/Core/Portable/Shared/Extensions/SourceTextExtensions.cs
@@ -4,9 +4,7 @@
using System;
using System.Collections.Immutable;
-using System.Diagnostics;
using System.IO;
-using System.Linq;
using System.Text;
using System.Threading;
using Microsoft.CodeAnalysis.Host;
@@ -238,87 +236,6 @@ public static SourceText ReadFrom(ITextFactoryService textService, ObjectReader
return textService.CreateText(textReader, encoding, checksumAlgorithm, cancellationToken);
}
- public static SourceText CreateSourceText(
- SyntaxNode node, Encoding? encoding, SourceHashAlgorithm checksumAlgorithm, CancellationToken cancellationToken)
- {
- // If this node is small enough to not go into the LOH, we can just fast path directly to creating a SourceText from it.
- var totalLength = node.FullWidth();
- if (totalLength <= SourceTextLengthThreshold)
- return SourceText.From(node.ToFullString(), encoding, checksumAlgorithm);
-
- // Allocate the space to write the node into. Explicitly chunked so that nothing goes into the LOH.
- var chunks = CreateChunks(totalLength);
-
- // Write the node into that temp space.
- using var chunkWriter = new CharArrayChunkTextWriter(totalLength, chunks, encoding!, cancellationToken);
- node.WriteTo(chunkWriter);
- Contract.ThrowIfTrue(totalLength != chunkWriter.Position);
-
- // Call into the text service to make us a SourceText from the chunks. Disposal of this reader will free all
- // the intermediary chunks we allocated.
-
- Contract.ThrowIfTrue(chunks.Any(static (c, s) => c.Length != s, CharArrayLength));
-
- using var chunkReader = new CharArrayChunkTextReader(chunks, totalLength);
- var result = SourceText.From(chunkReader, totalLength, encoding, checksumAlgorithm);
- Contract.ThrowIfTrue(totalLength != chunkReader.Position);
-
- return result;
-
- static ImmutableArray CreateChunks(int totalLength)
- {
- var numberOfChunks = 1 + (totalLength / CharArrayLength);
- var buffer = new FixedSizeArrayBuilder(numberOfChunks);
- for (var i = 0; i < numberOfChunks; i++)
- buffer.Add(s_charArrayPool.Allocate());
-
- return buffer.MoveToImmutable();
- }
- }
-
- private static int GetIndexFromPosition(int position) => position / CharArrayLength;
- private static int GetColumnFromPosition(int position) => position % CharArrayLength;
-
- private sealed class CharArrayChunkTextWriter(
- int totalLength, ImmutableArray chunks, Encoding encoding, CancellationToken cancellationToken) : TextWriter
- {
- private readonly int _totalLength = totalLength;
- private readonly ImmutableArray _chunks = chunks;
- private readonly CancellationToken _cancellationToken = cancellationToken;
-
- ///
- /// Public so that caller can assert that writing out the text actually wrote out the full text of the node.
- ///
- public int Position { get; private set; }
-
- public override Encoding Encoding { get; } = encoding;
-
- public override void Write(string? value)
- {
- Contract.ThrowIfNull(value);
-
- var valueSpan = value.AsSpan();
- while (valueSpan.Length > 0)
- {
- _cancellationToken.ThrowIfCancellationRequested();
-
- var chunk = _chunks[GetIndexFromPosition(Position)];
- Contract.ThrowIfTrue(chunk.Length != CharArrayLength);
-
- var chunkIndex = GetColumnFromPosition(Position);
- Contract.ThrowIfTrue(chunkIndex >= CharArrayLength);
-
- var count = Math.Min(valueSpan.Length, CharArrayLength - chunkIndex);
- valueSpan[..count].CopyTo(chunk.AsSpan().Slice(chunkIndex, count));
-
- Position += count;
- valueSpan = valueSpan[count..];
- }
-
- Contract.ThrowIfTrue(Position > _totalLength);
- }
- }
-
private sealed class CharArrayChunkTextReader(ImmutableArray chunks, int length) : TextReaderWithLength(length)
{
private readonly ImmutableArray _chunks = chunks;
@@ -329,6 +246,9 @@ private sealed class CharArrayChunkTextReader(ImmutableArray chunks, int
///
public int Position { get; private set; }
+ private static int GetIndexFromPosition(int position) => position / CharArrayLength;
+ private static int GetColumnFromPosition(int position) => position % CharArrayLength;
+
public static TextReader CreateFromObjectReader(ObjectReader reader)
{
var length = reader.ReadInt32();
diff --git a/src/Workspaces/VisualBasic/Portable/Workspace/LanguageServices/VisualBasicSyntaxTreeFactoryService.ParsedSyntaxTree.vb b/src/Workspaces/VisualBasic/Portable/Workspace/LanguageServices/VisualBasicSyntaxTreeFactoryService.ParsedSyntaxTree.vb
index 751738b8b856..99b66db0d1bc 100644
--- a/src/Workspaces/VisualBasic/Portable/Workspace/LanguageServices/VisualBasicSyntaxTreeFactoryService.ParsedSyntaxTree.vb
+++ b/src/Workspaces/VisualBasic/Portable/Workspace/LanguageServices/VisualBasicSyntaxTreeFactoryService.ParsedSyntaxTree.vb
@@ -41,8 +41,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Public Overrides Function GetText(Optional cancellationToken As CancellationToken = Nothing) As SourceText
If _lazyText Is Nothing Then
- Dim text = SourceTextExtensions.CreateSourceText(GetRoot(cancellationToken), Encoding, _checksumAlgorithm, cancellationToken)
- Interlocked.CompareExchange(_lazyText, text, Nothing)
+ Interlocked.CompareExchange(_lazyText, GetRoot(cancellationToken).GetText(Encoding, _checksumAlgorithm), Nothing)
End If
Return _lazyText