一、概述

上一篇文章C++解析头文件-Qt自动生成信号声明我们主要讲解了怎么去解析C++头文件,然后在指定位置插入函数声明,已达到自动化的效果。既然函数声明已经自动插入了,那么函数实现的定义当然也可以做到自动化插入,而且实现起来比头文件插入还要简单,稍微思考下就能得出结论,.cpp文件的复杂程度要远远低于.h文件。

本篇文章我们就来分享下怎么去插入函数定义

二、实现思路

头文件插入函数声明时,我们选择了先分析头文件,并记住关键位置的行号,然后在指定位置插入字符串,本篇文章我们还是沿用之前的套路,先分析.cpp文件中的所有函数,并记录在内存中,当我们插入新的函数时,我们只需要找到我们要插到哪个函数的下边,或者插入到所有函数之下的行号,执行插入操作即可。

这里有一个很重要的问题,我们怎么知道上一个函数是谁?这个就是函数定义插入的关键所在。

答案:通过分析头文件后的内存结构来获取。既然我们分析了头文件中所有的类,而且类中的函数和作用域我们都有存储,并且记录了所有的行号,那我们只需要找到指定作用域(或者上一个作用)的最后一个函数即可,这就是我们要插入的位置,当我们在实现文件中寻找行号时,只需要找到这个函数的最后一个行即可。

本篇文章是继上一篇文章C++解析头文件-Qt自动生成信号声明的后续,本篇文章的代码也是前一篇博客的完善,而且结构有了一定的修改。

三、代码讲解

1、类图

讲述代码之前,我们先把修改过后的类图贴上,更简洁。

  • QtGrammaAnalusis:对外接口类
  • QtDescription:头文件分析类基类,提供一些基础操作,包含了一个自己的指针,主要是头文件QtHeaderDescription和QtCppDescription可以相互访问
  • QtHeaderDescription:头文件分析类
  • QtCppDescription:实现文件分析类

2、QtCppDescription

本篇文章的细节代码比较少,因此这里我们稍微讲细一点儿,把关键代码都贴上来。首先看下头文件

a、类定义

看下接口是不是相当简单,公有接口是对外暴露的,私有函数主要是解析实现文件,下面让我们看下几个比较重要的函数

class QtCppDescription : public QtDescription
{
Q_OBJECT public:
QtCppDescription(QObject * parent);
~QtCppDescription(); public:
virtual void GenerateFuncationCode(FuncType, const QString &, const QString & = "") override; protected:
virtual void AnalysisFile() override;
private:
StatementType GuessType(int);
void AnalysisOne(int &); void AnalysisFunc(int &); private:
QList<BaseItem> m_funcations;//函数(变量)列表
};

b、分析一个完整的函数

