- redesign the project parser, more efficient and correct

- enhancement: todo parser for project
This commit is contained in:
Roy Qu 2022-10-22 23:29:12 +08:00
parent f0bdfed9b4
commit e8300abd65
8 changed files with 178 additions and 29 deletions

View File

@ -1,3 +1,8 @@
Red Panda C++ Version 2.0
- redesign the project parser, more efficient and correct
- enhancement: todo parser for project
Red Panda C++ Version 1.5 Red Panda C++ Version 1.5
- fix: project files that lies in project include folder is wrongly openned in Read-only mode - fix: project files that lies in project include folder is wrongly openned in Read-only mode

View File

@ -1290,6 +1290,8 @@ void Editor::showEvent(QShowEvent */*event*/)
} }
pMainWindow->debugger()->setIsForProject(inProject()); pMainWindow->debugger()->setIsForProject(inProject());
pMainWindow->bookmarkModel()->setIsForProject(inProject()); pMainWindow->bookmarkModel()->setIsForProject(inProject());
pMainWindow->todoModel()->setIsForProject(inProject());
// if (pSettings->codeCompletion().clearWhenEditorHidden() // if (pSettings->codeCompletion().clearWhenEditorHidden()
// && !inProject()) { // && !inProject()) {
// reparse(); // reparse();
@ -2711,7 +2713,7 @@ void Editor::reparseTodo()
{ {
if (!highlighter()) if (!highlighter())
return; return;
pMainWindow->todoParser()->parseFile(mFilename); pMainWindow->todoParser()->parseFile(mFilename, inProject());
} }
void Editor::insertString(const QString &value, bool moveCursor) void Editor::insertString(const QString &value, bool moveCursor)

View File

@ -1358,6 +1358,8 @@ void MainWindow::openProject(const QString &filename, bool openFiles)
mDebugger->loadForProject( mDebugger->loadForProject(
changeFileExt(mProject->filename(), PROJECT_DEBUG_EXT), changeFileExt(mProject->filename(), PROJECT_DEBUG_EXT),
mProject->directory()); mProject->directory());
mTodoModel.setIsForProject(true);
mTodoParser->parseFiles(mProject->unitFiles());
if (openFiles) { if (openFiles) {
PProjectUnit unit = mProject->doAutoOpen(); PProjectUnit unit = mProject->doAutoOpen();
@ -4358,12 +4360,16 @@ void MainWindow::enableDebugActions()
} }
} }
void MainWindow::onTodoParseStarted(const QString&) void MainWindow::onTodoParsingFile(const QString& filename)
{
mTodoModel.removeTodosForFile(filename);
}
void MainWindow::onTodoParseStarted()
{ {
mTodoModel.clear(); mTodoModel.clear();
} }
void MainWindow::onTodoParsing(const QString& filename, int lineNo, int ch, const QString& line) void MainWindow::onTodoFound(const QString& filename, int lineNo, int ch, const QString& line)
{ {
mTodoModel.addItem(filename,lineNo,ch,line); mTodoModel.addItem(filename,lineNo,ch,line);
} }
@ -4470,6 +4476,7 @@ void MainWindow::closeProject(bool refreshEditor)
if (!mQuitting) { if (!mQuitting) {
mBookmarkModel->setIsForProject(false); mBookmarkModel->setIsForProject(false);
mDebugger->setIsForProject(false); mDebugger->setIsForProject(false);
mTodoModel.setIsForProject(false);
// Clear error browser // Clear error browser
clearIssues(); clearIssues();
updateProjectView(); updateProjectView();
@ -7111,6 +7118,11 @@ const PBookmarkModel &MainWindow::bookmarkModel() const
return mBookmarkModel; return mBookmarkModel;
} }
TodoModel *MainWindow::todoModel()
{
return &mTodoModel;
}
void MainWindow::on_actionAdd_bookmark_triggered() void MainWindow::on_actionAdd_bookmark_triggered()
{ {

View File

@ -196,6 +196,8 @@ public:
const PBookmarkModel &bookmarkModel() const; const PBookmarkModel &bookmarkModel() const;
TodoModel* todoModel();
Editor* openFile(const QString& filename, bool activate=true, QTabWidget* page=nullptr); Editor* openFile(const QString& filename, bool activate=true, QTabWidget* page=nullptr);
void openProject(const QString& filename, bool openFiles = true); void openProject(const QString& filename, bool openFiles = true);
void changeOptions(const QString& widgetName=QString(), const QString& groupName=QString()); void changeOptions(const QString& widgetName=QString(), const QString& groupName=QString());
@ -235,8 +237,9 @@ public slots:
void onEditorTabContextMenu(QTabWidget* tabWidget, const QPoint& pos); void onEditorTabContextMenu(QTabWidget* tabWidget, const QPoint& pos);
void disableDebugActions(); void disableDebugActions();
void enableDebugActions(); void enableDebugActions();
void onTodoParseStarted(const QString& filename); void onTodoParsingFile(const QString& filename);
void onTodoParsing(const QString& filename, int lineNo, int ch, const QString& line); void onTodoParseStarted();
void onTodoFound(const QString& filename, int lineNo, int ch, const QString& line);
void onTodoParseFinished(); void onTodoParseFinished();
void setActiveBreakpoint(QString FileName, int Line, bool setFocus); void setActiveBreakpoint(QString FileName, int Line, bool setFocus);
void updateDPI(int oldDPI, int newDPI); void updateDPI(int oldDPI, int newDPI);

View File

@ -456,6 +456,15 @@ QList<PProjectUnit> Project::unitList()
return units; return units;
} }
QStringList Project::unitFiles()
{
QStringList units;
foreach(PProjectUnit unit, mUnits) {
units.append(unit->fileName());
}
return units;
}
void Project::rebuildNodes() void Project::rebuildNodes()
{ {
mModel.beginUpdate(); mModel.beginUpdate();

View File

@ -230,6 +230,7 @@ public:
Editor* unitEditor(const ProjectUnit* unit) const; Editor* unitEditor(const ProjectUnit* unit) const;
QList<PProjectUnit> unitList(); QList<PProjectUnit> unitList();
QStringList unitFiles();
PProjectModelNode pointerToNode(ProjectModelNode * p, PProjectModelNode parent=PProjectModelNode()); PProjectModelNode pointerToNode(ProjectModelNode * p, PProjectModelNode parent=PProjectModelNode());
void rebuildNodes(); void rebuildNodes();

View File

@ -18,8 +18,6 @@
#include "mainwindow.h" #include "mainwindow.h"
#include "editor.h" #include "editor.h"
#include "editorlist.h" #include "editorlist.h"
#include "HighlighterManager.h"
#include "qsynedit/Constants.h"
TodoParser::TodoParser(QObject *parent) : QObject(parent), TodoParser::TodoParser(QObject *parent) : QObject(parent),
mMutex(QMutex::Recursive) mMutex(QMutex::Recursive)
@ -27,7 +25,7 @@ TodoParser::TodoParser(QObject *parent) : QObject(parent),
mThread = nullptr; mThread = nullptr;
} }
void TodoParser::parseFile(const QString &filename) void TodoParser::parseFile(const QString &filename,bool isForProject)
{ {
QMutexLocker locker(&mMutex); QMutexLocker locker(&mMutex);
if (mThread) { if (mThread) {
@ -42,10 +40,40 @@ void TodoParser::parseFile(const QString &filename)
mThread = nullptr; mThread = nullptr;
} }
}); });
if (!isForProject) {
connect(mThread, &TodoThread::parseStarted, connect(mThread, &TodoThread::parseStarted,
pMainWindow, &MainWindow::onTodoParseStarted); pMainWindow, &MainWindow::onTodoParseStarted);
}
connect(mThread, &TodoThread::parsingFile,
pMainWindow, &MainWindow::onTodoParsingFile);
connect(mThread, &TodoThread::todoFound, connect(mThread, &TodoThread::todoFound,
pMainWindow, &MainWindow::onTodoParsing); pMainWindow, &MainWindow::onTodoFound);
connect(mThread, &TodoThread::parseFinished,
pMainWindow, &MainWindow::onTodoParseFinished);
mThread->start();
}
void TodoParser::parseFiles(const QStringList &files)
{
QMutexLocker locker(&mMutex);
if (mThread) {
return;
}
mThread = new TodoThread(files);
connect(mThread,&QThread::finished,
[this] {
QMutexLocker locker(&mMutex);
if (mThread) {
mThread->deleteLater();
mThread = nullptr;
}
});
connect(mThread, &TodoThread::parseStarted,
pMainWindow, &MainWindow::onTodoParseStarted);
connect(mThread, &TodoThread::parsingFile,
pMainWindow, &MainWindow::onTodoParsingFile);
connect(mThread, &TodoThread::todoFound,
pMainWindow, &MainWindow::onTodoFound);
connect(mThread, &TodoThread::parseFinished, connect(mThread, &TodoThread::parseFinished,
pMainWindow, &MainWindow::onTodoParseFinished); pMainWindow, &MainWindow::onTodoParseFinished);
mThread->start(); mThread->start();
@ -59,18 +87,39 @@ bool TodoParser::parsing() const
TodoThread::TodoThread(const QString &filename, QObject *parent): QThread(parent) TodoThread::TodoThread(const QString &filename, QObject *parent): QThread(parent)
{ {
mFilename = filename; mFilename = filename;
mParseFiles = false;
} }
void TodoThread::run() TodoThread::TodoThread(const QStringList &files, QObject *parent): QThread(parent)
{
mFiles = files;
mParseFiles = true;
}
void TodoThread::parseFile()
{ {
QSynedit::PHighlighter highlighter = highlighterManager.getCppHighlighter(); QSynedit::PHighlighter highlighter = highlighterManager.getCppHighlighter();
emit parseStarted(mFilename); emit parseStarted();
auto action = finally([this]{ doParseFile(mFilename,highlighter);
emit parseFinished(); emit parseFinished();
}); }
void TodoThread::parseFiles()
{
QSynedit::PHighlighter highlighter = highlighterManager.getCppHighlighter();
emit parseStarted();
foreach(const QString& filename,mFiles) {
doParseFile(filename,highlighter);
}
emit parseFinished();
}
void TodoThread::doParseFile(const QString &filename, QSynedit::PHighlighter highlighter)
{
emit parsingFile(filename);
QStringList lines; QStringList lines;
if (!pMainWindow->editorList()->getContentFromOpenedEditor(mFilename,lines)) { if (!pMainWindow->editorList()->getContentFromOpenedEditor(filename,lines)) {
return; lines = readFileToLines(filename);
} }
QSynedit::PHighlighterAttribute commentAttr = highlighter->getAttribute(SYNS_AttrComment); QSynedit::PHighlighterAttribute commentAttr = highlighter->getAttribute(SYNS_AttrComment);
@ -82,6 +131,7 @@ void TodoThread::run()
attr = highlighter->getTokenAttribute(); attr = highlighter->getTokenAttribute();
if (attr == commentAttr) { if (attr == commentAttr) {
QString token = highlighter->getToken(); QString token = highlighter->getToken();
qDebug()<<token;
int pos = token.indexOf("TODO:",0,Qt::CaseInsensitive); int pos = token.indexOf("TODO:",0,Qt::CaseInsensitive);
if (pos>=0) { if (pos>=0) {
emit todoFound( emit todoFound(
@ -95,29 +145,54 @@ void TodoThread::run()
highlighter->next(); highlighter->next();
} }
} }
}
void TodoThread::run()
{
if (mParseFiles) {
parseFiles();
} else {
parseFile();
}
} }
TodoModel::TodoModel(QObject *parent) : QAbstractListModel(parent) TodoModel::TodoModel(QObject *parent) : QAbstractListModel(parent)
{ {
mIsForProject=false;
} }
void TodoModel::addItem(const QString &filename, int lineNo, int ch, const QString &line) void TodoModel::addItem(const QString &filename, int lineNo, int ch, const QString &line)
{ {
beginInsertRows(QModelIndex(),mItems.count(),mItems.count()); QList<PTodoItem> &items=getItems(mIsForProject);
beginInsertRows(QModelIndex(),items.count(),items.count());
PTodoItem item = std::make_shared<TodoItem>(); PTodoItem item = std::make_shared<TodoItem>();
item->filename = filename; item->filename = filename;
item->lineNo = lineNo; item->lineNo = lineNo;
item->ch = ch; item->ch = ch;
item->line = line; item->line = line;
mItems.append(item); items.append(item);
endInsertRows(); endInsertRows();
} }
void TodoModel::removeTodosForFile(const QString &filename)
{
QList<PTodoItem> &items=getItems(mIsForProject);
for(int i=items.count()-1;i>=0;i--) {
PTodoItem item = items[i];
if (item->filename==filename) {
beginRemoveRows(QModelIndex(),i,i);
items.removeAt(i);
endRemoveRows();
}
}
}
void TodoModel::clear() void TodoModel::clear()
{ {
beginResetModel(); beginResetModel();
mItems.clear(); QList<PTodoItem> &items=getItems(mIsForProject);
items.clear();
endResetModel(); endResetModel();
} }
@ -125,20 +200,46 @@ PTodoItem TodoModel::getItem(const QModelIndex &index)
{ {
if (!index.isValid()) if (!index.isValid())
return PTodoItem(); return PTodoItem();
return mItems[index.row()]; return getItems(mIsForProject)[index.row()];
}
QList<PTodoItem> &TodoModel::getItems(bool forProject)
{
return forProject?mProjectItems:mItems;
}
const QList<PTodoItem> &TodoModel::getConstItems(bool forProject) const
{
return forProject?mProjectItems:mItems;
}
bool TodoModel::isForProject() const
{
return mIsForProject;
}
void TodoModel::setIsForProject(bool newIsForProject)
{
if (mIsForProject!=newIsForProject) {
beginResetModel();
mIsForProject = newIsForProject;
endResetModel();
}
} }
int TodoModel::rowCount(const QModelIndex &) const int TodoModel::rowCount(const QModelIndex &) const
{ {
return mItems.count(); const QList<PTodoItem> &items=getConstItems(mIsForProject);
return items.count();
} }
QVariant TodoModel::data(const QModelIndex &index, int role) const QVariant TodoModel::data(const QModelIndex &index, int role) const
{ {
const QList<PTodoItem> &items=getConstItems(mIsForProject);
if (!index.isValid()) if (!index.isValid())
return QVariant(); return QVariant();
if (role==Qt::DisplayRole) { if (role==Qt::DisplayRole) {
PTodoItem item = mItems[index.row()]; PTodoItem item = items[index.row()];
switch(index.column()) { switch(index.column()) {
case 0: case 0:
return item->filename; return item->filename;

View File

@ -21,6 +21,8 @@
#include <QThread> #include <QThread>
#include <QMutex> #include <QMutex>
#include <QAbstractListModel> #include <QAbstractListModel>
#include "HighlighterManager.h"
#include "qsynedit/Constants.h"
struct TodoItem { struct TodoItem {
QString filename; QString filename;
@ -37,20 +39,25 @@ public:
explicit TodoModel(QObject* parent=nullptr); explicit TodoModel(QObject* parent=nullptr);
void addItem(const QString& filename, int lineNo, void addItem(const QString& filename, int lineNo,
int ch, const QString& line); int ch, const QString& line);
void removeTodosForFile(const QString& filename);
void clear(); void clear();
PTodoItem getItem(const QModelIndex& index); PTodoItem getItem(const QModelIndex& index);
private:
QList<PTodoItem> &getItems(bool forProject);
const QList<PTodoItem> &getConstItems(bool forProject) const;
private: private:
QList<PTodoItem> mItems; QList<PTodoItem> mItems;
QList<PTodoItem> mProjectItems;
bool mIsForProject;
// QAbstractItemModel interface // QAbstractItemModel interface
public: public:
int rowCount(const QModelIndex &parent) const override; int rowCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override; QVariant data(const QModelIndex &index, int role) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role) const override; QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
// QAbstractItemModel interface
public:
int columnCount(const QModelIndex &parent) const override; int columnCount(const QModelIndex &parent) const override;
bool isForProject() const;
void setIsForProject(bool newIsForProject);
}; };
class TodoThread: public QThread class TodoThread: public QThread
@ -58,12 +65,20 @@ class TodoThread: public QThread
Q_OBJECT Q_OBJECT
public: public:
explicit TodoThread(const QString& filename, QObject* parent = nullptr); explicit TodoThread(const QString& filename, QObject* parent = nullptr);
explicit TodoThread(const QStringList& files, QObject* parent = nullptr);
signals: signals:
void parseStarted(const QString& filename); void parseStarted();
void parsingFile(const QString& fileName);
void todoFound(const QString& filename, int lineNo, int ch, const QString& line); void todoFound(const QString& filename, int lineNo, int ch, const QString& line);
void parseFinished(); void parseFinished();
private:
void parseFile();
void parseFiles();
void doParseFile(const QString& filename, QSynedit::PHighlighter highlighter);
private: private:
QString mFilename; QString mFilename;
QStringList mFiles;
bool mParseFiles;
// QThread interface // QThread interface
protected: protected:
@ -77,7 +92,8 @@ class TodoParser : public QObject
Q_OBJECT Q_OBJECT
public: public:
explicit TodoParser(QObject *parent = nullptr); explicit TodoParser(QObject *parent = nullptr);
void parseFile(const QString& filename); void parseFile(const QString& filename,bool isForProject);
void parseFiles(const QStringList& files);
bool parsing() const; bool parsing() const;
private: private: