Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(224)

Side by Side Diff: experimental/visual_studio_plugin/third_party/Microsoft.VisualStudio.Project/ProjectReferenceNode.cs

Issue 10928195: First round of dead file removal (Closed) Base URL: https://github.com/samclegg/nativeclient-sdk.git@master
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /// Copyright (c) Microsoft Corporation. All rights reserved.
2
3 using System;
4 using System.Diagnostics;
5 using System.Globalization;
6 using System.IO;
7 using System.Runtime.InteropServices;
8 using Microsoft.VisualStudio;
9 using Microsoft.VisualStudio.Shell;
10 using Microsoft.VisualStudio.Shell.Interop;
11
12 namespace Microsoft.VisualStudio.Project
13 {
14 [CLSCompliant(false), ComVisible(true)]
15 public class ProjectReferenceNode : ReferenceNode
16 {
17 #region fieds
18 /// <summary>
19 /// The name of the assembly this refernce represents
20 /// </summary>
21 private Guid referencedProjectGuid;
22
23 private string referencedProjectName = String.Empty;
24
25 private string referencedProjectRelativePath = String.Empty;
26
27 private string referencedProjectFullPath = String.Empty;
28
29 private BuildDependency buildDependency;
30
31 /// <summary>
32 /// This is a reference to the automation object for the referen ced project.
33 /// </summary>
34 private EnvDTE.Project referencedProject;
35
36 /// <summary>
37 /// This state is controlled by the solution events.
38 /// The state is set to false by OnBeforeUnloadProject.
39 /// The state is set to true by OnBeforeCloseProject event.
40 /// </summary>
41 private bool canRemoveReference = true;
42
43 /// <summary>
44 /// Possibility for solution listener to update the state on the dangling reference.
45 /// It will be set in OnBeforeUnloadProject then the nopde is in validated then it is reset to false.
46 /// </summary>
47 private bool isNodeValid;
48
49 #endregion
50
51 #region properties
52
53 public override string Url
54 {
55 get
56 {
57 return this.referencedProjectFullPath;
58 }
59 }
60
61 public override string Caption
62 {
63 get
64 {
65 return this.referencedProjectName;
66 }
67 }
68
69 internal Guid ReferencedProjectGuid
70 {
71 get
72 {
73 return this.referencedProjectGuid;
74 }
75 }
76
77 /// <summary>
78 /// Possiblity to shortcut and set the dangling project referenc e icon.
79 /// It is ussually manipulated by solution listsneres who handle reference updates.
80 /// </summary>
81 internal protected bool IsNodeValid
82 {
83 get
84 {
85 return this.isNodeValid;
86 }
87 set
88 {
89 this.isNodeValid = value;
90 }
91 }
92
93 /// <summary>
94 /// Controls the state whether this reference can be removed or not. Think of the project unload scenario where the project reference should not be deleted.
95 /// </summary>
96 internal bool CanRemoveReference
97 {
98 get
99 {
100 return this.canRemoveReference;
101 }
102 set
103 {
104 this.canRemoveReference = value;
105 }
106 }
107
108 internal string ReferencedProjectName
109 {
110 get { return this.referencedProjectName; }
111 }
112
113 /// <summary>
114 /// Gets the automation object for the referenced project.
115 /// </summary>
116 internal EnvDTE.Project ReferencedProjectObject
117 {
118 get
119 {
120 // If the referenced project is null then re-rea d.
121 if(this.referencedProject == null)
122 {
123
124 // Search for the project in the collect ion of the projects in the
125 // current solution.
126 EnvDTE.DTE dte = (EnvDTE.DTE)this.Projec tMgr.GetService(typeof(EnvDTE.DTE));
127 if((null == dte) || (null == dte.Solutio n))
128 {
129 return null;
130 }
131 foreach(EnvDTE.Project prj in dte.Soluti on.Projects)
132 {
133 //Skip this project if it is an umodeled project (unloaded)
134 if(string.Compare(EnvDTE.Constan ts.vsProjectKindUnmodeled, prj.Kind, StringComparison.OrdinalIgnoreCase) == 0)
135 {
136 continue;
137 }
138
139 // Get the full path of the curr ent project.
140 EnvDTE.Property pathProperty = n ull;
141 try
142 {
143 pathProperty = prj.Prope rties.Item("FullPath");
144 if(null == pathProperty)
145 {
146 // The full path should alway be availabe, but if this is not the
147 // case then we have to skip it.
148 continue;
149 }
150 }
151 catch(ArgumentException)
152 {
153 continue;
154 }
155 string prjPath = pathProperty.Va lue.ToString();
156 EnvDTE.Property fileNameProperty = null;
157 // Get the name of the project f ile.
158 try
159 {
160 fileNameProperty = prj.P roperties.Item("FileName");
161 if(null == fileNamePrope rty)
162 {
163 // Again, this s hould never be the case, but we handle it anyway.
164 continue;
165 }
166 }
167 catch(ArgumentException)
168 {
169 continue;
170 }
171 prjPath = System.IO.Path.Combine (prjPath, fileNameProperty.Value.ToString());
172
173 // If the full path of this proj ect is the same as the one of this
174 // reference, then we have found the right project.
175 if(NativeMethods.IsSamePath(prjP ath, referencedProjectFullPath))
176 {
177 this.referencedProject = prj;
178 break;
179 }
180 }
181 }
182
183 return this.referencedProject;
184 }
185 set
186 {
187 this.referencedProject = value;
188 }
189 }
190
191 /// <summary>
192 /// Gets the full path to the assembly generated by this project .
193 /// </summary>
194 internal string ReferencedProjectOutputPath
195 {
196 get
197 {
198 // Make sure that the referenced project impleme nts the automation object.
199 if(null == this.ReferencedProjectObject)
200 {
201 return null;
202 }
203
204 // Get the configuration manager from the projec t.
205 EnvDTE.ConfigurationManager confManager = this.R eferencedProjectObject.ConfigurationManager;
206 if(null == confManager)
207 {
208 return null;
209 }
210
211 // Get the active configuration.
212 EnvDTE.Configuration config = confManager.Active Configuration;
213 if(null == config)
214 {
215 return null;
216 }
217
218 // Get the output path for the current configura tion.
219 EnvDTE.Property outputPathProperty = config.Prop erties.Item("OutputPath");
220 if(null == outputPathProperty)
221 {
222 return null;
223 }
224
225 string outputPath = outputPathProperty.Value.ToS tring();
226
227 // Ususally the output path is relative to the p roject path, but it is possible
228 // to set it as an absolute path. If it is not a bsolute, then evaluate its value
229 // based on the project directory.
230 if(!System.IO.Path.IsPathRooted(outputPath))
231 {
232 string projectDir = System.IO.Path.GetDi rectoryName(referencedProjectFullPath);
233 outputPath = System.IO.Path.Combine(proj ectDir, outputPath);
234 }
235
236 // Now get the name of the assembly from the pro ject.
237 // Some project system throw if the property doe s not exist. We expect an ArgumentException.
238 EnvDTE.Property assemblyNameProperty = null;
239 try
240 {
241 assemblyNameProperty = this.ReferencedPr ojectObject.Properties.Item("OutputFileName");
242 }
243 catch(ArgumentException)
244 {
245 }
246
247 if(null == assemblyNameProperty)
248 {
249 return null;
250 }
251 // build the full path adding the name of the as sembly to the output path.
252 outputPath = System.IO.Path.Combine(outputPath, assemblyNameProperty.Value.ToString());
253
254 return outputPath;
255 }
256 }
257
258 private Automation.OAProjectReference projectReference;
259 internal override object Object
260 {
261 get
262 {
263 if(null == projectReference)
264 {
265 projectReference = new Automation.OAProj ectReference(this);
266 }
267 return projectReference;
268 }
269 }
270 #endregion
271
272 #region ctors
273 /// <summary>
274 /// Constructor for the ReferenceNode. It is called when the pro ject is reloaded, when the project element representing the refernce exists.
275 /// </summary>
276 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usag e", "CA2234:PassSystemUriObjectsInsteadOfStrings")]
277 public ProjectReferenceNode(ProjectNode root, ProjectElement ele ment)
278 : base(root, element)
279 {
280 this.referencedProjectRelativePath = this.ItemNode.GetMe tadata(ProjectFileConstants.Include);
281 Debug.Assert(!String.IsNullOrEmpty(this.referencedProjec tRelativePath), "Could not retrive referenced project path form project file");
282
283 string guidString = this.ItemNode.GetMetadata(ProjectFil eConstants.Project);
284
285 // Continue even if project setttings cannot be read.
286 try
287 {
288 this.referencedProjectGuid = new Guid(guidString );
289
290 this.buildDependency = new BuildDependency(this. ProjectMgr, this.referencedProjectGuid);
291 this.ProjectMgr.AddBuildDependency(this.buildDep endency);
292 }
293 finally
294 {
295 Debug.Assert(this.referencedProjectGuid != Guid. Empty, "Could not retrive referenced project guidproject file");
296
297 this.referencedProjectName = this.ItemNode.GetMe tadata(ProjectFileConstants.Name);
298
299 Debug.Assert(!String.IsNullOrEmpty(this.referenc edProjectName), "Could not retrive referenced project name form project file");
300 }
301
302 Uri uri = new Uri(this.ProjectMgr.BaseURI.Uri, this.refe rencedProjectRelativePath);
303
304 if(uri != null)
305 {
306 this.referencedProjectFullPath = Microsoft.Visua lStudio.Shell.Url.Unescape(uri.LocalPath, true);
307 }
308 }
309
310 /// <summary>
311 /// constructor for the ProjectReferenceNode
312 /// </summary>
313 public ProjectReferenceNode(ProjectNode root, string referencedP rojectName, string projectPath, string projectReference)
314 : base(root)
315 {
316 Debug.Assert(root != null && !String.IsNullOrEmpty(refer encedProjectName) && !String.IsNullOrEmpty(projectReference)
317 && !String.IsNullOrEmpty(projectPath), "Can not add a reference because the input for adding one is invalid.");
318 this.referencedProjectName = referencedProjectName;
319
320 int indexOfSeparator = projectReference.IndexOf('|');
321
322
323 string fileName = String.Empty;
324
325 // Unfortunately we cannot use the path part of the proj ectReference string since it is not resolving correctly relative pathes.
326 if(indexOfSeparator != -1)
327 {
328 string projectGuid = projectReference.Substring( 0, indexOfSeparator);
329 this.referencedProjectGuid = new Guid(projectGui d);
330 if(indexOfSeparator + 1 < projectReference.Lengt h)
331 {
332 string remaining = projectReference.Subs tring(indexOfSeparator + 1);
333 indexOfSeparator = remaining.IndexOf('|' );
334
335 if(indexOfSeparator == -1)
336 {
337 fileName = remaining;
338 }
339 else
340 {
341 fileName = remaining.Substring(0 , indexOfSeparator);
342 }
343 }
344 }
345
346 Debug.Assert(!String.IsNullOrEmpty(fileName), "Can not a dd a project reference because the input for adding one is invalid.");
347
348 // Did we get just a file or a relative path?
349 Uri uri = new Uri(projectPath);
350
351 string referenceDir = PackageUtilities.GetPathDistance(t his.ProjectMgr.BaseURI.Uri, uri);
352
353 Debug.Assert(!String.IsNullOrEmpty(referenceDir), "Can n ot add a project reference because the input for adding one is invalid.");
354
355 string justTheFileName = Path.GetFileName(fileName);
356 this.referencedProjectRelativePath = Path.Combine(refere nceDir, justTheFileName);
357
358 this.referencedProjectFullPath = Path.Combine(projectPat h, justTheFileName);
359
360 this.buildDependency = new BuildDependency(this.ProjectM gr, this.referencedProjectGuid);
361
362 }
363 #endregion
364
365 #region methods
366 protected override NodeProperties CreatePropertiesObject()
367 {
368 return new ProjectReferencesProperties(this);
369 }
370
371 /// <summary>
372 /// The node is added to the hierarchy and then updates the buil d dependency list.
373 /// </summary>
374 public override void AddReference()
375 {
376 if(this.ProjectMgr == null)
377 {
378 return;
379 }
380 base.AddReference();
381 this.ProjectMgr.AddBuildDependency(this.buildDependency) ;
382 return;
383 }
384
385 /// <summary>
386 /// Overridden method. The method updates the build dependency l ist before removing the node from the hierarchy.
387 /// </summary>
388 public override void Remove(bool removeFromStorage)
389 {
390 if(this.ProjectMgr == null || !this.CanRemoveReference)
391 {
392 return;
393 }
394 this.ProjectMgr.RemoveBuildDependency(this.buildDependen cy);
395 base.Remove(removeFromStorage);
396 return;
397 }
398
399 /// <summary>
400 /// Links a reference node to the project file.
401 /// </summary>
402 protected override void BindReferenceData()
403 {
404 Debug.Assert(!String.IsNullOrEmpty(this.referencedProjec tName), "The referencedProjectName field has not been initialized");
405 Debug.Assert(this.referencedProjectGuid != Guid.Empty, " The referencedProjectName field has not been initialized");
406
407 this.ItemNode = new ProjectElement(this.ProjectMgr, this .referencedProjectRelativePath, ProjectFileConstants.ProjectReference);
408
409 this.ItemNode.SetMetadata(ProjectFileConstants.Name, thi s.referencedProjectName);
410 this.ItemNode.SetMetadata(ProjectFileConstants.Project, this.referencedProjectGuid.ToString("B"));
411 this.ItemNode.SetMetadata(ProjectFileConstants.Private, true.ToString());
412 }
413
414 /// <summary>
415 /// Defines whether this node is valid node for painting the ref ererence icon.
416 /// </summary>
417 /// <returns></returns>
418 protected override bool CanShowDefaultIcon()
419 {
420 if(this.referencedProjectGuid == Guid.Empty || this.Proj ectMgr == null || this.ProjectMgr.IsClosed || this.isNodeValid)
421 {
422 return false;
423 }
424
425 IVsHierarchy hierarchy = null;
426
427 hierarchy = VsShellUtilities.GetHierarchy(this.ProjectMg r.Site, this.referencedProjectGuid);
428
429 if(hierarchy == null)
430 {
431 return false;
432 }
433
434 //If the Project is unloaded return false
435 if(this.ReferencedProjectObject == null)
436 {
437 return false;
438 }
439
440 return (!String.IsNullOrEmpty(this.referencedProjectFull Path) && File.Exists(this.referencedProjectFullPath));
441 }
442
443 /// <summary>
444 /// Checks if a project reference can be added to the hierarchy. It calls base to see if the reference is not already there, then checks for cir cular references.
445 /// </summary>
446 /// <param name="errorHandler">The error handler delegate to ret urn</param>
447 /// <returns></returns>
448 protected override bool CanAddReference(out CannotAddReferenceEr rorMessage errorHandler)
449 {
450 // When this method is called this refererence has not y et been added to the hierarchy, only instantiated.
451 if(!base.CanAddReference(out errorHandler))
452 {
453 return false;
454 }
455
456 errorHandler = null;
457 if(this.IsThisProjectReferenceInCycle())
458 {
459 errorHandler = new CannotAddReferenceErrorMessag e(ShowCircularReferenceErrorMessage);
460 return false;
461 }
462
463 return true;
464 }
465
466 private bool IsThisProjectReferenceInCycle()
467 {
468 return IsReferenceInCycle(this.referencedProjectGuid);
469 }
470
471 private void ShowCircularReferenceErrorMessage()
472 {
473 string message = String.Format(CultureInfo.CurrentCultur e, SR.GetString(SR.ProjectContainsCircularReferences, CultureInfo.CurrentUICultu re), this.referencedProjectName);
474 string title = string.Empty;
475 OLEMSGICON icon = OLEMSGICON.OLEMSGICON_CRITICAL;
476 OLEMSGBUTTON buttons = OLEMSGBUTTON.OLEMSGBUTTON_OK;
477 OLEMSGDEFBUTTON defaultButton = OLEMSGDEFBUTTON.OLEMSGDE FBUTTON_FIRST;
478 VsShellUtilities.ShowMessageBox(this.ProjectMgr.Site, ti tle, message, icon, buttons, defaultButton);
479 }
480
481 /// <summary>
482 /// Recursively search if this project reference guid is in cycl e.
483 /// </summary>
484 private bool IsReferenceInCycle(Guid projectGuid)
485 {
486 IVsHierarchy hierarchy = VsShellUtilities.GetHierarchy(t his.ProjectMgr.Site, projectGuid);
487
488 IReferenceContainerProvider provider = hierarchy as IRef erenceContainerProvider;
489 if(provider != null)
490 {
491 IReferenceContainer referenceContainer = provide r.GetReferenceContainer();
492
493 Debug.Assert(referenceContainer != null, "Could not found the References virtual node");
494
495 foreach(ReferenceNode refNode in referenceContai ner.EnumReferences())
496 {
497 ProjectReferenceNode projRefNode = refNo de as ProjectReferenceNode;
498 if(projRefNode != null)
499 {
500 if(projRefNode.ReferencedProject Guid == this.ProjectMgr.ProjectIDGuid)
501 {
502 return true;
503 }
504
505 if(this.IsReferenceInCycle(projR efNode.ReferencedProjectGuid))
506 {
507 return true;
508 }
509 }
510 }
511 }
512
513 return false;
514 }
515 #endregion
516 }
517
518 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698