1 Star 0 Fork 0

yuanerhh/GenUML

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
ClangAnalyzer.cpp 5.83 KB
一键复制 编辑 原始数据 按行查看 历史
yuanerhh 提交于 2024-11-10 23:28 +08:00 . 可以生成类图。
#include <QThread>
#include <QDebug>
#include "ClangAnalyzer.h"
#include "ClangUtils.h"
#include "Utils.h"
CClangAnalyzer::CClangAnalyzer()
: m_bParsing(false)
, m_bEnableQuit(false)
{
m_clangIndex = clang_createIndex(0, 0);
}
CClangAnalyzer::~CClangAnalyzer()
{
clang_disposeIndex(m_clangIndex);
}
STATUS CClangAnalyzer::parse(const FILE_INFO_CONTAINER& fileList)
{
m_mapClassElem.clear();
m_strDiagnostics = "";
m_bParsing = true;
m_bEnableQuit = false;
for (auto it = fileList.constBegin(); (!m_bEnableQuit) && (it != fileList.end()); ++it)
{
parseOne(it.key(), it.value());
}
m_bParsing = false;
return 0;
}
STATUS CClangAnalyzer::parseOne(uint64_t ui64ID, const FILE_INFO& fileInfo)
{
Q_UNUSED(ui64ID);
std::vector<std::string> vecStrArgs;
vecStrArgs.push_back("-std=c++14");
vecStrArgs.push_back("-c");
for (const auto& item : m_vecIncludePath)
{
vecStrArgs.push_back("-I" + item.toStdString());
}
std::vector<char*> vecArgs;
for (const auto& item : vecStrArgs)
{
vecArgs.push_back((char *)item.c_str());
}
CUtils::printArgs(vecArgs);
CXTranslationUnit unit;
CXErrorCode errCode = clang_parseTranslationUnit2(m_clangIndex,
fileInfo.strPath.toStdString().data(), vecArgs.data(), vecArgs.size(), nullptr, 0, CXTranslationUnit_None | CXTranslationUnit_SkipFunctionBodies
| CXTranslationUnit_KeepGoing | CXTranslationUnit_IncludeAttributedTypes
| CXTranslationUnit_VisitImplicitAttributes | CXTranslationUnit_DetailedPreprocessingRecord
| CXTranslationUnit_RetainExcludedConditionalBlocks, &unit);
if (CXError_Success != errCode)
{
qDebug() << "clang_parseTranslationUnit2 failed, errcode: " << errCode;
}
scope_exit delUnit([&unit]() {
clang_disposeTranslationUnit(unit);
});
ClangUtils::checkDiagnostics(unit);
m_strDiagnostics += ClangUtils::getDiagnostics(unit);
CXCursor cursor = clang_getTranslationUnitCursor(unit);
// 遍历顶层声明,找到类声明
clang_visitChildren(cursor, [](CXCursor cursor, CXCursor parent,
CXClientData client_data) -> CXChildVisitResult {
CClangAnalyzer* ptr = static_cast<CClangAnalyzer *>(client_data);
auto kind = clang_getCursorKind(cursor);
switch (kind)
{
case CXCursor_ClassDecl:
ptr->handleClassDeclaration(cursor);
break;
default:
ptr->handleAllClass(cursor);
break;
}
return CXChildVisit_Continue;
}, this);
return 0;
}
void CClangAnalyzer::terminateParse(uint32_t ui32Timeout)
{
m_bEnableQuit = true;
uint32_t count = ui32Timeout / 10;
while(m_bParsing && count > 0)
{
QThread::msleep(10);
--count;
}
}
QList<CClassElem::ptr> CClangAnalyzer::getAllClassElemList()
{
return m_mapClassElem.values();
}
CClassElem::ptr CClangAnalyzer::getClassElem(QString strType)
{
return m_mapClassElem[strType];
}
void CClangAnalyzer::setExcludePath(QVector<QString> vecPath)
{
m_vecExcludePath = vecPath;
}
void CClangAnalyzer::setIncludePath(QVector<QString> vecPath)
{
m_vecIncludePath = vecPath;
}
QString CClangAnalyzer::getDiagnostics()
{
return m_strDiagnostics;
}
// 处理类声明
void CClangAnalyzer::handleClassDeclaration(CXCursor cursor)
{
QString path = ClangUtils::getCursorFilePath(cursor);
if (__IsExcludePathContains(path))
{
return;
}
QString type = ClangUtils::getCursorType(cursor);
std::shared_ptr<CClassElem> clsPtr;
if (m_mapClassElem.contains(type))
{
clsPtr = m_mapClassElem[type];
}
else
{
clsPtr = std::make_shared<CClassElem>();
clsPtr->setName(ClangUtils::getCursorName(cursor));
clsPtr->setType(type);
clsPtr->setFilePath(path);
m_mapClassElem[type] = clsPtr;
}
// qDebug() << "handleClassDeclaration type: " << clsInfo.first
// << "name, " << clsInfo.second;
// 遍历类的成员
clang_visitChildren(cursor, [](CXCursor cursor, CXCursor parent,
CXClientData client_data) -> CXChildVisitResult {
CClassElem* ptr = static_cast<CClassElem *>(client_data);
auto kind = clang_getCursorKind(cursor);
switch (kind)
{
//如果是成员变量
case CXCursor_FieldDecl:
ptr->appendMemVar(ClangUtils::getCursorName(cursor), ClangUtils::getCursorType(cursor));
break;
//如果是基类
case CXCursor_CXXBaseSpecifier:
ptr->appendBaseClass(ClangUtils::getCursorType(cursor));
break;
default:
break;
}
return CXChildVisit_Continue; }, clsPtr.get());
}
void CClangAnalyzer::handleAllClass(CXCursor cursor)
{
// 遍历类的成员
clang_visitChildren(cursor, [](CXCursor cursor, CXCursor parent,
CXClientData client_data) -> CXChildVisitResult {
CClangAnalyzer* ptr = static_cast<CClangAnalyzer *>(client_data);
auto kind = clang_getCursorKind(cursor);
// 如果是成员变量
switch (kind)
{
case CXCursor_ClassDecl:
ptr->handleClassDeclaration(cursor); //注意没有break,需要继续递归
default:
ptr->handleAllClass(cursor);
break;
}
return CXChildVisit_Continue; }, this);
}
bool CClangAnalyzer::__IsExcludePathContains(const QString& path)
{
foreach(const auto& item, m_vecExcludePath)
{
if (item == "")
{
continue;
}
if (path.contains(item))
{
return true;
}
}
return false;
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/yuanerhh/GenUML.git
[email protected]:yuanerhh/GenUML.git
yuanerhh
GenUML
GenUML
master

搜索帮助