代码分析中,当出现()*{这样的字符串时,我们认为是要匹配一个函数了,实际上也确实如此。

当我们开始匹配函数时,一个函数的结束也就是,函数中的左右花括号成对出现时

如下代码所示,当我们匹配完一个函数时,我们构造了一个BaseItem结构来存储它,主要是记录了开始行号、结束行号和函数名称,并存储在m_funcations结构中

void QtCppDescription::AnalysisFunc(int & row)
{
QString code = GenerateString(m_iCurRow, row);
int rIndex = code.indexOf("(");
int lIndex = code.lastIndexOf("::", rIndex);
QString name = code.mid(lIndex + 2, rIndex - lIndex - 2);
++row; while (row < m_strRowContexts.size())
{
QString funcCode = GenerateString(m_iCurRow, row);
if (funcCode.count("{") == funcCode.count("}"))
{
BaseItem item;
item.start = m_iCurRow;
item.end = row;
item.name = name;
m_funcations.append(item);
break;
}
++row;
}
}

记录函数末尾行号主要是为了我们方便插入新代码。

c、插入代码

插入函数定义代码也比较简单,首先就是根据头文件分析后的类结构查找到我们要插在哪个函数之后,接着我们去m_funcations结构中去查找相应的对象,获取我们要插入的行号,最后进行插入操作即可,是不是有了头文件的帮主,实现文件插入操作就变得相当简单啦。

void QtCppDescription::GenerateFuncationCode(FuncType type, const QString & code, const QString & /*= ""*/)
{
QtHeaderDescription * headerDescrition = dynamic_cast<QtHeaderDescription *>(m_pDescription);
if (nullptr != headerDescrition)
{
const ClassDescription & classDesc = headerDescrition->GetDescription();
//获取上一个函数名称 int index = type;
const QMap<int, ScopePiece> & scopeIndexs = classDesc.pieceIndexs;
while (index >= 0)
{
if (scopeIndexs.contains(index) && scopeIndexs[index].funcations.size() != 0)
{
break;
}
--index;
} if (index == -1)
{
return;
} QString preFuncName = scopeIndexs[index].funcations.last().name;
int r = preFuncName.indexOf("(");
QString leftName = preFuncName.left(r).trimmed();
int l = leftName.lastIndexOf(" ");
QString preBaseName = leftName.mid(l + 1); auto iter = std::find_if(m_funcations.begin(), m_funcations.end(), [preBaseName](const BaseItem & item) {
return item.name == preBaseName;
}); if (iter != m_funcations.end())
{
int insertRow = iter->end;
m_strRowContexts.insert(insertRow + 1, code);
m_bDirty = true; AnalysisFile();
}
}
}

3、测试

3.1、测试代码

QtGrammaAnalysis analysis;
QString oldFilePath = fileInfo.absoluteFilePath();
analysis.SetHeaderFile(oldFilePath);
analysis.SetCppFile(oldFilePath.replace(".h", ".cpp")); analysis.GenerateDefinition("\nvoid test1()\n{\n\t\n}");
analysis.GenerateDeclaration("\tvoid test1();"); analysis.SetScopeType(FT_PROTECT_SLOT);
analysis.GenerateDefinition("\nvoid test1_1()\n{\n\t\n}");
analysis.GenerateDeclaration("\tvoid test1_1();"); analysis.SetScopeType(FT_PUBLIC_SLOT);
analysis.GenerateDefinition("\nvoid test1_2()\n{\n\t\n}");
analysis.GenerateDeclaration("\tvoid test1_2();"); analysis.Save();

3.2、实现文件测试结果

3.2、头文件测试结果

四、源代码

需要源代码留邮箱,不提供csdn下载了,麻烦

简书地址文章名称


转载声明:本站文章无特别说明,皆为原创,版权所有,转载请注明:朝十晚八 or Twowords


C++解析头文件-Qt自动生成信号定义的更多相关文章

  1. C++解析头文件-Qt自动生成信号声明

    目录 一.瞎白话 二.背景 三.思路分析 四.代码讲解 1.类图 2.内存结构声明 3.QtHeaderDescription 4.私有函数讲解 五.分析结果 六.下载 一.瞎白话 时间过的ZTMK, ...

  2. 用shell脚本新建shell文件并自动生成头说明信息

    目标: 新建文件后,直接给文件写入下图信息 代码实现: [root@localhost test]# vi AutoHead.sh #!/bin/bash#此程序的功能是新建shell文件并自动生成头 ...

  3. 用shell脚本新建文件并自动生成头说明信息

    目标: 新建文件后,直接给文件写入下图信息 代码实现: [root@localhost test]# vi AutoHead.sh #!/bin/bash #此程序的功能是新建shell文件并自动生成 ...

  4. Eclipse中R文件不能自动生成

       R文件不能自动生成主要是因为编译有错误,这时你想什么办法都是没有用的,clean, fix properties,都不是从根上解决问题.    R文件主要是自动生成资源文件的id的,里边静态子类 ...

  5. 安装Ruby、Sass在WebStrom添加Watcher实现编辑scss文件时自动生成.map和压缩后的.css文件

    前言 这段时间一直在看Bootstrap,V3官方直接提供了Less版本的源码,就先将Less学完了,很简单的语法,学习写Demo都是在Webstorm里写的,配置了Watcher自动编译(详见< ...

  6. R.java文件无法自动生成的问题

    如果出现R.java文件无法自动生成的问题,同时Console窗口提示下列信息: Android requires compiler compliance level 5.0 or 6.0. Foun ...

  7. webstorm创建js文件时自动生成js注释

    设置webstorm创建js文件时自动生成js注释 settings--Editor--File and Code Temlates 黑色框框里的内容自己填写上去,以下是参考的代码块: /** * @ ...

  8. Qt自动生成.rc文件并配置对应属性 程序图标 版本 描述等

    Qt项目配置文件pro里需要如下配置,进行qmake,build后会自动生成.rc文件,并将对应的信息写入文件中 VERSION = 1.0.0.1 RC_ICONS = "http.ico ...

  9. sublime打开文件时自动生成并打开.dump文件

    GBK Encoding Support 没有安装前打开ASNI格式编码文件会乱码,安装成功重启则可以打开正常 关于.dump文件生成的解释: 当打开一个非utf-8格式且包含汉字的文件时,subli ...

随机推荐

  1. TokuMX写操作无法加锁的问题

    问题: TokuMX删除文档时,符合删除条件的文档很多,删除操作持续时间长,期间,服务写操作OPS大幅下降,同时日志log里发现大量“ Lock not granted. Try restarting ...

  2. python while语句写法

    count=5 while count>0: print 'i love python' count=count-1 else: print 'over'

  3. js导出到word、json、excel、csv

    tableExport.js ///*The MIT License (MIT) //Copyright (c) 2014 https://github.com/kayalshri/ //Permis ...

  4. MetroApp保存UIEment为图片

    写本文的起因是想截取Metro App画面作为图片来使用Win8的共享. 话说自从大MS的客户端UI技术进入XAML时代之后,每次截屏的代码都不太一样,无论silverlight.WPF还是Windo ...

  5. 2018.08.16 POJ1183反正切函数的应用(简单数学)

    传送门 代数变形一波. 显然有b,c>a. 那么这样的话可以令b=a+m,c=a+n. 又有a=(bc-1)/(b+c). 带入展开可知m*n=a*a+1. 要让m+n最小只需让m最大,这个结论 ...

  6. =delete(c++11)

    1.为什么要阻止类对象的拷贝? 1)有些类,不需要拷贝和赋值运算符,如:IO类,以避免多个拷贝对象写入或读取相同的IO缓冲 2.如何阻止? 1)不定义拷贝构造函数和拷贝赋值运算符时,好心的编译器也会及 ...

  7. WPF 嵌入字体文件

    官方说明文档:将字体与应用程序一起打包 https://docs.microsoft.com/zh-cn/dotnet/framework/wpf/advanced/packaging-fonts-w ...

  8. IOS11下fixed中input光标错位问题

    项目遇到了这个问题,故作了个临时解决方案,暂时没有想到更好的方法,查阅了网上的方案,也没有找到完美的解决方案. 方案思路: ①弹窗打开时,阻止 body 滚动,禁用 touchmove ,同时记录当前 ...

  9. (字典树模板)统计难题--hdu--1251

    链接: http://acm.hdu.edu.cn/showproblem.php?pid=1251 在自己敲了一遍后终于懂了,这不就用了链表的知识来建立了树,对!就是这样的,然后再查找 代码: #i ...

  10. noip第7课作业

    1.    求平均值 [问题描述] 在一次运动会方队表演中,学校安排了十名老师进行打分.对于给定的每个参赛班级的不同打分(百分制整数),按照去掉一个最高分.去掉一个最低分,再算出平均分的方法,得到改班 ...