Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove ItemCollection from CodeRenderingContext #10764

Merged
merged 24 commits into from
Aug 22, 2024

Conversation

DustinCampbell
Copy link
Member

@DustinCampbell DustinCampbell commented Aug 19, 2024

Because of a dare from @333fred, I'm currently on a crusade to remove ItemCollection from the Razor Compiler completely. Previously, I removed ItemCollection from TagHelperDescriptorProviderContext (#10720). This time, I'm removing it from CodeRenderingContext.

It turns out that every CodeRenderingContext greedily creates an ItemCollection, though there are only ever two things stored there:

  1. A string to use for new lines in CodeWriter.
  2. A string representing "suppress IDs", which is already specified in RazorCodeGenerationOptions.

These two items were really present as a hook that compiler tests could set. However, it's much easier and less wasteful to elevate both items to RazorCodeGenerationOptions and make tests set the options directly.

I made a few other refactorings as part of this change:

  • I merged several abstract base classes with their single default concrete type:
    • CodeRenderingContext and DefaultCodeRenderingContext
    • RazorCSharpDocument and DefaultRazorCSharpDocument,
    • RazorCodeGenerationOptions and DefaultRazorCodeGenerationOptions
    • RazorCodeGenerationOptionsBuilder and DefaultRazorCodeGenerationOptionsBuilder.
  • Reworked RazorCodeGenerationOptions and introduced RazorCodeGenerationOptionsFlags to track its boolean fields.
  • Cleaned up RazorCSharpDocument and unified its collections on ImmutableArray<> rather than IReadOnlyList<>.
  • Enabled nullability annotations for several types.
  • Used more pooled collections in CodeRenderingContext.

Note: I was careful with my commit history, and it should be clean enough to review commit-by-commit if that's your preference.

@DustinCampbell DustinCampbell requested review from a team as code owners August 19, 2024 23:47
Comment on lines -61 to -80
private static ImmutableArray<TResult> WrapAll<TInner, TResult>(IReadOnlyList<TInner> list, Func<TInner, TResult> createWrapper)
where TInner : class
where TResult : class
{
var count = list.Count;
if (count == 0)
{
return ImmutableArray<TResult>.Empty;
}

using var builder = new PooledArrayBuilder<TResult>(capacity: count);

for (var i = 0; i < count; i++)
{
builder.Add(createWrapper(list[i]));
}

return builder.DrainToImmutable();
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ After converting RazorCSharpDocument to an ImmutableArray<RazorDiagnostic>, this method is no longer used.

Copy link
Contributor

@davidwengier davidwengier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tooling ✅

@maryamariyan
Copy link
Member

Used more pooled collections in CodeRenderingContext

is it worth adding concurrency tests to make sure the usage is thread safe?

@DustinCampbell
Copy link
Member Author

Used more pooled collections in CodeRenderingContext

is it worth adding concurrency tests to make sure the usage is thread safe?

Razor compilation is generally synchronous and CodeRenderingContext shouldn't be accessed by more than a single thread. Also, nothing about CodeRenderingContext before this change was more or less thread safe than it is now. Is there a scenario that you're thinking might be problematic? Is there something related to pooled collections that you think might not be thread-safe? Note that acquiring and returning a collection from a pool is an inherently thread-safe operation.

Copy link
Contributor

@chsienki chsienki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Compiler side LGTM

@maryamariyan
Copy link
Member

Used more pooled collections in CodeRenderingContext

is it worth adding concurrency tests to make sure the usage is thread safe?
Razor compilation is generally synchronous and CodeRenderingContext shouldn't be accessed by more than a single thread. Also, nothing about CodeRenderingContext before this change was more or less thread safe than it is now. Is there a scenario that you're thinking might be problematic? Is there something related to pooled collections that you think might not be thread-safe? Note that acquiring and returning a collection from a pool is an inherently thread-safe operation.

it sounds like we don't need to worry about concurrency. I just wanted to double-check.

@DustinCampbell DustinCampbell merged commit 3423142 into dotnet:main Aug 22, 2024
12 checks passed
@DustinCampbell DustinCampbell deleted the remove-item-collection2 branch August 22, 2024 20:53
@DustinCampbell
Copy link
Member Author

Thanks all!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants