Skip to content

Conversation

@ToddGrun
Copy link
Contributor

@ToddGrun ToddGrun commented Mar 31, 2025

This method is called once for each project in the solution during solution open, and each call was essentially switching to the main thread twice (once explicitly, once via call to _visualStudioWorkspaceImpl.RefreshProjectExistsUIContextForLanguageAsync). For my testing of opening Roslyn.sln, this removed over 600 main thread switches.

Instead:

  1. Move the first main thread switch to just occur once in an initialization task. This task is joined when CreateAndAddToWorkspaceAsync is invoked to ensure that that initialization is completed.
  2. Move the second main thread switch to instead only occur when the known uicontext state would have it's active state changed. This essentially only happens when opening the first or closing the last project for a language.

…dToWorkspaceAsync

This method is called once for each project in the solution during solution open, and each call was essentially switching to the main thread twice (once explicitly, once via call to _visualStudioWorkspaceImpl.RefreshProjectExistsUIContextForLanguageAsync). For my testing of opening Roslyn.sln, this removed over 600 main thread switches.

Instead:

1) Move the first main thread switch to just occur once in an initialization task. This task is joined when CreateAndAddToWorkspaceAsync is invoked to ensure that that initialization is completed.
2) Move the second main thread switch to instead move inside the callback from an ABWQ. The code being called needs the UI thread, but doesn't need to occur synchronously during the call to CreateAndAddToWorkspaceAsync.
@ToddGrun ToddGrun requested a review from CyrusNajmabadi March 31, 2025 20:14
@ToddGrun ToddGrun requested a review from a team as a code owner March 31, 2025 20:14
@ghost ghost added Area-IDE untriaged Issues and PRs which have not yet been triaged by a lead labels Mar 31, 2025
Copy link
Member

@jasonmalinowski jasonmalinowski left a comment

Choose a reason for hiding this comment

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

There's a bug around loading a different solution.

Comment on lines 86 to 91
// Since we're on the UI thread here anyways, use that as an opportunity to grab the
// IVsSolution object and solution file path.
var solution = await _solution2.GetValueOrNullAsync(cancellationToken).ConfigureAwait(true);
_solutionFilePath = solution != null && ErrorHandler.Succeeded(solution.GetSolutionInfo(out _, out var filePath, out _))
? filePath
: null;
Copy link
Member

Choose a reason for hiding this comment

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

This will only run once, which will break things badly if the user closes one solution and opens another. That said though, in the last few releases a bunch of the solution-loading mechanics in the shell were rewritten to be managed code, so maybe there's a free-threaded way to get this now. Or this could subscribe to an event and update it whenever that event fires.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm curious if this worked before, I'll test it out.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The GetSolutionInfo call would differ after the solution changed. Need to handle that better.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

IVsBackgroundSolution seems to work with the project types I've tested which allows obtaining the solution path off the main thread.

Comment on lines 138 to 139
// Ensure that other VS contexts get accurate information that the UIContext for this language is now active.
// This is not cancellable as we have already mutated the solution.
await _visualStudioWorkspaceImpl.RefreshProjectExistsUIContextForLanguageAsync(language, CancellationToken.None);
_uiContextUpdateWorkQueue.AddWork(language);
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure if asynchronously updating this will cause issues, or whether we had a (soft) guarantee that when we return the context would be set. But there might be an even better approach here: we only need to update the contexts when the number of projects will go from zero to non-zero during a load. Which in our case of loading Roslyn as a benchmark would be a grand total of two. So maybe a small tweak to simply have it realize the update isn't necessary in the first place might be even better.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It feels like the only way to know whether the update is necessary is to check the state of the UIContext, which would need to be done on the UI thread. It doesn't seem like just keeping track if we go to/from zero projects with the language name would handle cases where other code could change that UIContext's state.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not seeing where this is even used (other than tests). Is there somewhere with IVT that is using these flags?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@jasonmalinowski -- do you have a preference between:

  1. Loosen the requirement that uicontext.IsActive is set during CreateAndAddToWorkspaceAsync execution. Change the integration tests that look like they might rely on this to instead do a WaitForAllAsyncOperationsAsync.

  2. Change RefreshProjectExistsUIContextForLanguageAsync to assume that no one else changes the UIContext.IsActive state and have it set the value when the number of projects for a language switches to/from zero.

  3. Something else

I personally prefer 1 since I can't find any other users of these UIContexts, but I'm not too opinionated.

Copy link
Member

@jasonmalinowski jasonmalinowski Mar 31, 2025

Choose a reason for hiding this comment

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

The UI contexts are used for things like enabling/disabling commands, and also to help with other components that want to be able to ask "is there a C# project even there before I load up all my Roslyn support?" for things like test explorer. We're the only one who should be setting it so this assumption:

to assume that no one else changes the UIContext.IsActive state

Is completely fine to assume I'd say.

I'd be worried about weakening the support because it could have downstream ramifications -- package loads and such can trigger on UIContexts being changed, and delaying that on some time delay could break integration tests, including divisional tests.

Copy link
Member

Choose a reason for hiding this comment

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

That said, if 2 is hard to write, maybe 1 is just the easier option.

Copy link
Member

Choose a reason for hiding this comment

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

I missed this question:

Is there somewhere with IVT that is using these flags?

Anything can use the GUID for the context to ask if that context is active. I'm not sure if the GUIDs got formally documented but any other repo could have it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Tried out 2), let me know if you were thinking along a different line for it.

Note that only calls to CreateAndAddToWorkspaceAsync that will change the UIContext state wait for it to update before returning. Is this acceptable?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Note that only calls to CreateAndAddToWorkspaceAsync that will change the UIContext state wait for it to update before returning. Is this acceptable?

@jasonmalinowski -- this is my only remaining concern. Is this acceptable?

Copy link
Member

Choose a reason for hiding this comment

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

My apologies I had missed that question.

That is a potential concern. My worry about this was mostly if this could introduce flakiness to integration tests -- some integration test loads a project, and then does something that implicitly checks the UI context and then fails if this hasn't been updated yet.

What might work, instead of just doing SwitchToMainThread outside the lock, instead have a JoinableTaskCollection where we can add a task to; everything always waits for that collection to be empty before returning.

_visualStudioWorkspaceImpl.SubscribeExternalErrorDiagnosticUpdateSourceToSolutionBuildEvents();
_visualStudioWorkspaceImpl.SubscribeToSourceGeneratorImpactingEvents();

return await _vsixAnalyzerProviderFactory.GetOrCreateProviderAsync(cancellationToken).ConfigureAwait(true);
Copy link
Member

Choose a reason for hiding this comment

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

You could switch this to ConfigureAwait(false), as otherwise you're going to pay for a switch back to the UI thread just to do the return.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

full disclosure: I have a tendency to get CA calls wrong.

Given that, and that GetOrCreateProviderAsync does all it's work on the main thread, isn't a CA(true) here going to prevent a thread switch back to the thread pool? If it was CA(false), then it would be a switch back to the thread pool for sure, right?

