PageRenderTime 60ms CodeModel.GetById 43ms RepoModel.GetById 0ms app.codeStats 1ms

/ICSharpCode.NRefactory.CSharp.Refactoring/CodeIssues/Synced/CompilerWarnings/CS1573ParameterHasNoMatchingParamTagIssue.cs

http://github.com/icsharpcode/NRefactory
C# | 283 lines | 246 code | 12 blank | 25 comment | 4 complexity | ea9dbb99d708ea7dcb2a88e0d55fd736 MD5 | raw file
  1. //
  2. // CS1573ParameterHasNoMatchingParamTagIssue.cs
  3. //
  4. // Author:
  5. // Mike Kr├╝ger <mkrueger@xamarin.com>
  6. //
  7. // Copyright (c) 2013 Xamarin Inc. (http://xamarin.com)
  8. //
  9. // Permission is hereby granted, free of charge, to any person obtaining a copy
  10. // of this software and associated documentation files (the "Software"), to deal
  11. // in the Software without restriction, including without limitation the rights
  12. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. // copies of the Software, and to permit persons to whom the Software is
  14. // furnished to do so, subject to the following conditions:
  15. //
  16. // The above copyright notice and this permission notice shall be included in
  17. // all copies or substantial portions of the Software.
  18. //
  19. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. // THE SOFTWARE.
  26. using System;
  27. using System.Collections.Generic;
  28. using ICSharpCode.NRefactory.Semantics;
  29. using ICSharpCode.NRefactory.TypeSystem;
  30. using ICSharpCode.NRefactory.PatternMatching;
  31. using ICSharpCode.NRefactory.Refactoring;
  32. using System.Linq;
  33. using System.Text;
  34. using System.Xml;
  35. using System.IO;
  36. using ICSharpCode.NRefactory.Documentation;
  37. namespace ICSharpCode.NRefactory.CSharp.Refactoring
  38. {
  39. [IssueDescription("Parameter has no matching param tag in the XML comment",
  40. Description = "Parameter has no matching param tag in the XML comment",
  41. Category = IssueCategories.CompilerWarnings,
  42. Severity = Severity.Warning,
  43. PragmaWarning = 1573,
  44. AnalysisDisableKeyword = "CSharpWarnings::CS1573")]
  45. public class CS1573ParameterHasNoMatchingParamTagIssue : GatherVisitorCodeIssueProvider
  46. {
  47. protected override IGatherVisitor CreateVisitor(BaseRefactoringContext context)
  48. {
  49. return new GatherVisitor(context);
  50. }
  51. class GatherVisitor : GatherVisitorBase<CS1573ParameterHasNoMatchingParamTagIssue>
  52. {
  53. readonly List<Comment> storedXmlComment = new List<Comment>();
  54. public GatherVisitor(BaseRefactoringContext ctx)
  55. : base (ctx)
  56. {
  57. }
  58. void InvalideXmlComments()
  59. {
  60. storedXmlComment.Clear();
  61. }
  62. public override void VisitComment(Comment comment)
  63. {
  64. base.VisitComment(comment);
  65. if (comment.CommentType == CommentType.Documentation)
  66. storedXmlComment.Add(comment);
  67. }
  68. public override void VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration)
  69. {
  70. InvalideXmlComments();
  71. base.VisitNamespaceDeclaration(namespaceDeclaration);
  72. }
  73. public override void VisitUsingDeclaration(UsingDeclaration usingDeclaration)
  74. {
  75. InvalideXmlComments();
  76. base.VisitUsingDeclaration(usingDeclaration);
  77. }
  78. public override void VisitUsingAliasDeclaration(UsingAliasDeclaration usingDeclaration)
  79. {
  80. InvalideXmlComments();
  81. base.VisitUsingAliasDeclaration(usingDeclaration);
  82. }
  83. public override void VisitExternAliasDeclaration(ExternAliasDeclaration externAliasDeclaration)
  84. {
  85. InvalideXmlComments();
  86. base.VisitExternAliasDeclaration(externAliasDeclaration);
  87. }
  88. void AddXmlIssue(int line, int col, int length, string str)
  89. {
  90. var cmt = storedXmlComment [Math.Max(0, Math.Min(storedXmlComment.Count - 1, line))];
  91. AddIssue(new CodeIssue(new TextLocation(cmt.StartLocation.Line, cmt.StartLocation.Column + 3 + col),
  92. new TextLocation(cmt.StartLocation.Line, cmt.StartLocation.Column + 3 + col + length),
  93. str));
  94. }
  95. int SearchAttributeColumn(int x, int line)
  96. {
  97. var comment = storedXmlComment [Math.Max(0, Math.Min(storedXmlComment.Count - 1, line))];
  98. var idx = comment.Content.IndexOfAny(new char[] { '"', '\'' }, x);
  99. return idx < 0 ? x : idx + 1;
  100. }
  101. void CheckXmlDoc(AstNode node)
  102. {
  103. ResolveResult resolveResult = ctx.Resolve(node);
  104. IEntity member = null;
  105. if (resolveResult is TypeResolveResult)
  106. member = resolveResult.Type.GetDefinition();
  107. if (resolveResult is MemberResolveResult)
  108. member = ((MemberResolveResult)resolveResult).Member;
  109. var xml = new StringBuilder();
  110. xml.AppendLine("<root>");
  111. foreach (var cmt in storedXmlComment)
  112. xml.AppendLine(cmt.Content);
  113. xml.AppendLine("</root>");
  114. List<Tuple<string, int>> parameters = new List<Tuple<string, int>>();
  115. using (var reader = new XmlTextReader(new StringReader(xml.ToString()))) {
  116. reader.XmlResolver = null;
  117. try {
  118. while (reader.Read()) {
  119. if (member == null)
  120. continue;
  121. if (reader.NodeType == XmlNodeType.Element) {
  122. switch (reader.Name) {
  123. case "param":
  124. reader.MoveToFirstAttribute();
  125. var line = reader.LineNumber;
  126. var name = reader.GetAttribute("name");
  127. if (name == null)
  128. break;
  129. parameters.Add(Tuple.Create(name, line));
  130. break;
  131. }
  132. }
  133. }
  134. } catch (XmlException) {
  135. }
  136. if (storedXmlComment.Count > 0 && parameters.Count > 0) {
  137. var pm = member as IParameterizedMember;
  138. if (pm != null) {
  139. for (int i = 0; i < pm.Parameters.Count; i++) {
  140. var p = pm.Parameters [i];
  141. if (!parameters.Any(tp => tp.Item1 == p.Name)) {
  142. AstNode before = i < parameters.Count ? storedXmlComment [parameters [i].Item2 - 2] : null;
  143. AstNode afterNode = before == null ? storedXmlComment [storedXmlComment.Count - 1] : null;
  144. AddIssue(new CodeIssue(
  145. GetParameterHighlightNode(node, i),
  146. string.Format(ctx.TranslateString("Missing xml documentation for Parameter '{0}'"), p.Name),
  147. string.Format(ctx.TranslateString("Create xml documentation for Parameter '{0}'"), p.Name),
  148. script => {
  149. if (before != null) {
  150. script.InsertBefore(
  151. before,
  152. new Comment(string.Format(" <param name = \"{0}\"></param>", p.Name), CommentType.Documentation)
  153. );
  154. } else {
  155. script.InsertAfter(
  156. afterNode,
  157. new Comment(string.Format(" <param name = \"{0}\"></param>", p.Name), CommentType.Documentation)
  158. );
  159. }
  160. }));
  161. }
  162. }
  163. }
  164. }
  165. storedXmlComment.Clear();
  166. }
  167. }
  168. AstNode GetParameterHighlightNode(AstNode node, int i)
  169. {
  170. if (node is MethodDeclaration)
  171. return ((MethodDeclaration)node).Parameters.ElementAt(i).NameToken;
  172. if (node is ConstructorDeclaration)
  173. return ((ConstructorDeclaration)node).Parameters.ElementAt(i).NameToken;
  174. if (node is OperatorDeclaration)
  175. return ((OperatorDeclaration)node).Parameters.ElementAt(i).NameToken;
  176. if (node is IndexerDeclaration)
  177. return ((IndexerDeclaration)node).Parameters.ElementAt(i).NameToken;
  178. throw new InvalidOperationException("invalid parameterized node:" + node);
  179. }
  180. protected virtual void VisitXmlChildren(AstNode node)
  181. {
  182. AstNode next;
  183. var child = node.FirstChild;
  184. while (child != null && (child is Comment || child is PreProcessorDirective || child.Role == Roles.NewLine)) {
  185. next = child.NextSibling;
  186. child.AcceptVisitor(this);
  187. child = next;
  188. }
  189. CheckXmlDoc(node);
  190. for (; child != null; child = next) {
  191. // Store next to allow the loop to continue
  192. // if the visitor removes/replaces child.
  193. next = child.NextSibling;
  194. child.AcceptVisitor(this);
  195. }
  196. InvalideXmlComments();
  197. }
  198. public override void VisitTypeDeclaration(TypeDeclaration typeDeclaration)
  199. {
  200. VisitXmlChildren(typeDeclaration);
  201. }
  202. public override void VisitMethodDeclaration(MethodDeclaration methodDeclaration)
  203. {
  204. VisitXmlChildren(methodDeclaration);
  205. }
  206. public override void VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration)
  207. {
  208. VisitXmlChildren(delegateDeclaration);
  209. }
  210. public override void VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration)
  211. {
  212. VisitXmlChildren(constructorDeclaration);
  213. }
  214. public override void VisitCustomEventDeclaration(CustomEventDeclaration eventDeclaration)
  215. {
  216. VisitXmlChildren(eventDeclaration);
  217. }
  218. public override void VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration)
  219. {
  220. VisitXmlChildren(destructorDeclaration);
  221. }
  222. public override void VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration)
  223. {
  224. VisitXmlChildren(enumMemberDeclaration);
  225. }
  226. public override void VisitEventDeclaration(EventDeclaration eventDeclaration)
  227. {
  228. VisitXmlChildren(eventDeclaration);
  229. }
  230. public override void VisitFieldDeclaration(FieldDeclaration fieldDeclaration)
  231. {
  232. VisitXmlChildren(fieldDeclaration);
  233. }
  234. public override void VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration)
  235. {
  236. VisitXmlChildren(indexerDeclaration);
  237. }
  238. public override void VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration)
  239. {
  240. VisitXmlChildren(propertyDeclaration);
  241. }
  242. public override void VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration)
  243. {
  244. VisitXmlChildren(operatorDeclaration);
  245. }
  246. }
  247. }
  248. }