[TOC]html
上一篇文章C++解析头文件-Qt自动生成信号声明咱们主要讲解了怎么去解析C++头文件,而后在指定位置插入函数声明,已达到自动化的效果。既然函数声明已经自动插入了,那么函数实现的定义固然也能够作到自动化插入,并且实现起来比头文件插入还要简单,稍微思考下就能得出结论,.cpp
文件的复杂程度要远远低于.h
文件。app
本篇文章咱们就来分享下怎么去插入函数定义ide
头文件插入函数声明时,咱们选择了先分析头文件,并记住关键位置的行号,而后在指定位置插入字符串,本篇文章咱们仍是沿用以前的套路,先分析.cpp
文件中的全部函数,并记录在内存中,当咱们插入新的函数时,咱们只须要找到咱们要插到哪一个函数的下边,或者插入到全部函数之下的行号,执行插入操做便可。函数
这里有一个很重要的问题,咱们怎么知道上一个函数是谁?这个就是函数定义插入的关键所在。测试
答案:经过分析头文件后的内存结构来获取。既然咱们分析了头文件中全部的类,并且类中的函数和做用域咱们都有存储,而且记录了全部的行号,那咱们只须要找到指定做用域(或者上一个做用)的最后一个函数便可,这就是咱们要插入的位置,当咱们在实现文件中寻找行号时,只须要找到这个函数的最后一个行便可。spa
本篇文章是继上一篇文章C++解析头文件-Qt自动生成信号声明的后续,本篇文章的代码也是前一篇博客的完善,并且结构有了必定的修改。指针
讲述代码以前,咱们先把修改事后的类图贴上,更简洁。 code
本篇文章的细节代码比较少,所以这里咱们稍微讲细一点儿,把关键代码都贴上来。首先看下头文件htm
看下接口是否是至关简单,公有接口是对外暴露的,私有函数主要是解析实现文件,下面让咱们看下几个比较重要的函数对象
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;//函数(变量)列表 };
代码分析中,当出现*(){这样的字符串时,咱们认为是要匹配一个函数了,实际上也确实如此。 当咱们开始匹配函数时,一个函数的结束也就是,函数中的左右花括号成对出现时
以下代码所示,当咱们匹配完一个函数时,咱们构造了一个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; } }
记录函数末尾行号主要是为了咱们方便插入新代码。
插入函数定义代码也比较简单,首先就是根据头文件分析后的类结构查找到咱们要插在哪一个函数以后,接着咱们去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(); } } }
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();
须要源代码留邮箱,不提供csdn下载了,麻烦 <br><br>
简书地址文章名称 <br><br>
转载声明:本站文章无特别说明,皆为原创,版权全部,转载请注明:朝十晚八 or Twowords
原文出处:https://www.cnblogs.com/swarmbees/p/10793254.html