- enhancement: Parse files that contains C++ 20 'concept' keyword. (No code suggesion for concepts now)
- enhancement: Parse files that contains C++ 20 'requires' keyword. - fix: Code suggestions in namespace. - enhancement: Code suggestions for namespace alias. - fix: Correctly handle statements like 'using xxx::operator()'.
This commit is contained in:
parent
9467645bef
commit
30cabe2faa
5
NEWS.md
5
NEWS.md
|
@ -4,6 +4,11 @@ Red Panda C++ Version 2.26
|
|||
- enhancement: Auto adjust position of the suggestion popup window.
|
||||
- enhancement: Windows XP support ( by cyano.CN )
|
||||
- fix: __attribute__ is not correctly handled if it is after 'static'.
|
||||
- enhancement: Parse files that contains C++ 20 'concept' keyword. (No code suggesion for concepts now)
|
||||
- enhancement: Parse files that contains C++ 20 'requires' keyword.
|
||||
- fix: Code suggestions in namespace.
|
||||
- enhancement: Code suggestions for namespace alias.
|
||||
- fix: Correctly handle statements like 'using xxx::operator()'.
|
||||
|
||||
Red Panda C++ Version 2.25
|
||||
|
||||
|
|
|
@ -216,7 +216,7 @@ QByteArray Compiler::pipedText()
|
|||
return QByteArray();
|
||||
}
|
||||
|
||||
bool Compiler::beforeRunExtraCommand(int idx)
|
||||
bool Compiler::beforeRunExtraCommand(int /* idx */)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1958,6 +1958,8 @@ bool CppParser::checkForKeyword(KeywordType& keywordType)
|
|||
case KeywordType::NotKeyword:
|
||||
case KeywordType::DeclType:
|
||||
case KeywordType::Operator:
|
||||
case KeywordType::Requires:
|
||||
case KeywordType::Concept:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
|
@ -2577,6 +2579,19 @@ void CppParser::handleCatchBlock()
|
|||
mIndex=mTokenizer[mIndex]->matchIndex+1;
|
||||
}
|
||||
|
||||
void CppParser::handleConcept()
|
||||
{
|
||||
mIndex++; // skip 'concept';
|
||||
// just skip it;
|
||||
mIndex = indexOfNextSemicolonOrLeftBrace(mIndex);
|
||||
if (mIndex<mTokenizer.tokenCount()) {
|
||||
if (mTokenizer[mIndex]->text=='{')
|
||||
mIndex = mTokenizer[mIndex]->matchIndex+1; // skip '}'
|
||||
else
|
||||
mIndex++; // skip ;
|
||||
}
|
||||
}
|
||||
|
||||
void CppParser::handleEnum(bool isTypedef)
|
||||
{
|
||||
int tokenCount = mTokenizer.tokenCount();
|
||||
|
@ -3244,6 +3259,17 @@ void CppParser::handleNamespace(KeywordType skipType)
|
|||
QString aliasName;
|
||||
if ((mIndex+2<tokenCount) && (mTokenizer[mIndex]->text == '=')) {
|
||||
aliasName=mTokenizer[mIndex+1]->text;
|
||||
mIndex+=2;
|
||||
if (aliasName == "::" && mIndex<tokenCount) {
|
||||
aliasName += mTokenizer[mIndex]->text;
|
||||
mIndex++;
|
||||
}
|
||||
while(mIndex+1<tokenCount && mTokenizer[mIndex]->text == "::") {
|
||||
aliasName+="::";
|
||||
aliasName+=mTokenizer[mIndex+1]->text;
|
||||
mIndex+=2;
|
||||
}
|
||||
//qDebug()<<command<<aliasName;
|
||||
//namespace alias
|
||||
addStatement(
|
||||
getCurrentScope(),
|
||||
|
@ -3259,7 +3285,7 @@ void CppParser::handleNamespace(KeywordType skipType)
|
|||
getScope(),
|
||||
mCurrentMemberAccessibility,
|
||||
StatementProperty::spHasDefinition);
|
||||
mIndex+=2; //skip ;
|
||||
mIndex++; // skip ;
|
||||
return;
|
||||
} else if (isInline) {
|
||||
//inline namespace , just skip it
|
||||
|
@ -3589,6 +3615,10 @@ bool CppParser::handleStatement()
|
|||
mIndex=moveToEndOfStatement(mIndex,true);
|
||||
} else if (checkForKeyword(keywordType)) { // includes template now
|
||||
handleKeyword(keywordType);
|
||||
} else if (keywordType==KeywordType::Concept) {
|
||||
handleConcept();
|
||||
} else if (keywordType==KeywordType::Requires) {
|
||||
skipRequires();
|
||||
} else if (keywordType==KeywordType::For) { // (for/catch)
|
||||
handleForBlock();
|
||||
} else if (keywordType==KeywordType::Catch) { // (for/catch)
|
||||
|
@ -3980,10 +4010,18 @@ void CppParser::handleUsing()
|
|||
|| (mTokenizer[mIndex]->text != "namespace")) {
|
||||
QString fullName;
|
||||
QString usingName;
|
||||
bool appendUsingName = false;
|
||||
while (mIndex<tokenCount &&
|
||||
mTokenizer[mIndex]->text!=';') {
|
||||
fullName += mTokenizer[mIndex]->text;
|
||||
usingName = mTokenizer[mIndex]->text;
|
||||
if (!appendUsingName) {
|
||||
usingName = mTokenizer[mIndex]->text;
|
||||
if (usingName == "operator") {
|
||||
appendUsingName=true;
|
||||
}
|
||||
} else {
|
||||
usingName += mTokenizer[mIndex]->text;
|
||||
}
|
||||
mIndex++;
|
||||
}
|
||||
if (fullName!=usingName) {
|
||||
|
@ -4327,6 +4365,43 @@ void CppParser::handleVar(const QString& typePrefix,bool isExtern,bool isStatic)
|
|||
mIndex++;
|
||||
}
|
||||
|
||||
void CppParser::skipRequires()
|
||||
{
|
||||
mIndex++; //skip 'requires';
|
||||
|
||||
int tokenCount = mTokenizer.tokenCount();
|
||||
while (mIndex < tokenCount) { // ||
|
||||
while (mIndex < tokenCount) { // &&
|
||||
if (mTokenizer[mIndex]->text=='(') {
|
||||
//skip parenthesized expression
|
||||
mIndex = mTokenizer[mIndex]->matchIndex+1;
|
||||
} else if (isIdentifier(mTokenizer[mIndex]->text)) {
|
||||
// skip foo<T> or foo::boo::ttt<T>
|
||||
while (mIndex < tokenCount) {
|
||||
if (!isIdentifier(mTokenizer[mIndex]->text))
|
||||
return;
|
||||
mIndex++;
|
||||
if (mIndex>=tokenCount)
|
||||
return;
|
||||
if (mTokenizer[mIndex]->text!="::")
|
||||
break;
|
||||
mIndex++; // skip '::';
|
||||
}
|
||||
}
|
||||
if (mIndex>=tokenCount)
|
||||
return;
|
||||
if (mTokenizer[mIndex]->text!="&&")
|
||||
break;
|
||||
mIndex++; // skip '&&';
|
||||
}
|
||||
if (mIndex>=tokenCount)
|
||||
return;
|
||||
if (mTokenizer[mIndex]->text!="||")
|
||||
break;
|
||||
mIndex++; // skip '||';
|
||||
}
|
||||
}
|
||||
|
||||
void CppParser::internalParse(const QString &fileName)
|
||||
{
|
||||
// Perform some validation before we start
|
||||
|
@ -5209,6 +5284,9 @@ PEvalStatement CppParser::doEvalTerm(const QString &fileName,
|
|||
case StatementKind::skNamespace:
|
||||
result = doCreateEvalNamespace(statement);
|
||||
break;
|
||||
case StatementKind::skNamespaceAlias:
|
||||
result = doFindAliasedNamespace(statement);
|
||||
break;
|
||||
case StatementKind::skAlias: {
|
||||
statement = doFindAliasedStatement(statement);
|
||||
if (statement)
|
||||
|
@ -5421,6 +5499,29 @@ PEvalStatement CppParser::doCreateEvalNamespace(const PStatement &namespaceState
|
|||
namespaceStatement);
|
||||
}
|
||||
|
||||
PEvalStatement CppParser::doFindAliasedNamespace(const PStatement &namespaceAlias) const
|
||||
{
|
||||
QStringList expList;
|
||||
QString s = namespaceAlias->type;
|
||||
int pos = s.indexOf("::");
|
||||
while (pos>=0) {
|
||||
expList.append(s.left(pos));
|
||||
expList.append("::");
|
||||
s = s.mid(pos+2);
|
||||
pos = s.indexOf("::");
|
||||
}
|
||||
expList.append(s);
|
||||
pos=0;
|
||||
return doEvalExpression(
|
||||
namespaceAlias->fileName,
|
||||
expList,
|
||||
pos,
|
||||
namespaceAlias->parentScope.lock(),
|
||||
PEvalStatement(),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
PEvalStatement CppParser::doCreateEvalType(const QString &fileName, const QString &typeName, const PStatement& parentScope) const
|
||||
{
|
||||
QString baseType;
|
||||
|
|
|
@ -223,11 +223,13 @@ private:
|
|||
int evaluateConstExprTerm(int endIndex, bool &ok);
|
||||
int evaluateLiteralNumber(int endIndex, bool &ok);
|
||||
|
||||
bool checkForConcept(KeywordType &keywordType) { return keywordType == KeywordType::Concept; }
|
||||
bool checkForKeyword(KeywordType &keywordType);
|
||||
bool checkForNamespace(KeywordType keywordType);
|
||||
bool checkForPreprocessor();
|
||||
// bool checkForLambda();
|
||||
bool checkForAccessibilitySpecifiers(KeywordType keywordType);
|
||||
bool checkForRequires(KeywordType keywordType) { return keywordType == KeywordType::Requires; }
|
||||
bool checkForStructs(KeywordType keywordType);
|
||||
bool checkForTypedefEnum();
|
||||
bool checkForTypedefStruct();
|
||||
|
@ -371,6 +373,8 @@ private:
|
|||
|
||||
PEvalStatement doCreateEvalNamespace(const PStatement& namespaceStatement) const;
|
||||
|
||||
PEvalStatement doFindAliasedNamespace(const PStatement& namespaceAlias) const;
|
||||
|
||||
PEvalStatement doCreateEvalType(const QString& fileName,const QString& typeName, const PStatement& parentScope) const;
|
||||
PEvalStatement doCreateEvalType(const QString& fileName,const PStatement& typeStatement) const;
|
||||
PEvalStatement doCreateEvalType(const QString& primitiveType) const;
|
||||
|
@ -485,6 +489,7 @@ private:
|
|||
PStatement getTypeDef(const PStatement& statement,
|
||||
const QString& fileName, const QString& aType) const;
|
||||
void handleCatchBlock();
|
||||
void handleConcept();
|
||||
void handleEnum(bool isTypedef);
|
||||
void handleForBlock();
|
||||
void handleKeyword(KeywordType skipType);
|
||||
|
@ -510,6 +515,7 @@ private:
|
|||
void handleStructs(bool isTypedef = false);
|
||||
void handleUsing();
|
||||
void handleVar(const QString& typePrefix,bool isExtern,bool isStatic);
|
||||
void skipRequires();
|
||||
void internalParse(const QString& fileName);
|
||||
// function FindMacroDefine(const Command: AnsiString): PStatement;
|
||||
void inheritClassStatement(
|
||||
|
|
|
@ -135,20 +135,21 @@ void initParser()
|
|||
CppKeywords.insert("__asm",KeywordType::SkipNextParenthesis);
|
||||
// Skip to {
|
||||
|
||||
CppKeywords.insert("requires",KeywordType::Requires);
|
||||
CppKeywords.insert("concept",KeywordType::Concept);
|
||||
|
||||
// wont handle
|
||||
|
||||
//Not supported yet
|
||||
CppKeywords.insert("atomic_cancel",KeywordType::None);
|
||||
CppKeywords.insert("atomic_commit",KeywordType::None);
|
||||
CppKeywords.insert("atomic_noexcept",KeywordType::None);
|
||||
CppKeywords.insert("concept",KeywordType::None);
|
||||
CppKeywords.insert("consteval",KeywordType::None);
|
||||
CppKeywords.insert("constinit",KeywordType::None);
|
||||
CppKeywords.insert("co_wait",KeywordType::None);
|
||||
CppKeywords.insert("co_return",KeywordType::None);
|
||||
CppKeywords.insert("co_yield",KeywordType::None);
|
||||
CppKeywords.insert("reflexpr",KeywordType::None);
|
||||
CppKeywords.insert("requires",KeywordType::None);
|
||||
|
||||
// its a type
|
||||
CppKeywords.insert("auto",KeywordType::None);
|
||||
|
|
|
@ -81,6 +81,8 @@ enum class KeywordType {
|
|||
Using, //using
|
||||
DeclType, // decltype
|
||||
Operator, //operator
|
||||
Concept, //concept
|
||||
Requires, //requires
|
||||
None, // It's a keyword but don't process here
|
||||
NotKeyword
|
||||
};
|
||||
|
|
|
@ -664,7 +664,13 @@ void CodeCompletionPopup::getCompletionFor(
|
|||
// repeat until reach global
|
||||
while (scopeStatement) {
|
||||
//add members of current scope that not added before
|
||||
if (scopeStatement->kind == StatementKind::skClass) {
|
||||
if (scopeStatement->kind == StatementKind::skNamespace) {
|
||||
PStatementList namespaceStatementsList =
|
||||
mParser->findNamespace(scopeStatement->fullName);
|
||||
foreach (const PStatement& namespaceStatement,*namespaceStatementsList) {
|
||||
addChildren(namespaceStatement, fileName, line, isLambdaReturnType);
|
||||
}
|
||||
} else if (scopeStatement->kind == StatementKind::skClass) {
|
||||
addChildren(scopeStatement, fileName, -1, isLambdaReturnType);
|
||||
} else {
|
||||
addChildren(scopeStatement, fileName, line, isLambdaReturnType);
|
||||
|
|
|
@ -148,7 +148,7 @@ public:
|
|||
virtual bool getTokenFinished() const = 0;
|
||||
virtual bool isLastLineCommentNotFinished(int state) const = 0;
|
||||
virtual bool isLastLineStringNotFinished(int state) const = 0;
|
||||
virtual bool isDocstringNotFinished(int state) const { return false; }
|
||||
virtual bool isDocstringNotFinished(int /* state */) const { return false; }
|
||||
virtual bool eol() const = 0;
|
||||
virtual SyntaxState getState() const = 0;
|
||||
virtual QString getToken() const=0;
|
||||
|
|
Loading…
Reference in New Issue