Skip to content

Comments

Further clean up Roslyn's package load#80598

Merged
jasonmalinowski merged 4 commits intodotnet:mainfrom
jasonmalinowski:clean-up-package-load
Dec 5, 2025
Merged

Further clean up Roslyn's package load#80598
jasonmalinowski merged 4 commits intodotnet:mainfrom
jasonmalinowski:clean-up-package-load

Conversation

@jasonmalinowski
Copy link
Member

This simplifies our package initialization further, and moves more stuff off the UI thread when free-threaded alternatives exist. This PR is still a stepping stone to the ultimate goal which is we get rid of our PackageLoadTasks infrastructure since at this point there's very little left that needs it. But that will be a separate PR after this one.

Commit-at-a-time recommended for the individual changes.

@jasonmalinowski jasonmalinowski self-assigned this Oct 8, 2025
@jasonmalinowski jasonmalinowski requested a review from a team as a code owner October 8, 2025 23:33
base.RegisterInitializeAsyncWork(packageInitializationTasks);

packageInitializationTasks.AddTask(isMainThreadTask: false, task: PackageInitializationBackgroundThreadAsync);
packageInitializationTasks.AddTask(isMainThreadTask: true, task: PackageInitializationMainThreadAsync);
Copy link
Member Author

Choose a reason for hiding this comment

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

Woohoo! Nothing needed here anymore.

base.RegisterOnAfterPackageLoadedAsyncWork(afterPackageLoadedTasks);

afterPackageLoadedTasks.AddTask(isMainThreadTask: false, task: OnAfterPackageLoadedBackgroundThreadAsync);
afterPackageLoadedTasks.AddTask(isMainThreadTask: true, task: OnAfterPackageLoadedMainThreadAsync);
Copy link
Member Author

@jasonmalinowski jasonmalinowski Oct 8, 2025

Choose a reason for hiding this comment

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

This will be a follow-up to switch this to a background thread, since LoadComponentsInUIContextOnceSolutionFullyLoadedAsync is just waiting for a UIContext to be active before doing more background loading.

var registerEditors = await GetServiceAsync<SVsRegisterEditors, IVsRegisterEditors>(throwOnFailure: true, cancellationToken).ConfigureAwait(true);
Assumes.Present(registerEditors);

ErrorHandler.ThrowOnFailure(registerEditors.RegisterEditor(editorFactory.GetType().GUID, editorFactory, out _));
Copy link
Contributor

@ToddGrun ToddGrun Oct 9, 2025

Choose a reason for hiding this comment

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

RegisterEditor

Looks like this was made threadsafe a couple months ago, so this is nice!

Not related to this PR, but when looking this up, the first usage of RegisterEditor I found was still doing a main thread switch before calling RegisterEditor in VSCorePackage.InitializeAsync, which is a core package load sequence so I would have thought DavKean would have ensured it was changed already. Which makes me question whether I understand whether this is thread safe.

I guess I'm also a little confused why this RegisterEditorFactoryAsync isn't defined in the Shell's Package class. Maybe the additional public surface area wasn't worth it for getting the IVsRegisterEditors via GetServiceAsync?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, there really should be a method we can call here. FYI to @davkean for the other questions.

@jasonmalinowski
Copy link
Member Author

Running an internal validation build, this is breaking the product because this change assumes that CreateEditorFactories() is safe to call off the UI thread. TypeScript's is not and has a direct assertion to the contrary. Moving this to draft before somebody tries to merge this.

@jasonmalinowski jasonmalinowski marked this pull request as draft October 9, 2025 20:45
@jasonmalinowski
Copy link
Member Author

The TypeScript team is going to fix their editor factories to allow them to be created off the UI thread; once that's merged we'll go ahead with this change again.

@jasonmalinowski
Copy link
Member Author

TypeScript has inserted their changes and an internal validation run is clean; so this is unblocked. I'll still need to respond to the current code review feedback before marking this as ready for review.

The implementation now imports all the persisters lazily, so this
won't even have any benefit.
This can be done off the UI thread now.
This is free-threaded compared to asking IVsShell.
This isn't needed anymore since nothing on the main thread is still
consuming the ComponentModel.
@jasonmalinowski jasonmalinowski marked this pull request as ready for review December 4, 2025 22:48
@jasonmalinowski
Copy link
Member Author

This is now ready for review, and the draft feedback is responded to.

Copy link
Contributor

@ToddGrun ToddGrun left a comment

Choose a reason for hiding this comment

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

:shipit:

@jasonmalinowski jasonmalinowski merged commit 6dba733 into dotnet:main Dec 5, 2025
26 checks passed
@jasonmalinowski jasonmalinowski deleted the clean-up-package-load branch December 5, 2025 19:35
@dotnet-policy-service dotnet-policy-service bot added this to the Next milestone Dec 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants