PageRenderTime 54ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/Trunk/Source/VSSDKAssist.Assets/VSSDKAssist.Assets/Helpers/FileCodeModelHelper.cs

#
C# | 463 lines | 326 code | 44 blank | 93 comment | 44 complexity | b89dc000fc78528df579fb8cebfcfa07 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using EnvDTE;
  5. using EnvDTE80;
  6. using VSLangProj;
  7. namespace VSSDKAssist.Assets.Helpers
  8. {
  9. /// <summary>
  10. /// Visual Studio FileCodeModel helper class
  11. /// </summary>
  12. public static class FileCodeModelHelper
  13. {
  14. #region Public Implementation
  15. /// <summary>
  16. /// Gets the active code element.
  17. /// </summary>
  18. /// <param name="vs">The vs.</param>
  19. /// <param name="fileCodeModel">The file code model.</param>
  20. /// <param name="codeElementType">Type of the code element.</param>
  21. /// <returns></returns>
  22. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods")]
  23. public static object GetActiveCodeElement(DTE vs, FileCodeModel fileCodeModel, Type codeElementType)
  24. {
  25. Guard.ArgumentNotNull(vs, "vs");
  26. Guard.ArgumentNotNull(fileCodeModel, "fileCodeModel");
  27. Guard.ArgumentNotNull(codeElementType, "codeElementType");
  28. TextSelection textSelection = (TextSelection)vs.ActiveDocument.Selection;
  29. TextPoint point = textSelection.ActivePoint;
  30. object element;
  31. if(codeElementType.IsAssignableFrom(typeof(CodeNamespace)))
  32. {
  33. try
  34. {
  35. element = (CodeNamespace)fileCodeModel.CodeElementFromPoint(
  36. point,
  37. vsCMElement.vsCMElementNamespace);
  38. return element;
  39. }
  40. catch
  41. {
  42. return null;
  43. }
  44. }
  45. else if(codeElementType.IsAssignableFrom(typeof(CodeAttribute)))
  46. {
  47. try
  48. {
  49. element = (CodeAttribute)fileCodeModel.CodeElementFromPoint(
  50. point,
  51. vsCMElement.vsCMElementAttribute);
  52. return element;
  53. }
  54. catch
  55. {
  56. return null;
  57. }
  58. }
  59. else if(codeElementType.IsAssignableFrom(typeof(CodeClass)))
  60. {
  61. try
  62. {
  63. element = (CodeClass)fileCodeModel.CodeElementFromPoint(
  64. point,
  65. vsCMElement.vsCMElementClass);
  66. return element;
  67. }
  68. catch
  69. {
  70. return null;
  71. }
  72. }
  73. else if(codeElementType.IsAssignableFrom(typeof(CodeProperty)))
  74. {
  75. try
  76. {
  77. element = (CodeProperty)fileCodeModel.CodeElementFromPoint(
  78. point,
  79. vsCMElement.vsCMElementProperty);
  80. return element;
  81. }
  82. catch
  83. {
  84. return null;
  85. }
  86. }
  87. else if(codeElementType.IsAssignableFrom(typeof(CodeFunction)))
  88. {
  89. try
  90. {
  91. element = (CodeFunction)fileCodeModel.CodeElementFromPoint(
  92. point,
  93. vsCMElement.vsCMElementFunction);
  94. return element;
  95. }
  96. catch
  97. {
  98. return null;
  99. }
  100. }
  101. return null;
  102. }
  103. /// <summary>
  104. /// Determines whether the specified element has attribute.
  105. /// </summary>
  106. /// <param name="element">The element.</param>
  107. /// <param name="attributeName">Name of the attribute.</param>
  108. /// <returns>
  109. /// <c>true</c> if the specified element has attribute; otherwise, <c>false</c>.
  110. /// </returns>
  111. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods")]
  112. public static bool HasAttribute(CodeClass element, string attributeName)
  113. {
  114. Guard.ArgumentNotNull(element, "element");
  115. Guard.ArgumentNotNull(attributeName, "attributeName");
  116. if(element.Attributes.Count > 0)
  117. {
  118. foreach(CodeElement att in element.Attributes)
  119. {
  120. if(att.Name.Equals(attributeName, StringComparison.InvariantCultureIgnoreCase))
  121. {
  122. return true;
  123. }
  124. }
  125. }
  126. return false;
  127. }
  128. /// <summary>
  129. /// Adds the attribute.
  130. /// </summary>
  131. /// <param name="element">The element.</param>
  132. /// <param name="attributeName">Name of the attribute.</param>
  133. /// <param name="attributeValue">The attribute value.</param>
  134. /// <param name="dontCreateIfExists">if set to <c>true</c> [dont create if exists].</param>
  135. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods")]
  136. public static void AddAttribute(CodeClass element, string attributeName, string attributeValue, bool dontCreateIfExists)
  137. {
  138. Guard.ArgumentNotNull(element, "element");
  139. Guard.ArgumentNotNullOrEmptyString(attributeName, "attributeName");
  140. Guard.ArgumentNotNullOrEmptyString(attributeValue, "attributeValue");
  141. if(dontCreateIfExists && !HasAttribute(element, attributeName))
  142. {
  143. return;
  144. }
  145. element.AddAttribute(attributeName, attributeValue, element.Attributes.Count);
  146. }
  147. /// <summary>
  148. /// Inserts the text to code element.
  149. /// </summary>
  150. /// <param name="codeElement">The code element.</param>
  151. /// <param name="text">The text.</param>
  152. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods")]
  153. public static void InsertTextToCodeElement(CodeElement codeElement, string text)
  154. {
  155. Guard.ArgumentNotNull(codeElement, "codeElement");
  156. Guard.ArgumentNotNullOrEmptyString(text, "text");
  157. EditPoint startEditPoint = codeElement.StartPoint.CreateEditPoint();
  158. EditPoint editPoint = codeElement.EndPoint.CreateEditPoint();
  159. editPoint.MoveToLineAndOffset(editPoint.Line, 1);
  160. ((EditPoint2)editPoint).InsertNewLine(1);
  161. editPoint.LineUp(1);
  162. editPoint.Insert(text);
  163. //Re Format inserted text
  164. startEditPoint.StartOfDocument();
  165. editPoint.EndOfDocument();
  166. startEditPoint.SmartFormat(editPoint);
  167. }
  168. /// <summary>
  169. /// Updates the attribute.
  170. /// </summary>
  171. /// <param name="attribute">The attribute.</param>
  172. /// <param name="attributeValue">The attribute value.</param>
  173. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods")]
  174. public static void UpdateAttribute(CodeAttribute attribute, string attributeValue)
  175. {
  176. Guard.ArgumentNotNull(attribute, "attribute");
  177. Guard.ArgumentNotNull(attributeValue, "attributeValue");
  178. attribute.Value = attributeValue;
  179. }
  180. /// <summary>
  181. /// Gets the attribute.
  182. /// </summary>
  183. /// <param name="codeClass">The code class.</param>
  184. /// <param name="attributeName">Name of the attribute.</param>
  185. /// <returns></returns>
  186. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods")]
  187. public static CodeAttribute GetAttribute(CodeClass codeClass, string attributeName)
  188. {
  189. Guard.ArgumentNotNull(codeClass, "codeClass");
  190. Guard.ArgumentNotNull(attributeName, "attributeName");
  191. if(codeClass.Attributes.Count > 0)
  192. {
  193. foreach(CodeElement att in codeClass.Attributes)
  194. {
  195. CodeAttribute codeAttribute = (CodeAttribute)att;
  196. if(att.Name.Equals(attributeName, StringComparison.InvariantCultureIgnoreCase))
  197. {
  198. return codeAttribute;
  199. }
  200. }
  201. }
  202. return null;
  203. }
  204. /// <summary>
  205. /// Gets the code function.
  206. /// </summary>
  207. /// <param name="codeClass">The code class.</param>
  208. /// <param name="functionName">Name of the function.</param>
  209. /// <returns></returns>
  210. public static CodeFunction GetCodeFunction(CodeClass codeClass, string functionName)
  211. {
  212. CodeElementsIterator iterator = new CodeElementsIterator(codeClass as CodeElement);
  213. foreach(CodeElement element in iterator)
  214. {
  215. CodeFunction function = element as CodeFunction;
  216. if(function != null && (element.Name == functionName))
  217. {
  218. return function;
  219. }
  220. }
  221. return null;
  222. }
  223. /// <summary>
  224. /// Gets the attribute argument.
  225. /// </summary>
  226. /// <param name="attribute">The attribute.</param>
  227. /// <param name="attributeArgument">The attribute argument.</param>
  228. /// <returns></returns>
  229. public static CodeAttributeArgument GetAttributeArgument(CodeAttribute attribute, string attributeArgument)
  230. {
  231. CodeAttribute2 attribute2 = (EnvDTE80.CodeAttribute2)attribute;
  232. foreach(CodeAttributeArgument argument in attribute2.Arguments)
  233. {
  234. if(argument.Name.Equals(attributeArgument, StringComparison.InvariantCultureIgnoreCase))
  235. {
  236. return argument;
  237. }
  238. }
  239. return null;
  240. }
  241. /// <summary>
  242. /// Updates the code attribute argument.
  243. /// </summary>
  244. /// <param name="attributes">The attributes.</param>
  245. /// <param name="attributeName">Name of the attribute.</param>
  246. /// <param name="argumentName">Name of the argument.</param>
  247. /// <param name="argumentValue">The argument value.</param>
  248. /// <returns></returns>
  249. public static bool UpdateCodeAttributeArgument(
  250. CodeElements attributes,
  251. string attributeName,
  252. string argumentName,
  253. string argumentValue)
  254. {
  255. return UpdateCodeAttributeArgument(attributes, attributeName, argumentName, argumentValue, true);
  256. }
  257. /// <summary>
  258. /// Updates the code attribute argument.
  259. /// </summary>
  260. /// <param name="attributes">The attributes.</param>
  261. /// <param name="attributeName">Name of the attribute.</param>
  262. /// <param name="argumentName">Name of the argument.</param>
  263. /// <param name="argumentValue">The argument value.</param>
  264. /// <param name="createIfNew">if set to <c>true</c> [create if new].</param>
  265. /// <returns></returns>
  266. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:ValidateArgumentsOfPublicMethods")]
  267. public static bool UpdateCodeAttributeArgument(
  268. CodeElements attributes,
  269. string attributeName,
  270. string argumentName,
  271. string argumentValue,
  272. bool createIfNew)
  273. {
  274. Guard.ArgumentNotNull(attributes, "attributes");
  275. Guard.ArgumentNotNullOrEmptyString(attributeName, "attributeName");
  276. Guard.ArgumentNotNullOrEmptyString(argumentName, "argumentName");
  277. Guard.ArgumentNotNullOrEmptyString(argumentValue, "argumentValue");
  278. bool result = false;
  279. foreach(CodeElement attribute in attributes)
  280. {
  281. CodeAttribute codeAttribute = (CodeAttribute)attribute;
  282. if(attribute.FullName.Equals(attributeName, StringComparison.InvariantCultureIgnoreCase))
  283. {
  284. result = UpdateCodeAttributeArgument(codeAttribute, argumentName, argumentValue, createIfNew);
  285. break;
  286. }
  287. }
  288. return result;
  289. }
  290. /// <summary>
  291. /// Updates the code attribute argument.
  292. /// </summary>
  293. /// <param name="codeAttribute">The code attribute.</param>
  294. /// <param name="argumentName">Name of the argument.</param>
  295. /// <param name="argumentValue">The argument value.</param>
  296. /// <param name="createIfNew">if set to <c>true</c> [create if new].</param>
  297. /// <returns></returns>
  298. public static bool UpdateCodeAttributeArgument(
  299. CodeAttribute codeAttribute,
  300. string argumentName,
  301. string argumentValue,
  302. bool createIfNew)
  303. {
  304. Guard.ArgumentNotNull(codeAttribute, "codeAttribute");
  305. Guard.ArgumentNotNullOrEmptyString(argumentName, "argumentName");
  306. bool result = false;
  307. CodeAttribute2 attribute2 = (EnvDTE80.CodeAttribute2)codeAttribute;
  308. CodeAttributeArgument argumentMatch = null;
  309. foreach(CodeAttributeArgument argument in attribute2.Arguments)
  310. {
  311. if(argument.Name.Equals(argumentName, StringComparison.InvariantCultureIgnoreCase))
  312. {
  313. argumentMatch = argument;
  314. break;
  315. }
  316. }
  317. if(argumentMatch != null)
  318. {
  319. argumentMatch.Value = argumentValue;
  320. result = true;
  321. }
  322. else if(createIfNew)
  323. {
  324. attribute2.AddArgument(argumentValue, argumentName, attribute2.Arguments.Count);
  325. result = true;
  326. }
  327. return result;
  328. }
  329. /// <summary>
  330. /// Finds the name of the code element by type.
  331. /// </summary>
  332. /// <param name="project">The project.</param>
  333. /// <param name="typeName">Name of the type.</param>
  334. /// <param name="elementKind">Kind of the element.</param>
  335. /// <returns></returns>
  336. public static CodeElement FindCodeElementByTypeName(Project project, string typeName, vsCMElement elementKind)
  337. {
  338. CodeElement result = null;
  339. if(project == null ||
  340. string.IsNullOrEmpty(typeName))
  341. {
  342. return null;
  343. }
  344. foreach(ProjectItem projectItem in new ProjectItemIterator(project))
  345. {
  346. CodeElement element = FindCodeElementByTypeName(projectItem, typeName, elementKind);
  347. if(element != null)
  348. {
  349. result = element;
  350. break;
  351. }
  352. }
  353. if(result == null)
  354. {
  355. VSProject vsProject = project.Object as VSProject;
  356. foreach(Reference reference in vsProject.References)
  357. {
  358. result = FindCodeElementByTypeName(reference.SourceProject, typeName, elementKind);
  359. if(result != null &&
  360. result.InfoLocation == vsCMInfoLocation.vsCMInfoLocationProject)
  361. {
  362. break;
  363. }
  364. }
  365. }
  366. return result;
  367. }
  368. /// <summary>
  369. /// Finds the name of the code element by type.
  370. /// </summary>
  371. /// <param name="projectItem">The project item.</param>
  372. /// <param name="typeName">Name of the type.</param>
  373. /// <param name="elementKind">Kind of the element.</param>
  374. /// <returns></returns>
  375. public static CodeElement FindCodeElementByTypeName(
  376. ProjectItem projectItem, string typeName, vsCMElement elementKind)
  377. {
  378. foreach(CodeElement element in new CodeElementsIterator(projectItem))
  379. {
  380. if(element.Kind == vsCMElement.vsCMElementNamespace)
  381. {
  382. foreach(CodeElement type in ((CodeNamespace)element).Members)
  383. {
  384. CodeElement result = InspectCodeElement(type, typeName, elementKind);
  385. if(result != null)
  386. {
  387. return result;
  388. }
  389. }
  390. }
  391. else
  392. {
  393. CodeElement result = InspectCodeElement(element, typeName, elementKind);
  394. if(result != null)
  395. {
  396. return result;
  397. }
  398. }
  399. }
  400. return null;
  401. }
  402. #endregion
  403. #region Private Implementation
  404. private static CodeElement InspectCodeElement(
  405. CodeElement element, string targetFullName, vsCMElement elementKind)
  406. {
  407. if(element.IsCodeType)
  408. {
  409. if(element.Kind == elementKind &&
  410. element.FullName.Equals(targetFullName, StringComparison.InvariantCultureIgnoreCase))
  411. {
  412. return element;
  413. }
  414. }
  415. return null;
  416. }
  417. #endregion
  418. }
  419. }