Force load active configured projects#3032
Conversation
|
tag @lifengl as per discussed today. Tests are coming. |
There was a problem hiding this comment.
@lifengl This looks like the right time to do this - just after we've flowed the configured project capabilities -> unconfigured project. I could go this or AfterLoadInitialConfiguration
|
Note that @lifengl is on vacation right now. This change looks okay to me, but waiting for tests. |
|
Tests are coming, it took me about 2 hours to figure out how to Moq dataflow. |
CPS force loads the active configuration during project initialization and when the active configuration changes. This ensures that any ConfiguredProjectAutoLoad services are created and run.
This is the equivalent, except for all configurations that we consider "active". In the following multi-targeted project:
-> All known project configurations:
Configuration Platform TargetFramework
-------------------------------------------
Debug | AnyCPU | net45
Debug | AnyCPU | net46
Release | AnyCPU | net45
Release | AnyCPU | net46
-> Active solution configuration:
Debug | AnyCPU | net45
These configurations are explicitly loaded:
Debug | AnyCPU | net45
Debug | AnyCPU | net46
Previously, these configurations were implicitly loaded when an auto-load component (typically language service) happend to call through IActiveConfiguredProjectsProvider. This makes loading of configurations deliberate and explicit, and always occur regardless of auto-load component that is run.
We don't need to Dispose on a background thread as we don't hold any locks in Dispose.
dbfad6e to
4faca5e
Compare
|
@Pilchie Pushed tests. Note I've slightly changed the implementation to make it test consumable (TargetBlock needs to be public so that I can await on Completion) and I now await all Loads so that any exceptions don't get lost, fault the block and NFW. |
| } | ||
|
|
||
| public ITargetBlock<IProjectVersionedValue<IConfigurationGroup<ProjectConfiguration>>> TargetBlock | ||
| { |
| foreach (ProjectConfiguration configuration in e.Value) | ||
| { | ||
| await _project.LoadConfiguredProjectAsync(configuration) | ||
| .ConfigureAwait(false); |
There was a problem hiding this comment.
What is the threading here? Worth fanning out and doing a Task.WhenAll() instead?
There was a problem hiding this comment.
Yeah, after submitted this - had a similar thought, but wondered about competition for the UI thread. @lifengl Thoughts?
When a new config is added, and it is considered active - I would expect to get callback here. I only want to load active configs, nothing else.
Yeah, that's a good concern.
Hmm, let me play around with what happens in that case. |
| var configurationGroups = IConfigurationGroupFactory.CreateFromConfigurationNames(configurationNames); | ||
|
|
||
| var results = new List<string>(); | ||
| var project = UnconfiguredProjectFactory.ImplementLoadConfiguredProjectAsync(configuration => { |
There was a problem hiding this comment.
I believe we want the { on its own line
| [AppliesTo(ProjectCapability.CSharpOrVisualBasicOrFSharpLanguageService)] | ||
| public Task InitializeAsync() | ||
| { | ||
| Initialize(); |
There was a problem hiding this comment.
Should probably use EnsureInitialized()
- Stop loading configs while unloading - Stop unload from occuring while in the middle of loading a config
|
Updated the PR to address comments.
A couple of things;
|
(this depends on and includes #3020, just look at the last commit)
CPS always force loads the active configuration during project initialization and when the active configuration changes. This makes sure that any
ConfiguredProjectAutoLoadservices are created and run.This is the equivalent, except for all configurations that we consider "active". For example in the following multi-targeted project:
These configurations are explicitly loaded:
When active solution configuration changes to:
These configurations are explicitly loaded:
Previously, these configurations were implicitly loaded when an auto-load component (typically language service) happened to call through IActiveConfiguredProjectsProvider. This makes loading of configurations deliberate and explicit, and always occur regardless of the auto-load component that is run.
This basically moves loading these configs from implicit model when a random component calls IActiveConfiguredProjectsProvider.GetActiveConfiguredProjectsAsync (which is being replaced) to a more explicit and predictable model.