From 1728e953bfc95233113301877964555ea7286fc4 Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Tue, 27 Feb 2024 18:08:38 +0800 Subject: [PATCH] - fix: Parser: invalidating file may break class inheritance infos. --- NEWS.md | 1 + RedPandaIDE/parser/cppparser.cpp | 69 +++++++++++++++++++++++------ RedPandaIDE/parser/cppparser.h | 2 + RedPandaIDE/parser/statementmodel.h | 13 ++++++ 4 files changed, 72 insertions(+), 13 deletions(-) diff --git a/NEWS.md b/NEWS.md index 260938eb..c3f59d80 100644 --- a/NEWS.md +++ b/NEWS.md @@ -11,6 +11,7 @@ Red Panda C++ Version 2.27 - enhancement: Don't force fixed-width when using non fixed-width fonts. - change: Replace non-ascii font with fallback font. - enhancement: Display ascii control chars. + - fix: Parser: invalidating file may break class inheritance infos. Red Panda C++ Version 2.26 - enhancement: Code suggestion for embedded std::vectors. diff --git a/RedPandaIDE/parser/cppparser.cpp b/RedPandaIDE/parser/cppparser.cpp index 56f25778..6a87ea78 100644 --- a/RedPandaIDE/parser/cppparser.cpp +++ b/RedPandaIDE/parser/cppparser.cpp @@ -1107,10 +1107,9 @@ void CppParser::resetParser() mFilesToScan.clear(); // list of base files to scan mNamespaces.clear(); // namespace and the statements in its scope mInlineNamespaces.clear(); - + mClassInheritances.clear(); mPreprocessor.clear(); mTokenizer.clear(); - } } @@ -1436,8 +1435,6 @@ PStatement CppParser::addStatement(const PStatement& parent, // if (result->command=="sync_with_stdio") { // qDebug()<fullName<isStatic()<<(int)result->accessibility; // } - - return result; } @@ -1605,13 +1602,17 @@ void CppParser::setInheritance(int index, const PStatement& classStatement, bool } } - // Find the corresponding PStatement - PStatement statement = doFindStatementOf(mCurrentFile,basename, - isGlobal?PStatement():classStatement->parentScope.lock()); + PClassInheritanceInfo inheritanceInfo = std::make_shared(); - if (statement && statement->kind == StatementKind::skClass) { - inheritClassStatement(classStatement,isStruct,statement,lastInheritScopeType); - } + inheritanceInfo->derivedClass = classStatement; + inheritanceInfo->file = mCurrentFile; + inheritanceInfo->parentClassName = basename; + inheritanceInfo->isGlobal = isGlobal; + inheritanceInfo->isStruct = isStruct; + inheritanceInfo->visibility = lastInheritScopeType; + inheritanceInfo->handled = false; + + mClassInheritances.append(inheritanceInfo); } } @@ -4372,6 +4373,39 @@ void CppParser::handleVar(const QString& typePrefix,bool isExtern,bool isStatic) mIndex++; } +void CppParser::handleInheritances() +{ + for (int i=mClassInheritances.length()-1;i>=0;i--) { + PClassInheritanceInfo inheritanceInfo = mClassInheritances[i]; + PStatement derivedStatement = inheritanceInfo->derivedClass.lock(); + if (!derivedStatement) { + //the derived class is invalid, remove it + if (ihandled) + continue; + PStatement statement = doFindStatementOf( + inheritanceInfo->file, + inheritanceInfo->parentClassName, + inheritanceInfo->isGlobal?PStatement():derivedStatement->parentScope.lock()); + + if (statement && statement->kind == StatementKind::skClass) { + inheritClassStatement(derivedStatement, + inheritanceInfo->isStruct, + statement, + inheritanceInfo->visibility); + inheritanceInfo->parentClassFilename = statement->fileName; + inheritanceInfo->handled = true; + } + } + //mClassInheritances.clear(); +} + void CppParser::skipRequires() { mIndex++; //skip 'requires'; @@ -4459,10 +4493,12 @@ void CppParser::internalParse(const QString &fileName) if (!handleStatement()) break; } + + handleInheritances(); // qDebug()<<"parse"<kind == StatementKind::skConstructor || statement->kind == StatementKind::skDestructor) continue; + if (derived->children.contains(statement->command)) + continue; StatementAccessibility m_acc; switch(access) { case StatementAccessibility::Public: @@ -5960,7 +5998,12 @@ void CppParser::internalInvalidateFile(const QString &fileName) mNamespaces.remove(key); } } - + // class inheritance + // invalid class inheritance infos (derived class is not valid) whould be auto removed in handleInheritances() + foreach (const PClassInheritanceInfo& info, mClassInheritances) { + if (info->handled && info->parentClassFilename == fileName) + info->handled = false; + } // delete it from scannedfiles mPreprocessor.removeScannedFile(fileName); } diff --git a/RedPandaIDE/parser/cppparser.h b/RedPandaIDE/parser/cppparser.h index 8398c6df..e4497ee1 100644 --- a/RedPandaIDE/parser/cppparser.h +++ b/RedPandaIDE/parser/cppparser.h @@ -516,6 +516,7 @@ private: void handleStructs(bool isTypedef = false); void handleUsing(); void handleVar(const QString& typePrefix,bool isExtern,bool isStatic); + void handleInheritances(); void skipRequires(); void internalParse(const QString& fileName); // function FindMacroDefine(const Command: AnsiString): PStatement; @@ -718,6 +719,7 @@ private: int mLockCount; // lock(don't reparse) when we need to find statements in a batch bool mParsing; QHash mNamespaces; // namespace and the statements in its scope + QList mClassInheritances; QSet mInlineNamespaces; #ifdef QT_DEBUG int mLastIndex; diff --git a/RedPandaIDE/parser/statementmodel.h b/RedPandaIDE/parser/statementmodel.h index 7bc26a7c..aa18710c 100644 --- a/RedPandaIDE/parser/statementmodel.h +++ b/RedPandaIDE/parser/statementmodel.h @@ -53,4 +53,17 @@ private: #endif }; +struct ClassInheritanceInfo { + std::weak_ptr derivedClass; + QString file; + QString parentClassName; + bool isGlobal; + bool isStruct; + StatementAccessibility visibility; + QString parentClassFilename; + bool handled; +}; + +using PClassInheritanceInfo = std::shared_ptr; + #endif // STATEMENTMODEL_H