Skip to content
This repository has been archived by the owner on Oct 4, 2021. It is now read-only.

[Ide] Consider MSBuild item conditions in Solution pad #9407

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

mrward
Copy link
Member

@mrward mrward commented Dec 2, 2019

Creating an ASP.NET Core project when .NET Core 3.1 SDK was installed
would result in .json files being displayed twice in the Solution pad.
.NET Core 3.1 SDK defines .json files twice.

<Content Include="**\*.json" ... Condition="'$(ExcludeConfigFilesFromBuildOutput)'!='true'" />

<Content Include="**\*.json" ... Condition="'$(ExcludeConfigFilesFromBuildOutput)'=='true'" />

Older .NET Core SDKs did not define the Content items more than once.
The Condition was not considered when showing files in the Solution
pad.

To support conditional files the Solution pad asks the project for
its visible files. The project uses the MSBuildEvaluationContext
to evaluate the condition to see if the file is visible or not.

Note that conditions on parent ItemGroups are currently not taken into
account. Also that visible files are not updated if the active config
is changed.

Out of scope for this change (to minimize changes for 8.4):

  • Handling ItemGroup definitions.
  • Changing visible files in the Solution pad on changing the active configuration.

Fixes VSTS #1005277 Create ASP.NET Core project, open Properties
folder, there are two launchSettings.json files.

@mrward
Copy link
Member Author

mrward commented Dec 2, 2019

@monojenkins backport release-8.4

get { return properties.Values; }
get {
lock (properties) {
return properties.Values.ToArray ();
Copy link
Contributor

Choose a reason for hiding this comment

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

:(

Copy link
Contributor

Choose a reason for hiding this comment

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

I guess there's no way to avoid this.

Copy link
Member Author

Choose a reason for hiding this comment

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

The ToArray part? I did also try ConcurrentDictionary but that broke a test. There is some code that relies on the order of the items in the dictionary which works when using Dictionary. Using the lock was a way to make sure the test did not fail.

Copy link
Member

Choose a reason for hiding this comment

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

Why do we need this collection to allow concurrency?

Copy link
Member Author

Choose a reason for hiding this comment

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

When testing this change I ran into an InvalidOperationException Collection was modified being thrown when getting the properties for a project configuration (ProjectConfiguration.Properties.GetProperties ()).

Adding a new file to the project saves the project and the project configuration properties are modified. Values are added and then removed (if they are to be merged up to the parent group) when OnWriteProjectHeader is called. If that save happens at the same time as another thread accesses the project configuration properties then the InvalidOperationException can occur.

Copy link
Member

Choose a reason for hiding this comment

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

So this InvalidOperationException is not really related to the changes you are doing, isn't it? If that's the case, it would be better to do them in a separate PR.

Copy link
Member Author

Choose a reason for hiding this comment

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

It looks to be related as far as I can see. The change made here, to look at the MSBuild condition, makes use of the project configuration properties on the UI thread and the first time I tested adding a file it triggered the InvalidOperationException resulting in no files being displayed in a folder in the Solution pad window. The comment on the second commit has the exception callstack I ran into - 78345ea

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 concerned about doing this change in 8.4, since it might have an important impact in performance.

@rodrmoya
Copy link
Contributor

rodrmoya commented Jan 3, 2020

@monojenkins rebase

Creating an ASP.NET Core project when .NET Core 3.1 SDK was installed
would result in .json files being displayed twice in the Solution pad.
.NET Core 3.1 SDK defines .json files twice.

    <Content Include="**\*.json" ... Condition="'$(ExcludeConfigFilesFromBuildOutput)'!='true'" />

    <Content Include="**\*.json" ... Condition="'$(ExcludeConfigFilesFromBuildOutput)'=='true'" />

Older .NET Core SDKs did not define the Content items more than once.
The Condition was not considered when showing files in the Solution
pad.

To support conditional files the Solution pad asks the project for
its visible files. The project uses the MSBuildEvaluationContext
to evaluate the condition to see if the file is visible or not.

Note that conditions on parent ItemGroups are currently not taken into
account. Also that visible files are not updated if the active config
is changed.

Fixes VSTS #1005277 Create ASP.NET Core project, open Properties
folder, there are two launchSettings.json files.
Adding a new .json file to a ASP.NET Core 3.1 project resulted in the
files not being displayed in the Properties folder due to the project
configuration's Properties being updated on a background thread on
saving and the UI thread reading these properties to determine if a
file is visible in the Solution pad. Switch to using a concurrent
dictionary in MSBuildPropertyGroupEvaluated.

System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
  at System.Collections.Generic.Dictionary`2+ValueCollection+Enumerator[TKey,TValue].MoveNext () [0x00085] in mono-x64/external/corefx/src/Common/src/CoreLib/System/Collections/Generic/Dictionary.cs:1628
  at MonoDevelop.Projects.MSBuild.MSBuildEvaluatedPropertyCollection+<MonoDevelop-Projects-IPropertySet-GetProperties>d__11.MoveNext () [0x0008e] in monodevelop/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.MSBuild/MSBuildPropertyGroupEvaluated.cs:207
  at MonoDevelop.Projects.Project+<GetVisibleFiles>d__143.MoveNext () [0x0017d] in monodevelop/main/src/core/MonoDevelop.Core/MonoDevelop.Projects/Project.cs:1231
  at MonoDevelop.Ide.Gui.Pads.ProjectPad.FolderNodeBuilder.GetFolderContent (MonoDevelop.Projects.Project project, System.String folder, System.Collections.Generic.List`1[MonoDevelop.Projects.ProjectFile]& files, System.Collections.Generic.List`1[System.String]& folders) [0x00149] in monodevelop/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/FolderNodeBuilder.cs:87
  at MonoDevelop.Ide.Gui.Pads.ProjectPad.FolderNodeBuilder.BuildChildNodes (MonoDevelop.Ide.Gui.Components.ITreeBuilder builder, System.Object dataObject) [0x00048] in monodevelop/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/FolderNodeBuilder.cs:74
  at MonoDevelop.Ide.Gui.Components.ExtensibleTreeView+TransactedTreeBuilder.FillNode () [0x00082] in monodevelop/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/TransactedTreeBuilder.cs:522
Using a ConcurrentDictionary broke the tests that rely on the items
being ordered in the Dictionary. The item definition test
ItemDefinitionGroup_AddFilesWithoutMetadata_MetadataUsesEmptyElements
failed due to the item definition properties being re-ordered. For
now using a lock around the Dictionary instead of a
ConcurrentDictionary.
Base automatically changed from master to main March 9, 2021 14:17
@akoeplinger akoeplinger changed the base branch from main to master March 15, 2021 17:01
Base automatically changed from master to main March 15, 2021 17:03
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants