From 67b2ec1bc73f3b41086034aa35262b86d7668430 Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Thu, 2 May 2024 16:58:01 +0800 Subject: [PATCH] - fix: Current editor wouldn't get parsed, when it's switched from another editor being parsed. - enhancement: Support macro in #include preprocessing statements. (Issue #497) --- NEWS.md | 1 + RedPandaIDE/editor.cpp | 4 +-- RedPandaIDE/mainwindow.cpp | 21 ++++++--------- RedPandaIDE/parser/cppparser.cpp | 37 ++++++++++++++++---------- RedPandaIDE/parser/cppparser.h | 11 ++++++++ RedPandaIDE/parser/cpppreprocessor.cpp | 20 +++++++++++++- 6 files changed, 64 insertions(+), 30 deletions(-) diff --git a/NEWS.md b/NEWS.md index bc426bc0..b536251d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -154,6 +154,7 @@ Red Panda C++ Version 2.27 - enhancement: New code format option: "Remove superfluous empty lines exceeding" - enhancement: New code format option: "Remove superfluous spaces" - change: Remove code format option: "Delete continuous empty lines" + - fix: Current editor wouldn't get parsed, when it's switched from another editor being parsed. Red Panda C++ Version 2.26 - enhancement: Code suggestion for embedded std::vectors. diff --git a/RedPandaIDE/editor.cpp b/RedPandaIDE/editor.cpp index 884e6b76..7cae8c53 100644 --- a/RedPandaIDE/editor.cpp +++ b/RedPandaIDE/editor.cpp @@ -4064,10 +4064,10 @@ Editor::TipType Editor::getTipType(QPoint point, QSynedit::BufferCoord& pos) // do not allow when dragging selection if (isPointInSelection(pos)) return TipType::Selection; - } else if (mParser && mParser->isIncludeLine(lineText(pos.line))) { - return TipType::Preprocessor; } else if (attr->tokenType() == QSynedit::TokenType::Identifier) { return TipType::Identifier; + } else if (mParser && mParser->isIncludeLine(lineText(pos.line))) { + return TipType::Preprocessor; } else if (attr->tokenType() == QSynedit::TokenType::Number) { return TipType::Number; } else if (attr->tokenType() == QSynedit::TokenType::Keyword) { diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index d764b721..95d2c2ad 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -1681,14 +1681,17 @@ void MainWindow::setProjectCurrentFile(const QString &filename) void MainWindow::openFiles(const QStringList &files) { mOpeningFiles=true; - auto action=finally([this]{ - mOpeningFiles=false; - }); mEditorList->beginUpdate(); - mOpenningFiles = true; auto end = finally([this] { this->mEditorList->endUpdate(); - mOpenningFiles = false; + mOpeningFiles=false; + Editor* e=mEditorList->getEditor(); + if (e) { + e->reparse(false); + e->checkSyntaxInBack(); + e->reparseTodo(); + e->activate(); + } }); //Check if there is a project file in the list and open it for (const QString& file:files) { @@ -1704,14 +1707,6 @@ void MainWindow::openFiles(const QStringList &files) if (files.length()>0) { openFile(files.last(),true); } - mEditorList->endUpdate(); - Editor* e=mEditorList->getEditor(); - if (e) { - e->reparse(false); - e->checkSyntaxInBack(); - e->reparseTodo(); - e->activate(); - } } Editor* MainWindow::openFile(QString filename, bool activate, QTabWidget* page) diff --git a/RedPandaIDE/parser/cppparser.cpp b/RedPandaIDE/parser/cppparser.cpp index 26bdb838..3ceb6e19 100644 --- a/RedPandaIDE/parser/cppparser.cpp +++ b/RedPandaIDE/parser/cppparser.cpp @@ -995,22 +995,40 @@ void CppParser::parseFile(const QString &fileName, bool inProject, bool onlyIfNo return; { QMutexLocker locker(&mMutex); - if (mParsing || mLockCount>0) + if (mParsing) { + mLastParseFileCommand = std::make_unique(); + mLastParseFileCommand->fileName = fileName; + mLastParseFileCommand->inProject = inProject; + mLastParseFileCommand->onlyIfNotParsed = onlyIfNotParsed; + mLastParseFileCommand->updateView = updateView; + return; + } + if (mLockCount>0) return; - updateSerialId(); mParsing = true; + updateSerialId(); if (updateView) emit onBusy(); emit onStartParsing(); } { auto action = finally([&,this]{ - mParsing = false; - + QMutexLocker locker(&mMutex); if (updateView) emit onEndParsing(mFilesScannedCount,1); else emit onEndParsing(mFilesScannedCount,0); + + if (mLastParseFileCommand) { + mParsing = false; + ::parseFile(PCppParser{this}, + mLastParseFileCommand->fileName, + mLastParseFileCommand->inProject, + mLastParseFileCommand->onlyIfNotParsed, + mLastParseFileCommand->updateView); + mLastParseFileCommand = nullptr; + } + mParsing = false; }); QString fName = fileName; if (onlyIfNotParsed && mPreprocessor.fileScanned(fName)) @@ -1040,15 +1058,6 @@ void CppParser::parseFile(const QString &fileName, bool inProject, bool onlyIfNo emit onProgress(fileName,mFilesToScanCount,mFilesScannedCount); internalParse(fileName); } - -// if (inProject) -// mProjectFiles.insert(fileName); -// else { -// mProjectFiles.remove(fileName); -// } - - // Parse from disk or stream - } } @@ -6758,7 +6767,7 @@ CppFileParserThread::CppFileParserThread( void CppFileParserThread::run() { - if (mParser && !mParser->parsing()) { + if (mParser) { mParser->parseFile(mFileName,mInProject,mOnlyIfNotParsed,mUpdateView); } } diff --git a/RedPandaIDE/parser/cppparser.h b/RedPandaIDE/parser/cppparser.h index b7d7f5cb..ca54f118 100644 --- a/RedPandaIDE/parser/cppparser.h +++ b/RedPandaIDE/parser/cppparser.h @@ -30,6 +30,15 @@ class CppParser : public QObject Q_OBJECT public: + + struct ParseFileCommand { + QString fileName; + bool inProject; + bool onlyIfNotParsed; + bool updateView; + }; + + using PParseFileCommand = std::unique_ptr; explicit CppParser(QObject *parent = nullptr); CppParser(const CppParser&)=delete; CppParser& operator=(const CppParser)=delete; @@ -732,6 +741,8 @@ private: QRecursiveMutex mMutex; QMap mCppKeywords; QSet mCppTypeKeywords; + + PParseFileCommand mLastParseFileCommand; }; using PCppParser = std::shared_ptr; diff --git a/RedPandaIDE/parser/cpppreprocessor.cpp b/RedPandaIDE/parser/cpppreprocessor.cpp index 1399820c..2feac9d9 100644 --- a/RedPandaIDE/parser/cpppreprocessor.cpp +++ b/RedPandaIDE/parser/cpppreprocessor.cpp @@ -380,9 +380,27 @@ void CppPreprocessor::handleInclude(const QString &line, bool fromNext) includes = mIncludePathList; projectIncludes = mProjectIncludePathList; } + + int i=1; // skip '#' + int len=line.length(); + //skip spaces + while (i=line.length()) + return; + QString s=line.mid(i); + QSet usedMacros; + s = expandMacros(s, usedMacros); + fileName = getHeaderFilename( file->fileName, - line, + s, includes, projectIncludes);