diff --git a/NEWS.md b/NEWS.md index 0c7249f1..61a0a539 100644 --- a/NEWS.md +++ b/NEWS.md @@ -76,7 +76,7 @@ Red Panda C++ Version 2.27 - enhancement: Show "std::function" in the completion list. - enhancement: Improvement in italic font support. - fix: History not correctly loaded with up/down arrow key in the debug console. - - enhancement: Improve lambda support. + - enhancement: Improve lambda expression support. - enhancement: Show type completion hint after "constexpr"/"extern"/"static"/"consteval"/"constinit"/"const"/"volatile" etc. - enhancement: Restore line position after file is modified outside and reloaded. diff --git a/RedPandaIDE/parser/cppparser.cpp b/RedPandaIDE/parser/cppparser.cpp index cfa9ee29..fb0ca9b8 100644 --- a/RedPandaIDE/parser/cppparser.cpp +++ b/RedPandaIDE/parser/cppparser.cpp @@ -1458,8 +1458,6 @@ PStatement CppParser::addStatement(const PStatement& parent, result->setInProject(false); result->setInSystemHeader(true); } - //result->children; - //result->friends; if (scope == StatementScope::Local) result->fullName = newCommand; else @@ -2887,6 +2885,7 @@ void CppParser::handleKeyword(KeywordType skipType, int maxIndex) void CppParser::handleLambda(int index, int maxIndex) { Q_ASSERT(mTokenizer[index]->text.startsWith('[')); + QSet captures = parseLambdaCaptures(index); int startLine=mTokenizer[index]->line; int argStart=index+1; if (mTokenizer[argStart]->text!='(') @@ -2910,10 +2909,11 @@ void CppParser::handleLambda(int index, int maxIndex) "", "", startLine, - StatementKind::skBlock, + StatementKind::skLambda, StatementScope::Local, StatementAccessibility::None, StatementProperty::spHasDefinition); + lambdaBlock->lambdaCaptures = captures; scanMethodArgs(lambdaBlock,argStart); addSoloScopeLevel(lambdaBlock,mTokenizer[bodyStart]->line); int oldIndex = mIndex; @@ -5979,8 +5979,35 @@ void CppParser::scanMethodArgs(const PStatement& functionStatement, int argStart } } addMethodParameterStatement(words,mTokenizer[i-1]->line,functionStatement); +} - +QSet CppParser::parseLambdaCaptures(int index) +{ + QString s = mTokenizer[index]->text; + QString word; + QSet result; + //skip '[' ']' + for (int i=1;i& files); QSet calculateFilesToBeReparsed(const QString& fileName); -// int calcKeyLenForStruct(const QString& word); -// { -// function GetClass(const Phrase: AnsiString): AnsiString; -// function GetMember(const Phrase: AnsiString): AnsiString; -// function GetOperator(const Phrase: AnsiString): AnsiString; -// function GetRemainder(const Phrase: AnsiString): AnsiString; -// } void scanMethodArgs( const PStatement& functionStatement, int argStart); + QSet parseLambdaCaptures(int index); QString splitPhrase(const QString& phrase, QString& sClazz, QString& sOperator, QString &sMember) const; QString removeTemplateParams(const QString& phrase) const; diff --git a/RedPandaIDE/parser/parserutils.h b/RedPandaIDE/parser/parserutils.h index 7a97c2ad..0b94b35d 100644 --- a/RedPandaIDE/parser/parserutils.h +++ b/RedPandaIDE/parser/parserutils.h @@ -107,6 +107,7 @@ enum StatementKind { skOperator, skParameter, skBlock, + skLambda, skUserCodeSnippet, // user code template skKeyword, // keywords skKeywordType, //keywords for type (for color management) @@ -197,6 +198,7 @@ struct Statement { QString fullName; // fullname(including class and namespace), ClassA::foo QSet usingList; // using namespaces QString noNameArgs;// Args without name + QSet lambdaCaptures; StatementProperties properties; // fields for code completion diff --git a/RedPandaIDE/widgets/classbrowser.cpp b/RedPandaIDE/widgets/classbrowser.cpp index 88cd0fc2..30810469 100644 --- a/RedPandaIDE/widgets/classbrowser.cpp +++ b/RedPandaIDE/widgets/classbrowser.cpp @@ -363,7 +363,8 @@ void ClassBrowserModel::filterChildren(ClassBrowserNode *node, const StatementMa if (statement->kind == StatementKind::skBlock) continue; - + if (statement->kind == StatementKind::skLambda) + continue; if (statement->isInherited() && !pSettings->ui().classBrowserShowInherited()) continue; diff --git a/RedPandaIDE/widgets/codecompletionpopup.cpp b/RedPandaIDE/widgets/codecompletionpopup.cpp index be444f1b..de2e7f78 100644 --- a/RedPandaIDE/widgets/codecompletionpopup.cpp +++ b/RedPandaIDE/widgets/codecompletionpopup.cpp @@ -287,6 +287,7 @@ void CodeCompletionPopup::addStatement(const PStatement& statement, const QStrin if (statement->kind == StatementKind::skConstructor || statement->kind == StatementKind::skDestructor || statement->kind == StatementKind::skBlock + || statement->kind == StatementKind::skLambda || statement->properties.testFlag(StatementProperty::spOperatorOverloading) || statement->properties.testFlag(StatementProperty::spDummyStatement) ) @@ -687,6 +688,28 @@ void CodeCompletionPopup::getCompletionFor( addChildren(namespaceStatement, fileName, line, isLambdaReturnType); } } + if (scopeStatement->kind == StatementKind::skLambda) { + foreach (const QString& phrase, scopeStatement->lambdaCaptures) { + if (phrase=="&" || phrase == "=" || phrase =="this") + continue; + PStatement statement = mParser->findStatementOf( + scopeStatement->fileName, + phrase,scopeStatement->line); + if (statement) + addStatement(statement,scopeStatement->fileName, scopeStatement->line); + } + if (scopeStatement->lambdaCaptures.contains("&") + || scopeStatement->lambdaCaptures.contains("=")) { + scopeStatement = scopeStatement->parentScope.lock(); + continue; + } else if (scopeStatement->lambdaCaptures.contains("this")) { + do { + scopeStatement = scopeStatement->parentScope.lock(); + } while (scopeStatement && scopeStatement->kind!=StatementKind::skClass); + continue; + } + break; + } scopeStatement=scopeStatement->parentScope.lock(); }