Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check for missing hierarchies when mapping to Roslyn projects #19559

Merged
merged 2 commits into from
May 16, 2017

Conversation

tmeschter
Copy link
Contributor

@tmeschter tmeschter commented May 16, 2017

In order to shows the "Analyzers" node under the "References" node in
Solution Explorer and show the correct sets of analyzer assemblies and
diagnostics, we need to map the node for the project to the actual
Roslyn AbstractProject instance. This is done by matching up various
properties of the IVsHierarchy for the node to the same properties on
the IVsHierarchy returned by AbstractProject.Hierarchy.

This code path was initially written this Hierarchy property would
never return null; its value was supplied by the project system.
However, Delayed Project Load (DPL) bypasses the project system until
the user expands the project node in Solution Explorer, and as a result
we may now encounter AbstractProjects where Hierarchy returns null.
Currently if we run across one of these we'll throw a
NullReferenceException which has the end effect of preventing the
user from expanding the project node in Solution Explorer, and may even
result in a crash.

This commit adds in the null check. If the Hierarchy property is null
then it can't be the project we're looking for.

Customer scenario

Customer opens a solution with DPL enabled. When they expand a project node in Solution Explorer, nothing happens (the arrow indicates that the project is expanded, but nothing shows up under the project node).

Subsequently searching in Solution Explorer may lead to a crash.

Bugs this fixes:

Fixes #19517.

Workarounds, if any

Disable DPL for the solution.

Risk

Low; we're adding a null check that always should have been there.

Performance impact

Low; just the cost an additional null check when the user initially expands a project.

Is this a regression from a previous update?

Yes.

Root cause analysis:

This code path predates DPL, and until DPL the property in question couldn't be null. A subsequent refactoring to support the new project system made use of the property, but I didn't realize the null check was now necessary.

How was the bug found?

Internal customer report

Fixes dotnet#19517.

In order to shows the "Analyzers" node under the "References" node in
Solution Explorer and show the correct sets of analyzer assemblies and
diagnostics, we need to map the node for the project to the actual
Roslyn `AbstractProject` instance. This is done by matching up various
properties of the `IVsHierarchy` for the node to the same properties on
the `IVsHierarchy` returned by `AbstractProject.Hierarchy`.

This code path was initially written this `Hierarchy` property would
never return null; its value was supplied by the project system.
However, Delayed Project Load (DPL) bypasses the project system until
the user expands the project node in Solution Explorer, and as a result
we may now encounter `AbstractProjects` where `Hierarchy` returns null.
Currently if we run across one of these we'll throw a
`NullReferenceException` which has the end effect of preventing the
user from expanding the project node in Solution Explorer, and may even
result in a crash.

This commit adds in the null check. If the `Hierarchy` property is null
then it can't be the project we're looking for.
@tmeschter
Copy link
Contributor Author

@Pilchie @dotnet/roslyn-ide Please review.

@@ -62,7 +62,8 @@ public bool TryGetProjectId(IVsHierarchyItem hierarchyItem, string targetFramewo
// project files are in the same folder--they both use the full path to the _folder_ as the canonical
// name. To distinguish them we also examine the "regular" name, which will necessarily be different
// if the two projects are in the same folder.
if (p.Hierarchy.TryGetCanonicalName((uint)VSConstants.VSITEMID.Root, out string projectCanonicalName)
if (p.Hierarchy != null
Copy link
Member

Choose a reason for hiding this comment

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

Add a comment explaining when Hierarchy is null.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good idea.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@tmat Done.

Update the code comment to explain why we need to check for null.
Copy link
Member

@Pilchie Pilchie left a comment

Choose a reason for hiding this comment

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

Thanks!

@tmeschter
Copy link
Contributor Author

Adding @MattGertz for approval, pending tests.

@tmeschter
Copy link
Contributor Author

@dotnet-bot test windows_release_unit32_prtest please

@tmeschter tmeschter merged commit 96990d2 into dotnet:master May 16, 2017
@tmeschter tmeschter deleted the CheckForNullHierarchies branch May 16, 2017 21:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

NullReferenceException at SolutionExplorer.HierarchyItemToProjectIdMap.TryGetProjectId
5 participants