diff --git a/RedPandaIDE/parser/cppparser.cpp b/RedPandaIDE/parser/cppparser.cpp index b509436b..39b719ff 100644 --- a/RedPandaIDE/parser/cppparser.cpp +++ b/RedPandaIDE/parser/cppparser.cpp @@ -110,6 +110,89 @@ void CppParser::fillListOfFunctions(const QString &fileName, const QString &phra fillListOfFunctions(fileName,line,statement,parentScope,list); } +PStatement CppParser::findAndScanBlockAt(const QString &filename, int line) +{ + QMutexLocker locker(&mMutex); + if (mParsing) + return PStatement(); + PFileIncludes fileIncludes = findFileIncludes(filename); + if (!fileIncludes) + return PStatement(); + + + PStatement statement = fileIncludes->scopes.findScopeAtLine(line); + return statement; +} + +PFileIncludes CppParser::findFileIncludes(const QString &filename, bool deleteIt) +{ + QMutexLocker locker(&mMutex); + PFileIncludes fileIncludes = mIncludesList->value(filename,PFileIncludes()); + if (deleteIt && fileIncludes) + mIncludesList->remove(filename); + return fileIncludes; +} + +QString CppParser::findFirstTemplateParamOf(const QString &fileName, const QString &phrase, PStatement currentScope) +{ + QMutexLocker locker(&mMutex); + QString result = ""; + if (mParsing) + return ""; + // Remove pointer stuff from type + QString s = phrase; // 'Type' is a keyword + int i = s.indexOf('<'); + if (i>=0) { + int t=getFirstTemplateParamEnd(s,i); + return s.mid(i+1,t-i-1); + } + int position = s.length()-1; + while ((position >= 0) && (s[position] == '*' + || s[position] == ' ' + || s[position] == '&')) + position--; + if (position != s.length()-1) + s.truncate(position+1); + + PStatement scopeStatement = currentScope; + + PStatement statement = findStatementOf(fileName,s,currentScope); + return getFirstTemplateParam(statement,fileName, phrase, currentScope); +} + +QString CppParser::getFirstTemplateParam(PStatement statement, const QString& filename, const QString& phrase, PStatement currentScope) +{ + if (!statement) + return ""; + if (statement->kind != StatementKind::skTypedef) + return ""; + if (statement->type == phrase) // prevent infinite loop + return ""; + return findFirstTemplateParamOf(filename,statement->type, currentScope); +} + +int CppParser::getFirstTemplateParamEnd(const QString &s, int startAt) +{ + int i = startAt; + int level = 0; // assume we start on top of '<' + while (i < s.length()) { + switch (s[i].unicode()) { + case '<': + level++; + break; + case ',': + if (level == 1) + return i; + case '>': + level--; + if (level==0) + return i; + } + i++; + } + return startAt; +} + void CppParser::addFileToScan(QString value, bool inProject) { QMutexLocker locker(&mMutex); @@ -334,7 +417,7 @@ void CppParser::addSoloScopeLevel(PStatement statement, int line) PFileIncludes fileIncludes = findFileIncludes(mCurrentFile); if (fileIncludes) { - fileIncludes->scopes.insert(line,statement); + fileIncludes->scopes.addScope(line,statement); } // Set new scope @@ -359,8 +442,8 @@ void CppParser::removeScopeLevel(int line) if (currentScope && (currentScope->kind == StatementKind::skBlock)) { if (currentScope->children.isEmpty()) { // remove no children block - if (fileIncludes && !fileIncludes->scopes.isEmpty()) { - fileIncludes->scopes.remove(currentScope->line); + if (fileIncludes) { + fileIncludes->scopes.removeLastScope(); } mStatementList.deleteStatement(currentScope); } else { @@ -374,9 +457,8 @@ void CppParser::removeScopeLevel(int line) // Set new scope currentScope = getCurrentScope(); // fileIncludes:=FindFileIncludes(fCurrentFile); - if (fileIncludes && !fileIncludes->scopes.isEmpty() - && fileIncludes->scopes.value(fileIncludes->scopes.keys().back())!=currentScope) { - fileIncludes->scopes.insert(line,currentScope); + if (fileIncludes && fileIncludes->scopes.lastScope()!=currentScope) { + fileIncludes->scopes.addScope(line,currentScope); } if (!currentScope) { diff --git a/RedPandaIDE/parser/cppparser.h b/RedPandaIDE/parser/cppparser.h index dbaf90de..5d61ecb9 100644 --- a/RedPandaIDE/parser/cppparser.h +++ b/RedPandaIDE/parser/cppparser.h @@ -24,7 +24,6 @@ public: void clearProjectIncludePaths(); void clearProjectFiles(); void parseHardDefines(); - PFileIncludes findFileIncludes(const QString &filename, bool deleteIt = false); void invalidateFile(const QString& fileName); QStringList getFileDirectIncludes(const QString& filename) const; const QList& getFileIncludes(const QString& filename) const; @@ -57,6 +56,11 @@ public: int line, QStringList& list); PStatement findAndScanBlockAt(const QString& filename, int line); + PFileIncludes findFileIncludes(const QString &filename, bool deleteIt = false); + QString findFirstTemplateParamOf(const QString& fileName, + const QString& phrase, + PStatement currentScope); + PStatement findStatementOf(const QString& fileName, const QString& phrase, int line); @@ -84,9 +88,6 @@ public: PStatement findTypeDefinitionOf(const QString& fileName, const QString& phrase, PStatement currentClass); - QString FindFirstTemplateParamOf(const QString& fileName, - const QString& phrase, - PStatement currentClass); int findLastOperator(const QString& phrase) const; PStatementList findNamespace(const QString& name); // return a list of PSTATEMENTS (of the namespace) bool freeze(); // Freeze/Lock (stop reparse while searching) @@ -182,6 +183,9 @@ private: int getCurrentBlockEndSkip(); int getCurrentInlineNamespaceEndSkip(); PStatement getCurrentScope(); // gets last item from last level + QString getFirstTemplateParam(PStatement statement, const QString& filename, + const QString& phrase, PStatement currentScope); + int getFirstTemplateParamEnd(const QString& s, int startAt); void getFullNameSpace( const QString& phrase, QString& sNamespace, diff --git a/RedPandaIDE/parser/parserutils.cpp b/RedPandaIDE/parser/parserutils.cpp index 3c07b69b..340e0faa 100644 --- a/RedPandaIDE/parser/parserutils.cpp +++ b/RedPandaIDE/parser/parserutils.cpp @@ -3,6 +3,7 @@ #include #include #include +#include QStringList CppDirectives; QStringList JavadocTags; @@ -369,3 +370,59 @@ bool isCfile(const QString filename) QFileInfo fileInfo(filename); return CppSourceExts.contains(fileInfo.suffix().toLower()); } + +PStatement CppScopes::findScopeAtLine(int line) +{ + if (mScopes.isEmpty()) + return PStatement(); + int start = 0; + int end = mScopes.size()-1; + while (start<=end) { + int mid = (start+end)/2; + PCppScope midScope = mScopes[mid]; + if (midScope->startLine == line) { + while (mid-1>=0 && (mScopes[mid-1]->startLine == line)) { + mid--; + } + return mScopes[mid]->statement; + } else if (midScope->startLine > line) { + end = mid-1; + } else { + start = mid+1; + } + } + if (startstatement; + else + return mScopes.back()->statement; +} + +void CppScopes::addScope(int line, PStatement scopeStatement) +{ + PCppScope scope = std::make_shared(); + scope->startLine = line; + scope->statement = scopeStatement; + mScopes.append(scope); + if (!mScopes.isEmpty() && mScopes.back()->startLine>line) { + qDebug()<fullName, line,mScopes.back()->startLine>line); + } +} + +PStatement CppScopes::lastScope() +{ + if (mScopes.isEmpty()) + return PStatement(); + return mScopes.back()->statement; +} + +void CppScopes::removeLastScope() +{ + if (!mScopes.isEmpty()) + mScopes.pop_back(); +} + +void CppScopes::clear() +{ + mScopes.clear(); +} diff --git a/RedPandaIDE/parser/parserutils.h b/RedPandaIDE/parser/parserutils.h index 22270405..1877ad4e 100644 --- a/RedPandaIDE/parser/parserutils.h +++ b/RedPandaIDE/parser/parserutils.h @@ -139,13 +139,31 @@ struct IncompleteClass { }; using PIncompleteClass = std::shared_ptr; +struct CppScope { + int startLine; + PStatement statement; +}; + +using PCppScope = std::shared_ptr; +class CppScopes { + +public: + PStatement findScopeAtLine(int line); + void addScope(int line, PStatement scopeStatement); + PStatement lastScope(); + void removeLastScope(); + void clear(); +private: + QVector mScopes; +}; + struct FileIncludes { QString baseFile; QMap includeFiles; // true means the file is directly included, false means included indirectly QSet usings; // namespaces it usings StatementMap statements; // but we don't save temporary statements (full name as key) StatementMap declaredStatements; // statements declared in this file (full name as key) - QMap scopes; // int is start line of the statement scope + CppScopes scopes; // int is start line of the statement scope QSet dependingFiles; // The files I depeneds on QSet dependedFiles; // the files depends on me };