From 0d0332aa7d4689b1c97465acaf09c9ac6fbdbcd0 Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Tue, 29 Nov 2022 12:06:29 +0800 Subject: [PATCH] - fix: can't correctly show completion suggest for type with template parameters - enhancement: correctly evaluate auto variable of stl container iterator. --- NEWS.md | 3 +- RedPandaIDE/editor.cpp | 2 +- RedPandaIDE/parser/cppparser.cpp | 125 ++++++++++++++++++++--------- RedPandaIDE/parser/cppparser.h | 4 +- RedPandaIDE/parser/parserutils.cpp | 23 ++++-- RedPandaIDE/parser/parserutils.h | 13 ++- 6 files changed, 118 insertions(+), 52 deletions(-) diff --git a/NEWS.md b/NEWS.md index 8a8dbed9..a911df2c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -10,8 +10,9 @@ Red Panda C++ Version 2.5 - change: Default value of option "Auto clear symbols in hidden editors" is ON if number of CPU cores > 8 and "Editors share one code analyzer" is on - enhancement: show completion suggest for "namespace" after "using" - fix: MinGW-w64 gcc displayed as "MinGW GCC" - - enhancement: Deduce type info for "auto" in some simple cases. + - enhancement: Deduce type info for "auto" in some simple cases for stl containers. - fix: crash when no semicolon or left brace after the keyword "namespace" + - fix: can't correctly show completion suggest for type with template parameters Red Panda C++ Version 2.4 diff --git a/RedPandaIDE/editor.cpp b/RedPandaIDE/editor.cpp index a4a1ca4e..2a3a34aa 100644 --- a/RedPandaIDE/editor.cpp +++ b/RedPandaIDE/editor.cpp @@ -2141,7 +2141,7 @@ QStringList Editor::getExpressionAtPosition( case LastSymbolType::MatchingAngleQuotation: if (token=="<") { if (symbolMatchingLevel==0) { - lastSymbolType=LastSymbolType::MatchingAngleQuotation; + lastSymbolType=LastSymbolType::AngleQuotationMatched; } else { symbolMatchingLevel--; } diff --git a/RedPandaIDE/parser/cppparser.cpp b/RedPandaIDE/parser/cppparser.cpp index 7be65495..50862164 100644 --- a/RedPandaIDE/parser/cppparser.cpp +++ b/RedPandaIDE/parser/cppparser.cpp @@ -3685,9 +3685,11 @@ void CppParser::handleVar(const QString& typePrefix,bool isExtern,bool isStatic) PEvalStatement(), true); if(aliasStatement) { - if (aliasStatement->effectiveTypeStatement) + if (aliasStatement->effectiveTypeStatement) { addedVar->type = aliasStatement->effectiveTypeStatement->fullName; - else + if (!addedVar->type.endsWith(">")) + addedVar->type += aliasStatement->templateParams; + } else addedVar->type = aliasStatement->baseType; if (aliasStatement->pointerLevel>0) addedVar->type += QString(aliasStatement->pointerLevel,'*'); @@ -3728,9 +3730,11 @@ void CppParser::handleVar(const QString& typePrefix,bool isExtern,bool isStatic) PEvalStatement(), true); if(aliasStatement && aliasStatement->effectiveTypeStatement) { - if (aliasStatement->effectiveTypeStatement) + if (aliasStatement->effectiveTypeStatement) { addedVar->type = aliasStatement->effectiveTypeStatement->fullName; - else + if (!addedVar->type.endsWith(">")) + addedVar->type += aliasStatement->templateParams; + } else addedVar->type = aliasStatement->baseType; if (aliasStatement->pointerLevel>0) addedVar->type += QString(aliasStatement->pointerLevel,'*'); @@ -4102,19 +4106,36 @@ PEvalStatement CppParser::doEvalCCast(const QString &fileName, freeScoped); if (result) { //todo: STL container; + if (result->pointerLevel==0) { - PStatement typeStatement = result->effectiveTypeStatement; - if ((typeStatement) + //STL smart pointers + if (result->typeStatement + && STLIterators.contains(result->typeStatement->command) + ) { + PStatement parentScope = result->typeStatement->parentScope.lock(); + if (STLContainers.contains(parentScope->fullName)) { + QString typeName=findFirstTemplateParamOf(fileName,result->templateParams, parentScope); + // qDebug()<<"typeName"<baseStatement->type<baseStatement->command; + PStatement typeStatement=findTypeDefinitionOf(fileName, typeName,parentScope); + if (typeStatement) { + result = doCreateEvalType(fileName,typeStatement); + result->kind = EvalStatementKind::Variable; + } + } + } else { + PStatement typeStatement = result->effectiveTypeStatement; + if ((typeStatement) && STLPointers.contains(typeStatement->fullName) && result->kind == EvalStatementKind::Variable && result->baseStatement) { - PStatement parentScope = result->baseStatement->parentScope.lock(); - QString typeName=findFirstTemplateParamOf(fileName,result->baseStatement->type, parentScope); -// qDebug()<<"typeName"<kind = EvalStatementKind::Variable; + PStatement parentScope = result->baseStatement->parentScope.lock(); + QString typeName=findFirstTemplateParamOf(fileName,result->baseStatement->type, parentScope); + // qDebug()<<"typeName"<kind = EvalStatementKind::Variable; + } } } } else @@ -4443,18 +4464,7 @@ PEvalStatement CppParser::doEvalTerm(const QString &fileName, if (!previousResult) { statement = findStatementInScope(phraseExpression[pos],PStatement()); } else { -// if (previousResult->effectiveTypeStatement) { -// qDebug()<effectiveTypeStatement->fullName; -// } else { -// qDebug()<effectiveTypeStatement); -// if (!statement) { -// qDebug()<<"not found!"; -// } else { -// qDebug()<fullName; -// qDebug()<kind; -// } } } pos++; @@ -4488,6 +4498,17 @@ PEvalStatement CppParser::doEvalTerm(const QString &fileName, default: result = PEvalStatement(); } + if (result + && result->typeStatement + && STLIterators.contains(result->typeStatement->command) + && previousResult) { + PStatement parentStatement = result->typeStatement->parentScope.lock(); + if (parentStatement + && STLContainers.contains(parentStatement->fullName)) { +// result->baseType = parentStatement->fullName+previousResult->templateParams+result->typeStatement->command; + result->templateParams = previousResult->templateParams; + } + } } } else if (isIntegerLiteral(phraseExpression[pos])) { result = doCreateEvalLiteral("int"); @@ -4525,6 +4546,7 @@ PEvalStatement CppParser::doEvalTerm(const QString &fileName, // if (!result) { // qDebug()<<"not found !!!!"; // } + return result; } @@ -4536,6 +4558,7 @@ PEvalStatement CppParser::doCreateEvalNamespace(const PStatement &namespaceState namespaceStatement->fullName, EvalStatementKind::Namespace, PStatement(), + namespaceStatement, namespaceStatement); } @@ -4546,24 +4569,31 @@ PEvalStatement CppParser::doCreateEvalType(const QString& fileName,const PStatem if (typeStatement->kind == StatementKind::skTypedef) { QString baseType; int pointerLevel=0; - PStatement statement = doParseEvalTypeInfo( + QString templateParams; + PStatement tempStatement; + PStatement effetiveTypeStatement = doParseEvalTypeInfo( fileName, typeStatement->parentScope.lock(), typeStatement->type + typeStatement->args, baseType, - pointerLevel); + tempStatement, + pointerLevel, + templateParams); return std::make_shared( baseType, EvalStatementKind::Type, PStatement(), - typeStatement, - pointerLevel + typeStatement, + effetiveTypeStatement, + pointerLevel, + templateParams ); } else { return std::make_shared( typeStatement->fullName, EvalStatementKind::Type, PStatement(), + typeStatement, typeStatement); } } @@ -4574,6 +4604,7 @@ PEvalStatement CppParser::doCreateEvalType(const QString &primitiveType) primitiveType, EvalStatementKind::Type, PStatement(), + PStatement(), PStatement()); } @@ -4583,19 +4614,25 @@ PEvalStatement CppParser::doCreateEvalVariable(const QString &fileName, PStateme return PEvalStatement(); QString baseType; int pointerLevel=0; - PStatement typeStatement = doParseEvalTypeInfo( + QString templateParams; + PStatement typeStatement; + PStatement effetiveTypeStatement = doParseEvalTypeInfo( fileName, varStatement->parentScope.lock(), - varStatement->type+ varStatement->args, + varStatement->type+varStatement->args, baseType, - pointerLevel); + typeStatement, + pointerLevel, + templateParams); // qDebug()<<"parse ..."<( baseType, EvalStatementKind::Variable, varStatement, typeStatement, - pointerLevel + effetiveTypeStatement, + pointerLevel, + templateParams ); } @@ -4605,18 +4642,24 @@ PEvalStatement CppParser::doCreateEvalFunction(const QString &fileName, PStateme return PEvalStatement(); QString baseType; int pointerLevel=0; - PStatement typeStatement = doParseEvalTypeInfo( + QString templateParams; + PStatement typeStatement; + PStatement effetiveTypeStatement = doParseEvalTypeInfo( fileName, funcStatement->parentScope.lock(), funcStatement->type, baseType, - pointerLevel); + typeStatement, + pointerLevel, + templateParams); return std::make_shared( baseType, EvalStatementKind::Function, funcStatement, typeStatement, - pointerLevel + effetiveTypeStatement, + pointerLevel, + templateParams ); } @@ -4626,6 +4669,7 @@ PEvalStatement CppParser::doCreateEvalLiteral(const QString &type) type, EvalStatementKind::Literal, PStatement(), + PStatement(), PStatement()); } @@ -4652,7 +4696,9 @@ PStatement CppParser::doParseEvalTypeInfo( const PStatement &scope, const QString &type, QString &baseType, - int &pointerLevel) + PStatement& typeStatement, + int &pointerLevel, + QString& templateParams) { // Remove pointer stuff from type QString s = type; @@ -4678,6 +4724,7 @@ PStatement CppParser::doParseEvalTypeInfo( } else if (token == "<") { templateLevel++; baseType += token; + templateParams += token; } else if (token == "::") { baseType += token; } @@ -4694,6 +4741,7 @@ PStatement CppParser::doParseEvalTypeInfo( templateLevel--; } baseType += token; + templateParams += token; } highlighter.next(); } @@ -4705,9 +4753,8 @@ PStatement CppParser::doParseEvalTypeInfo( } position--; } - PStatement statement = findStatementOf(fileName,baseType,scope,true); - return getTypeDef(statement,fileName,baseType); - + typeStatement = findStatementOf(fileName,baseType,scope,true); + return getTypeDef(typeStatement,fileName,baseType); } int CppParser::getBracketEnd(const QString &s, int startAt) diff --git a/RedPandaIDE/parser/cppparser.h b/RedPandaIDE/parser/cppparser.h index 544add4b..0fed2cdc 100644 --- a/RedPandaIDE/parser/cppparser.h +++ b/RedPandaIDE/parser/cppparser.h @@ -391,7 +391,9 @@ private: const PStatement& scope, const QString& type, QString& baseType, - int& pointerLevel); + PStatement& typeStatement, + int& pointerLevel, + QString& templateParams); int getBracketEnd(const QString& s, int startAt); StatementClassScope getClassScope(const QString& text); diff --git a/RedPandaIDE/parser/parserutils.cpp b/RedPandaIDE/parser/parserutils.cpp index 149599ea..ea81cf7e 100644 --- a/RedPandaIDE/parser/parserutils.cpp +++ b/RedPandaIDE/parser/parserutils.cpp @@ -32,6 +32,7 @@ QSet CKeywords; QSet STLPointers; QSet STLContainers; QSet STLElementMethods; +QSet STLIterators; QSet MemberOperators; QSet IOManipulators; @@ -275,14 +276,20 @@ void initParser() STLElementMethods.insert("front"); STLElementMethods.insert("top"); + //STL iterator + STLIterators.insert("iterator"); + STLIterators.insert("const_iterator"); + STLIterators.insert("reverse_iterator"); + STLIterators.insert("const_reverse_iterator"); + //STL pointers STLPointers.insert("std::unique_ptr"); STLPointers.insert("std::auto_ptr"); STLPointers.insert("std::shared_ptr"); STLPointers.insert("std::weak_ptr"); - STLPointers.insert("__gnu_cxx::__normal_iterator"); - STLPointers.insert("std::reverse_iterator"); - STLPointers.insert("std::iterator"); + //STLPointers.insert("__gnu_cxx::__normal_iterator"); + //STLPointers.insert("std::reverse_iterator"); + //STLPointers.insert("std::iterator"); //C/CPP preprocessor directives CppDirectives.append("#include"); @@ -568,14 +575,18 @@ EvalStatement::EvalStatement( const QString &baseType, EvalStatementKind kind, const PStatement &baseStatement, - const PStatement &typeStatement, - int pointerLevel) + const PStatement& typeStatement, + const PStatement& effectiveTypeStatement, + int pointerLevel, + const QString& templateParams) { this->baseType = baseType; this->kind = kind; this->baseStatement = baseStatement; - this->effectiveTypeStatement = typeStatement; + this->typeStatement = typeStatement; + this->effectiveTypeStatement = effectiveTypeStatement; this->pointerLevel = pointerLevel; + this->templateParams = templateParams; } void EvalStatement::assignType(const PEvalStatement &typeStatement) diff --git a/RedPandaIDE/parser/parserutils.h b/RedPandaIDE/parser/parserutils.h index cee98571..04d3c374 100644 --- a/RedPandaIDE/parser/parserutils.h +++ b/RedPandaIDE/parser/parserutils.h @@ -239,16 +239,20 @@ using PEvalStatement = std::shared_ptr; */ struct EvalStatement { QString baseType; // type "int" + QString templateParams; EvalStatementKind kind; // namespace / type / variable / function / literal int pointerLevel; // 0 for "int", 1 for "int *", 2 for "int **"... PStatement baseStatement; // if not literal or primitive type, the base statement + PStatement typeStatement; PStatement effectiveTypeStatement; public: EvalStatement (const QString& baseType, - EvalStatementKind kind, - const PStatement& baseStatement, - const PStatement& typeStatement, - int pointerLevel = 0); + EvalStatementKind kind, + const PStatement& baseStatement, + const PStatement& typeStatement, + const PStatement& effectiveTypeStatement, + int pointerLevel=0, + const QString& templateParams=QString()); void assignType(const PEvalStatement& typeStatement); }; @@ -300,6 +304,7 @@ extern QSet CppTypeKeywords; extern QSet STLPointers; extern QSet STLContainers; extern QSet STLElementMethods; +extern QSet STLIterators; extern QSet MemberOperators; extern QSet IOManipulators;