Skip to content

Commit 72d7998

Browse files
perf: use ValueListBuilder for PrivatePrintLeadingTrivia
1 parent 3f1753f commit 72d7998

File tree

3 files changed

+61
-28
lines changed

3 files changed

+61
-28
lines changed

Src/CSharpier/DocTypes/Doc.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,16 @@ public static Doc Concat(List<Doc> contents) =>
5656

5757
public static Doc Concat(params Doc[] contents) => new Concat(contents);
5858

59+
public static Doc Concat(ref ValueListBuilder<Doc> contents)
60+
{
61+
return contents.Length switch
62+
{
63+
0 => Null,
64+
1 => contents[0],
65+
_ => Concat(contents.ToList()),
66+
};
67+
}
68+
5969
public static Doc Join(Doc separator, IEnumerable<Doc> array)
6070
{
6171
var docs = new List<Doc>();

Src/CSharpier/SyntaxPrinter/Token.cs

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ private static Doc PrivatePrintLeadingTrivia(
233233
return Doc.Null;
234234
}
235235

236-
var docs = new List<Doc>();
236+
var docs = new ValueListBuilder<Doc>([null, null, null, null, null, null, null, null]);
237237

238238
// we don't print any new lines until we run into a comment or directive
239239
// the PrintExtraNewLines method takes care of printing the initial new lines for a given node
@@ -246,18 +246,18 @@ private static Doc PrivatePrintLeadingTrivia(
246246

247247
if (printNewLines && kind == SyntaxKind.EndOfLineTrivia)
248248
{
249-
if (docs.Count > 0 && docs[^1] == Doc.HardLineSkipBreakIfFirstInGroup)
249+
if (docs.Length > 0 && docs[^1] == Doc.HardLineSkipBreakIfFirstInGroup)
250250
{
251251
printNewLines = false;
252252
}
253-
docs.Add(Doc.HardLineSkipBreakIfFirstInGroup);
253+
docs.Append(Doc.HardLineSkipBreakIfFirstInGroup);
254254
}
255255
if (kind is not (SyntaxKind.EndOfLineTrivia or SyntaxKind.WhitespaceTrivia))
256256
{
257257
printNewLines = true;
258258
}
259259

260-
void AddLeadingComment(CommentType commentType)
260+
void AddLeadingComment(CommentType commentType, ref ValueListBuilder<Doc> docs)
261261
{
262262
var comment = trivia.ToFullString().TrimEnd('\n', '\r');
263263
if (
@@ -269,43 +269,43 @@ void AddLeadingComment(CommentType commentType)
269269
comment = leadingTrivia[x - 1] + comment;
270270
}
271271

272-
docs.Add(Doc.LeadingComment(comment, commentType));
272+
docs.Append(Doc.LeadingComment(comment, commentType));
273273
}
274274

275275
if (IsSingleLineComment(kind))
276276
{
277-
AddLeadingComment(CommentType.SingleLine);
278-
docs.Add(
277+
AddLeadingComment(CommentType.SingleLine, ref docs);
278+
docs.Append(
279279
kind == SyntaxKind.SingleLineDocumentationCommentTrivia
280280
? Doc.HardLineSkipBreakIfFirstInGroup
281281
: Doc.Null
282282
);
283283
}
284284
else if (IsMultiLineComment(kind))
285285
{
286-
AddLeadingComment(CommentType.MultiLine);
286+
AddLeadingComment(CommentType.MultiLine, ref docs);
287287
}
288288
else if (kind == SyntaxKind.DisabledTextTrivia)
289289
{
290-
docs.Add(Doc.Trim, trivia.ToString());
290+
docs.Append(Doc.Trim, trivia.ToString());
291291
}
292292
else if (IsRegion(kind))
293293
{
294294
var triviaText = trivia.ToString();
295-
docs.Add(Doc.HardLineIfNoPreviousLine);
296-
docs.Add(Doc.Trim);
297-
docs.Add(
295+
docs.Append(Doc.HardLineIfNoPreviousLine);
296+
docs.Append(Doc.Trim);
297+
docs.Append(
298298
kind == SyntaxKind.RegionDirectiveTrivia
299299
? Doc.BeginRegion(triviaText)
300300
: Doc.EndRegion(triviaText)
301301
);
302-
docs.Add(Doc.HardLine);
302+
docs.Append(Doc.HardLine);
303303
}
304304
else if (trivia.IsDirective)
305305
{
306306
var triviaText = trivia.ToString();
307307

308-
docs.Add(
308+
docs.Append(
309309
// adding two of these to ensure we get a new line when a directive follows a trailing comment
310310
Doc.HardLineIfNoPreviousLineSkipBreakIfFirstInGroup,
311311
Doc.HardLineIfNoPreviousLineSkipBreakIfFirstInGroup,
@@ -323,16 +323,16 @@ void AddLeadingComment(CommentType commentType)
323323
)
324324
{
325325
x++;
326-
docs.Add(Doc.HardLineSkipBreakIfFirstInGroup);
326+
docs.Append(Doc.HardLineSkipBreakIfFirstInGroup);
327327
}
328328
printNewLines = false;
329329
}
330330
}
331331
}
332332

333-
while (skipLastHardline && docs.Count != 0 && docs.Last() is HardLine or NullDoc)
333+
while (skipLastHardline && docs.Length != 0 && docs[^1] is HardLine or NullDoc)
334334
{
335-
docs.RemoveAt(docs.Count - 1);
335+
docs.Pop();
336336
}
337337

338338
if (context.State.NextTriviaNeedsLine)
@@ -343,7 +343,7 @@ void AddLeadingComment(CommentType commentType)
343343
}
344344
else
345345
{
346-
var index = docs.Count - 1;
346+
var index = docs.Length - 1;
347347
while (
348348
index >= 0
349349
&& (docs[index] is HardLine or LeadingComment || docs[index] == Doc.Null)
@@ -354,7 +354,7 @@ void AddLeadingComment(CommentType commentType)
354354
// this handles an edge case where we get here but already added the line
355355
// it relates to the fact that single line comments include new line directives
356356
if (
357-
index + 2 >= docs.Count
357+
index + 2 >= docs.Length
358358
|| !(docs[index + 1] is HardLine && docs[index + 2] is HardLine)
359359
)
360360
{
@@ -364,7 +364,7 @@ void AddLeadingComment(CommentType commentType)
364364
context.State.NextTriviaNeedsLine = false;
365365
}
366366

367-
return docs.Count > 0 ? Doc.Concat(docs) : Doc.Null;
367+
return docs.Length > 0 ? Doc.Concat(ref docs) : Doc.Null;
368368
}
369369

370370
private static bool IsSingleLineComment(SyntaxKind kind) =>

Src/CSharpier/Utilities/ValueListBuilder.cs

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -89,18 +89,19 @@ private void AppendMultiChar(scoped ReadOnlySpan<T> source)
8989
_pos += source.Length;
9090
}
9191

92-
public void Insert(int index, scoped ReadOnlySpan<T> source)
92+
public void Insert(int index, T item)
9393
{
94-
Debug.Assert(index == 0, "Implementation currently only supports index == 0");
95-
96-
if ((uint)(_pos + source.Length) > (uint)_span.Length)
94+
int pos = _pos;
95+
if ((uint)pos >= (uint)_span.Length)
9796
{
98-
Grow(source.Length);
97+
Grow(1);
9998
}
10099

101-
_span.Slice(0, _pos).CopyTo(_span.Slice(source.Length));
102-
source.CopyTo(_span);
103-
_pos += source.Length;
100+
var sp = _span;
101+
102+
_span.Slice(index, _pos - index).CopyTo(_span.Slice(index + 1));
103+
_span[index] = item;
104+
_pos += 1;
104105
}
105106

106107
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -141,11 +142,33 @@ private void AddWithResize(T item)
141142
_pos = pos + 1;
142143
}
143144

145+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
146+
public T Pop()
147+
{
148+
_pos--;
149+
return _span[_pos];
150+
}
151+
144152
public ReadOnlySpan<T> AsSpan()
145153
{
146154
return _span.Slice(0, _pos);
147155
}
148156

157+
public List<T> ToList()
158+
{
159+
var list = new List<T>(_pos);
160+
#if NETSTANDARD2_0
161+
foreach (var item in _span[.._pos])
162+
{
163+
list.Add(item);
164+
}
165+
#else
166+
list.AddRange(_span[.._pos]);
167+
#endif
168+
169+
return list;
170+
}
171+
149172
public bool TryCopyTo(Span<T> destination, out int itemsWritten)
150173
{
151174
if (_span.Slice(0, _pos).TryCopyTo(destination))

0 commit comments

Comments
 (0)