diff --git a/NEWS.md b/NEWS.md index 60d74835..a7cb5069 100644 --- a/NEWS.md +++ b/NEWS.md @@ -19,7 +19,10 @@ Red Panda C++ Version 2.17 - enhancement: If no selection, Ctrl+C (Copy) auto selects the current line and put the cursor to the beginning. - fix: Chinese characters in the source code is not correctly displayed in the CPU info window. - fix: Can't undo & save after copy by drag with mouse. - - fix: '::' is not correctly handle when skip to next ':' in the parser. + - fix: '::' is not correctly handled when skip to next ':' in the parser. + - fix: '::' is not correctly handled when parsing class definitions. + - enhancement: Don't show operator overloading functions in the complete suggestions + - enhancement: Correctly hanlde operator overloading functions like "operator ClassA" Red Panda C++ Version 2.16 diff --git a/RedPandaIDE/parser/cppparser.cpp b/RedPandaIDE/parser/cppparser.cpp index f38605a2..654c606e 100644 --- a/RedPandaIDE/parser/cppparser.cpp +++ b/RedPandaIDE/parser/cppparser.cpp @@ -1377,8 +1377,8 @@ void CppParser::setInheritance(int index, const PStatement& classStatement, bool //skip to matching ')' index=mTokenizer[index]->matchIndex; } else if (inheritScopeType == StatementClassScope::None) { - if (currentText.front()!=',' - && currentText.front()!=':') { + if (currentText !=',' + && currentText!=':') { QString basename = currentText; //remove template staff if (basename.endsWith('>')) { @@ -1728,8 +1728,17 @@ void CppParser::checkAndHandleMethodOrVar(KeywordType keywordType) currentText=mTokenizer[mIndex+1]->text; mIndex+=2; } - } else + } else { + if (currentText=="operator") { + handleOperatorOverloading("", + "", + mIndex, + false, + false); + return; + } mIndex++; + } //next token must be */&/word/(/{ if (mTokenizer[mIndex]->text=='(') { int indexAfterParentheis=mTokenizer[mIndex]->matchIndex+1; @@ -1742,7 +1751,7 @@ void CppParser::checkAndHandleMethodOrVar(KeywordType keywordType) mIndex=indexAfterParentheis; handleMethod(StatementKind::skFunction,"", mergeArgs(mIndex+1,mTokenizer[mIndex]->matchIndex-1), - indexAfterParentheis,false,false); + indexAfterParentheis,false,false,true); } else { handleVar(currentText,false,false); } @@ -1751,7 +1760,7 @@ void CppParser::checkAndHandleMethodOrVar(KeywordType keywordType) // operator overloading handleOperatorOverloading( "", - currentText, + "", mIndex, false, false); @@ -2539,6 +2548,9 @@ void CppParser::handleOperatorOverloading(const QString &sType, const QString &p } else { op=mTokenizer[index]->text; index++; + while (indextext != "(") + index++; } while (indextext == ")") @@ -2548,15 +2560,17 @@ void CppParser::handleOperatorOverloading(const QString &sType, const QString &p mIndex=index; return; } + Q_ASSERT(!op.isEmpty()); handleMethod(StatementKind::skFunction, sType, - prefix+"operator"+op, + prefix+"operator"+(isIdentChar(op.front())?op+" ":op), index, isStatic, - isFriend); + isFriend, + true); } -void CppParser::handleMethod(StatementKind functionKind,const QString &sType, const QString &sName, int argStart, bool isStatic, bool isFriend) +void CppParser::handleMethod(StatementKind functionKind,const QString &sType, const QString &sName, int argStart, bool isStatic, bool isFriend,bool isOperatorOverload) { bool isValid = true; bool isDeclaration = false; // assume it's not a prototype @@ -2618,7 +2632,7 @@ void CppParser::handleMethod(StatementKind functionKind,const QString &sType, co // Use the class the function belongs to as the parent ID if the function is declared outside of the class body QString scopelessName; QString parentClassName; - if (splitLastMember(sName,scopelessName,parentClassName)) { + if (!isOperatorOverload && splitLastMember(sName,scopelessName,parentClassName)) { // Provide Bar instead of Foo::Bar scopeStatement = getIncompleteClass(parentClassName,getCurrentScope()); @@ -2647,7 +2661,8 @@ void CppParser::handleMethod(StatementKind functionKind,const QString &sType, co getScope(), mClassScope, StatementProperty::spHasDefinition - | (isStatic?StatementProperty::spStatic:StatementProperty::spNone)); + | (isStatic?StatementProperty::spStatic:StatementProperty::spNone) + | (isOperatorOverload?StatementProperty::spOperatorOverloading:StatementProperty::spNone)); scanMethodArgs(functionStatement, argStart); // add variable this to the class function if (scopeStatement && scopeStatement->kind == StatementKind::skClass && @@ -2665,7 +2680,8 @@ void CppParser::handleMethod(StatementKind functionKind,const QString &sType, co StatementKind::skVariable, StatementScope::Local, StatementClassScope::None, - StatementProperty::spHasDefinition); + StatementProperty::spHasDefinition + | (isOperatorOverload?StatementProperty::spOperatorOverloading:StatementProperty::spNone)); } // add "__func__ variable" @@ -2681,7 +2697,8 @@ void CppParser::handleMethod(StatementKind functionKind,const QString &sType, co StatementKind::skVariable, StatementScope::Local, StatementClassScope::None, - StatementProperty::spHasDefinition); + StatementProperty::spHasDefinition + | (isOperatorOverload?StatementProperty::spOperatorOverloading:StatementProperty::spNone)); } else { functionStatement = addStatement( @@ -2697,7 +2714,8 @@ void CppParser::handleMethod(StatementKind functionKind,const QString &sType, co functionKind, getScope(), mClassScope, - (isStatic?StatementProperty::spStatic:StatementProperty::spNone)); + (isStatic?StatementProperty::spStatic:StatementProperty::spNone) + | (isOperatorOverload?StatementProperty::spOperatorOverloading:StatementProperty::spNone)); } } @@ -3208,17 +3226,17 @@ void CppParser::handleStructs(bool isTypedef) } else { PStatement firstSynonym; // Add class/struct name BEFORE opening brace - if (mTokenizer[mIndex]->text.front() != '{') { + if (mTokenizer[mIndex]->text != "{") { while(mIndex < mTokenizer.tokenCount()) { - if (mTokenizer[mIndex]->text.front() == ':' - || mTokenizer[mIndex]->text.front() == '{' - || mTokenizer[mIndex]->text.front() == ';') { + if (mTokenizer[mIndex]->text == ":" + || mTokenizer[mIndex]->text == "{" + || mTokenizer[mIndex]->text == ";") { break; } else if ((mIndex + 1 < mTokenizer.tokenCount()) - && (mTokenizer[mIndex + 1]->text.front() == ',' - || mTokenizer[mIndex + 1]->text.front() == ';' - || mTokenizer[mIndex + 1]->text.front() == '{' - || mTokenizer[mIndex + 1]->text.front() == ':')) { + && (mTokenizer[mIndex + 1]->text == "," + || mTokenizer[mIndex + 1]->text == ";" + || mTokenizer[mIndex + 1]->text == "{" + || mTokenizer[mIndex + 1]->text == ":")) { QString command = mTokenizer[mIndex]->text; PStatement scopeStatement=getCurrentScope(); @@ -3250,8 +3268,8 @@ void CppParser::handleStructs(bool isTypedef) break; } else if ((mIndex + 2 < mTokenizer.tokenCount()) && (mTokenizer[mIndex + 1]->text == "final") - && (mTokenizer[mIndex + 2]->text.front()==',' - || mTokenizer[mIndex + 2]->text.front()==':' + && (mTokenizer[mIndex + 2]->text=="," + || mTokenizer[mIndex + 2]->text==":" || isblockChar(mTokenizer[mIndex + 2]->text.front()))) { QString command = mTokenizer[mIndex]->text; if (!command.isEmpty()) { @@ -3279,7 +3297,7 @@ void CppParser::handleStructs(bool isTypedef) } // Walk to opening brace if we encountered inheritance statements - if ((mIndex < mTokenizer.tokenCount()) && (mTokenizer[mIndex]->text.front() == ':')) { + if ((mIndex < mTokenizer.tokenCount()) && (mTokenizer[mIndex]->text == ":")) { if (firstSynonym) setInheritance(mIndex, firstSynonym, isStruct); // set the _InheritanceList value mIndex=indexOfNextLeftBrace(mIndex); @@ -3416,7 +3434,7 @@ void CppParser::handleStructs(bool isTypedef) addSoloScopeLevel(firstSynonym,startLine); // Step over { - if ((mIndex < mTokenizer.tokenCount()) && (mTokenizer[mIndex]->text.front() == '{')) + if ((mIndex < mTokenizer.tokenCount()) && (mTokenizer[mIndex]->text == "{")) mIndex++; } } @@ -3817,7 +3835,7 @@ void CppParser::internalParse(const QString &fileName) QStringList preprocessResult = mPreprocessor.result(); #ifdef QT_DEBUG - stringsToFile(mPreprocessor.result(),QString("r:\\preprocess-%1.txt").arg(extractFileName(fileName))); +// stringsToFile(mPreprocessor.result(),QString("r:\\preprocess-%1.txt").arg(extractFileName(fileName))); // mPreprocessor.dumpDefinesTo("r:\\defines.txt"); // mPreprocessor.dumpIncludesListTo("r:\\includes.txt"); #endif @@ -3831,7 +3849,7 @@ void CppParser::internalParse(const QString &fileName) if (mTokenizer.tokenCount() == 0) return; #ifdef QT_DEBUG - mTokenizer.dumpTokens(QString("r:\\tokens-%1.txt").arg(extractFileName(fileName))); +// mTokenizer.dumpTokens(QString("r:\\tokens-%1.txt").arg(extractFileName(fileName))); #endif #ifdef QT_DEBUG mLastIndex = -1; @@ -3842,8 +3860,8 @@ void CppParser::internalParse(const QString &fileName) break; } #ifdef QT_DEBUG - mStatementList.dumpAll(QString("r:\\all-stats-%1.txt").arg(extractFileName(fileName))); - mStatementList.dump(QString("r:\\stats-%1.txt").arg(extractFileName(fileName))); +// mStatementList.dumpAll(QString("r:\\all-stats-%1.txt").arg(extractFileName(fileName))); +// mStatementList.dump(QString("r:\\stats-%1.txt").arg(extractFileName(fileName))); #endif //reduce memory usage internalClear(); diff --git a/RedPandaIDE/parser/cppparser.h b/RedPandaIDE/parser/cppparser.h index 3bcbd832..2c88062c 100644 --- a/RedPandaIDE/parser/cppparser.h +++ b/RedPandaIDE/parser/cppparser.h @@ -455,7 +455,8 @@ private: const QString& sName, int argStart, bool isStatic, - bool isFriend); + bool isFriend, + bool isOperatorOverload=false); void handleNamespace(KeywordType skipType); void handleOtherTypedefs(); void handlePreprocessor(); diff --git a/RedPandaIDE/parser/parserutils.h b/RedPandaIDE/parser/parserutils.h index 51428971..3b4c5516 100644 --- a/RedPandaIDE/parser/parserutils.h +++ b/RedPandaIDE/parser/parserutils.h @@ -141,16 +141,17 @@ struct StatementMatchPosition{ }; enum StatementProperty { - spNone = 0x0, - spStatic = 0x0001, - spHasDefinition = 0x0002, - spInProject = 0x0004, - spInSystemHeader = 0x0008, - spInherited = 0x0010, - spVirtual = 0x0020, - spOverride = 0x0040, - spConstexpr = 0x0080, - spFunctionPointer = 0x0100 + spNone = 0x0, + spStatic = 0x0001, + spHasDefinition = 0x0002, + spInProject = 0x0004, + spInSystemHeader = 0x0008, + spInherited = 0x0010, + spVirtual = 0x0020, + spOverride = 0x0040, + spConstexpr = 0x0080, + spFunctionPointer = 0x0100, + spOperatorOverloading = 0x0200 }; Q_DECLARE_FLAGS(StatementProperties, StatementProperty) diff --git a/RedPandaIDE/widgets/codecompletionpopup.cpp b/RedPandaIDE/widgets/codecompletionpopup.cpp index 05272d0b..31513a43 100644 --- a/RedPandaIDE/widgets/codecompletionpopup.cpp +++ b/RedPandaIDE/widgets/codecompletionpopup.cpp @@ -252,7 +252,8 @@ void CodeCompletionPopup::addStatement(const PStatement& statement, const QStrin return; if (statement->kind == StatementKind::skConstructor || statement->kind == StatementKind::skDestructor - || statement->kind == StatementKind::skBlock) + || statement->kind == StatementKind::skBlock + || statement->properties.testFlag(StatementProperty::spOperatorOverloading)) return; if ((line!=-1) && (line < statement->line)