support lambda expression captures.

This commit is contained in:
Roy Qu 2024-03-23 09:03:20 +08:00
parent d63aa1a58f
commit 09a61c4c32
6 changed files with 60 additions and 13 deletions

View File

@ -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.

View File

@ -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<QString> 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<QString> CppParser::parseLambdaCaptures(int index)
{
QString s = mTokenizer[index]->text;
QString word;
QSet<QString> result;
//skip '[' ']'
for (int i=1;i<s.length()-1;i++) {
switch(s[i].unicode()){
case ',':
if (!word.isEmpty()) {
result.insert(word);
word.clear();
}
break;
case ' ':
case '\t':
case '*':
break;
default:
if (word=="&")
word.clear();
word+=s[i];
}
}
if (!word.isEmpty())
result.insert(word);
return result;
}
QString CppParser::splitPhrase(const QString &phrase, QString &sClazz,

View File

@ -531,16 +531,10 @@ private:
void internalInvalidateFile(const QString& fileName);
void internalInvalidateFiles(const QSet<QString>& files);
QSet<QString> 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<QString> parseLambdaCaptures(int index);
QString splitPhrase(const QString& phrase, QString& sClazz,
QString& sOperator, QString &sMember) const;
QString removeTemplateParams(const QString& phrase) const;

View File

@ -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<QString> usingList; // using namespaces
QString noNameArgs;// Args without name
QSet<QString> lambdaCaptures;
StatementProperties properties;
// fields for code completion

View File

@ -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;

View File

@ -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();
}