- improve template parameters checker
- streamline cppparser
This commit is contained in:
parent
ef79640eb0
commit
8d9740dd57
4
NEWS.md
4
NEWS.md
|
@ -1,8 +1,8 @@
|
||||||
Red Panda C++ Version 2.2
|
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
|
- 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: 'using =' / 'namespace =' not correctly handled
|
||||||
- fix: Pressing '*' at begin of line will crash app
|
- fix: Pressing '*' at begin of line will crash app
|
||||||
|
|
||||||
|
|
|
@ -957,7 +957,6 @@ void CppParser::resetParser()
|
||||||
|
|
||||||
mCurrentScope.clear();
|
mCurrentScope.clear();
|
||||||
mCurrentClassScope.clear();
|
mCurrentClassScope.clear();
|
||||||
mSkipList.clear();
|
|
||||||
mStatementList.clear();
|
mStatementList.clear();
|
||||||
|
|
||||||
mProjectFiles.clear();
|
mProjectFiles.clear();
|
||||||
|
@ -1460,7 +1459,8 @@ void CppParser::removeScopeLevel(int line)
|
||||||
// qDebug()<<"--remove scope"<<mCurrentFile<<line<<mCurrentClassScope.count();
|
// qDebug()<<"--remove scope"<<mCurrentFile<<line<<mCurrentClassScope.count();
|
||||||
PStatement currentScope = getCurrentScope();
|
PStatement currentScope = getCurrentScope();
|
||||||
PFileIncludes fileIncludes = mPreprocessor.includesList().value(mCurrentFile);
|
PFileIncludes fileIncludes = mPreprocessor.includesList().value(mCurrentFile);
|
||||||
if (currentScope && (currentScope->kind == StatementKind::skBlock)) {
|
if (currentScope) {
|
||||||
|
if (currentScope->kind == StatementKind::skBlock) {
|
||||||
if (currentScope->children.isEmpty()) {
|
if (currentScope->children.isEmpty()) {
|
||||||
// remove no children block
|
// remove no children block
|
||||||
if (fileIncludes) {
|
if (fileIncludes) {
|
||||||
|
@ -1470,6 +1470,9 @@ void CppParser::removeScopeLevel(int line)
|
||||||
} else {
|
} else {
|
||||||
fileIncludes->statements.insert(currentScope->fullName,currentScope);
|
fileIncludes->statements.insert(currentScope->fullName,currentScope);
|
||||||
}
|
}
|
||||||
|
} else if (currentScope->kind == StatementKind::skClass) {
|
||||||
|
mIndex=indexOfNextSemicolon(mIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mCurrentScope.pop_back();
|
mCurrentScope.pop_back();
|
||||||
mCurrentClassScope.pop_back();
|
mCurrentClassScope.pop_back();
|
||||||
|
@ -1494,7 +1497,6 @@ void CppParser::internalClear()
|
||||||
mCurrentClassScope.clear();
|
mCurrentClassScope.clear();
|
||||||
mIndex = 0;
|
mIndex = 0;
|
||||||
mClassScope = StatementClassScope::None;
|
mClassScope = StatementClassScope::None;
|
||||||
mSkipList.clear();
|
|
||||||
mBlockBeginSkips.clear();
|
mBlockBeginSkips.clear();
|
||||||
mBlockEndSkips.clear();
|
mBlockEndSkips.clear();
|
||||||
mInlineNamespaceEndSkips.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)
|
bool CppParser::checkForStructs(KeywordType keywordType)
|
||||||
{
|
{
|
||||||
int dis = 0;
|
int dis = 0;
|
||||||
|
@ -2181,7 +2175,7 @@ void CppParser::handleCatchBlock()
|
||||||
true,
|
true,
|
||||||
false);
|
false);
|
||||||
addSoloScopeLevel(block,startLine);
|
addSoloScopeLevel(block,startLine);
|
||||||
scanMethodArgs(block,mIndex, mTokenizer[mIndex]->matchIndex);
|
scanMethodArgs(block,mIndex);
|
||||||
mIndex=mTokenizer[mIndex]->matchIndex+1;
|
mIndex=mTokenizer[mIndex]->matchIndex+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2450,8 +2444,9 @@ void CppParser::handleKeyword(KeywordType skipType)
|
||||||
void CppParser::handleLambda(int index)
|
void CppParser::handleLambda(int index)
|
||||||
{
|
{
|
||||||
Q_ASSERT(mTokenizer[index]->text.startsWith('['));
|
Q_ASSERT(mTokenizer[index]->text.startsWith('['));
|
||||||
|
Q_ASSERT(mTokenizer[index+1]->text.startsWith('('));
|
||||||
int startLine=mTokenizer[index]->line;
|
int startLine=mTokenizer[index]->line;
|
||||||
int argStart=index;
|
int argStart=index+1;
|
||||||
int argEnd= mTokenizer[argStart]->matchIndex;
|
int argEnd= mTokenizer[argStart]->matchIndex;
|
||||||
int blockLine=mTokenizer[argStart]->line;
|
int blockLine=mTokenizer[argStart]->line;
|
||||||
//TODO: parse captures
|
//TODO: parse captures
|
||||||
|
@ -2473,7 +2468,7 @@ void CppParser::handleLambda(int index)
|
||||||
StatementClassScope::None,
|
StatementClassScope::None,
|
||||||
true,
|
true,
|
||||||
false);
|
false);
|
||||||
scanMethodArgs(lambdaBlock,argStart,argEnd);
|
scanMethodArgs(lambdaBlock,argStart);
|
||||||
addSoloScopeLevel(lambdaBlock,blockLine);
|
addSoloScopeLevel(lambdaBlock,blockLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2536,7 +2531,6 @@ void CppParser::handleMethod(StatementKind functionKind,const QString &sType, co
|
||||||
scopeStatement->friends.insert(scopelessName);
|
scopeStatement->friends.insert(scopelessName);
|
||||||
} else if (isValid) {
|
} else if (isValid) {
|
||||||
// Use the class the function belongs to as the parent ID if the function is declared outside of the class body
|
// 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 scopelessName;
|
||||||
QString parentClassName;
|
QString parentClassName;
|
||||||
if (splitLastMember(sName,scopelessName,parentClassName)) {
|
if (splitLastMember(sName,scopelessName,parentClassName)) {
|
||||||
|
@ -2563,7 +2557,7 @@ void CppParser::handleMethod(StatementKind functionKind,const QString &sType, co
|
||||||
mClassScope,
|
mClassScope,
|
||||||
true,
|
true,
|
||||||
isStatic);
|
isStatic);
|
||||||
scanMethodArgs(functionStatement, argStart,argEnd);
|
scanMethodArgs(functionStatement, argStart);
|
||||||
// add variable this to the class function
|
// add variable this to the class function
|
||||||
if (scopeStatement && scopeStatement->kind == StatementKind::skClass &&
|
if (scopeStatement && scopeStatement->kind == StatementKind::skClass &&
|
||||||
!isStatic) {
|
!isStatic) {
|
||||||
|
@ -3031,10 +3025,10 @@ bool CppParser::handleStatement()
|
||||||
}
|
}
|
||||||
Q_ASSERT(mIndex<999999);
|
Q_ASSERT(mIndex<999999);
|
||||||
|
|
||||||
while (mTokenizer.lambdasCount()>0 && mTokenizer.indexOfFirstLambda()<mIndex) {
|
// while (mTokenizer.lambdasCount()>0 && mTokenizer.indexOfFirstLambda()<mIndex) {
|
||||||
handleLambda(mTokenizer.indexOfFirstLambda());
|
// handleLambda(mTokenizer.indexOfFirstLambda());
|
||||||
mTokenizer.removeFirstLambda();
|
// mTokenizer.removeFirstLambda();
|
||||||
}
|
// }
|
||||||
// else if (checkForMethod(funcType, funcName, argStart,argEnd, isStatic, isFriend)) {
|
// else if (checkForMethod(funcType, funcName, argStart,argEnd, isStatic, isFriend)) {
|
||||||
// handleMethod(funcType, funcName, argStart, argEnd, isStatic, isFriend); // don't recalculate parts
|
// handleMethod(funcType, funcName, argStart, argEnd, isStatic, isFriend); // don't recalculate parts
|
||||||
// } else if (tryHandleVar()) {
|
// } else if (tryHandleVar()) {
|
||||||
|
@ -3043,7 +3037,7 @@ bool CppParser::handleStatement()
|
||||||
// mIndex++;
|
// mIndex++;
|
||||||
|
|
||||||
//todo: remove mSkipList (we can check '}''s statement type instead)
|
//todo: remove mSkipList (we can check '}''s statement type instead)
|
||||||
checkForSkipStatement();
|
// checkForSkipStatement();
|
||||||
|
|
||||||
return mIndex < mTokenizer.tokenCount();
|
return mIndex < mTokenizer.tokenCount();
|
||||||
|
|
||||||
|
@ -3210,7 +3204,6 @@ void CppParser::handleStructs(bool isTypedef)
|
||||||
mTokenizer[i + 1]->text.front() == ';'
|
mTokenizer[i + 1]->text.front() == ';'
|
||||||
|| mTokenizer[i + 1]->text.front() == '}')) {
|
|| mTokenizer[i + 1]->text.front() == '}')) {
|
||||||
// When encountering names again after struct body scanning, skip it
|
// 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 command = "";
|
||||||
QString args = "";
|
QString args = "";
|
||||||
|
|
||||||
|
@ -3599,7 +3592,7 @@ void CppParser::internalParse(const QString &fileName)
|
||||||
|
|
||||||
QStringList preprocessResult = mPreprocessor.result();
|
QStringList preprocessResult = mPreprocessor.result();
|
||||||
#ifdef QT_DEBUG
|
#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.dumpDefinesTo("r:\\defines.txt");
|
||||||
// mPreprocessor.dumpIncludesListTo("r:\\includes.txt");
|
// mPreprocessor.dumpIncludesListTo("r:\\includes.txt");
|
||||||
#endif
|
#endif
|
||||||
|
@ -3613,7 +3606,7 @@ void CppParser::internalParse(const QString &fileName)
|
||||||
if (mTokenizer.tokenCount() == 0)
|
if (mTokenizer.tokenCount() == 0)
|
||||||
return;
|
return;
|
||||||
#ifdef QT_DEBUG
|
#ifdef QT_DEBUG
|
||||||
mTokenizer.dumpTokens(QString("r:\\tokens-%1.txt").arg(extractFileName(fileName)));
|
// mTokenizer.dumpTokens(QString("r:\\tokens-%1.txt").arg(extractFileName(fileName)));
|
||||||
#endif
|
#endif
|
||||||
// Process the token list
|
// Process the token list
|
||||||
while(true) {
|
while(true) {
|
||||||
|
@ -3621,8 +3614,8 @@ void CppParser::internalParse(const QString &fileName)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifdef QT_DEBUG
|
#ifdef QT_DEBUG
|
||||||
mStatementList.dumpAll(QString("r:\\all-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)));
|
// mStatementList.dump(QString("r:\\stats-%1.txt").arg(extractFileName(fileName)));
|
||||||
#endif
|
#endif
|
||||||
//reduce memory usage
|
//reduce memory usage
|
||||||
internalClear();
|
internalClear();
|
||||||
|
@ -4637,8 +4630,10 @@ int CppParser::calcKeyLenForStruct(const QString &word)
|
||||||
return -1;
|
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 paramStart = argStart+1;
|
||||||
int i = paramStart ; // assume it starts with ( and ends with )
|
int i = paramStart ; // assume it starts with ( and ends with )
|
||||||
// Keep going and stop on top of the variable name
|
// Keep going and stop on top of the variable name
|
||||||
|
|
|
@ -216,7 +216,6 @@ private:
|
||||||
bool checkForPreprocessor();
|
bool checkForPreprocessor();
|
||||||
// bool checkForLambda();
|
// bool checkForLambda();
|
||||||
bool checkForScope(KeywordType keywordType);
|
bool checkForScope(KeywordType keywordType);
|
||||||
void checkForSkipStatement();
|
|
||||||
bool checkForStructs(KeywordType keywordType);
|
bool checkForStructs(KeywordType keywordType);
|
||||||
bool checkForTypedefEnum();
|
bool checkForTypedefEnum();
|
||||||
bool checkForTypedefStruct();
|
bool checkForTypedefStruct();
|
||||||
|
@ -451,8 +450,7 @@ private:
|
||||||
// }
|
// }
|
||||||
void scanMethodArgs(
|
void scanMethodArgs(
|
||||||
const PStatement& functionStatement,
|
const PStatement& functionStatement,
|
||||||
int argStart,
|
int argStart);
|
||||||
int argEnd);
|
|
||||||
QString splitPhrase(const QString& phrase, QString& sClazz,
|
QString splitPhrase(const QString& phrase, QString& sClazz,
|
||||||
QString& sOperator, QString &sMember);
|
QString& sOperator, QString &sMember);
|
||||||
QString removeTemplateParams(const QString& phrase);
|
QString removeTemplateParams(const QString& phrase);
|
||||||
|
@ -608,9 +606,6 @@ private:
|
||||||
QVector<PStatement> mCurrentScope;
|
QVector<PStatement> mCurrentScope;
|
||||||
QVector<StatementClassScope> mCurrentClassScope;
|
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;
|
StatementClassScope mClassScope;
|
||||||
StatementModel mStatementList;
|
StatementModel mStatementList;
|
||||||
//It's used in preprocessor, so we can't use fIncludeList instead
|
//It's used in preprocessor, so we can't use fIncludeList instead
|
||||||
|
|
|
@ -113,7 +113,9 @@ void CppTokenizer::addToken(const QString &sText, int iLine, TokenType tokenType
|
||||||
PToken token = std::make_shared<Token>();
|
PToken token = std::make_shared<Token>();
|
||||||
token->text = sText;
|
token->text = sText;
|
||||||
token->line = iLine;
|
token->line = iLine;
|
||||||
|
#ifdef Q_DEBUG
|
||||||
token->matchIndex = 1000000000;
|
token->matchIndex = 1000000000;
|
||||||
|
#endif
|
||||||
switch(tokenType) {
|
switch(tokenType) {
|
||||||
case TokenType::LeftBrace:
|
case TokenType::LeftBrace:
|
||||||
token->matchIndex=-1;
|
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++;
|
mCurrent++;
|
||||||
while (*mCurrent != 0) {
|
while (*mCurrent != 0) {
|
||||||
if (*mCurrent == '(') {
|
if (*mCurrent == '(') {
|
||||||
skipPair('(', ')',keepLambda);
|
skipPair('(', ')');
|
||||||
} else if (*mCurrent == '[') {
|
} else if (*mCurrent == '[') {
|
||||||
skipPair('[', ']',keepLambda);
|
skipPair('[', ']');
|
||||||
} else if (*mCurrent == '{') {
|
} else if (*mCurrent == '{') {
|
||||||
skipPair('{', '}',keepLambda);
|
skipPair('{', '}');
|
||||||
} else if (*mCurrent == cStart) {
|
} else if (*mCurrent == cStart) {
|
||||||
skipPair(cStart, cEnd);
|
skipPair(cStart, cEnd);
|
||||||
} else if (*mCurrent == 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!
|
skipSingleQuote(); // don't do it inside AnsiString!
|
||||||
else
|
else
|
||||||
mCurrent++;
|
mCurrent++;
|
||||||
} else if (failChars.contains(*mCurrent)) {
|
|
||||||
break;
|
|
||||||
} else {
|
} else {
|
||||||
mCurrent++;
|
mCurrent++;
|
||||||
}
|
}
|
||||||
|
@ -614,26 +614,40 @@ void CppTokenizer::skipPair(const QChar &cStart, const QChar cEnd, bool keepLamb
|
||||||
bool CppTokenizer::skipAngleBracketPair()
|
bool CppTokenizer::skipAngleBracketPair()
|
||||||
{
|
{
|
||||||
QChar* backup=mCurrent;
|
QChar* backup=mCurrent;
|
||||||
int level=0;
|
QVector<QChar> stack;
|
||||||
while (*mCurrent != '\0') {
|
while (*mCurrent != '\0') {
|
||||||
switch((*mCurrent).unicode()) {
|
switch((*mCurrent).unicode()) {
|
||||||
case '<':
|
case '<':
|
||||||
case '(':
|
case '(':
|
||||||
case '[':
|
case '[':
|
||||||
level++;
|
stack.push_back(*mCurrent);
|
||||||
break;
|
break;
|
||||||
case ')':
|
case ')':
|
||||||
case ']':
|
while (!stack.isEmpty() && stack.back()!='(') {
|
||||||
level--;
|
stack.pop_back();
|
||||||
if (level==0) {
|
}
|
||||||
|
//pop up '('
|
||||||
|
if (stack.isEmpty()) {
|
||||||
mCurrent=backup;
|
mCurrent=backup;
|
||||||
return false;
|
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;
|
break;
|
||||||
case '>':
|
case '>':
|
||||||
level--;
|
if (stack.back()=='<')
|
||||||
if (level==0) {
|
stack.pop_back();
|
||||||
mCurrent++; //skip over >
|
if (stack.isEmpty()) {
|
||||||
|
mCurrent++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -766,9 +780,11 @@ void CppTokenizer::removeFirstLambda()
|
||||||
void CppTokenizer::advance()
|
void CppTokenizer::advance()
|
||||||
{
|
{
|
||||||
switch(mCurrent->unicode()) {
|
switch(mCurrent->unicode()) {
|
||||||
case '\"': skipDoubleQuotes();
|
case '\"':
|
||||||
|
skipDoubleQuotes();
|
||||||
break;
|
break;
|
||||||
case '\'': skipSingleQuote();
|
case '\'':
|
||||||
|
skipSingleQuote();
|
||||||
break;
|
break;
|
||||||
case '/':
|
case '/':
|
||||||
if (*(mCurrent + 1) == '=')
|
if (*(mCurrent + 1) == '=')
|
||||||
|
|
Loading…
Reference in New Issue