PageRenderTime 63ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/Tools/IronStudio/IronStudio/VisualStudio/Project/ProjectNode.cs

http://github.com/IronLanguages/main
C# | 1744 lines | 1165 code | 224 blank | 355 comment | 123 complexity | ac5e67b8271799df63619bc3bd6c1e47 MD5 | raw file
Possible License(s): CPL-1.0, BSD-3-Clause, ISC, GPL-2.0, MPL-2.0-no-copyleft-exception

Large files files are truncated, but you can click here to view the full file

  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) Microsoft Corporation.
  4. *
  5. * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
  6. * copy of the license can be found in the License.html file at the root of this distribution. If
  7. * you cannot locate the Apache License, Version 2.0, please send an email to
  8. * ironpy@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
  9. * by the terms of the Apache License, Version 2.0.
  10. *
  11. * You must not remove this notice, or any other, from this software.
  12. *
  13. * ***************************************************************************/
  14. using System;
  15. using System.CodeDom.Compiler;
  16. using System.Collections.Generic;
  17. using System.Collections.Specialized;
  18. using System.Diagnostics;
  19. using System.Diagnostics.CodeAnalysis;
  20. using System.Globalization;
  21. using System.IO;
  22. using System.Linq;
  23. using System.Runtime.InteropServices;
  24. using System.Xml;
  25. using EnvDTE;
  26. using Microsoft.Build.Evaluation;
  27. using Microsoft.Build.Execution;
  28. using Microsoft.VisualStudio.OLE.Interop;
  29. using Microsoft.VisualStudio.Shell;
  30. using Microsoft.VisualStudio.Shell.Interop;
  31. using IOleServiceProvider = Microsoft.VisualStudio.OLE.Interop.IServiceProvider;
  32. using IServiceProvider = System.IServiceProvider;
  33. using MSBuild = Microsoft.Build.Evaluation;
  34. using MSBuildConstruction = Microsoft.Build.Construction;
  35. using MSBuildExecution = Microsoft.Build.Execution;
  36. using OleConstants = Microsoft.VisualStudio.OLE.Interop.Constants;
  37. using VsCommands = Microsoft.VisualStudio.VSConstants.VSStd97CmdID;
  38. using VsCommands2K = Microsoft.VisualStudio.VSConstants.VSStd2KCmdID;
  39. using Microsoft.Build.BackEnd;
  40. namespace Microsoft.VisualStudio.Project
  41. {
  42. /// <summary>
  43. /// Manages the persistent state of the project (References, options, files, etc.) and deals with user interaction via a GUI in the form a hierarchy.
  44. /// </summary>
  45. [CLSCompliant(false)]
  46. [ComVisible(true)]
  47. public abstract partial class ProjectNode : HierarchyNode,
  48. IVsGetCfgProvider,
  49. IVsProject3,
  50. IVsAggregatableProject,
  51. IVsProjectFlavorCfgProvider,
  52. IPersistFileFormat,
  53. IVsProjectBuildSystem,
  54. IVsBuildPropertyStorage,
  55. IVsComponentUser,
  56. IVsDependencyProvider,
  57. IVsSccProject2,
  58. IBuildDependencyUpdate,
  59. IProjectEventsListener,
  60. IProjectEventsProvider,
  61. IReferenceContainerProvider,
  62. IVsProjectSpecialFiles
  63. {
  64. #region nested types
  65. public enum ImageName
  66. {
  67. OfflineWebApp = 0,
  68. WebReferencesFolder = 1,
  69. OpenReferenceFolder = 2,
  70. ReferenceFolder = 3,
  71. Reference = 4,
  72. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "SDL")]
  73. SDLWebReference = 5,
  74. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "DISCO")]
  75. DISCOWebReference = 6,
  76. Folder = 7,
  77. OpenFolder = 8,
  78. ExcludedFolder = 9,
  79. OpenExcludedFolder = 10,
  80. ExcludedFile = 11,
  81. DependentFile = 12,
  82. MissingFile = 13,
  83. WindowsForm = 14,
  84. WindowsUserControl = 15,
  85. WindowsComponent = 16,
  86. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "XML")]
  87. XMLSchema = 17,
  88. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "XML")]
  89. XMLFile = 18,
  90. WebForm = 19,
  91. WebService = 20,
  92. WebUserControl = 21,
  93. WebCustomUserControl = 22,
  94. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "ASP")]
  95. ASPPage = 23,
  96. GlobalApplicationClass = 24,
  97. WebConfig = 25,
  98. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "HTML")]
  99. HTMLPage = 26,
  100. StyleSheet = 27,
  101. ScriptFile = 28,
  102. TextFile = 29,
  103. SettingsFile = 30,
  104. Resources = 31,
  105. Bitmap = 32,
  106. Icon = 33,
  107. Image = 34,
  108. ImageMap = 35,
  109. XWorld = 36,
  110. Audio = 37,
  111. Video = 38,
  112. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "CAB")]
  113. CAB = 39,
  114. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "JAR")]
  115. JAR = 40,
  116. DataEnvironment = 41,
  117. PreviewFile = 42,
  118. DanglingReference = 43,
  119. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "XSLT")]
  120. XSLTFile = 44,
  121. Cursor = 45,
  122. AppDesignerFolder = 46,
  123. Data = 47,
  124. Application = 48,
  125. DataSet = 49,
  126. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "PFX")]
  127. PFX = 50,
  128. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "SNK")]
  129. SNK = 51,
  130. ImageLast = 51
  131. }
  132. /// <summary>
  133. /// Flags for specifying which events to stop triggering.
  134. /// </summary>
  135. [Flags]
  136. internal enum EventTriggering
  137. {
  138. TriggerAll = 0,
  139. DoNotTriggerHierarchyEvents = 1,
  140. DoNotTriggerTrackerEvents = 2
  141. }
  142. #endregion
  143. #region constants
  144. /// <summary>
  145. /// The user file extension.
  146. /// </summary>
  147. internal const string PerUserFileExtension = ".user";
  148. #endregion
  149. #region fields
  150. /// <summary>
  151. /// List of output groups names and their associated target
  152. /// </summary>
  153. private static KeyValuePair<string, string>[] outputGroupNames =
  154. { // Name Target (MSBuild)
  155. new KeyValuePair<string, string>("Built", "BuiltProjectOutputGroup"),
  156. new KeyValuePair<string, string>("ContentFiles", "ContentFilesProjectOutputGroup"),
  157. new KeyValuePair<string, string>("LocalizedResourceDlls", "SatelliteDllsProjectOutputGroup"),
  158. new KeyValuePair<string, string>("Documentation", "DocumentationProjectOutputGroup"),
  159. new KeyValuePair<string, string>("Symbols", "DebugSymbolsProjectOutputGroup"),
  160. new KeyValuePair<string, string>("SourceFiles", "SourceFilesProjectOutputGroup"),
  161. new KeyValuePair<string, string>("XmlSerializer", "SGenFilesOutputGroup"),
  162. };
  163. /// <summary>A project will only try to build if it can obtain a lock on this object</summary>
  164. private volatile static object BuildLock = new object();
  165. /// <summary>Maps integer ids to project item instances</summary>
  166. private EventSinkCollection itemIdMap = new EventSinkCollection();
  167. /// <summary>A service provider call back object provided by the IDE hosting the project manager</summary>
  168. private ServiceProvider site;
  169. private TrackDocumentsHelper tracker;
  170. /// <summary>
  171. /// This property returns the time of the last change made to this project.
  172. /// It is not the time of the last change on the project file, but actually of
  173. /// the in memory project settings. In other words, it is the last time that
  174. /// SetProjectDirty was called.
  175. /// </summary>
  176. private DateTime lastModifiedTime;
  177. /// <summary>
  178. /// MSBuild engine we are going to use
  179. /// </summary>
  180. private MSBuild.ProjectCollection buildEngine;
  181. private Microsoft.Build.Utilities.Logger buildLogger;
  182. private bool useProvidedLogger;
  183. private MSBuild.Project buildProject;
  184. private MSBuildExecution.ProjectInstance currentConfig;
  185. private ConfigProvider configProvider;
  186. private TaskProvider taskProvider;
  187. private string filename;
  188. private Microsoft.VisualStudio.Shell.Url baseUri;
  189. private bool isDirty;
  190. private bool isNewProject;
  191. private bool projectOpened;
  192. private bool buildIsPrepared;
  193. private ImageHandler imageHandler;
  194. private string errorString;
  195. private string warningString;
  196. private Guid projectIdGuid;
  197. private bool isClosed;
  198. private EventTriggering eventTriggeringFlag = EventTriggering.TriggerAll;
  199. private bool invokeMSBuildWhenResumed;
  200. private uint suspendMSBuildCounter;
  201. private bool canFileNodesHaveChilds;
  202. private bool isProjectEventsListener = true;
  203. /// <summary>
  204. /// The build dependency list passed to IVsDependencyProvider::EnumDependencies
  205. /// </summary>
  206. private List<IVsBuildDependency> buildDependencyList = new List<IVsBuildDependency>();
  207. /// <summary>
  208. /// Defines if Project System supports Project Designer
  209. /// </summary>
  210. private bool supportsProjectDesigner;
  211. private bool showProjectInSolutionPage = true;
  212. private bool buildInProcess;
  213. /// <summary>
  214. /// Field for determining whether sourcecontrol should be disabled.
  215. /// </summary>
  216. private bool disableScc;
  217. private string sccProjectName;
  218. private string sccLocalPath;
  219. private string sccAuxPath;
  220. private string sccProvider;
  221. /// <summary>
  222. /// Flag for controling how many times we register with the Scc manager.
  223. /// </summary>
  224. private bool isRegisteredWithScc;
  225. /// <summary>
  226. /// Flag for controling query edit should communicate with the scc manager.
  227. /// </summary>
  228. private bool disableQueryEdit;
  229. /// <summary>
  230. /// Control if command with potential destructive behavior such as delete should
  231. /// be enabled for nodes of this project.
  232. /// </summary>
  233. private bool canProjectDeleteItems;
  234. /// <summary>
  235. /// Token processor used by the project sample.
  236. /// </summary>
  237. private TokenProcessor tokenProcessor;
  238. /// <summary>
  239. /// Member to store output base relative path. Used by OutputBaseRelativePath property
  240. /// </summary>
  241. private string outputBaseRelativePath = "bin";
  242. private IProjectEvents projectEventsProvider;
  243. /// <summary>
  244. /// Used for flavoring to hold the XML fragments
  245. /// </summary>
  246. private XmlDocument xmlFragments;
  247. /// <summary>
  248. /// Used to map types to CATID. This provide a generic way for us to do this
  249. /// and make it simpler for a project to provide it's CATIDs for the different type of objects
  250. /// for which it wants to support extensibility. This also enables us to have multiple
  251. /// type mapping to the same CATID if we choose to.
  252. /// </summary>
  253. private Dictionary<Type, Guid> catidMapping = new Dictionary<Type, Guid>();
  254. /// <summary>
  255. /// The internal package implementation.
  256. /// </summary>
  257. private ProjectPackage package;
  258. // Has the object been disposed.
  259. private bool isDisposed;
  260. #endregion
  261. #region abstract properties
  262. /// <summary>
  263. /// This Guid must match the Guid you registered under
  264. /// HKLM\Software\Microsoft\VisualStudio\%version%\Projects.
  265. /// Among other things, the Project framework uses this
  266. /// guid to find your project and item templates.
  267. /// </summary>
  268. public abstract Guid ProjectGuid
  269. {
  270. get;
  271. }
  272. /// <summary>
  273. /// Returns a caption for VSHPROPID_TypeName.
  274. /// </summary>
  275. /// <returns></returns>
  276. public abstract string ProjectType
  277. {
  278. get;
  279. }
  280. #endregion
  281. #region virtual properties
  282. /// <summary>
  283. /// This is the project instance guid that is peristed in the project file
  284. /// </summary>
  285. [System.ComponentModel.BrowsableAttribute(false)]
  286. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "ID")]
  287. public virtual Guid ProjectIDGuid
  288. {
  289. get
  290. {
  291. return this.projectIdGuid;
  292. }
  293. set
  294. {
  295. if (this.projectIdGuid != value)
  296. {
  297. this.projectIdGuid = value;
  298. if (this.buildProject != null)
  299. {
  300. this.SetProjectProperty("ProjectGuid", this.projectIdGuid.ToString("B"));
  301. }
  302. }
  303. }
  304. }
  305. #endregion
  306. #region properties
  307. #region overridden properties
  308. public override int MenuCommandId
  309. {
  310. get
  311. {
  312. return VsMenus.IDM_VS_CTXT_PROJNODE;
  313. }
  314. }
  315. public override string Url
  316. {
  317. get
  318. {
  319. return this.GetMkDocument();
  320. }
  321. }
  322. public override string Caption
  323. {
  324. get
  325. {
  326. // Default to file name
  327. string caption = this.buildProject.FullPath;
  328. if (String.IsNullOrEmpty(caption))
  329. {
  330. if (this.buildProject.GetProperty(ProjectFileConstants.Name) != null)
  331. {
  332. caption = this.buildProject.GetProperty(ProjectFileConstants.Name).EvaluatedValue;
  333. if (caption == null || caption.Length == 0)
  334. {
  335. caption = this.ItemNode.GetMetadata(ProjectFileConstants.Include);
  336. }
  337. }
  338. }
  339. else
  340. {
  341. caption = Path.GetFileNameWithoutExtension(caption);
  342. }
  343. return caption;
  344. }
  345. }
  346. public override Guid ItemTypeGuid
  347. {
  348. get
  349. {
  350. return this.ProjectGuid;
  351. }
  352. }
  353. public override int ImageIndex
  354. {
  355. get
  356. {
  357. return (int)ProjectNode.ImageName.Application;
  358. }
  359. }
  360. #endregion
  361. #region virtual properties
  362. public virtual string ErrorString
  363. {
  364. get
  365. {
  366. if (this.errorString == null)
  367. {
  368. this.errorString = SR.GetString(SR.Error, CultureInfo.CurrentUICulture);
  369. }
  370. return this.errorString;
  371. }
  372. }
  373. public virtual string WarningString
  374. {
  375. get
  376. {
  377. if (this.warningString == null)
  378. {
  379. this.warningString = SR.GetString(SR.Warning, CultureInfo.CurrentUICulture);
  380. }
  381. return this.warningString;
  382. }
  383. }
  384. /// <summary>
  385. /// The target name that will be used for evaluating the project file (i.e., pseudo-builds).
  386. /// This target is used to trigger a build with when the project system changes.
  387. /// Example: The language projrcts are triggering a build with the Compile target whenever
  388. /// the project system changes.
  389. /// </summary>
  390. [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "ReEvaluate")]
  391. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Re")]
  392. protected internal virtual string ReEvaluateProjectFileTargetName
  393. {
  394. get
  395. {
  396. return null;
  397. }
  398. }
  399. /// <summary>
  400. /// This is the object that will be returned by EnvDTE.Project.Object for this project
  401. /// </summary>
  402. protected internal virtual object ProjectObject
  403. {
  404. get
  405. {
  406. return null;
  407. }
  408. }
  409. /// <summary>
  410. /// Override this property to specify when the project file is dirty.
  411. /// </summary>
  412. protected virtual bool IsProjectFileDirty
  413. {
  414. get
  415. {
  416. string document = this.GetMkDocument();
  417. if (String.IsNullOrEmpty(document))
  418. {
  419. return this.isDirty;
  420. }
  421. return (this.isDirty || !File.Exists(document));
  422. }
  423. }
  424. /// <summary>
  425. /// True if the project uses the Project Designer Editor instead of the property page frame to edit project properties.
  426. /// </summary>
  427. protected virtual bool SupportsProjectDesigner
  428. {
  429. get
  430. {
  431. return this.supportsProjectDesigner;
  432. }
  433. set
  434. {
  435. this.supportsProjectDesigner = value;
  436. }
  437. }
  438. protected virtual Guid ProjectDesignerEditor
  439. {
  440. get
  441. {
  442. return VSConstants.GUID_ProjectDesignerEditor;
  443. }
  444. }
  445. /// <summary>
  446. /// Defines the flag that supports the VSHPROPID.ShowProjInSolutionPage
  447. /// </summary>
  448. protected virtual bool ShowProjectInSolutionPage
  449. {
  450. get
  451. {
  452. return this.showProjectInSolutionPage;
  453. }
  454. set
  455. {
  456. this.showProjectInSolutionPage = value;
  457. }
  458. }
  459. #endregion
  460. /// <summary>
  461. /// Gets or sets the ability of a project filenode to have child nodes (sub items).
  462. /// Example would be C#/VB forms having resx and designer files.
  463. /// </summary>
  464. protected internal bool CanFileNodesHaveChilds
  465. {
  466. get
  467. {
  468. return canFileNodesHaveChilds;
  469. }
  470. set
  471. {
  472. canFileNodesHaveChilds = value;
  473. }
  474. }
  475. /// <summary>
  476. /// Get and set the Token processor.
  477. /// </summary>
  478. public TokenProcessor FileTemplateProcessor
  479. {
  480. get
  481. {
  482. if (tokenProcessor == null)
  483. tokenProcessor = new TokenProcessor();
  484. return tokenProcessor;
  485. }
  486. set
  487. {
  488. tokenProcessor = value;
  489. }
  490. }
  491. /// <summary>
  492. /// Gets a service provider object provided by the IDE hosting the project
  493. /// </summary>
  494. [SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods")]
  495. public IServiceProvider Site
  496. {
  497. get
  498. {
  499. return this.site;
  500. }
  501. }
  502. /// <summary>
  503. /// Gets an ImageHandler for the project node.
  504. /// </summary>
  505. public ImageHandler ImageHandler
  506. {
  507. get
  508. {
  509. if (null == imageHandler)
  510. {
  511. imageHandler = new ImageHandler(typeof(ProjectNode).Assembly.GetManifestResourceStream("Microsoft.VisualStudio.Project.Resources.imagelis.bmp"));
  512. }
  513. return imageHandler;
  514. }
  515. }
  516. /// <summary>
  517. /// This property returns the time of the last change made to this project.
  518. /// It is not the time of the last change on the project file, but actually of
  519. /// the in memory project settings. In other words, it is the last time that
  520. /// SetProjectDirty was called.
  521. /// </summary>
  522. public DateTime LastModifiedTime
  523. {
  524. get
  525. {
  526. return this.lastModifiedTime;
  527. }
  528. }
  529. /// <summary>
  530. /// Determines whether this project is a new project.
  531. /// </summary>
  532. public bool IsNewProject
  533. {
  534. get
  535. {
  536. return this.isNewProject;
  537. }
  538. }
  539. /// <summary>
  540. /// Gets the path to the folder containing the project.
  541. /// </summary>
  542. public string ProjectFolder
  543. {
  544. get
  545. {
  546. return Path.GetDirectoryName(this.filename);
  547. }
  548. }
  549. /// <summary>
  550. /// Gets or sets the project filename.
  551. /// </summary>
  552. public string ProjectFile
  553. {
  554. get
  555. {
  556. return Path.GetFileName(this.filename);
  557. }
  558. set
  559. {
  560. this.SetEditLabel(value);
  561. }
  562. }
  563. /// <summary>
  564. /// Gets the Base Uniform Resource Identifier (URI).
  565. /// </summary>
  566. [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "URI")]
  567. public Microsoft.VisualStudio.Shell.Url BaseURI
  568. {
  569. get
  570. {
  571. if (baseUri == null && this.buildProject != null)
  572. {
  573. string path = System.IO.Path.GetDirectoryName(this.buildProject.FullPath);
  574. // Uri/Url behave differently when you have trailing slash and when you dont
  575. if (!path.EndsWith("\\", StringComparison.Ordinal) && !path.EndsWith("/", StringComparison.Ordinal))
  576. path += "\\";
  577. baseUri = new Url(path);
  578. }
  579. Debug.Assert(baseUri != null, "Base URL should not be null. Did you call BaseURI before loading the project?");
  580. return baseUri;
  581. }
  582. }
  583. /// <summary>
  584. /// Gets whether or not the project is closed.
  585. /// </summary>
  586. public bool IsClosed
  587. {
  588. get
  589. {
  590. return this.isClosed;
  591. }
  592. }
  593. /// <summary>
  594. /// Gets whether or not the project is being built.
  595. /// </summary>
  596. public bool BuildInProgress
  597. {
  598. get
  599. {
  600. return buildInProcess;
  601. }
  602. }
  603. /// <summary>
  604. /// Gets or set the relative path to the folder containing the project ouput.
  605. /// </summary>
  606. public virtual string OutputBaseRelativePath
  607. {
  608. get
  609. {
  610. return this.outputBaseRelativePath;
  611. }
  612. set
  613. {
  614. if (Path.IsPathRooted(value))
  615. {
  616. throw new ArgumentException("Path must not be rooted.");
  617. }
  618. this.outputBaseRelativePath = value;
  619. }
  620. }
  621. /// <summary>
  622. /// Gets or sets the flag whether query edit should communicate with the scc manager.
  623. /// </summary>
  624. protected bool DisableQueryEdit
  625. {
  626. get
  627. {
  628. return this.disableQueryEdit;
  629. }
  630. set
  631. {
  632. this.disableQueryEdit = value;
  633. }
  634. }
  635. /// <summary>
  636. /// Gets a collection of integer ids that maps to project item instances
  637. /// </summary>
  638. internal EventSinkCollection ItemIdMap
  639. {
  640. get
  641. {
  642. return this.itemIdMap;
  643. }
  644. }
  645. /// <summary>
  646. /// Get the helper object that track document changes.
  647. /// </summary>
  648. internal TrackDocumentsHelper Tracker
  649. {
  650. get
  651. {
  652. return this.tracker;
  653. }
  654. }
  655. /// <summary>
  656. /// Gets or sets the build logger.
  657. /// </summary>
  658. protected Microsoft.Build.Utilities.Logger BuildLogger
  659. {
  660. get
  661. {
  662. return this.buildLogger;
  663. }
  664. set
  665. {
  666. this.buildLogger = value;
  667. this.useProvidedLogger = true;
  668. }
  669. }
  670. /// <summary>
  671. /// Gets the taskprovider.
  672. /// </summary>
  673. protected TaskProvider TaskProvider
  674. {
  675. get
  676. {
  677. return this.taskProvider;
  678. }
  679. }
  680. /// <summary>
  681. /// Gets the project file name.
  682. /// </summary>
  683. protected string FileName
  684. {
  685. get
  686. {
  687. return this.filename;
  688. }
  689. }
  690. /// <summary>
  691. /// Gets the configuration provider.
  692. /// </summary>
  693. protected ConfigProvider ConfigProvider
  694. {
  695. get
  696. {
  697. if (this.configProvider == null)
  698. {
  699. this.configProvider = CreateConfigProvider();
  700. }
  701. return this.configProvider;
  702. }
  703. }
  704. /// <summary>
  705. /// Gets or sets whether or not source code control is disabled for this project.
  706. /// </summary>
  707. [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Scc")]
  708. protected bool IsSccDisabled
  709. {
  710. get
  711. {
  712. return this.disableScc;
  713. }
  714. set
  715. {
  716. this.disableScc = value;
  717. }
  718. }
  719. /// <summary>
  720. /// Gets or set whether items can be deleted for this project.
  721. /// Enabling this feature can have the potential destructive behavior such as deleting files from disk.
  722. /// </summary>
  723. protected internal bool CanProjectDeleteItems
  724. {
  725. get
  726. {
  727. return canProjectDeleteItems;
  728. }
  729. set
  730. {
  731. canProjectDeleteItems = value;
  732. }
  733. }
  734. /// <summary>
  735. /// Determines whether the project was fully opened. This is set when the OnAfterOpenProject has triggered.
  736. /// </summary>
  737. protected internal bool HasProjectOpened
  738. {
  739. get
  740. {
  741. return this.projectOpened;
  742. }
  743. }
  744. /// <summary>
  745. /// Gets or sets event triggering flags.
  746. /// </summary>
  747. internal EventTriggering EventTriggeringFlag
  748. {
  749. get
  750. {
  751. return this.eventTriggeringFlag;
  752. }
  753. set
  754. {
  755. this.eventTriggeringFlag = value;
  756. }
  757. }
  758. /// <summary>
  759. /// Defines the build project that has loaded the project file.
  760. /// </summary>
  761. protected internal MSBuild.Project BuildProject
  762. {
  763. get
  764. {
  765. return this.buildProject;
  766. }
  767. set
  768. {
  769. SetBuildProject(value);
  770. }
  771. }
  772. /// <summary>
  773. /// Gets the current config.
  774. /// </summary>
  775. /// <value>The current config.</value>
  776. protected internal Microsoft.Build.Execution.ProjectInstance CurrentConfig
  777. {
  778. get { return this.currentConfig; }
  779. }
  780. /// <summary>
  781. /// Defines the build engine that is used to build the project file.
  782. /// </summary>
  783. internal MSBuild.ProjectCollection BuildEngine
  784. {
  785. get
  786. {
  787. return this.buildEngine;
  788. }
  789. set
  790. {
  791. this.buildEngine = value;
  792. }
  793. }
  794. /// <summary>
  795. /// The internal package implementation.
  796. /// </summary>
  797. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
  798. internal ProjectPackage Package
  799. {
  800. get
  801. {
  802. return this.package;
  803. }
  804. set
  805. {
  806. this.package = value;
  807. }
  808. }
  809. #endregion
  810. #region ctor
  811. protected ProjectNode()
  812. {
  813. this.Initialize();
  814. }
  815. #endregion
  816. #region overridden methods
  817. protected override NodeProperties CreatePropertiesObject()
  818. {
  819. return new ProjectNodeProperties(this);
  820. }
  821. /// <summary>
  822. /// Sets the properties for the project node.
  823. /// </summary>
  824. /// <param name="propid">Identifier of the hierarchy property. For a list of propid values, <see cref="__VSHPROPID"/> </param>
  825. /// <param name="value">The value to set. </param>
  826. /// <returns>A success or failure value.</returns>
  827. public override int SetProperty(int propid, object value)
  828. {
  829. __VSHPROPID id = (__VSHPROPID)propid;
  830. switch (id)
  831. {
  832. case __VSHPROPID.VSHPROPID_ShowProjInSolutionPage:
  833. this.ShowProjectInSolutionPage = (bool)value;
  834. return VSConstants.S_OK;
  835. }
  836. return base.SetProperty(propid, value);
  837. }
  838. /// <summary>
  839. /// Renames the project node.
  840. /// </summary>
  841. /// <param name="label">The new name</param>
  842. /// <returns>A success or failure value.</returns>
  843. public override int SetEditLabel(string label)
  844. {
  845. // Validate the filename.
  846. if (String.IsNullOrEmpty(label))
  847. {
  848. throw new InvalidOperationException(SR.GetString(SR.ErrorInvalidFileName, CultureInfo.CurrentUICulture));
  849. }
  850. else if (this.ProjectFolder.Length + label.Length + 1 > NativeMethods.MAX_PATH)
  851. {
  852. throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, SR.GetString(SR.PathTooLong, CultureInfo.CurrentUICulture), label));
  853. }
  854. else if (Utilities.IsFileNameInvalid(label))
  855. {
  856. throw new InvalidOperationException(SR.GetString(SR.ErrorInvalidFileName, CultureInfo.CurrentUICulture));
  857. }
  858. string fileName = Path.GetFileNameWithoutExtension(label);
  859. // if there is no filename or it starts with a leading dot issue an error message and quit.
  860. if (String.IsNullOrEmpty(fileName) || fileName[0] == '.')
  861. {
  862. throw new InvalidOperationException(SR.GetString(SR.FileNameCannotContainALeadingPeriod, CultureInfo.CurrentUICulture));
  863. }
  864. // Nothing to do if the name is the same
  865. string oldFileName = Path.GetFileNameWithoutExtension(this.Url);
  866. if (String.Compare(oldFileName, label, StringComparison.Ordinal) == 0)
  867. {
  868. return VSConstants.S_FALSE;
  869. }
  870. // Now check whether the original file is still there. It could have been renamed.
  871. if (!File.Exists(this.Url))
  872. {
  873. throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, SR.GetString(SR.FileOrFolderCannotBeFound, CultureInfo.CurrentUICulture), this.ProjectFile));
  874. }
  875. // Get the full file name and then rename the project file.
  876. string newFile = Path.Combine(this.ProjectFolder, label);
  877. string extension = Path.GetExtension(this.Url);
  878. // Make sure it has the correct extension
  879. if (String.Compare(Path.GetExtension(newFile), extension, StringComparison.OrdinalIgnoreCase) != 0)
  880. {
  881. newFile += extension;
  882. }
  883. this.RenameProjectFile(newFile);
  884. return VSConstants.S_OK;
  885. }
  886. /// <summary>
  887. /// Gets the automation object for the project node.
  888. /// </summary>
  889. /// <returns>An instance of an EnvDTE.Project implementation object representing the automation object for the project.</returns>
  890. public override object GetAutomationObject()
  891. {
  892. return new Automation.OAProject(this);
  893. }
  894. /// <summary>
  895. /// Closes the project node.
  896. /// </summary>
  897. /// <returns>A success or failure value.</returns>
  898. public override int Close()
  899. {
  900. int hr = VSConstants.S_OK;
  901. try
  902. {
  903. // Walk the tree and close all nodes.
  904. // This has to be done before the project closes, since we want still state available for the ProjectMgr on the nodes
  905. // when nodes are closing.
  906. try
  907. {
  908. CloseAllNodes(this);
  909. }
  910. finally
  911. {
  912. this.Dispose(true);
  913. }
  914. }
  915. catch (COMException e)
  916. {
  917. hr = e.ErrorCode;
  918. }
  919. finally
  920. {
  921. ErrorHandler.ThrowOnFailure(base.Close());
  922. }
  923. this.isClosed = true;
  924. return hr;
  925. }
  926. /// <summary>
  927. /// Sets the service provider from which to access the services.
  928. /// </summary>
  929. /// <param name="site">An instance to an Microsoft.VisualStudio.OLE.Interop object</param>
  930. /// <returns>A success or failure value.</returns>
  931. public override int SetSite(Microsoft.VisualStudio.OLE.Interop.IServiceProvider site)
  932. {
  933. CCITracing.TraceCall();
  934. this.site = new ServiceProvider(site);
  935. if (taskProvider != null)
  936. {
  937. taskProvider.Dispose();
  938. }
  939. taskProvider = new TaskProvider(this.site);
  940. return VSConstants.S_OK;
  941. }
  942. /// <summary>
  943. /// Gets the properties of the project node.
  944. /// </summary>
  945. /// <param name="propId">The __VSHPROPID of the property.</param>
  946. /// <returns>A property dependent value. See: <see cref="__VSHPROPID"/> for details.</returns>
  947. public override object GetProperty(int propId)
  948. {
  949. switch ((__VSHPROPID)propId)
  950. {
  951. case __VSHPROPID.VSHPROPID_ConfigurationProvider:
  952. return this.ConfigProvider;
  953. case __VSHPROPID.VSHPROPID_ProjectName:
  954. return this.Caption;
  955. case __VSHPROPID.VSHPROPID_ProjectDir:
  956. return this.ProjectFolder;
  957. case __VSHPROPID.VSHPROPID_TypeName:
  958. return this.ProjectType;
  959. case __VSHPROPID.VSHPROPID_ShowProjInSolutionPage:
  960. return this.ShowProjectInSolutionPage;
  961. case __VSHPROPID.VSHPROPID_ExpandByDefault:
  962. return true;
  963. // Use the same icon as if the folder was closed
  964. case __VSHPROPID.VSHPROPID_OpenFolderIconIndex:
  965. return GetProperty((int)__VSHPROPID.VSHPROPID_IconIndex);
  966. }
  967. switch ((__VSHPROPID2)propId)
  968. {
  969. case __VSHPROPID2.VSHPROPID_SupportsProjectDesigner:
  970. return this.SupportsProjectDesigner;
  971. case __VSHPROPID2.VSHPROPID_PropertyPagesCLSIDList:
  972. return Utilities.CreateSemicolonDelimitedListOfStringFromGuids(this.GetConfigurationIndependentPropertyPages());
  973. case __VSHPROPID2.VSHPROPID_CfgPropertyPagesCLSIDList:
  974. return Utilities.CreateSemicolonDelimitedListOfStringFromGuids(this.GetConfigurationDependentPropertyPages());
  975. case __VSHPROPID2.VSHPROPID_PriorityPropertyPagesCLSIDList:
  976. return Utilities.CreateSemicolonDelimitedListOfStringFromGuids(this.GetPriorityProjectDesignerPages());
  977. case __VSHPROPID2.VSHPROPID_Container:
  978. return true;
  979. default:
  980. break;
  981. }
  982. return base.GetProperty(propId);
  983. }
  984. /// <summary>
  985. /// Gets the GUID value of the node.
  986. /// </summary>
  987. /// <param name="propid">A __VSHPROPID or __VSHPROPID2 value of the guid property</param>
  988. /// <param name="guid">The guid to return for the property.</param>
  989. /// <returns>A success or failure value.</returns>
  990. public override int GetGuidProperty(int propid, out Guid guid)
  991. {
  992. guid = Guid.Empty;
  993. if ((__VSHPROPID)propid == __VSHPROPID.VSHPROPID_ProjectIDGuid)
  994. {
  995. guid = this.ProjectIDGuid;
  996. }
  997. else if (propid == (int)__VSHPROPID.VSHPROPID_CmdUIGuid)
  998. {
  999. guid = this.ProjectGuid;
  1000. }
  1001. else if ((__VSHPROPID2)propid == __VSHPROPID2.VSHPROPID_ProjectDesignerEditor && this.SupportsProjectDesigner)
  1002. {
  1003. guid = this.ProjectDesignerEditor;
  1004. }
  1005. else
  1006. {
  1007. base.GetGuidProperty(propid, out guid);
  1008. }
  1009. if (guid.CompareTo(Guid.Empty) == 0)
  1010. {
  1011. return VSConstants.DISP_E_MEMBERNOTFOUND;
  1012. }
  1013. return VSConstants.S_OK;
  1014. }
  1015. /// <summary>
  1016. /// Sets Guid properties for the project node.
  1017. /// </summary>
  1018. /// <param name="propid">A __VSHPROPID or __VSHPROPID2 value of the guid property</param>
  1019. /// <param name="guid">The guid value to set.</param>
  1020. /// <returns>A success or failure value.</returns>
  1021. public override int SetGuidProperty(int propid, ref Guid guid)
  1022. {
  1023. switch ((__VSHPROPID)propid)
  1024. {
  1025. case __VSHPROPID.VSHPROPID_ProjectIDGuid:
  1026. this.ProjectIDGuid = guid;
  1027. return VSConstants.S_OK;
  1028. }
  1029. CCITracing.TraceCall(String.Format(CultureInfo.CurrentCulture, "Property {0} not found", propid));
  1030. return VSConstants.DISP_E_MEMBERNOTFOUND;
  1031. }
  1032. /// <summary>
  1033. /// Removes items from the hierarchy.
  1034. /// </summary>
  1035. /// <devdoc>Project overwrites this.</devdoc>
  1036. public override void Remove(bool removeFromStorage)
  1037. {
  1038. // the project will not be deleted from disk, just removed
  1039. if (removeFromStorage)
  1040. {
  1041. return;
  1042. }
  1043. // Remove the entire project from the solution
  1044. IVsSolution solution = this.Site.GetService(typeof(SVsSolution)) as IVsSolution;
  1045. uint iOption = 1; // SLNSAVEOPT_PromptSave
  1046. ErrorHandler.ThrowOnFailure(solution.CloseSolutionElement(iOption, this, 0));
  1047. }
  1048. /// <summary>
  1049. /// Gets the moniker for the project node. That is the full path of the project file.
  1050. /// </summary>
  1051. /// <returns>The moniker for the project file.</returns>
  1052. public override string GetMkDocument()
  1053. {
  1054. Debug.Assert(!String.IsNullOrEmpty(this.filename));
  1055. Debug.Assert(this.BaseURI != null && !String.IsNullOrEmpty(this.BaseURI.AbsoluteUrl));
  1056. return Path.Combine(this.BaseURI.AbsoluteUrl, this.filename);
  1057. }
  1058. /// <summary>
  1059. /// Disposes the project node object.
  1060. /// </summary>
  1061. /// <param name="disposing">Flag determining ehether it was deterministic or non deterministic clean up.</param>
  1062. protected override void Dispose(bool disposing)
  1063. {
  1064. if (this.isDisposed)
  1065. {
  1066. return;
  1067. }
  1068. try
  1069. {
  1070. try
  1071. {
  1072. this.UnRegisterProject();
  1073. }
  1074. finally
  1075. {
  1076. try
  1077. {
  1078. this.RegisterClipboardNotifications(false);
  1079. }
  1080. finally
  1081. {
  1082. try
  1083. {
  1084. if (this.projectEventsProvider != null)
  1085. {
  1086. this.projectEventsProvider.AfterProjectFileOpened -= this.OnAfterProjectOpen;
  1087. }
  1088. if (this.taskProvider != null)
  1089. {
  1090. taskProvider.Tasks.Clear();
  1091. this.taskProvider.Dispose();
  1092. this.taskProvider = null;
  1093. }
  1094. if (this.buildLogger != null)
  1095. {
  1096. this.buildLogger.Shutdown();
  1097. buildLogger = null;
  1098. }
  1099. if (this.site != null)
  1100. {
  1101. this.site.Dispose();
  1102. }
  1103. }
  1104. finally
  1105. {
  1106. this.buildEngine = null;
  1107. }
  1108. }
  1109. }
  1110. if (this.buildProject != null)
  1111. {
  1112. this.buildProject.ProjectCollection.UnloadProject(this.buildProject);
  1113. this.buildProject.ProjectCollection.UnloadProject(this.buildProject.Xml);
  1114. this.buildProject = null;
  1115. }
  1116. if (null != imageHandler)
  1117. {
  1118. imageHandler.Close();
  1119. imageHandler = null;
  1120. }
  1121. }
  1122. finally
  1123. {
  1124. base.Dispose(disposing);
  1125. this.isDisposed = true;
  1126. }
  1127. }
  1128. /// <summary>
  1129. /// Handles command status on the project node. If a command cannot be handled then the base should be called.
  1130. /// </summary>
  1131. /// <param name="cmdGroup">A unique identifier of the command group. The pguidCmdGroup parameter can be NULL to specify the standard group.</param>
  1132. /// <param name="cmd">The command to query status for.</param>
  1133. /// <param name="pCmdText">Pointer to an OLECMDTEXT structure in which to return the name and/or status information of a single command. Can be NULL to indicate that the caller does not require this information.</param>
  1134. /// <param name="result">An out parameter specifying the QueryStatusResult of the command.</param>
  1135. /// <returns>If the method succeeds, it returns S_OK. If it fails, it returns an error code.</returns>
  1136. protected override int QueryStatusOnNode(Guid cmdGroup, uint cmd, IntPtr pCmdText, ref QueryStatusResult result)
  1137. {
  1138. if (cmdGroup == VsMenus.guidStandardCommandSet97)
  1139. {
  1140. switch ((VsCommands)cmd)
  1141. {
  1142. case VsCommands.Copy:
  1143. case VsCommands.Paste:
  1144. case VsCommands.Cut:
  1145. case VsCommands.Rename:
  1146. case VsCommands.Exit:
  1147. case VsCommands.ProjectSettings:
  1148. case VsCommands.BuildSln:
  1149. case VsCommands.UnloadProject:
  1150. result |= QueryStatusResult.SUPPORTED | QueryStatusResult.ENABLED;
  1151. return VSConstants.S_OK;
  1152. case VsCommands.ViewForm:
  1153. if (this.HasDesigner)
  1154. {
  1155. result |= QueryStatusResult.SUPPORTED | QueryStatusResult.ENABLED;
  1156. return VSConstants.S_OK;
  1157. }
  1158. break;
  1159. case VsCommands.CancelBuild:
  1160. result |= QueryStatusResult.SUPPORTED;
  1161. if (this.buildInProcess)
  1162. result |= QueryStatusResult.ENABLED;
  1163. else
  1164. result |= QueryStatusResult.INVISIBLE;
  1165. return VSConstants.S_OK;
  1166. case VsCommands.NewFolder:
  1167. case VsCommands.AddNewItem:
  1168. case VsCommands.AddExistingItem:
  1169. result |= QueryStatusResult.SUPPORTED | QueryStatusResult.ENABLED;
  1170. return VSConstants.S_OK;
  1171. case VsCommands.SetStartupProject:
  1172. result |= QueryStatusResult.SUPPORTED | QueryStatusResult.ENABLED;
  1173. return VSConstants.S_OK;
  1174. }
  1175. }
  1176. else if (cmdGroup == VsMenus.guidStandardCommandSet2K)
  1177. {
  1178. switch ((VsCommands2K)cmd)
  1179. {
  1180. case VsCommands2K.ADDREFERENCE:
  1181. result |= QueryStatusResult.SUPPORTED | QueryStatusResult.ENABLED;
  1182. return VSConstants.S_OK;
  1183. case VsCommands2K.EXCLUDEFROMPROJECT:
  1184. result |= QueryStatusResult.SUPPORTED | QueryStatusResult.INVISIBLE;
  1185. return VSConstants.S_OK;
  1186. }
  1187. }
  1188. else
  1189. {
  1190. return (int)OleConstants.OLECMDERR_E_UNKNOWNGROUP;
  1191. }
  1192. return base.QueryStatusOnNode(cmdGroup, cmd, pCmdText, ref result);
  1193. }
  1194. /// <summary>
  1195. /// Handles command execution.
  1196. /// </summary>
  1197. /// <param name="cmdGroup">Unique identifier of the command group</param>
  1198. /// <param name="cmd">The command to be executed.</param>
  1199. /// <param name="nCmdexecopt">Values describe how the object should execute the command.</param>
  1200. /// <param name="pvaIn">Pointer to a VARIANTARG structure containing input arguments. Can be NULL</param>
  1201. /// <param name="pvaOut">VARIANTARG structure to receive command output. Can be NULL.</param>
  1202. /// <returns>If the method succeeds, it returns S_OK. If it fails, it returns an error code.</returns>
  1203. protected override int ExecCommandOnNode(Guid cmdGroup, uint cmd, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
  1204. {
  1205. if (cmdGroup == VsMenus.guidStandardCommandSet97)
  1206. {
  1207. switch ((VsCommands)cmd)
  1208. {
  1209. case VsCommands.UnloadProject:
  1210. return this.UnloadProject();
  1211. case VsCommands.CleanSel:
  1212. case VsCommands.CleanCtx:
  1213. return this.CleanProject();
  1214. }
  1215. }
  1216. else if (cmdGroup == VsMenus.guidStandardCommandSet2K)
  1217. {
  1218. switch ((VsCommands2K)cmd)
  1219. {
  1220. case VsCommands2K.ADDREFERENCE:
  1221. return this.AddProjectReference();
  1222. case VsCommands2K.ADDWEBREFERENCE:
  1223. case VsCommands2K.ADDWEBREFERENCECTX:
  1224. return this.AddWebReference();
  1225. }
  1226. }
  1227. return base.ExecCommandOnNode(cmdGroup, cmd, nCmdexecopt, pvaIn, pvaOut);
  1228. }
  1229. /// <summary>
  1230. /// Get the boolean value for the deletion of a project item
  1231. /// </summary>
  1232. /// <param name="deleteOperation">A flag that specifies the type of delete operation (delete from storage or remove from project)</param>
  1233. /// <returns>true if item can be deleted from project</returns>
  1234. protected override bool CanDeleteItem(__VSDELETEITEMOPERATION deleteOperation)
  1235. {
  1236. if (deleteOperation == __VSDELETEITEMOPERATION.DELITEMOP_RemoveFromProject)
  1237. {
  1238. return true;
  1239. }
  1240. return false;
  1241. }
  1242. /// <summary>
  1243. /// Returns a specific Document manager to handle opening and closing of the Project(Application) Designer if projectdesigner is supported.
  1244. /// </summary>
  1245. /// <returns>Document manager object</returns>
  1246. protected internal override DocumentManager GetDocumentManager()
  1247. {
  1248. if (this.SupportsProjectDesigner)
  1249. {
  1250. return new ProjectDesignerDocumentManager(this);
  1251. }
  1252. return null;
  1253. }
  1254. #endre

Large files files are truncated, but you can click here to view the full file