Skip to content

Force load active configured projects#3032

Merged
davkean merged 10 commits intodotnet:masterfrom
davkean:ForceConfiguredProjects
Dec 18, 2017
Merged

Force load active configured projects#3032
davkean merged 10 commits intodotnet:masterfrom
davkean:ForceConfiguredProjects

Conversation

@davkean
Copy link
Copy Markdown
Member

@davkean davkean commented Dec 8, 2017

(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 ConfiguredProjectAutoLoad services are created and run.

This is the equivalent, except for all configurations that we consider "active". For example 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

These configurations are explicitly loaded:

              Debug |   AnyCPU  |           net45
              Debug |   AnyCPU  |           net46

When active solution configuration changes to:

            Release |   AnyCPU

These configurations are explicitly loaded:

            Release |   AnyCPU  |           net45
            Release |   AnyCPU  |           net46

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.

@davkean
Copy link
Copy Markdown
Member Author

davkean commented Dec 8, 2017

tag @lifengl as per discussed today.

Tests are coming.

@davkean davkean changed the title Force load configured projects Force load active configured projects Dec 8, 2017
Copy link
Copy Markdown
Member Author

@davkean davkean Dec 8, 2017

Choose a reason for hiding this comment

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

@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

@davkean davkean requested a review from a team December 8, 2017 06:13
@Pilchie
Copy link
Copy Markdown
Member

Pilchie commented Dec 13, 2017

Note that @lifengl is on vacation right now.

This change looks okay to me, but waiting for tests.

@davkean
Copy link
Copy Markdown
Member Author

davkean commented Dec 13, 2017

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.
@davkean davkean force-pushed the ForceConfiguredProjects branch from dbfad6e to 4faca5e Compare December 14, 2017 03:05
@davkean
Copy link
Copy Markdown
Member Author

davkean commented Dec 14, 2017

@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.

@lifengl
Copy link
Copy Markdown
Contributor

lifengl commented Dec 14, 2017 via email

}

public ITargetBlock<IProjectVersionedValue<IConfigurationGroup<ProjectConfiguration>>> TargetBlock
{
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

not => _targetBlock;

foreach (ProjectConfiguration configuration in e.Value)
{
await _project.LoadConfiguredProjectAsync(configuration)
.ConfigureAwait(false);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What is the threading here? Worth fanning out and doing a Task.WhenAll() instead?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yeah, after submitted this - had a similar thought, but wondered about competition for the UI thread. @lifengl Thoughts?

@davkean
Copy link
Copy Markdown
Member Author

davkean commented Dec 14, 2017

@lifengl

When a new configuration is added, this code won’t run to see whether to load it. Will that be handled by some other code?

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.

Should we protect or stop loading configured projects when the project is unloaded in the middle?

Yeah, that's a good concern.

Or is it possible that a configuration it planned to load was removed in another thread?

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 => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I believe we want the { on its own line

[AppliesTo(ProjectCapability.CSharpOrVisualBasicOrFSharpLanguageService)]
public Task InitializeAsync()
{
Initialize();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should probably use EnsureInitialized()

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Nice catch.

- Stop loading configs while unloading
- Stop unload from occuring while in the middle of loading a config
@davkean
Copy link
Copy Markdown
Member Author

davkean commented Dec 15, 2017

Updated the PR to address comments.

  • Now stop loading configs if the project starts unloading and prevent unloading while loading a config.
  • Fixed the double-initialization
  • Few style things

A couple of things;

  • Don't understand this "When a new configuration is added, this code won’t run to see whether to load it. Will that be handled by some other code?" I suspect you are referring to the fact that we don't add/remove configs when the project is loaded? If so, yes - we need to make sure CPS has the right call backs to enable that. I'm going to open a new bug for that, post 15.6.
  • Don't overlap loading of configs. Wouldn't mind Lifeng to chime in with thoughts around this.
  • Don't handle when a configuration is removed. I suspect here long term we should unload unused/remove configs (that would clean up the novariables as well).

@davkean davkean merged commit b65f6af into dotnet:master Dec 18, 2017
@davkean davkean deleted the ForceConfiguredProjects branch December 18, 2017 03:28
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.

7 participants