{
(uiContext, var isContextActive) = _languageToProjectExistsUIContext.GetOrAdd(
language,
language => (Services.GetLanguageServices(language).GetService<IProjectExistsUIContextProviderLanguageService>()?.GetUIContext(), false));
Copy link
Member

Choose a reason for hiding this comment

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

Is fetching the UI context itself free-threaded? I feel like when this was originally written that wasn't the case.

Copy link
Member

Choose a reason for hiding this comment

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

(and if it's not, the fix is simple to just defer that bit to the UI thread...)

Copy link
Member

Choose a reason for hiding this comment

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

And also frankly now since we're avoiding unnecessary updates, you could just remove the UIContext from the map entirely, since we're only going to fetch it 'rarely'.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Although I do believe this is safe because of the comment linked to above, I do prefer your idea of just retrieving the UIContext while on the main thread, instead of caching it. It simplifies the data structures, and the removes the dependency that creating the ui context is free threaded.

Copy link
Member

@jasonmalinowski jasonmalinowski left a comment

Choose a reason for hiding this comment

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

Looks good, but let's double check that UIContext is safe to grab off the UI thread.

2) Update comment to reflect why a value calculated before a thread switch isn't used.
@ToddGrun
Copy link
Contributor Author

ToddGrun commented Apr 3, 2025

Changed to no longer cache the UIContext and just grab it while on the UI thread and it's needed.


In reply to: 2737437422

Comment on lines 138 to 139
// Ensure that other VS contexts get accurate information that the UIContext for this language is now active.
// This is not cancellable as we have already mutated the solution.
await _visualStudioWorkspaceImpl.RefreshProjectExistsUIContextForLanguageAsync(language, CancellationToken.None);
_uiContextUpdateWorkQueue.AddWork(language);
Copy link
Member

Choose a reason for hiding this comment

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

My apologies I had missed that question.

That is a potential concern. My worry about this was mostly if this could introduce flakiness to integration tests -- some integration test loads a project, and then does something that implicitly checks the UI context and then fails if this hasn't been updated yet.

What might work, instead of just doing SwitchToMainThread outside the lock, instead have a JoinableTaskCollection where we can add a task to; everything always waits for that collection to be empty before returning.

Copy link
Member

@jasonmalinowski jasonmalinowski left a comment

Choose a reason for hiding this comment

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

:shipit:


private async Task UpdateUIContextAsync(string language, CancellationToken cancellationToken)
{
await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(alwaysYield: true, cancellationToken);
Copy link
Member

Choose a reason for hiding this comment

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

Do we still want/need the alwaysYield: true? It does mean this will never run inline in RefreshProjectExistsUIContextForLanguageAsync, but does mean that we'll take an extra transition if we might have already been on the UI thread....

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'd prefer to keep it. I see this method always entered on a bg thread. I'd like to limit the amount of time that I'm holding onto _gate.

@ToddGrun ToddGrun merged commit 15e0c3c into dotnet:release/dev17.15 Apr 4, 2025
25 checks passed
@CyrusNajmabadi
Copy link
Member

i thought we weren't using dev17.15 anymore?

@ToddGrun
Copy link
Contributor Author

ToddGrun commented Apr 4, 2025

i thought we weren't using dev17.15 anymore?

whoops! Here's the PR for it to main: #77998

ToddGrun added a commit that referenced this pull request Apr 4, 2025
…dToWorkspaceAsync (#77920) (#77998)

* Reduce main thread switches in VisualStudioProjectFactory.CreateAndAddToWorkspaceAsync

This method is called once for each project in the solution during solution open, and each call was essentially switching to the main thread twice (once explicitly, once via call to _visualStudioWorkspaceImpl.RefreshProjectExistsUIContextForLanguageAsync). For my testing of opening Roslyn.sln, this removed over 600 main thread switches.

Instead:

1) Move the first main thread switch to just occur once in an initialization task. This task is joined when CreateAndAddToWorkspaceAsync is invoked to ensure that that initialization is completed.
2) Move the second main thread switch to instead move inside the callback from an ABWQ. The code being called needs the UI thread, but doesn't need to occur synchronously during the call to CreateAndAddToWorkspaceAsync.
333fred added a commit that referenced this pull request Apr 12, 2025
* Addressing feedback

* Addressing PR feedback

* Addressing PR comments

* Remove workaround for dotnet/msbuild#10306

The VS SDK was fixed, so the problem shouldn't occur anymore.

* move to a workspace factory

* No need for solution

* Simplify handlers

* Add helper

* move more over

* move more over

* Add remove calls

* Move handlers over

* Move remote service over

* async lock

* async lock

* async lock

* More work

* Fixup

* Correct

* Move to immutable dictionary

* in progress

* in progress

* in progress

* in progress

* in progress

* in progress

* Simplify

* Serialize

* simplify

* simplify

* simplify

* in progress

* in progress

* Reset code

* Clelar

* renames

* Simplify

* rename

* No more null

* Simplify

* Exception throwing

* Extensions: update feature status (#77923)

* Add ignored directives feature status (#77965)

* Extensions: misc checks on receiver parameter and extension members (#77937)

* Add porject back in

* CHange how locking works

* Simplify

* Docs

* Add new message for getting registered method names

* IN progres

* in progress

* Simplify

* Simplify

* Handle exceptions

* Simplify

* Docs

* move method

* Simplify and regions

* Tweaks

* Docs

* Break into files

* Simplify exception handling

* Simplify

* Simplify

* Move

* Docs

* Simplify

* Simplify

* Share code

* Split into local and remote calls

* Add throw

* Add throw

* Simplify

* Simplify

* Simplify

* Simplify

* Simplify

* Simplify

* Simplify

* Simplify

* Simplify

* Simplify

* Simplify

* Simplify

* Avoid potential disposal exception during MEF shutdown (#77990)

Previously, if VS was shutdown before Workspace.EnsureEventListeners was invoked, we would cause an exception during MEF disposal. This would happen because our workspace disposal would attempt to get a service that hadn't already been cached, and thus would ask MEF to compose the item during MEF disposal (which doesn't work).

Instead, just cache the IWorkspaceEventListenerService for use during the dispose.

* Remove unused elements form PublishData.json (#77994)

Removing some elements that seem to be left over from how the publish tooling used to work

* Reduce main thread switches in VisualStudioProjectFactory.CreateAndAddToWorkspaceAsync (#77920)

* Reduce main thread switches in VisualStudioProjectFactory.CreateAndAddToWorkspaceAsync

This method is called once for each project in the solution during solution open, and each call was essentially switching to the main thread twice (once explicitly, once via call to _visualStudioWorkspaceImpl.RefreshProjectExistsUIContextForLanguageAsync). For my testing of opening Roslyn.sln, this removed over 600 main thread switches.

Instead:

1) Move the first main thread switch to just occur once in an initialization task. This task is joined when CreateAndAddToWorkspaceAsync is invoked to ensure that that initialization is completed.
2) Move the second main thread switch to instead move inside the callback from an ABWQ. The code being called needs the UI thread, but doesn't need to occur synchronously during the call to CreateAndAddToWorkspaceAsync.

* Explicitly releasE

* Cancellation is fine

* Reorder

* remove net

* docs

* docs

* remove exception handling

* Add public api

* lint

* Reduce main thread switches in VisualStudioProjectFactory.CreateAndAddToWorkspaceAsync (#77920) (#77998)

* Reduce main thread switches in VisualStudioProjectFactory.CreateAndAddToWorkspaceAsync

This method is called once for each project in the solution during solution open, and each call was essentially switching to the main thread twice (once explicitly, once via call to _visualStudioWorkspaceImpl.RefreshProjectExistsUIContextForLanguageAsync). For my testing of opening Roslyn.sln, this removed over 600 main thread switches.

Instead:

1) Move the first main thread switch to just occur once in an initialization task. This task is joined when CreateAndAddToWorkspaceAsync is invoked to ensure that that initialization is completed.
2) Move the second main thread switch to instead move inside the callback from an ABWQ. The code being called needs the UI thread, but doesn't need to occur synchronously during the call to CreateAndAddToWorkspaceAsync.

* make nested

* Simplify

* Simplify

* Simplify

* Simplify

* Simplify

* restore

* Update dependencies from https://github.com/dotnet/source-build-reference-packages build 20250402.2 (#77982)

Microsoft.SourceBuild.Intermediate.source-build-reference-packages
 From Version 10.0.618101 -> To Version 10.0.620202

Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>

* Allow null

* Simplify

* No VoidResult

* Make everything non-capturing

* 'nameof(T<>)' not supported yet.

* Update references

* Revert "Another attempt to move MiscellaneousFilesWorkspace to a bg thread (#77983)

This reverts commit 2e8fcbe.

* fix

* Exception work

* Update Roslyn.sln

* More exception work

* Add remote end

* Complete the exception handling work

* Add docs

* docs

* Add docs

* Rename type

* Rename type

* update publishdata

* Change SolutionState.ProjectStates from an ImmutableDictionary<ProjectId, ProjectState> to an ImmutableArray<ProjectState> (#77971)

* *** WIP. Definitely needs supporting speedometer numbers before being considered ***

Change SolutionState to keep/expose and ImmutableArray<ProjectState> instead of an IReadOnlyList<ProjectId>

By exposing the project states, there is a bunch of code that can be changed to enumerate over that collection rather than over the values of an ImmutableDictionary<ProjectId, ProjectState>. That enumeration is actually *very* expensive.

For example, during roslyn load, local etl traces indicates the following CPU usage enumerating this dictionary:

Under ComputeDocumentIdsWithFilePath: 2.6 seconds
Under GetFirstRelatedDocumentId: 1.1 seconds

There is a bit of a tradeoff associated with this change. The IReadOnlyList<ProjectId> could be reused very often, whereas there is much less opportunity for sharing ImmutableArray<ProjectState> when forking the solution state. I expect there to be more memory allocated in the speedometer runs, so I'd like to get a feel on how much worse that is before elevating this PR out of draft status.

Additionally, SolutionState had a CWT over a sorted version of this IReadOnlyList<ProjectId>. As mentioned earlier, the sharing of this data is quite a bit less common now that it's an ImmutableArray<ProjectState>. I locally measured the stopwatch time spent always sorting this data in ComputeChecksumsAsync and it was a total of 4 ms (averaged over two separate VS runs) when loading the roslyn sln.

The ImmutableDictionary is still present in SolutionState, but it was renamed to indicate that it's primarily useful as a lookup tool, and all references treating it as an enumeration mechanism were changed to instead use the ImmutableArray<ProjectState>.

* Update dependencies from https://github.com/dotnet/source-build-reference-packages build 20250404.2 (#78008)

Microsoft.SourceBuild.Intermediate.source-build-reference-packages
 From Version 10.0.620202 -> To Version 10.0.620402

Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>

* Fix VSTypeScript lsp tests

* localize servicehub service name

* Simplify workspace initialization in the LSP server

Right now we have the logic for which analyzers get added to a workspace
in Program.cs, which calls a special method that specifically
initializes the main host workspace. This refactors it so that could
be used to initialize any workspace, and removes any tricky ordering
problems that might happen by using cleaner MEF imports when we have
them.

* Update test

* Update dependencies from https://github.com/dotnet/arcade build 20250404.5

Microsoft.SourceBuild.Intermediate.arcade , Microsoft.DotNet.Arcade.Sdk , Microsoft.DotNet.Helix.Sdk , Microsoft.DotNet.XliffTasks
 From Version 9.0.0-beta.25164.2 -> To Version 9.0.0-beta.25204.5

* Update maintenance-packages versions (#78005)

* Update maintenance-packages versions

* Update dependencies from https://github.com/dotnet/source-build-reference-packages build 20250404.2

Microsoft.SourceBuild.Intermediate.source-build-reference-packages
 From Version 10.0.620202 -> To Version 10.0.620402

* Address feedback

---------

Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>

* Fix EA layering for Razor.ExternalAccess (#77927)

Moves things to /Shared to ship in both MS.CA.EA.Razor and MS.CA.EA.Razor.Features

At some point we can rename MS.CA.EA.Razor to MS.CA.EA.Razor.EditorFeatures but I didn't bother with that in this PR
Shipping in both to not require dual insertion. We can fix this after a consuming change in Razor is inserted

* Delete

* Update PublishData.json after VS snap to rel/d17.14

* Handle nameof(indexer) in ref analysis (#78015)

* Make a couple of features non-experimental

* Ensure external access extensions package gets codebase

* Feedback

* Add extension message handler service teest

* Add extension message handler service test

* FIx

* Add testS

* In progress

* Test work

* Tests

* Add test

* More tests

* Add tests

* Add tests

* Add tests

* Add test

* Add test

* Add test

* Add test

* Add test

* Update comment

* Disable TransitiveVersioningPinning for RoslynAnalyzers.

* Remove dependency on EditorFeatures from lsp tests

* Remove dependency on EditorFeatures from codelens layer

* Update dependencies from https://github.com/dotnet/source-build-reference-packages build 20250407.2

Microsoft.SourceBuild.Intermediate.source-build-reference-packages
 From Version 10.0.620402 -> To Version 10.0.620702

* Remove dependency on EditorFeatures from build tools

* Update dependency versions

* Extensions: ref safety analysis (#77967)

* Update PublishData.json after VS span to main

* In progress

* Fix crash in backing field nullability cycle scenario (#77993)

* More work

* Pass along when an extension was unloaded

* Add teset

* Add tests

* Docs

* Simplify

* Using alias

* Fix

* Add tests

* Add docs

* Update gladstone/roslyn api

* Simplify channels in SemanticSearch

* Semantic Search: Add support for async queries and FAR tool (#77906)

* Simplify further

* Simplify further

* Localize exception messages

* Docs

* Docs

* Docs

* named args

* named args

* Docs

* Move type

* Docs

* Fix name

* Compile just for NET

* Unseal LSP types (#78041)

* Simplify analyzer api

* Update RoslynAnalyzer package projects with dependencies

This will fix issues with transitive pinning during source builds.

* Ensure LSP uses actual signature help trigger characters

* Improve detection of code whose updates may not have effect (#78009)

* Do not return metadata names for document symbols

* Fix nullability warnings

* Review feedback

* Remove EditorFeatures from OOP (#78069)

* Add back EA.Razor for servicing branches

publishdata is pulled from main always.  this needs to be present even though the package no longer exists for servicing branches

* Remove unused ISemanticSearchWorkspaceHost (#78083)

* Split query execution into compile and execute calls (#78081)

* Update resourceManagement.yml (#77948)

* Expression trees: support optional arguments and named arguments in parameter order (#77972)

* Update ignored directives public API (#77968)

* Remove experiment

* Add Content token to IgnoredDirectiveTriviaSyntax

* Add Content token to ShebangDirectiveTriviaSyntax

* Fixup public API

* Fixup semantic search API list

* Fix CLI flag in error message

* Remove Update API

* Update SemanticSearch API list

---------

Co-authored-by: Matteo Prosperi <maprospe@microsoft.com>
Co-authored-by: Jason Malinowski <jason.malinowski@microsoft.com>
Co-authored-by: Cyrus Najmabadi <cyrus.najmabadi@gmail.com>
Co-authored-by: Cyrus Najmabadi <cyrusn@microsoft.com>
Co-authored-by: Julien Couvreur <julien.couvreur@gmail.com>
Co-authored-by: Jan Jones <janjones@microsoft.com>
Co-authored-by: Matteo Prosperi <41970398+matteo-prosperi@users.noreply.github.com>
Co-authored-by: Todd Grunke <toddgrun@microsoft.com>
Co-authored-by: Jared Parsons <jared@paranoidcoding.org>
Co-authored-by: dotnet-maestro[bot] <42748379+dotnet-maestro[bot]@users.noreply.github.com>
Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com>
Co-authored-by: David Barbet <dabarbet@microsoft.com>
Co-authored-by: Carlos Sánchez López <1175054+carlossanlop@users.noreply.github.com>
Co-authored-by: Andrew Hall <andrha@microsoft.com>
Co-authored-by: Charles Stoner <10732005+cston@users.noreply.github.com>
Co-authored-by: Tomas Matousek <tomat@microsoft.com>
Co-authored-by: Joey Robichaud <jorobich@microsoft.com>
Co-authored-by: Rikki Gibson <rigibson@microsoft.com>
Co-authored-by: Tomáš Matoušek <tmat@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area-IDE untriaged Issues and PRs which have not yet been triaged by a lead

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants