Skip to content

Commit ff0359d

Browse files
authored
Use IVsSolution to look up IVsHierarchy by project GUID (#35746)
* Use IVsSolution to look up IVsHierarchy by project GUID * Fix * Fix mocks * Add missing file * Fix bad merge * Fix merge
1 parent 168eed0 commit ff0359d

17 files changed

Lines changed: 269 additions & 98 deletions

src/VisualStudio/CSharp/Impl/LanguageService/CSharpCodeCleanupFixer.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,10 @@ private async Task<bool> FixHierarchyContentAsync(IVsHierarchyCodeCleanupScope h
8383

8484
ProjectId projectId = null;
8585
if (ErrorHandler.Succeeded(hierarchy.GetProperty((uint)VSConstants.VSITEMID.Root, (int)__VSHPROPID8.VSHPROPID_ActiveIntellisenseProjectContext, out var contextProjectNameObject))
86-
&& contextProjectNameObject is string contextProjectName)
86+
&& contextProjectNameObject is string contextProjectName
87+
&& hierarchy.TryGetProjectGuid(out var projectGuid))
8788
{
88-
projectId = _workspace.GetProjectWithHierarchyAndName(hierarchy, contextProjectName)?.Id;
89+
projectId = _workspace.GetProjectWithGuidAndName(projectGuid, contextProjectName)?.Id;
8990
}
9091

9192
if (projectId is null)

src/VisualStudio/Core/Def/Implementation/AbstractEditorFactory.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
22

33
using System;
4+
using System.Diagnostics;
45
using System.IO;
56
using System.Runtime.InteropServices;
67
using System.Runtime.Versioning;
@@ -241,14 +242,15 @@ int IVsEditorFactoryNotify.NotifyDependentItemSaved(IVsHierarchy pHier, uint ite
241242
int IVsEditorFactoryNotify.NotifyItemAdded(uint grfEFN, IVsHierarchy pHier, uint itemid, string pszMkDocument)
242243
{
243244
// Is this being added from a template?
244-
if (((__EFNFLAGS)grfEFN & __EFNFLAGS.EFN_ClonedFromTemplate) != 0)
245+
if (((__EFNFLAGS)grfEFN & __EFNFLAGS.EFN_ClonedFromTemplate) != 0 &&
246+
pHier.TryGetProjectGuid(out var projectGuid))
245247
{
246248
var waitIndicator = _componentModel.GetService<IWaitIndicator>();
247249
// TODO(cyrusn): Can this be cancellable?
248250
waitIndicator.Wait(
249251
"Intellisense",
250252
allowCancel: false,
251-
action: c => FormatDocumentCreatedFromTemplate(pHier, itemid, pszMkDocument, c.CancellationToken));
253+
action: c => FormatDocumentCreatedFromTemplate(projectGuid, pszMkDocument, c.CancellationToken));
252254
}
253255

254256
return VSConstants.S_OK;
@@ -259,8 +261,10 @@ int IVsEditorFactoryNotify.NotifyItemRenamed(IVsHierarchy pHier, uint itemid, st
259261
return VSConstants.S_OK;
260262
}
261263

262-
private void FormatDocumentCreatedFromTemplate(IVsHierarchy hierarchy, uint itemid, string filePath, CancellationToken cancellationToken)
264+
private void FormatDocumentCreatedFromTemplate(Guid projectGuid, string filePath, CancellationToken cancellationToken)
263265
{
266+
Debug.Assert(projectGuid != Guid.Empty);
267+
264268
// A file has been created on disk which the user added from the "Add Item" dialog. We need
265269
// to include this in a workspace to figure out the right options it should be formatted with.
266270
// This requires us to place it in the correct project.
@@ -271,7 +275,7 @@ private void FormatDocumentCreatedFromTemplate(IVsHierarchy hierarchy, uint item
271275

272276
foreach (var projectId in solution.ProjectIds)
273277
{
274-
if (workspace.GetHierarchy(projectId) == hierarchy)
278+
if (workspace.GetProjectGuid(projectId) == projectGuid)
275279
{
276280
projectIdToAddTo = projectId;
277281
break;

src/VisualStudio/Core/Def/Implementation/Diagnostics/VisualStudioDiagnosticAnalyzerService.cs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,27 +28,30 @@ public VisualStudioDiagnosticAnalyzerService(VisualStudioWorkspace workspace, ID
2828
// *DO NOT DELETE*
2929
// This is used by Ruleset Editor from ManagedSourceCodeAnalysis.dll.
3030
public IReadOnlyDictionary<string, IEnumerable<DiagnosticDescriptor>> GetAllDiagnosticDescriptors(IVsHierarchy hierarchyOpt)
31+
=> GetAllDiagnosticDescriptors(hierarchyOpt != null && hierarchyOpt.TryGetProjectGuid(out var guid) ? guid : Guid.Empty);
32+
33+
private IReadOnlyDictionary<string, IEnumerable<DiagnosticDescriptor>> GetAllDiagnosticDescriptors(Guid projectGuid)
3134
{
32-
if (hierarchyOpt == null)
35+
if (projectGuid == Guid.Empty)
3336
{
3437
return Transform(_diagnosticService.CreateDiagnosticDescriptorsPerReference(projectOpt: null));
3538
}
3639

3740
// Analyzers are only supported for C# and VB currently.
38-
var projectsWithHierarchy = _workspace.CurrentSolution.Projects
41+
var projects = _workspace.CurrentSolution.Projects
3942
.Where(p => p.Language == LanguageNames.CSharp || p.Language == LanguageNames.VisualBasic)
40-
.Where(p => _workspace.GetHierarchy(p.Id) == hierarchyOpt);
43+
.Where(p => _workspace.GetProjectGuid(p.Id) == projectGuid);
4144

42-
if (projectsWithHierarchy.Count() <= 1)
45+
if (projects.Count() <= 1)
4346
{
44-
return Transform(_diagnosticService.CreateDiagnosticDescriptorsPerReference(projectsWithHierarchy.FirstOrDefault()));
47+
return Transform(_diagnosticService.CreateDiagnosticDescriptorsPerReference(projects.FirstOrDefault()));
4548
}
4649
else
4750
{
48-
// Multiple workspace projects map to the same hierarchy, return a union of descriptors for all projects.
51+
// Multiple workspace projects map to the same project guid, return a union of descriptors for all projects.
4952
// For example, this can happen for web projects where we create on the fly projects for aspx files.
5053
var descriptorsMap = ImmutableDictionary.CreateBuilder<string, IEnumerable<DiagnosticDescriptor>>();
51-
foreach (var project in projectsWithHierarchy)
54+
foreach (var project in projects)
5255
{
5356
var newDescriptorTuples = _diagnosticService.CreateDiagnosticDescriptorsPerReference(project);
5457
foreach (var kvp in newDescriptorTuples)

src/VisualStudio/Core/Def/Implementation/LanguageService/AbstractLanguageService`2.IVsContainedLanguageFactory.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
22

33
using System;
4+
using System.Diagnostics;
45
using System.Linq;
56
using System.Runtime.InteropServices;
67
using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem;
@@ -14,6 +15,8 @@ internal abstract partial class AbstractLanguageService<TPackage, TLanguageServi
1415
{
1516
private VisualStudioProject FindMatchingProject(IVsHierarchy hierarchy, uint itemid)
1617
{
18+
Debug.Assert(hierarchy != null);
19+
1720
// Here we must determine the project that this file's document is to be a part of.
1821
// Venus creates a separate Project for a .aspx or .ascx file, and so we must associate
1922
// the document with that Project. We first query through a Venus-specific interface,
@@ -60,7 +63,12 @@ private VisualStudioProject FindMatchingProject(IVsHierarchy hierarchy, uint ite
6063
return null;
6164
}
6265

63-
return this.Workspace.GetProjectWithHierarchyAndName(hierarchy, projectName);
66+
if (!hierarchy.TryGetProjectGuid(out var projectGuid))
67+
{
68+
return null;
69+
}
70+
71+
return Workspace.GetProjectWithGuidAndName(projectGuid, projectName);
6472
}
6573

6674
public int GetLanguage(IVsHierarchy hierarchy, uint itemid, IVsTextBufferCoordinator bufferCoordinator, out IVsContainedLanguage language)

src/VisualStudio/Core/Def/Implementation/ProjectSystem/Extensions/IVsHierarchyExtensions.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,15 @@ public static bool TryGetProject(this IVsHierarchy hierarchy, out EnvDTE.Project
5454
return hierarchy.TryGetProperty(__VSHPROPID.VSHPROPID_ExtObject, out project);
5555
}
5656

57+
public static Guid GetProjectGuid(this IVsHierarchy hierarchy)
58+
{
59+
ErrorHandler.ThrowOnFailure(hierarchy.GetGuidProperty(VSConstants.VSITEMID_ROOT, (int)__VSHPROPID.VSHPROPID_ProjectIDGuid, out var guid));
60+
return guid;
61+
}
62+
63+
public static bool TryGetProjectGuid(this IVsHierarchy hierarchy, out Guid guid)
64+
=> ErrorHandler.Succeeded(hierarchy.GetGuidProperty(VSConstants.VSITEMID_ROOT, (int)__VSHPROPID.VSHPROPID_ProjectIDGuid, out guid)) && guid != Guid.Empty;
65+
5766
public static bool TryGetName(this IVsHierarchy hierarchy, out string name)
5867
{
5968
return hierarchy.TryGetProperty(__VSHPROPID.VSHPROPID_Name, out name);

src/VisualStudio/Core/Def/Implementation/ProjectSystem/InvisibleEditor.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,16 +103,13 @@ private IVsProject TryGetProjectOfHierarchy(IVsHierarchy hierarchyOpt)
103103
return null;
104104
}
105105

106-
if (!ErrorHandler.Succeeded(hierarchyOpt.GetGuidProperty(
107-
(uint)VSConstants.VSITEMID.Root,
108-
(int)__VSHPROPID.VSHPROPID_ProjectIDGuid,
109-
out var projectId)))
106+
if (!hierarchyOpt.TryGetProjectGuid(out var projectGuid))
110107
{
111108
return null;
112109
}
113110

114111
var solution = (IVsSolution)_serviceProvider.GetService(typeof(SVsSolution));
115-
if (!ErrorHandler.Succeeded(solution.GetProjectOfGuid(projectId, out var projectHierarchy)))
112+
if (!ErrorHandler.Succeeded(solution.GetProjectOfGuid(projectGuid, out var projectHierarchy)))
116113
{
117114
return null;
118115
}

src/VisualStudio/Core/Def/Implementation/ProjectSystem/Legacy/AbstractLegacyProject.cs

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,7 @@ public AbstractLegacyProject(
8888
// projectSystemName because they'll have a better one eventually.
8989
AssemblyName = projectSystemName,
9090
FilePath = projectFilePath,
91-
Hierarchy = hierarchy,
92-
ProjectGuid = GetProjectIDGuid(hierarchy),
91+
ProjectGuid = hierarchy.GetProjectGuid(),
9392
});
9493

9594
((VisualStudioWorkspaceImpl)Workspace).AddProjectRuleSetFileToInternalMaps(
@@ -253,32 +252,6 @@ protected void RefreshBinOutputPath()
253252
}
254253
}
255254

256-
private static Guid GetProjectIDGuid(IVsHierarchy hierarchy)
257-
{
258-
if (hierarchy.TryGetGuidProperty(__VSHPROPID.VSHPROPID_ProjectIDGuid, out var guid))
259-
{
260-
return guid;
261-
}
262-
263-
return Guid.Empty;
264-
}
265-
266-
private static bool GetIsWebsiteProject(IVsHierarchy hierarchy)
267-
{
268-
try
269-
{
270-
if (hierarchy.TryGetProject(out var project))
271-
{
272-
return project.Kind == VsWebSite.PrjKind.prjKindVenusProject;
273-
}
274-
}
275-
catch (Exception)
276-
{
277-
}
278-
279-
return false;
280-
}
281-
282255
/// <summary>
283256
/// Map of folder item IDs in the workspace to the string version of their path.
284257
/// </summary>

src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioProjectCreationInfo.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ internal sealed class VisualStudioProjectCreationInfo
1111
public string FilePath { get; set; }
1212
public ParseOptions ParseOptions { get; set; }
1313

14-
public IVsHierarchy Hierarchy { get; set; }
1514
public Guid ProjectGuid { get; set; }
1615
}
1716
}

src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioProjectFactory.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public VisualStudioProject CreateAndAddToWorkspace(string projectSystemName, str
5252

5353
var assemblyName = creationInfo.AssemblyName ?? projectSystemName;
5454

55-
_visualStudioWorkspaceImpl.AddProjectToInternalMaps(project, creationInfo.Hierarchy, creationInfo.ProjectGuid, projectSystemName);
55+
_visualStudioWorkspaceImpl.AddProjectToInternalMaps(project, creationInfo.ProjectGuid, projectSystemName);
5656

5757
_visualStudioWorkspaceImpl.ApplyChangeToWorkspace(w =>
5858
{

src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioProjectTracker.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,6 @@ public void AddProject(AbstractProject project)
154154
{
155155
AssemblyName = project.AssemblyName,
156156
FilePath = project.ProjectFilePath,
157-
Hierarchy = project.Hierarchy,
158157
ProjectGuid = project.Guid,
159158
};
160159
project.VisualStudioProject = _projectFactory.CreateAndAddToWorkspace(project.ProjectSystemName, project.Language, creationInfo);

0 commit comments

Comments
 (0)