OLD | NEW |
| (Empty) |
1 /// Copyright (c) Microsoft Corporation. All rights reserved. | |
2 | |
3 using System; | |
4 using System.Collections.Generic; | |
5 using System.Diagnostics; | |
6 using System.IO; | |
7 using System.Runtime.InteropServices; | |
8 using Microsoft.VisualStudio; | |
9 using Microsoft.VisualStudio.Shell.Interop; | |
10 using IServiceProvider = System.IServiceProvider; | |
11 | |
12 namespace Microsoft.VisualStudio.Project | |
13 { | |
14 [CLSCompliant(false)] | |
15 public class SolutionListenerForProjectReferenceUpdate : SolutionListene
r | |
16 { | |
17 | |
18 #region ctor | |
19 public SolutionListenerForProjectReferenceUpdate(IServiceProvide
r serviceProvider) | |
20 : base(serviceProvider) | |
21 { | |
22 } | |
23 #endregion | |
24 | |
25 #region overridden methods | |
26 /// <summary> | |
27 /// Delete this project from the references of projects of this
type, if it is found. | |
28 /// </summary> | |
29 /// <param name="hierarchy"></param> | |
30 /// <param name="removed"></param> | |
31 /// <returns></returns> | |
32 public override int OnBeforeCloseProject(IVsHierarchy hierarchy,
int removed) | |
33 { | |
34 if(removed != 0) | |
35 { | |
36 List<ProjectReferenceNode> projectReferences = t
his.GetProjectReferencesContainingThisProject(hierarchy); | |
37 | |
38 foreach(ProjectReferenceNode projectReference in
projectReferences) | |
39 { | |
40 projectReference.Remove(false); | |
41 // Set back the remove state on the proj
ect refererence. The reason why we are doing this is that the OnBeforeUnloadProj
ect immedaitely calls | |
42 // OnBeforeCloseProject, thus we would b
e deleting references when we should not. Unload should not remove references. | |
43 projectReference.CanRemoveReference = tr
ue; | |
44 } | |
45 } | |
46 | |
47 return VSConstants.S_OK; | |
48 } | |
49 | |
50 | |
51 /// <summary> | |
52 /// Needs to update the dangling reference on projects that cont
ain this hierarchy as project reference. | |
53 /// </summary> | |
54 /// <param name="stubHierarchy"></param> | |
55 /// <param name="realHierarchy"></param> | |
56 /// <returns></returns> | |
57 public override int OnAfterLoadProject(IVsHierarchy stubHierarch
y, IVsHierarchy realHierarchy) | |
58 { | |
59 List<ProjectReferenceNode> projectReferences = this.GetP
rojectReferencesContainingThisProject(realHierarchy); | |
60 | |
61 // Refersh the project reference node. That should trigg
er the drawing of the normal project reference icon. | |
62 foreach(ProjectReferenceNode projectReference in project
References) | |
63 { | |
64 projectReference.CanRemoveReference = true; | |
65 | |
66 projectReference.OnInvalidateItems(projectRefere
nce.Parent); | |
67 } | |
68 | |
69 return VSConstants.S_OK; | |
70 } | |
71 | |
72 | |
73 public override int OnAfterRenameProject(IVsHierarchy hierarchy) | |
74 { | |
75 if(hierarchy == null) | |
76 { | |
77 return VSConstants.E_INVALIDARG; | |
78 } | |
79 | |
80 try | |
81 { | |
82 List<ProjectReferenceNode> projectReferences = t
his.GetProjectReferencesContainingThisProject(hierarchy); | |
83 | |
84 // Collect data that is needed to initialize the
new project reference node. | |
85 string projectRef; | |
86 ErrorHandler.ThrowOnFailure(this.Solution.GetPro
jrefOfProject(hierarchy, out projectRef)); | |
87 | |
88 object nameAsObject; | |
89 ErrorHandler.ThrowOnFailure(hierarchy.GetPropert
y(VSConstants.VSITEMID_ROOT, (int)__VSHPROPID.VSHPROPID_Name, out nameAsObject))
; | |
90 string projectName = (string)nameAsObject; | |
91 | |
92 string projectPath = String.Empty; | |
93 | |
94 IVsProject3 project = hierarchy as IVsProject3; | |
95 | |
96 if(project != null) | |
97 { | |
98 ErrorHandler.ThrowOnFailure(project.GetM
kDocument(VSConstants.VSITEMID_ROOT, out projectPath)); | |
99 projectPath = Path.GetDirectoryName(proj
ectPath); | |
100 } | |
101 | |
102 // Remove and re add the node. | |
103 foreach(ProjectReferenceNode projectReference in
projectReferences) | |
104 { | |
105 ProjectNode projectMgr = projectReferenc
e.ProjectMgr; | |
106 IReferenceContainer refContainer = proje
ctMgr.GetReferenceContainer(); | |
107 projectReference.Remove(false); | |
108 | |
109 VSCOMPONENTSELECTORDATA selectorData = n
ew VSCOMPONENTSELECTORDATA(); | |
110 selectorData.type = VSCOMPONENTTYPE.VSCO
MPONENTTYPE_Project; | |
111 selectorData.bstrTitle = projectName; | |
112 selectorData.bstrFile = projectPath; | |
113 selectorData.bstrProjRef = projectRef; | |
114 refContainer.AddReferenceFromSelectorDat
a(selectorData); | |
115 } | |
116 } | |
117 catch(COMException e) | |
118 { | |
119 return e.ErrorCode; | |
120 } | |
121 | |
122 return VSConstants.S_OK; | |
123 } | |
124 | |
125 | |
126 public override int OnBeforeUnloadProject(IVsHierarchy realHiera
rchy, IVsHierarchy stubHierarchy) | |
127 { | |
128 List<ProjectReferenceNode> projectReferences = this.GetP
rojectReferencesContainingThisProject(realHierarchy); | |
129 | |
130 // Refresh the project reference node. That should trigg
er the drawing of the dangling project reference icon. | |
131 foreach(ProjectReferenceNode projectReference in project
References) | |
132 { | |
133 projectReference.IsNodeValid = true; | |
134 projectReference.OnInvalidateItems(projectRefere
nce.Parent); | |
135 projectReference.CanRemoveReference = false; | |
136 projectReference.IsNodeValid = false; | |
137 projectReference.ReferencedProjectObject = null; | |
138 } | |
139 | |
140 return VSConstants.S_OK; | |
141 | |
142 } | |
143 | |
144 #endregion | |
145 | |
146 #region helper methods | |
147 private List<ProjectReferenceNode> GetProjectReferencesContainin
gThisProject(IVsHierarchy inputHierarchy) | |
148 { | |
149 List<ProjectReferenceNode> projectReferences = new List<
ProjectReferenceNode>(); | |
150 if(this.Solution == null || inputHierarchy == null) | |
151 { | |
152 return projectReferences; | |
153 } | |
154 | |
155 uint flags = (uint)(__VSENUMPROJFLAGS.EPF_ALLPROJECTS |
__VSENUMPROJFLAGS.EPF_LOADEDINSOLUTION); | |
156 Guid enumOnlyThisType = Guid.Empty; | |
157 IEnumHierarchies enumHierarchies = null; | |
158 | |
159 ErrorHandler.ThrowOnFailure(this.Solution.GetProjectEnum
(flags, ref enumOnlyThisType, out enumHierarchies)); | |
160 Debug.Assert(enumHierarchies != null, "Could not get lis
t of hierarchies in solution"); | |
161 | |
162 IVsHierarchy[] hierarchies = new IVsHierarchy[1]; | |
163 uint fetched; | |
164 int returnValue = VSConstants.S_OK; | |
165 do | |
166 { | |
167 returnValue = enumHierarchies.Next(1, hierarchie
s, out fetched); | |
168 Debug.Assert(fetched <= 1, "We asked one project
to be fetched VSCore gave more than one. We cannot handle that"); | |
169 if(returnValue == VSConstants.S_OK && fetched ==
1) | |
170 { | |
171 IVsHierarchy hierarchy = hierarchies[0]; | |
172 Debug.Assert(hierarchy != null, "Could n
ot retrieve a hierarchy"); | |
173 IReferenceContainerProvider provider = h
ierarchy as IReferenceContainerProvider; | |
174 if(provider != null) | |
175 { | |
176 IReferenceContainer referenceCon
tainer = provider.GetReferenceContainer(); | |
177 | |
178 Debug.Assert(referenceContainer
!= null, "Could not found the References virtual node"); | |
179 ProjectReferenceNode projectRefe
renceNode = GetProjectReferenceOnNodeForHierarchy(referenceContainer.EnumReferen
ces(), inputHierarchy); | |
180 if(projectReferenceNode != null) | |
181 { | |
182 projectReferences.Add(pr
ojectReferenceNode); | |
183 } | |
184 } | |
185 } | |
186 } while(returnValue == VSConstants.S_OK && fetched == 1)
; | |
187 | |
188 return projectReferences; | |
189 } | |
190 | |
191 private static ProjectReferenceNode GetProjectReferenceOnNodeFor
Hierarchy(IList<ReferenceNode> references, IVsHierarchy inputHierarchy) | |
192 { | |
193 if(references == null) | |
194 { | |
195 return null; | |
196 } | |
197 | |
198 Guid projectGuid; | |
199 ErrorHandler.ThrowOnFailure(inputHierarchy.GetGuidProper
ty(VSConstants.VSITEMID_ROOT, (int)__VSHPROPID.VSHPROPID_ProjectIDGuid, out proj
ectGuid)); | |
200 | |
201 string canonicalName; | |
202 ErrorHandler.ThrowOnFailure(inputHierarchy.GetCanonicalN
ame(VSConstants.VSITEMID_ROOT, out canonicalName)); | |
203 foreach(ReferenceNode refNode in references) | |
204 { | |
205 ProjectReferenceNode projRefNode = refNode as Pr
ojectReferenceNode; | |
206 if(projRefNode != null) | |
207 { | |
208 if(projRefNode.ReferencedProjectGuid ==
projectGuid) | |
209 { | |
210 return projRefNode; | |
211 } | |
212 | |
213 // Try with canonical names, if the proj
ect that is removed is an unloaded project than the above criteria will not pass
. | |
214 if(!String.IsNullOrEmpty(projRefNode.Url
) && NativeMethods.IsSamePath(projRefNode.Url, canonicalName)) | |
215 { | |
216 return projRefNode; | |
217 } | |
218 } | |
219 } | |
220 | |
221 return null; | |
222 | |
223 } | |
224 #endregion | |
225 } | |
226 } | |
OLD | NEW |