- improve template parameters checker

- streamline cppparser
This commit is contained in:
Roy Qu 2022-11-05 08:42:54 +08:00
parent ef79640eb0
commit 8d9740dd57
4 changed files with 64 additions and 58 deletions

View File

@ -1,8 +1,8 @@
Red Panda C++ Version 2.2
- enhancement: basic code completion support for C++ lambda
- enhancement: basic code completion support for C++ lambdas
- enhancement: slightly reduce parsing time
- fix: Wrong charset name returned when saveing file
- fix: Wrong charset name returned when saving file
- fix: 'using =' / 'namespace =' not correctly handled
- fix: Pressing '*' at begin of line will crash app

View File

@ -957,7 +957,6 @@ void CppParser::resetParser()
mCurrentScope.clear();
mCurrentClassScope.clear();
mSkipList.clear();
mStatementList.clear();
mProjectFiles.clear();
@ -1460,15 +1459,19 @@ void CppParser::removeScopeLevel(int line)
// qDebug()<<"--remove scope"<<mCurrentFile<<line<<mCurrentClassScope.count();
PStatement currentScope = getCurrentScope();
PFileIncludes fileIncludes = mPreprocessor.includesList().value(mCurrentFile);
if (currentScope && (currentScope->kind == StatementKind::skBlock)) {
if (currentScope->children.isEmpty()) {
// remove no children block
if (fileIncludes) {
fileIncludes->scopes.removeLastScope();
if (currentScope) {
if (currentScope->kind == StatementKind::skBlock) {
if (currentScope->children.isEmpty()) {
// remove no children block
if (fileIncludes) {
fileIncludes->scopes.removeLastScope();
}
mStatementList.deleteStatement(currentScope);
} else {
fileIncludes->statements.insert(currentScope->fullName,currentScope);
}
mStatementList.deleteStatement(currentScope);
} else {
fileIncludes->statements.insert(currentScope->fullName,currentScope);
} else if (currentScope->kind == StatementKind::skClass) {
mIndex=indexOfNextSemicolon(mIndex);
}
}
mCurrentScope.pop_back();
@ -1494,7 +1497,6 @@ void CppParser::internalClear()
mCurrentClassScope.clear();
mIndex = 0;
mClassScope = StatementClassScope::None;
mSkipList.clear();
mBlockBeginSkips.clear();
mBlockEndSkips.clear();
mInlineNamespaceEndSkips.clear();
@ -1729,14 +1731,6 @@ bool CppParser::checkForScope(KeywordType keywordType)
);
}
void CppParser::checkForSkipStatement()
{
if ((mSkipList.count()>0) && (mIndex == mSkipList.back())) { // skip to next ';'
skipNextSemicolon(mIndex);
mSkipList.pop_back();
}
}
bool CppParser::checkForStructs(KeywordType keywordType)
{
int dis = 0;
@ -2181,7 +2175,7 @@ void CppParser::handleCatchBlock()
true,
false);
addSoloScopeLevel(block,startLine);
scanMethodArgs(block,mIndex, mTokenizer[mIndex]->matchIndex);
scanMethodArgs(block,mIndex);
mIndex=mTokenizer[mIndex]->matchIndex+1;
}
@ -2450,8 +2444,9 @@ void CppParser::handleKeyword(KeywordType skipType)
void CppParser::handleLambda(int index)
{
Q_ASSERT(mTokenizer[index]->text.startsWith('['));
Q_ASSERT(mTokenizer[index+1]->text.startsWith('('));
int startLine=mTokenizer[index]->line;
int argStart=index;
int argStart=index+1;
int argEnd= mTokenizer[argStart]->matchIndex;
int blockLine=mTokenizer[argStart]->line;
//TODO: parse captures
@ -2473,7 +2468,7 @@ void CppParser::handleLambda(int index)
StatementClassScope::None,
true,
false);
scanMethodArgs(lambdaBlock,argStart,argEnd);
scanMethodArgs(lambdaBlock,argStart);
addSoloScopeLevel(lambdaBlock,blockLine);
}
@ -2536,7 +2531,6 @@ void CppParser::handleMethod(StatementKind functionKind,const QString &sType, co
scopeStatement->friends.insert(scopelessName);
} else if (isValid) {
// Use the class the function belongs to as the parent ID if the function is declared outside of the class body
int delimPos = sName.lastIndexOf("::");
QString scopelessName;
QString parentClassName;
if (splitLastMember(sName,scopelessName,parentClassName)) {
@ -2563,7 +2557,7 @@ void CppParser::handleMethod(StatementKind functionKind,const QString &sType, co
mClassScope,
true,
isStatic);
scanMethodArgs(functionStatement, argStart,argEnd);
scanMethodArgs(functionStatement, argStart);
// add variable this to the class function
if (scopeStatement && scopeStatement->kind == StatementKind::skClass &&
!isStatic) {
@ -3031,10 +3025,10 @@ bool CppParser::handleStatement()
}
Q_ASSERT(mIndex<999999);
while (mTokenizer.lambdasCount()>0 && mTokenizer.indexOfFirstLambda()<mIndex) {
handleLambda(mTokenizer.indexOfFirstLambda());
mTokenizer.removeFirstLambda();
}
// while (mTokenizer.lambdasCount()>0 && mTokenizer.indexOfFirstLambda()<mIndex) {
// handleLambda(mTokenizer.indexOfFirstLambda());
// mTokenizer.removeFirstLambda();
// }
// else if (checkForMethod(funcType, funcName, argStart,argEnd, isStatic, isFriend)) {
// handleMethod(funcType, funcName, argStart, argEnd, isStatic, isFriend); // don't recalculate parts
// } else if (tryHandleVar()) {
@ -3043,7 +3037,7 @@ bool CppParser::handleStatement()
// mIndex++;
//todo: remove mSkipList (we can check '}''s statement type instead)
checkForSkipStatement();
// checkForSkipStatement();
return mIndex < mTokenizer.tokenCount();
@ -3210,7 +3204,6 @@ void CppParser::handleStructs(bool isTypedef)
mTokenizer[i + 1]->text.front() == ';'
|| mTokenizer[i + 1]->text.front() == '}')) {
// When encountering names again after struct body scanning, skip it
mSkipList.append(i+1); // add first name to skip statement so that we can skip it until the next ;
QString command = "";
QString args = "";
@ -3599,7 +3592,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
@ -3613,7 +3606,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
// Process the token list
while(true) {
@ -3621,8 +3614,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();
@ -4637,8 +4630,10 @@ int CppParser::calcKeyLenForStruct(const QString &word)
return -1;
}
void CppParser::scanMethodArgs(const PStatement& functionStatement, int argStart, int argEnd)
void CppParser::scanMethodArgs(const PStatement& functionStatement, int argStart)
{
Q_ASSERT(mTokenizer[argStart]->text=='(');
int argEnd=mTokenizer[argStart]->matchIndex;
int paramStart = argStart+1;
int i = paramStart ; // assume it starts with ( and ends with )
// Keep going and stop on top of the variable name

View File

@ -216,7 +216,6 @@ private:
bool checkForPreprocessor();
// bool checkForLambda();
bool checkForScope(KeywordType keywordType);
void checkForSkipStatement();
bool checkForStructs(KeywordType keywordType);
bool checkForTypedefEnum();
bool checkForTypedefStruct();
@ -451,8 +450,7 @@ private:
// }
void scanMethodArgs(
const PStatement& functionStatement,
int argStart,
int argEnd);
int argStart);
QString splitPhrase(const QString& phrase, QString& sClazz,
QString& sOperator, QString &sMember);
QString removeTemplateParams(const QString& phrase);
@ -608,9 +606,6 @@ private:
QVector<PStatement> mCurrentScope;
QVector<StatementClassScope> mCurrentClassScope;
// the start index in tokens to skip to ; when parsing typedef struct we need to skip
// the names after the closing bracket because we have processed it
QVector<int> mSkipList; // TList<Integer>
StatementClassScope mClassScope;
StatementModel mStatementList;
//It's used in preprocessor, so we can't use fIncludeList instead

View File

@ -113,7 +113,9 @@ void CppTokenizer::addToken(const QString &sText, int iLine, TokenType tokenType
PToken token = std::make_shared<Token>();
token->text = sText;
token->line = iLine;
#ifdef Q_DEBUG
token->matchIndex = 1000000000;
#endif
switch(tokenType) {
case TokenType::LeftBrace:
token->matchIndex=-1;
@ -573,16 +575,16 @@ void CppTokenizer::skipDoubleQuotes()
}
}
void CppTokenizer::skipPair(const QChar &cStart, const QChar cEnd, bool keepLambda)
void CppTokenizer::skipPair(const QChar &cStart, const QChar cEnd)
{
mCurrent++;
while (*mCurrent != 0) {
if (*mCurrent == '(') {
skipPair('(', ')',keepLambda);
skipPair('(', ')');
} else if (*mCurrent == '[') {
skipPair('[', ']',keepLambda);
skipPair('[', ']');
} else if (*mCurrent == '{') {
skipPair('{', '}',keepLambda);
skipPair('{', '}');
} else if (*mCurrent == cStart) {
skipPair(cStart, cEnd);
} else if (*mCurrent == cEnd) {
@ -603,8 +605,6 @@ void CppTokenizer::skipPair(const QChar &cStart, const QChar cEnd, bool keepLamb
skipSingleQuote(); // don't do it inside AnsiString!
else
mCurrent++;
} else if (failChars.contains(*mCurrent)) {
break;
} else {
mCurrent++;
}
@ -614,26 +614,40 @@ void CppTokenizer::skipPair(const QChar &cStart, const QChar cEnd, bool keepLamb
bool CppTokenizer::skipAngleBracketPair()
{
QChar* backup=mCurrent;
int level=0;
QVector<QChar> stack;
while (*mCurrent != '\0') {
switch((*mCurrent).unicode()) {
case '<':
case '(':
case '[':
level++;
stack.push_back(*mCurrent);
break;
case ')':
case ']':
level--;
if (level==0) {
while (!stack.isEmpty() && stack.back()!='(') {
stack.pop_back();
}
//pop up '('
if (stack.isEmpty()) {
mCurrent=backup;
return false;
}
stack.pop_back();
break;
case ']':
while (!stack.isEmpty() && stack.back()!='[')
stack.pop_back();
//pop up '['
if (stack.isEmpty()) {
mCurrent=backup;
return false;
}
stack.pop_back();
break;
case '>':
level--;
if (level==0) {
mCurrent++; //skip over >
if (stack.back()=='<')
stack.pop_back();
if (stack.isEmpty()) {
mCurrent++;
return true;
}
break;
@ -766,9 +780,11 @@ void CppTokenizer::removeFirstLambda()
void CppTokenizer::advance()
{
switch(mCurrent->unicode()) {
case '\"': skipDoubleQuotes();
case '\"':
skipDoubleQuotes();
break;
case '\'': skipSingleQuote();
case '\'':
skipSingleQuote();
break;
case '/':
if (*(mCurrent + 1) == '=')