• 【原创】从另一个角度看代码统计


    背景

    最近因为项目需要,要对工程的代码进行统计,网上有很多的代码统计工具,最常用的是<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

     声明:本博客原创文字只代表本人工作中在某一时间内总结的观点或结论,与本人所在单位没有直接利益关系。非商业,未授权贴子请以现状保留,转载时必须保留此段声明,且在文章页面明显位置给出原文连接。

     
  • 相关阅读:
    单元测试利器 JUnit 4 Mr
    firefox插件介绍 Mr
    js函数使用技巧集合 Mr
    单点登录
    2.SilverLight动态加载控件
    3.如何获取动态生成的SL控件的NAME值(一)
    ASP.Net中控件的EnableViewState属性 【转】
    三种在ASP.NET中重写URL的方法
    SQLHelper.cs
    c# IS与AS的使用方法
  • 原文地址:https://www.cnblogs.com/xhb-bky-blog/p/3677874.html
Copyright © 2020-2023  润新知