最近在做一个项目的移植工作,项目很大,光c文件大约有1800多。由于某些需要,想要对某些代码文件引用的.h文件进行分析。
网上找了好久,暂无发现类似的工具。
正好,今天放假,就做了这么个工具。
好了,废话不多说了,先上图。
QQ截图20141012191057" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="QQ截图20141012191057" src="/Upload/Images/2014101223/0AA05E8CE24389BB.png" width="1932" height="1084" />
由于是自己做的个demo,所以只是先注重大体功能上的实现,细节上还有很多不足。比如没有使用多线程,去除代码文件中注释的地方还有个漏洞(文件读取1M导致的,不过几乎没影响),还有循环绘制node的地方(逻辑上稍微修改下更好)。
后面奉上代码,大家可以自己根据需求继续修改,也可以凑合这么用。
言归正传。
树形关系呈现上使用了DotNetBar中的TreeGX控件。下载地址:
http://down2.cr173.com/soft1/DotNetBarSetup.zip先setup,再patcher。
装好后,先添加引用,然后在工具箱中添加treeGX。
没错,项目名Jonce,“穷死”。好名字。
界面布局。
其实整个流程很简单,1获取指定目录下的所有代码文件;2分析出文件中#include包含的文件;3绘制node节点
CType.cs文件内容:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Jonce { struct CType { public string FullPath; public string FileName; public List<string> IncludeList; } }
该类型用于描述每个代码文件。
CFileHelper.cs文件内容:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; namespace Jonce { class CFileHelper { private List<string> fileList = new List<string>(); /// <summary> /// 获取及分析所有C代码文件 /// </summary> /// <param name="path">C项目路径</param> /// <returns></returns> public List<CType> GetAllCFile(string path) { List<CType> retList = new List<CType>(); getAllByPath(path); //过滤出所有文件中的代码文件 //分析引用,并存入List<CType>结构内 foreach (string item in fileList) { string extension = Path.GetExtension(item).ToLower(); if (extension == ".c" || extension == ".h" || extension == ".cpp") { CType cType = new CType(); cType.FullPath = item; cType.FileName = Path.GetFileName(item); //获取C文件中include引用的头文件 cType.IncludeList = SourceHelper.GetIncludeFile(SourceHelper.RemoveComments(item)); retList.Add(cType); } } return retList; } //获取指定目录下的所有文件 private void getAllByPath(string path) { if (path.EndsWith("\\")) { fileList.Add(path); } else { fileList.Add(path + "\\"); } string[] dirs = Directory.GetDirectories(path); fileList.AddRange(Directory.GetFiles(path)); foreach (string dir in dirs) { getAllByPath(dir.ToString()); } } } }
SourceHelper.cs文件内容:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.Windows.Forms; using System.Text.RegularExpressions; namespace Jonce { class SourceHelper { /// <summary> /// 去掉代码文件中的注释 /// </summary> /// <param name="filePath">文件全路径</param> /// <returns>文件前1M内容(去掉注释)</returns> public static string RemoveComments(string filePath) { string retStr = ""; //1M缓冲区 char[] buffer = new char[1024 * 1024]; using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) { using (StreamReader sr = new StreamReader(fs, Encoding.Default)) { try { //string fileStr = sr.ReadToEnd(); //读取文件。只读取<=1M内容 sr.Read(buffer, 0, buffer.Length); //字符数组转换为字符串,进行正则匹配 string fileStr = new string(buffer); //正则表达式,匹配多行注释和单行注释 string regStr = @"/\*[\s\S]*?\*/|//.*"; //去掉多行注释 retStr = Regex.Replace(fileStr, regStr, ""); } catch (Exception ex) { MessageBox.Show(ex.ToString(), "ERR"); } } } return retStr; } /// <summary> /// 获取C文件中include引用的头文件 /// </summary> /// <param name="fileStr">文件全路径</param> /// <returns>头文件List集合</returns> public static List<string> GetIncludeFile(string fileStr) { List<string> headFileList = new List<string>(); //匹配include语句 string regStr1 = @"#\s*include\s(""|<).*"; //匹配头文件 string regStr2 = @"\w+\.(h|H)\b"; Match mc1 = Regex.Match(fileStr, regStr1); while (mc1.Success) { Match mc2 = Regex.Match(mc1.ToString(), regStr2); if (mc2.Success) { headFileList.Add(mc2.ToString()); } mc1 = mc1.NextMatch(); } return headFileList; } } }
Form1.cs内容:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; using DevComponents.Tree; namespace Jonce { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { //选取目录 FolderBrowserDialog fbd = new FolderBrowserDialog(); if (fbd.ShowDialog()==DialogResult.OK) { string path = fbd.SelectedPath; CFileHelper fileHelper = new CFileHelper(); //获取及分析所有C代码文件 List<CType> cTypeList = fileHelper.GetAllCFile(path); //treeGX.Node节点用style ElementStyle style = new ElementStyle(); //节点文字颜色设置 style.TextColor = Color.Blue; foreach (CType item in cTypeList) { if (Path.GetExtension(item.FullPath).ToLower() == ".c") { Node cNode = new Node(); cNode.Name = item.FileName; cNode.Text = item.FileName; cNode.Style = style; cNode.NodeDoubleClick += cNode_NodeDoubleClick; this.node1.Nodes.Add(cNode); loopDraw(cTypeList, item.FileName, ref cNode); } } //this.node1.ExpandAll(); this.node1.Text = path; //刷新treeGX this.treeGX1.Refresh(); } } void cNode_NodeDoubleClick(object sender, EventArgs e) { Node node = sender as Node; node.Expand(); //node.ExpandAll(); //throw new NotImplementedException(); } private void loopDraw(List<CType> cTypeList, string fileName,ref Node node) { foreach (CType item in cTypeList) { if (item.FileName==fileName) { foreach (string strItem in item.IncludeList) { Node incNode = new Node(); incNode.Name = strItem; incNode.Text = strItem; incNode.NodeDoubleClick += cNode_NodeDoubleClick; node.Nodes.Add(incNode); loopDraw(cTypeList, strItem, ref incNode); } } } } private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) { if (comboBox1.SelectedItem==null) { return; } //DevComponents.Tree.eNodeLayout layout = (DevComponents.Tree.eNodeLayout)Enum.Parse(typeof(DevComponents.Tree.eNodeLayout), comboBox1.SelectedItem.ToString()); DevComponents.Tree.eMapFlow mapFlow = (DevComponents.Tree.eMapFlow)Enum.Parse(typeof(DevComponents.Tree.eMapFlow), comboBox1.SelectedItem.ToString()); if (treeGX1.MapLayoutFlow != mapFlow) { treeGX1.MapLayoutFlow = mapFlow; treeGX1.RecalcLayout(); treeGX1.Refresh(); } } private void button2_Click(object sender, EventArgs e) { this.node1.ExpandAll(); treeGX1.Refresh(); } private void button3_Click(object sender, EventArgs e) { this.node1.Nodes.Clear(); treeGX1.Refresh(); } } }
以上就是所有代码,大家可以自己重新搭建一个。
当然,如果谁csdn下载积分多的,也可以下载整个项目:http://download.csdn.net/detail/geeking/8030119
只要两个下载积分。本来想免费发的,可是我的积分一个也没有了,很多资源都没法下。shit,积分制度就是shit。