_From @FransBouma on August 4, 2017 8:28_
Repro: CSharpEditorRepro.zip
The attached repro case has two csproj files, one targeting NetFX and one targeting NetStandard2.0. The Netstandard2.0 project references the cs file from the NetFX project. While I know in theory one could use 'multi-targeting', for now I'm not using that due to tooling being in preview state and this allows me to build two artifacts without problems.
The issue is that when I open the C# file in the vs 2017 15.3 prev 7 editor, it will always pick the netstandard project in the top bar: you can't select the NetFX project version, even if you open that solution item. This is particularly problematic when there are conditional compilation directives present, like the one in the example.
If there's more info needed, let me know. :)
_Copied from original issue: dotnet/project-system#2691_
Repro #1:
Expected: For ReproNetFx to be "current context"
Actual: ReproNetStandard is "current context""
Repro #2:
Expected: For ReproNetFx to be "current context"
Actual: ReproNetStandard is "current context""
@Pilchie @dpoeschl Is this known or a regression?
There's definitely something wrong where it's getting stuck, but "Repro #2" reliably actually switches the context for me (the first time).
Anyway, I do not think this was known.
Also tagging @mavasani who looked at this last.
I reliably hit this problem in vs 15.3 but it has existed in previous versions too.
There is another report here: https://github.com/dotnet/roslyn/issues/21358.
@jinujoseph Given the feedback around this - can we please put this back into a milestone?
also reproted at https://devdiv.visualstudio.com/DevDiv/_workitems/edit/535853
also reported at link
There seems to be at least two bugs here:
First, when you try transferring from csproj.dll project to the netstandard project, we run
which correctly updates the netstandard project to point to the (one and only) target of it. But we then return immediately which means we skip the TransferItem call farther down in that function, and so the RDT still thinks we're owned by csproj.dll. When you try switching back to the csproj.dll owned project, we call TransferProject() but we never get an RDT event because the RDT didn't change, from its perspective. Beyond here things just get weird since state is all screwed up.
So fixing that's not so difficult, but there's a second bug too. If you double click in the csproj.dll-based project, you'll see the context appears as the netstandard project. It seems this is a bug that starts to go wrong here:
(although the problem is farther in the child functions). There we are taking a document and asking "are you an active context?" In the netstandard case we confirm that the stub hierarchy we have for our CPS project is owned by the parent "shared hierarchy" project, but we never stop to check that the shared hierarchy owns the document in the RDT. So we consider it to active in both projects and that ends strangely.
This code has evolved (and not in a good way) and it seems the approach really isn't the right one. We should be _starting_ with the RDT hierarchy, chasing it around accordingly, deciding which project is active, and then updating the workspace accordingly.
I'm not going to try a fix at the moment; I worry I'll be having to rewrite some of this soonish.
This is kind of a show stopper for us, as we have multiple shared projects and cannot switch to the context we need due to conditional symbols.
Having this problem too. Seemed to start after we added some net standard 2.0 projects which we didn't have before, in VS 2017 15.7.6.
So dotnet/roslyn#32313 is now merged, I _believe_ the Roslyn side of this is now fixed. It still appeared there were project system bugs too. I'll be confirming that in a bit and potentially moving bugs around.
Moving this now back to the project system. The one remaining bug I see here is if you mix Shared Asset Projects with multitargeting projects. Imagine you have three projects:
The shared asset project's IVsHierarchy has a property (VSHPROPID_SharedItemContextHierarchy) that Roslyn queries to know which context the files in the shared asset project should be in. When we are changing contexts from the regular csproj to the CPS project, we _set_ this property on the shared asset project to which project we're switching to. (Note we also set the property on the multitargeting project to specify which target is being used. For the purposes of discussion, we can ignore this.)
This ultimately results in this code being ran inside of the shared project support in CPS:
> Microsoft.VisualStudio.ProjectSystem.VS.Implementation.dll!Microsoft.VisualStudio.ProjectSystem.VS.Implementation.SharedProjectFilesPackage.SharedProjectFileNode.IsProjectAValidActiveContext(System.Tuple<Microsoft.VisualStudio.Shell.Interop.IVsHierarchy, System.Guid> sharedFileUserProject, bool reportIfNotValid) Line 1429 C#
Microsoft.VisualStudio.ProjectSystem.VS.Implementation.dll!Microsoft.VisualStudio.ProjectSystem.VS.Implementation.SharedProjectFilesPackage.SharedProjectFileNode.EnsureActiveContextIsValid(System.Tuple<Microsoft.VisualStudio.Shell.Interop.IVsHierarchy, System.Guid> newContextToChangeTo, bool reportIfNotValid, bool deferEventFiring) Line 1356 C#
Microsoft.VisualStudio.ProjectSystem.VS.Implementation.dll!Microsoft.VisualStudio.ProjectSystem.VS.Implementation.SharedProjectFilesPackage.SharedProjectFileManagerHierarchy.Microsoft.Internal.VisualStudio.Shell.Interop.IVsSharedMSBuildFilesManagerHierarchy.SetActiveContextForSharedMSBuildFile.AnonymousMethod__0() Line 774 C#
Microsoft.VisualStudio.Threading.dll!Microsoft.VisualStudio.Threading.JoinableTaskFactory.ExecuteJob<Microsoft.VisualStudio.Threading.EmptyStruct>(System.Func<System.Threading.Tasks.Task> asyncMethod, Microsoft.VisualStudio.Threading.JoinableTask job) Unknown
Microsoft.VisualStudio.Threading.dll!Microsoft.VisualStudio.Threading.JoinableTaskFactory.RunAsync(System.Func<System.Threading.Tasks.Task> asyncMethod, bool synchronouslyBlocking, Microsoft.VisualStudio.Threading.JoinableTaskCreationOptions creationOptions, System.Delegate entrypointOverride) Unknown
Microsoft.VisualStudio.ProjectSystem.Implementation.dll!Microsoft.VisualStudio.ProjectSystem.ProjectMultiThreadedService.ExecuteSynchronously(System.Func<System.Threading.Tasks.Task> asyncAction) Line 134 C#
Microsoft.VisualStudio.ProjectSystem.VS.Implementation.dll!Microsoft.VisualStudio.ProjectSystem.VS.Implementation.SharedProjectFilesPackage.SharedProjectFileManagerHierarchy.Microsoft.Internal.VisualStudio.Shell.Interop.IVsSharedMSBuildFilesManagerHierarchy.SetActiveContextForSharedMSBuildFile(string sharedFileFullPath, Microsoft.VisualStudio.Shell.Interop.IVsHierarchy activeContextHierarchy) Line 776 C#
Microsoft.VisualStudio.ProjectSystem.VS.Implementation.dll!Microsoft.VisualStudio.ProjectSystem.VS.Implementation.Package.ImportingProjectsService.SetSharedItemContextHierarchyAsync(Microsoft.VisualStudio.Shell.Interop.IVsHierarchy hierarchy) Line 207 C#
Microsoft.VisualStudio.ProjectSystem.VS.Implementation.dll!Microsoft.VisualStudio.ProjectSystem.VS.Implementation.Package.ProjectNode.SetProperty.AnonymousMethod__0() Line 1891 C#
In the CPS-consuming-shared-asset-projects case, the call to set the hierarchy property is "succeeding", but internally fails. This check inside of IsProjectAValidContext is failing:
else if (!this.RegisteredSharingProjectsByID.Keys.Contains(sharedFileUserProject.Item2))
{
// The projectID is not registered as a user of our shared MSBuild project file.
Report.If(
reportIfNotValid,
string.Format(CultureInfo.CurrentCulture, "ActiveContext project '{0:B}' is not a registered user of shared MSBuild project file '{1}'.", sharedFileUserProject.Item2, this.FullPath));
return false;
}
So it seems CPS isn't telling the shared asset project it's actually consuming from it. This is odd, because asking the CPS project which project is hosting the items does return the shared asset project. So the link is happening in one way, but not the other!
I also filed this bug internally where it seems once you close these solutions, there's a bunch of object disposed exceptions happening around shared asset projects. Something tells me this isn't being wired up right at all.
@jasonmalinowski I think this is a separate issue as I can reproduce these issues without multi-targetting and without regular csproj projects in the mix. Simply having two CPS projects both using a shared project means switching contexts doesn't work and results in the same "project X is not a registered user of shared MSBuild project file".
I will log a new issue for this, just need to work out if it goes here or CPS.
Logged https://devdiv.visualstudio.com/DevDiv/_workitems/edit/792775 for the remaining work.
@davidwengier That url isn't accessible. Why not log it here, as the system is OSS?
@FransBouma Unfortunately the repository where this fix needs to happen is not OSS, hence the internal work item.
Fortunately the original issue you reported (#2691) has been fixed in Roslyn with https://github.com/dotnet/roslyn/pull/32313 so should be available in the latest Visual Studio 2019 Preview. The new work item is for a separate issue to do with Shared Projects.
@davidwengier Ah, thanks for clearing that up! 馃槃
One of the most annoying issues I have in VS. Still occurring in 16.4.2.
We figured out the root cause for the remaining issues and this will be fixed in 16.5 Preview 3: https://github.com/dotnet/project-system/pull/5805.