- 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
- 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->bookmarkModel()->setIsForProject(inProject());
pMainWindow->todoModel()->setIsForProject(inProject());
// if (pSettings->codeCompletion().clearWhenEditorHidden()
// && !inProject()) {
// reparse();
@ -2711,7 +2713,7 @@ void Editor::reparseTodo()
{
if (!highlighter())
return;
pMainWindow->todoParser()->parseFile(mFilename);
pMainWindow->todoParser()->parseFile(mFilename, inProject());
}
void Editor::insertString(const QString &value, bool moveCursor)

View File

@ -1358,6 +1358,8 @@ void MainWindow::openProject(const QString &filename, bool openFiles)
mDebugger->loadForProject(
changeFileExt(mProject->filename(), PROJECT_DEBUG_EXT),
mProject->directory());
mTodoModel.setIsForProject(true);
mTodoParser->parseFiles(mProject->unitFiles());
if (openFiles) {
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();
}
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);
}
@ -4470,6 +4476,7 @@ void MainWindow::closeProject(bool refreshEditor)
if (!mQuitting) {
mBookmarkModel->setIsForProject(false);
mDebugger->setIsForProject(false);
mTodoModel.setIsForProject(false);
// Clear error browser
clearIssues();
updateProjectView();
@ -7111,6 +7118,11 @@ const PBookmarkModel &MainWindow::bookmarkModel() const
return mBookmarkModel;
}
TodoModel *MainWindow::todoModel()
{
return &mTodoModel;
}
void MainWindow::on_actionAdd_bookmark_triggered()
{

View File

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

View File

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

View File

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

View File

@ -18,8 +18,6 @@
#include "mainwindow.h"
#include "editor.h"
#include "editorlist.h"
#include "HighlighterManager.h"
#include "qsynedit/Constants.h"
TodoParser::TodoParser(QObject *parent) : QObject(parent),
mMutex(QMutex::Recursive)
@ -27,7 +25,7 @@ TodoParser::TodoParser(QObject *parent) : QObject(parent),
mThread = nullptr;
}
void TodoParser::parseFile(const QString &filename)
void TodoParser::parseFile(const QString &filename,bool isForProject)
{
QMutexLocker locker(&mMutex);
if (mThread) {
@ -42,10 +40,40 @@ void TodoParser::parseFile(const QString &filename)
mThread = nullptr;
}
});
if (!isForProject) {
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,
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::onTodoParsing);
pMainWindow, &MainWindow::onTodoFound);
connect(mThread, &TodoThread::parseFinished,
pMainWindow, &MainWindow::onTodoParseFinished);
mThread->start();
@ -56,21 +84,42 @@ bool TodoParser::parsing() const
return (mThread!=nullptr);
}
TodoThread::TodoThread(const QString& filename, QObject *parent): QThread(parent)
TodoThread::TodoThread(const QString &filename, QObject *parent): QThread(parent)
{
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();
emit parseStarted(mFilename);
auto action = finally([this]{
emit parseFinished();
});
emit parseStarted();
doParseFile(mFilename,highlighter);
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;
if (!pMainWindow->editorList()->getContentFromOpenedEditor(mFilename,lines)) {
return;
if (!pMainWindow->editorList()->getContentFromOpenedEditor(filename,lines)) {
lines = readFileToLines(filename);
}
QSynedit::PHighlighterAttribute commentAttr = highlighter->getAttribute(SYNS_AttrComment);
@ -82,6 +131,7 @@ void TodoThread::run()
attr = highlighter->getTokenAttribute();
if (attr == commentAttr) {
QString token = highlighter->getToken();
qDebug()<<token;
int pos = token.indexOf("TODO:",0,Qt::CaseInsensitive);
if (pos>=0) {
emit todoFound(
@ -95,29 +145,54 @@ void TodoThread::run()
highlighter->next();
}
}
}
void TodoThread::run()
{
if (mParseFiles) {
parseFiles();
} else {
parseFile();
}
}
TodoModel::TodoModel(QObject *parent) : QAbstractListModel(parent)
{
mIsForProject=false;
}
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>();
item->filename = filename;
item->lineNo = lineNo;
item->ch = ch;
item->line = line;
mItems.append(item);
items.append(item);
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()
{
beginResetModel();
mItems.clear();
QList<PTodoItem> &items=getItems(mIsForProject);
items.clear();
endResetModel();
}
@ -125,20 +200,46 @@ PTodoItem TodoModel::getItem(const QModelIndex &index)
{
if (!index.isValid())
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
{
return mItems.count();
const QList<PTodoItem> &items=getConstItems(mIsForProject);
return items.count();
}
QVariant TodoModel::data(const QModelIndex &index, int role) const
{
const QList<PTodoItem> &items=getConstItems(mIsForProject);
if (!index.isValid())
return QVariant();
if (role==Qt::DisplayRole) {
PTodoItem item = mItems[index.row()];
PTodoItem item = items[index.row()];
switch(index.column()) {
case 0:
return item->filename;

View File

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