/Plugins/Statistics/GitStatistics/CodeFile.cs

https://github.com/yiketudou/gitextensions · C# · 180 lines · 144 code · 30 blank · 6 comment · 62 complexity · 03203e3fda4a640649ae4df68220abee MD5 · raw file

  1. using System.IO;
  2. namespace GitStatistics
  3. {
  4. /// <summary>
  5. /// Represents a .NET file containing code: a .vb, .cs, .cpp, or .h file here.
  6. /// </summary>
  7. public class CodeFile
  8. {
  9. private readonly bool _isDesignerFile;
  10. protected int NumberCodeFiles;
  11. private bool _inCodeGeneratedRegion;
  12. private bool _inCommentBlock;
  13. private bool _skipResetFlag;
  14. internal CodeFile(string fullName)
  15. {
  16. File = new FileInfo(fullName);
  17. _isDesignerFile = IsDesignerFile();
  18. IsTestFile = false;
  19. }
  20. public FileInfo File { get; private set; }
  21. protected internal int NumberLines { get; protected set; }
  22. protected internal int NumberBlankLines { get; protected set; }
  23. protected internal int NumberLinesInDesignerFiles { get; protected set; }
  24. protected internal int NumberCommentsLines { get; protected set; }
  25. internal bool IsTestFile { get; private set; }
  26. private bool IsDesignerFile()
  27. {
  28. return
  29. IsWebReferenceFile() ||
  30. File.Name.Contains(".Designer.") ||
  31. File.Name.Contains(".designer.");
  32. }
  33. private bool IsWebReferenceFile()
  34. {
  35. return File.FullName.Contains(@"\Web References\") &&
  36. File.Name == "Reference.cs"; // Ugh
  37. }
  38. public void CountLines()
  39. {
  40. InitializeCountLines();
  41. if (!File.Exists)
  42. return;
  43. using (var sr = new StreamReader(File.FullName, true))
  44. {
  45. try
  46. {
  47. while (!sr.EndOfStream)
  48. {
  49. var line = sr.ReadLine();
  50. if (line != null)
  51. IncrementLineCountsFromLine(line.Trim());
  52. }
  53. }
  54. finally
  55. {
  56. sr.Close();
  57. }
  58. }
  59. }
  60. private void InitializeCountLines()
  61. {
  62. SetLineCountsToZero();
  63. NumberCodeFiles = 1;
  64. _inCodeGeneratedRegion = false;
  65. _inCommentBlock = false;
  66. }
  67. protected void SetLineCountsToZero()
  68. {
  69. NumberLines = 0;
  70. NumberBlankLines = 0;
  71. NumberLinesInDesignerFiles = 0;
  72. NumberCommentsLines = 0;
  73. NumberCodeFiles = 0;
  74. }
  75. private void IncrementLineCountsFromLine(string line)
  76. {
  77. SetCodeBlockFlags(line);
  78. NumberLines++;
  79. if (_inCodeGeneratedRegion || _isDesignerFile)
  80. NumberLinesInDesignerFiles++;
  81. else if (line == "")
  82. NumberBlankLines++;
  83. else if (_inCommentBlock || line.StartsWith("'") || line.StartsWith(@"//"))
  84. NumberCommentsLines++;
  85. else if (File.Extension.ToLower() == ".py" && line.StartsWith("#"))
  86. NumberCommentsLines++;
  87. else if (File.Extension.ToLower() == ".rb" && line.StartsWith("#"))
  88. NumberCommentsLines++;
  89. if (!_skipResetFlag)
  90. ResetCodeBlockFlags(line);
  91. }
  92. private void SetCodeBlockFlags(string line)
  93. {
  94. _skipResetFlag = false;
  95. // The number of code-generated lines is an approximation at best, particularly
  96. // with VS 2003 code. Change code here if you don't like the way it's working.
  97. // if (line.Contains("Designer generated code") // Might be cleaner
  98. if (line.StartsWith("#region Windows Form Designer generated code") ||
  99. line.StartsWith("#Region \" Windows Form Designer generated code") ||
  100. line.StartsWith("#region Component Designer generated code") ||
  101. line.StartsWith("#Region \" Component Designer generated code \"") ||
  102. line.StartsWith("#region Web Form Designer generated code") ||
  103. line.StartsWith("#Region \" Web Form Designer Generated Code \"")
  104. )
  105. _inCodeGeneratedRegion = true;
  106. if (line.StartsWith("/*"))
  107. _inCommentBlock = true;
  108. if (File.Extension.ToLower() == ".pas" || File.Extension.ToLower() == ".inc")
  109. {
  110. if (line.StartsWith("(*") && !line.StartsWith("(*$"))
  111. _inCommentBlock = true;
  112. if (line.StartsWith("{") && !line.StartsWith("{$"))
  113. _inCommentBlock = true;
  114. }
  115. if (File.Extension.ToLower() == ".rb" && line.StartsWith("=begin"))
  116. _inCommentBlock = true;
  117. if (File.Extension.ToLower() == ".py" && !_inCommentBlock)
  118. {
  119. if (line.StartsWith("'''") || line.StartsWith("\"\"\""))
  120. {
  121. _inCommentBlock = true;
  122. _skipResetFlag = true;
  123. }
  124. }
  125. if (!_inCommentBlock && !_inCodeGeneratedRegion && line.StartsWith("[Test"))
  126. {
  127. IsTestFile = true;
  128. }
  129. }
  130. private void ResetCodeBlockFlags(string line)
  131. {
  132. if (_inCodeGeneratedRegion && (line.Contains("#endregion") || line.Contains("#End Region")))
  133. _inCodeGeneratedRegion = false;
  134. if (_inCommentBlock && line.Contains("*/"))
  135. _inCommentBlock = false;
  136. if (File.Extension.ToLower() == ".pas" || File.Extension.ToLower() == ".inc")
  137. {
  138. if (line.Contains("*)") || line.Contains("}"))
  139. _inCommentBlock = false;
  140. }
  141. if (File.Extension.ToLower() == ".rb" && line.Contains("=end"))
  142. _inCommentBlock = false;
  143. if (File.Extension.ToLower() == ".py")
  144. {
  145. if (line.Contains("'''") || line.Contains("\"\"\""))
  146. _inCommentBlock = false;
  147. }
  148. }
  149. }
  150. }