PageRenderTime 47ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/IronPython_Main/Tools/IronStudio/IronStudio/VisualStudio/Project/Automation/OAProjectItems.cs

#
C# | 230 lines | 136 code | 30 blank | 64 comment | 35 complexity | 1e156963074dc8c996cfed4ad91eb6a9 MD5 | raw file
Possible License(s): GPL-2.0, MPL-2.0-no-copyleft-exception, CPL-1.0, CC-BY-SA-3.0, BSD-3-Clause, ISC, AGPL-3.0, LGPL-2.1, Apache-2.0
  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.Diagnostics;
  16. using System.Diagnostics.CodeAnalysis;
  17. using System.Globalization;
  18. using System.IO;
  19. using System.Runtime.InteropServices;
  20. using EnvDTE;
  21. using Microsoft.VisualStudio;
  22. using Microsoft.VisualStudio.Shell.Interop;
  23. namespace Microsoft.VisualStudio.Project.Automation
  24. {
  25. /// <summary>
  26. /// Contains ProjectItem objects
  27. /// </summary>
  28. [SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")]
  29. [ComVisible(true), CLSCompliant(false)]
  30. public class OAProjectItems : OANavigableProjectItems
  31. {
  32. #region ctor
  33. public OAProjectItems(OAProject project, HierarchyNode nodeWithItems)
  34. : base(project, nodeWithItems)
  35. {
  36. }
  37. #endregion
  38. #region EnvDTE.ProjectItems
  39. /// <summary>
  40. /// Creates a new project item from an existing item template file and adds it to the project.
  41. /// </summary>
  42. /// <param name="fileName">The full path and file name of the template project file.</param>
  43. /// <param name="name">The file name to use for the new project item.</param>
  44. /// <returns>A ProjectItem object. </returns>
  45. public override EnvDTE.ProjectItem AddFromTemplate(string fileName, string name)
  46. {
  47. if(this.Project == null || this.Project.Project == null || this.Project.Project.Site == null || this.Project.Project.IsClosed)
  48. {
  49. throw new InvalidOperationException();
  50. }
  51. ProjectNode proj = this.Project.Project;
  52. EnvDTE.ProjectItem itemAdded = null;
  53. using(AutomationScope scope = new AutomationScope(this.Project.Project.Site))
  54. {
  55. // Determine the operation based on the extension of the filename.
  56. // We should run the wizard only if the extension is vstemplate
  57. // otherwise it's a clone operation
  58. VSADDITEMOPERATION op;
  59. if(Utilities.IsTemplateFile(fileName))
  60. {
  61. op = VSADDITEMOPERATION.VSADDITEMOP_RUNWIZARD;
  62. }
  63. else
  64. {
  65. op = VSADDITEMOPERATION.VSADDITEMOP_CLONEFILE;
  66. }
  67. VSADDRESULT[] result = new VSADDRESULT[1];
  68. // It is not a very good idea to throw since the AddItem might return Cancel or Abort.
  69. // The problem is that up in the call stack the wizard code does not check whether it has received a ProjectItem or not and will crash.
  70. // The other problem is that we cannot get add wizard dialog back if a cancel or abort was returned because we throw and that code will never be executed. Typical catch 22.
  71. ErrorHandler.ThrowOnFailure(proj.AddItem(this.NodeWithItems.ID, op, name, 0, new string[1] { fileName }, IntPtr.Zero, result));
  72. string fileDirectory = proj.GetBaseDirectoryForAddingFiles(this.NodeWithItems);
  73. string templateFilePath = System.IO.Path.Combine(fileDirectory, name);
  74. itemAdded = this.EvaluateAddResult(result[0], templateFilePath);
  75. }
  76. return itemAdded;
  77. }
  78. /// <summary>
  79. /// Adds a folder to the collection of ProjectItems with the given name.
  80. ///
  81. /// The kind must be null, empty string, or the string value of vsProjectItemKindPhysicalFolder.
  82. /// Virtual folders are not supported by this implementation.
  83. /// </summary>
  84. /// <param name="name">The name of the new folder to add</param>
  85. /// <param name="kind">A string representing a Guid of the folder kind.</param>
  86. /// <returns>A ProjectItem representing the newly added folder.</returns>
  87. public override ProjectItem AddFolder(string name, string kind)
  88. {
  89. if(this.Project == null || this.Project.Project == null || this.Project.Project.Site == null || this.Project.Project.IsClosed)
  90. {
  91. throw new InvalidOperationException();
  92. }
  93. //Verify name is not null or empty
  94. Utilities.ValidateFileName(this.Project.Project.Site, name);
  95. //Verify that kind is null, empty, or a physical folder
  96. if(!(string.IsNullOrEmpty(kind) || kind.Equals(EnvDTE.Constants.vsProjectItemKindPhysicalFolder)))
  97. {
  98. throw new ArgumentException("Parameter specification for AddFolder was not meet", "kind");
  99. }
  100. for(HierarchyNode child = this.NodeWithItems.FirstChild; child != null; child = child.NextSibling)
  101. {
  102. if(child.Caption.Equals(name, StringComparison.OrdinalIgnoreCase))
  103. {
  104. throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, "Folder already exists with the name '{0}'", name));
  105. }
  106. }
  107. ProjectNode proj = this.Project.Project;
  108. HierarchyNode newFolder = null;
  109. using(AutomationScope scope = new AutomationScope(this.Project.Project.Site))
  110. {
  111. //In the case that we are adding a folder to a folder, we need to build up
  112. //the path to the project node.
  113. name = Path.Combine(this.NodeWithItems.VirtualNodeName, name);
  114. newFolder = proj.CreateFolderNodes(name);
  115. }
  116. return newFolder.GetAutomationObject() as ProjectItem;
  117. }
  118. /// <summary>
  119. /// Copies a source file and adds it to the project.
  120. /// </summary>
  121. /// <param name="filePath">The path and file name of the project item to be added.</param>
  122. /// <returns>A ProjectItem object. </returns>
  123. public override EnvDTE.ProjectItem AddFromFileCopy(string filePath)
  124. {
  125. return this.AddItem(filePath, VSADDITEMOPERATION.VSADDITEMOP_CLONEFILE);
  126. }
  127. /// <summary>
  128. /// Adds a project item from a file that is installed in a project directory structure.
  129. /// </summary>
  130. /// <param name="fileName">The file name of the item to add as a project item. </param>
  131. /// <returns>A ProjectItem object. </returns>
  132. public override EnvDTE.ProjectItem AddFromFile(string fileName)
  133. {
  134. // TODO: VSADDITEMOP_LINKTOFILE
  135. return this.AddItem(fileName, VSADDITEMOPERATION.VSADDITEMOP_OPENFILE);
  136. }
  137. #endregion
  138. #region helper methods
  139. /// <summary>
  140. /// Adds an item to the project.
  141. /// </summary>
  142. /// <param name="path">The full path of the item to add.</param>
  143. /// <param name="op">The <paramref name="VSADDITEMOPERATION"/> to use when adding the item.</param>
  144. /// <returns>A ProjectItem object. </returns>
  145. protected virtual EnvDTE.ProjectItem AddItem(string path, VSADDITEMOPERATION op)
  146. {
  147. if(this.Project == null || this.Project.Project == null || this.Project.Project.Site == null || this.Project.Project.IsClosed)
  148. {
  149. throw new InvalidOperationException();
  150. }
  151. ProjectNode proj = this.Project.Project;
  152. EnvDTE.ProjectItem itemAdded = null;
  153. using(AutomationScope scope = new AutomationScope(this.Project.Project.Site))
  154. {
  155. VSADDRESULT[] result = new VSADDRESULT[1];
  156. ErrorHandler.ThrowOnFailure(proj.AddItem(this.NodeWithItems.ID, op, path, 0, new string[1] { path }, IntPtr.Zero, result));
  157. string fileName = System.IO.Path.GetFileName(path);
  158. string fileDirectory = proj.GetBaseDirectoryForAddingFiles(this.NodeWithItems);
  159. string filePathInProject = System.IO.Path.Combine(fileDirectory, fileName);
  160. itemAdded = this.EvaluateAddResult(result[0], filePathInProject);
  161. }
  162. return itemAdded;
  163. }
  164. /// <summary>
  165. /// Evaluates the result of an add operation.
  166. /// </summary>
  167. /// <param name="result">The <paramref name="VSADDRESULT"/> returned by the Add methods</param>
  168. /// <param name="path">The full path of the item added.</param>
  169. /// <returns>A ProjectItem object.</returns>
  170. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
  171. protected virtual EnvDTE.ProjectItem EvaluateAddResult(VSADDRESULT result, string path)
  172. {
  173. if(result == VSADDRESULT.ADDRESULT_Success)
  174. {
  175. HierarchyNode nodeAdded = this.NodeWithItems.FindChild(path);
  176. Debug.Assert(nodeAdded != null, "We should have been able to find the new element in the hierarchy");
  177. if(nodeAdded != null)
  178. {
  179. EnvDTE.ProjectItem item = null;
  180. if(nodeAdded is FileNode)
  181. {
  182. item = new OAFileItem(this.Project, nodeAdded as FileNode);
  183. }
  184. else if(nodeAdded is NestedProjectNode)
  185. {
  186. item = new OANestedProjectItem(this.Project, nodeAdded as NestedProjectNode);
  187. }
  188. else
  189. {
  190. item = new OAProjectItem<HierarchyNode>(this.Project, nodeAdded);
  191. }
  192. this.Items.Add(item);
  193. return item;
  194. }
  195. }
  196. return null;
  197. }
  198. #endregion
  199. }
  200. }