背景
最近因为项目需要,要对工程的代码进行统计,网上有很多的代码统计工具,最常用的是<SourceCounter>,但是我发现没有针对我的需求的功能,大多是递归目录、指定文件类型、统计所有代码行数和注释行、空白行等,而我的需求是在此基础之上,还要统计每个文件中方法的个数、每个方法的行数、方法的分级(这里说的分级是指每个方法的代码行数在某个范围内,就对应一个等级)等信息。在网上苦苦搜寻了一阵,发现并没有这样的代码统计工具(也许是我没有找到,呵呵,如果您知道可以告诉我,我可以参考下,互相学习),于是决定自己动手,丰衣足食。大致的思路就是正则匹配、标记、统计。由于时间紧促,功能不是十分地完善,希望能够通过这篇文章抛砖引玉,来完善这个小程序。废话不多说,直接上代码。
统计方法的个数
1 public static void CountMethods(string path) 2 { 3 int count = 0; 4 Regex reg = new Regex(@"\s*\w*\s*\w*\s*\w*\s+\w+\([^=!><]*\)(//.*)?\s*\{?$"); 5 string[] lines = File.ReadAllLines(path); 6 for (int i = 0; i < lines.Length; i++) 7 { 8 if (reg.IsMatch(lines[i].ToString())) 9 { 10 count++; 11 } 12 } 13 string info = string.Format("total methods:{0}",count); 14 Tool.Print(info); 15 }
统计方法名称
1 public static void GetMethodNameAndLines(string path) 2 { 3 string[] input = File.ReadAllLines(path); 4 MatchCollection mc = null; 5 Regex reg = new Regex(@"\s*\w*\s*\w*\s*\w+\s+\w+\([^=!><.]*\)(//.*)?\s*\{?$"); 6 ArrayList al = new ArrayList(); 7 for (int i = 0; i < input.Length; i++) 8 { 9 mc = reg.Matches(input[i]); 10 if (mc.Count > 0) 11 { 12 al.Add(mc[0].ToString()); 13 } 14 } 15 for (int m = 0; m < al.Count; m++) 16 { 17 Console.WriteLine(string.Format("第{0}个方法:{1}",m+1,al[m].ToString())); 18 } 19 Console.ReadLine(); 20 }
正则与栈结合,统计方法行数名称和个数
1 public static void StackCount(string path) 2 { 3 Stack stack = new Stack(); 4 //ht存放方法名和方法行数 5 Hashtable ht = new Hashtable(); 6 //指示是否为有效方法行 7 bool isLine = false; 8 //指示方法是否结束 9 bool isEnd = false; 10 string methodName = ""; 11 //标记后续是否还有方法 0-无 1-有 12 int flag = 0; 13 //临时存放方法行数 14 int count = 0; 15 //方法之外的普通行 16 int j = 0; 17 //匹配方法名 18 Regex regMethodName = new Regex(@"\s+\w+\s*\("); 19 //匹配方法开始行 20 Regex regLineStart = new Regex(@"\s*\w*\s*\w*\s*\w+\s+\w+\([^=!><.]*\)(//.*)?\s*\{?$"); 21 //匹配左大括号 22 Regex regLeft = new Regex(@"\s+\{"); 23 //匹配右大括号 24 Regex regRight = new Regex(@"\s+\}"); 25 //存放源码字符串数组 26 string[] lines = File.ReadAllLines(path); 27 for (int i = 0; i < lines.Length; i++) 28 { 29 if (regLineStart.IsMatch(lines[i])) 30 { 31 Match mc = regMethodName.Match(lines[i].ToString()); 32 methodName = Tool.GetMethodName(mc.ToString()); 33 if (lines[i].ToString().Contains('{')) 34 { 35 stack.Push(lines[i].ToString()); 36 } 37 isLine = true; 38 isEnd = false; 39 flag = 1; 40 count++; 41 } 42 else if (regLeft.IsMatch(lines[i].ToString())) 43 { 44 if (isLine) 45 { 46 count++; 47 //此处避免不规范写法导致的统计失误 48 if (lines[i].Contains('{') && lines[i].Contains('}')) 49 { 50 continue; 51 } 52 stack.Push(lines[i].ToString()); 53 } 54 } 55 else if (regRight.IsMatch(lines[i])) 56 { 57 if (!isEnd) 58 { 59 stack.Pop(); 60 count++; 61 } 62 if (stack.Count == 0) 63 { 64 isLine = false; 65 isEnd = true; 66 if (flag != 0) 67 { 68 //解决重载方法的重名问题 69 if (ht.ContainsKey(methodName)) 70 { 71 //isOverride += 1; 72 methodName = methodName + "重载+" + i; 73 } 74 ht.Add(methodName, count); 75 count = 0; 76 } 77 else 78 { 79 j++; 80 } 81 flag = 0; 82 } 83 } 84 else if (isLine) 85 { 86 count++; 87 } 88 else 89 { 90 j++; 91 } 92 } 93 foreach (DictionaryEntry de in ht) 94 { 95 Console.WriteLine(de.Key.ToString()); 96 Console.WriteLine(de.Value.ToString()); 97 } 98 Console.ReadLine(); 99 }
最后,附上运行效果图
作者:悠扬的牧笛
博客地址:http://www.cnblogs.com/xhb-bky-blog/p/3677874.html
声明:本博客原创文字只代表本人工作中在某一时间内总结的观点或结论,与本人所在单位没有直接利益关系。非商业,未授权贴子请以现状保留,转载时必须保留此段声明,且在文章页面明显位置给出原文连接。