[Vsintegration] Show project references of SDK style projects in the Dependencies node - #2048
Merged
RobertvanderHulst merged 1 commit intoAug 12, 2026
Conversation
…Dependencies node The "Projects" node under "Dependencies" stayed empty when a solution with SDK style X# projects was opened. It only appeared after adding a project reference interactively, and was gone again after the next reload. No ProjectReferenceNode was created at all: - XSharpSdkProjectNode.Clean() strips the Project (guid) and Name metadata from every ProjectReference item before saving, so a saved .xsproj only contains <ProjectReference Include="..\Foo\Foo.xsproj" />. - XSharpReferenceContainerNode.CreateProjectReferenceNode() resolved guid and name for the SDK case but never wrote them to the project element. - The ProjectReferenceNode constructor deliberately skips the "invent a guid" fallback for SDK projects and then called new Guid(guidString) on an empty string inside a try/finally without a catch, so it threw FormatException. - ReferenceContainerNode.CreateReferenceNode() swallows that exception without logging and returns null, so the node silently disappeared. Because the "Projects" folder is only created when the first XSharpProjectReferenceNode is added, the whole folder was missing. - Adding a reference through the dialog uses the other constructor, which parses the guid from the bstrProjRef string, which is why that path worked. FixReferences(), which is supposed to complete these references once the solution has finished loading, had nothing left to iterate over. It was broken on its own as well: when the referenced project was found it never assigned refnodeGuid, so it always reported failure. - XSharpReferenceContainerNode: store the resolved guid and name on the in memory project element and resolve foreign projects via ProjectInfo / GetProjectGuid, the same way FixReferences() does. Clean() still keeps them out of the saved project file. Node creation is wrapped in try/catch with Logger.Exception so a failure can no longer drop a reference silently. - ProjectReferenceNode: tolerate a missing or malformed guid. The node is created with Guid.Empty and without a build dependency instead of throwing. Added UpdateReferencedProjectGuid() to attach the guid and the build dependency later and redraw the icon. - XSharpProjectNode.FixReferences(): use refnode.ProjectIDGuid when the referenced project is one of ours, resolve per node instead of skipping the remaining nodes after the first failure, push the guid into the node and log what stayed unresolved. - ProjectNode.BuildDependencies: do not register a ProjectInfo with an empty guid. It would be cached by url and would block the later resolution. - XSharpShellEvents: also complete incomplete references on OnAfterBackgroundSolutionLoadComplete. With deferred solution load not all projects exist yet when OnAfterOpenSolution fires. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The Projects node under Dependencies stayed empty when a solution with SDK style X# projects was opened. It only showed up after adding a project reference through the dialog, and was gone again after the next reload.
Root cause
No
ProjectReferenceNodewas created at all:XSharpSdkProjectNode.Clean()strips theProject(guid) andNamemetadata from everyProjectReferenceitem before saving, so a saved.xsprojcorrectly only contains<ProjectReference Include="..\Foo\Foo.xsproj" />.XSharpReferenceContainerNode.CreateProjectReferenceNode()resolvedguidandnamefor the SDK case — and then dropped both on the floor. Nothing was written to the project element.ProjectReferenceNode(ProjectNode, ProjectElement)constructor deliberately skips the "invent a random guid" fallback for SDK projects, and then callednew Guid(guidString)on an empty string inside atry/finallywith nocatch→FormatException.ReferenceContainerNode.CreateReferenceNode()swallows that exception (aDebug.WriteLineonly when a debugger is attached) and returnsnull.Projectsfolder is created lazily, on the firstXSharpProjectReferenceNodethat is added — so the whole folder was missing, not just the reference.Adding a reference interactively goes through the other constructor, which parses the guid out of the
bstrProjRefstring, which is why that path worked.FixReferences(), the mechanism meant to complete these references once the solution has finished loading, had nothing left to iterate over. It was broken on its own as well: when the referenced project was found (refnode != null) it never assignedrefnodeGuid, so it always reported failure.Changes
XSharpReferenceContainerNode— the SDK branch now stores the resolved guid and name on the in-memory project element, and resolves foreign / not-yet-loaded projects viaProjectInfo/GetProjectGuid, the same wayFixReferences()does.Clean()still keeps them out of the saved project file. Node creation is wrapped intry/catch+Logger.Exception, consistent with the siblingCreate*Nodemethods, so a failure can never silently drop a reference again.ProjectReferenceNode— tolerate a missing or malformed guid: the node is created withGuid.Emptyand without a build dependency instead of throwing, so it always appears in the hierarchy. AddedUpdateReferencedProjectGuid()to attach the guid and the build dependency later and redraw the icon.XSharpProjectNode.FixReferences()— userefnode.ProjectIDGuidwhen the referenced project is one of ours; resolve per node instead of skipping the remaining nodes after the first failure; push the resolved guid into the node; log what stayed unresolved.ProjectNode.BuildDependencies— do not register aProjectInfowith an empty guid. It is cached by url and would block the later resolution of the real guid.XSharpShellEvents— also complete incomplete references onOnAfterBackgroundSolutionLoadComplete. With deferred solution load not all projects exist yet whenOnAfterOpenSolutionfires.Notes for reviewers
Project/Namemetadata does not reach the project file:ProjectNode.Save()callsBeforeSave()→XSharpSdkProjectNode.Clean(), which removes it, andSave()restores it afterwards viaRestoreProperties().Reload()clears the dirty flag in itsfinally, so writing the metadata duringProcessReferences()does not leave the project dirty.ProjectPackage2022builds clean. The VS2019 variant (ProjectPackage.csproj) does not build in my working tree, but that is pre-existing and unrelated — NuGet restore fornet472plus missingCommunity.VisualStudio.Toolkittypes inSupport.csproj/Logger.cs, files this PR does not touch.🤖 Generated with Claude Code