/Project/Src/StyleCop.CSharp/ClassBase.cs

https://github.com/StyleCop/StyleCop · C# · 254 lines · 144 code · 25 blank · 85 comment · 41 complexity · 49b3a2c892a72a7ad9e5c5431aa5424a MD5 · raw file

  1. // --------------------------------------------------------------------------------------------------------------------
  2. // <copyright file="ClassBase.cs" company="https://github.com/StyleCop">
  3. // MS-PL
  4. // </copyright>
  5. // <license>
  6. // This source code is subject to terms and conditions of the Microsoft
  7. // Public License. A copy of the license can be found in the License.html
  8. // file at the root of this distribution. If you cannot locate the
  9. // Microsoft Public License, please send an email to dlr@microsoft.com.
  10. // By using this source code in any fashion, you are agreeing to be bound
  11. // by the terms of the Microsoft Public License. You must not remove this
  12. // notice, or any other, from this software.
  13. // </license>
  14. // <summary>
  15. // The base class for classes, structs and interfaces.
  16. // </summary>
  17. // --------------------------------------------------------------------------------------------------------------------
  18. namespace StyleCop.CSharp
  19. {
  20. using System.Collections.Generic;
  21. using System.Diagnostics;
  22. /// <summary>
  23. /// The base class for classes, structs and interfaces.
  24. /// </summary>
  25. /// <subcategory>element</subcategory>
  26. public abstract class ClassBase : CsElement, ITypeConstraintContainer
  27. {
  28. #region Fields
  29. /// <summary>
  30. /// The list of type constraints on the item, if any.
  31. /// </summary>
  32. private readonly ICollection<TypeParameterConstraintClause> typeConstraints;
  33. /// <summary>
  34. /// The name of the base class that this item inherits from.
  35. /// </summary>
  36. private string baseClass = string.Empty;
  37. /// <summary>
  38. /// The list of interfaces that this item implements.
  39. /// </summary>
  40. private string[] implementedInterfaces = new string[] { };
  41. #endregion
  42. #region Constructors and Destructors
  43. /// <summary>
  44. /// Initializes a new instance of the ClassBase class.
  45. /// </summary>
  46. /// <param name="document">
  47. /// The document that contains the element.
  48. /// </param>
  49. /// <param name="parent">
  50. /// The parent of the element.
  51. /// </param>
  52. /// <param name="type">
  53. /// The element type.
  54. /// </param>
  55. /// <param name="name">
  56. /// The name of this element.
  57. /// </param>
  58. /// <param name="header">
  59. /// The Xml header for this element.
  60. /// </param>
  61. /// <param name="attributes">
  62. /// The list of attributes attached to this element.
  63. /// </param>
  64. /// <param name="declaration">
  65. /// The declaration code for this element.
  66. /// </param>
  67. /// <param name="typeConstraints">
  68. /// The list of type constraints on the element.
  69. /// </param>
  70. /// <param name="unsafeCode">
  71. /// Indicates whether the element resides within a block of unsafe code.
  72. /// </param>
  73. /// <param name="generated">
  74. /// Indicates whether the code element was generated or written by hand.
  75. /// </param>
  76. internal ClassBase(
  77. CsDocument document,
  78. CsElement parent,
  79. ElementType type,
  80. string name,
  81. XmlHeader header,
  82. ICollection<Attribute> attributes,
  83. Declaration declaration,
  84. ICollection<TypeParameterConstraintClause> typeConstraints,
  85. bool unsafeCode,
  86. bool generated)
  87. : base(document, parent, type, name, header, attributes, declaration, unsafeCode, generated)
  88. {
  89. Param.Ignore(document, parent, type, name, header, attributes, declaration, typeConstraints, unsafeCode, generated);
  90. this.typeConstraints = typeConstraints;
  91. // Set the parent of the type constraint clauses.
  92. if (typeConstraints != null)
  93. {
  94. Debug.Assert(typeConstraints.IsReadOnly, "The typeconstraints collection should be read-only.");
  95. foreach (TypeParameterConstraintClause constraint in typeConstraints)
  96. {
  97. constraint.ParentElement = this;
  98. }
  99. }
  100. }
  101. #endregion
  102. #region Public Properties
  103. /// <summary>
  104. /// Gets the name of the base element that this element inherits from.
  105. /// </summary>
  106. public string BaseClass
  107. {
  108. get
  109. {
  110. return this.baseClass;
  111. }
  112. }
  113. /// <summary>
  114. /// Gets the list of interfaces that this element implements.
  115. /// </summary>
  116. public ICollection<string> ImplementedInterfaces
  117. {
  118. get
  119. {
  120. return this.implementedInterfaces;
  121. }
  122. }
  123. /// <summary>
  124. /// Gets the list of partial interfaces with the same fully qualified name as this element.
  125. /// </summary>
  126. /// <remarks>If this is not a partial element, this property returns null.</remarks>
  127. public ICollection<CsElement> PartialElementList
  128. {
  129. get
  130. {
  131. if (this.Declaration.ContainsModifier(CsTokenType.Partial))
  132. {
  133. CsDocument doc = (CsDocument)this.Document;
  134. lock (doc.Parser.PartialElements)
  135. {
  136. List<CsElement> partialElementList;
  137. if (doc.Parser.PartialElements.TryGetValue(this.FullNamespaceName, out partialElementList))
  138. {
  139. return partialElementList.ToArray();
  140. }
  141. }
  142. }
  143. return null;
  144. }
  145. }
  146. /// <summary>
  147. /// Gets the list of type constraints on the element, if any.
  148. /// </summary>
  149. public ICollection<TypeParameterConstraintClause> TypeConstraints
  150. {
  151. get
  152. {
  153. return this.typeConstraints;
  154. }
  155. }
  156. #endregion
  157. #region Methods
  158. /// <summary>
  159. /// Sets the inherited items of the class.
  160. /// </summary>
  161. /// <param name="declaration">
  162. /// The class declaration.
  163. /// </param>
  164. protected void SetInheritedItems(Declaration declaration)
  165. {
  166. Param.RequireNotNull(declaration, "declaration");
  167. // Pull out the name of the base class and any implemented interfaces
  168. // from the declaration of this class.
  169. bool colon = false;
  170. bool comma = false;
  171. List<string> interfaces = new List<string>();
  172. foreach (CsToken token in declaration.Tokens)
  173. {
  174. if (colon)
  175. {
  176. if (token.CsTokenType != CsTokenType.WhiteSpace && token.CsTokenType != CsTokenType.EndOfLine && token.CsTokenType != CsTokenType.SingleLineComment
  177. && token.CsTokenType != CsTokenType.MultiLineComment && token.CsTokenType != CsTokenType.PreprocessorDirective)
  178. {
  179. if (token.Text.Length >= 2 && token.Text[0] == 'I' && char.IsUpper(token.Text[1]))
  180. {
  181. interfaces.Add(CodeParser.TrimType(token.Text));
  182. }
  183. else
  184. {
  185. this.baseClass = CodeParser.TrimType(token.Text);
  186. }
  187. colon = false;
  188. }
  189. }
  190. else if (comma)
  191. {
  192. if (token.CsTokenType != CsTokenType.WhiteSpace && token.CsTokenType != CsTokenType.EndOfLine && token.CsTokenType != CsTokenType.SingleLineComment
  193. && token.CsTokenType != CsTokenType.MultiLineComment && token.CsTokenType != CsTokenType.PreprocessorDirective)
  194. {
  195. interfaces.Add(CodeParser.TrimType(token.Text));
  196. comma = false;
  197. }
  198. }
  199. else
  200. {
  201. if (token.CsTokenType == CsTokenType.Where)
  202. {
  203. break;
  204. }
  205. else if (token.Text == ":")
  206. {
  207. if (this.baseClass.Length > 0)
  208. {
  209. break;
  210. }
  211. else
  212. {
  213. colon = true;
  214. }
  215. }
  216. else if (token.CsTokenType == CsTokenType.Comma)
  217. {
  218. comma = true;
  219. }
  220. }
  221. }
  222. if (interfaces.Count > 0)
  223. {
  224. this.implementedInterfaces = interfaces.ToArray();
  225. }
  226. }
  227. #endregion
  228. }
  229. }