diff --git a/NEWS.md b/NEWS.md index d9996552..f05a1013 100644 --- a/NEWS.md +++ b/NEWS.md @@ -17,6 +17,7 @@ Version 0.6.0 - implement: when startup , open file provided by command line options - implement: open files pasted by clipboard - fix: code fold parsing not correct + - enhancement: support #include_next (and clang libc++) Version 0.5.0 - enhancement: support C++ using type alias; diff --git a/RedPandaIDE/parser/cppparser.cpp b/RedPandaIDE/parser/cppparser.cpp index f2a12c99..83634581 100644 --- a/RedPandaIDE/parser/cppparser.cpp +++ b/RedPandaIDE/parser/cppparser.cpp @@ -68,25 +68,25 @@ void CppParser::addHardDefineByLine(const QString &line) void CppParser::addIncludePath(const QString &value) { QMutexLocker locker(&mMutex); - mPreprocessor.includePaths().insert(includeTrailingPathDelimiter(value)); + mPreprocessor.addIncludePath(includeTrailingPathDelimiter(value)); } void CppParser::addProjectIncludePath(const QString &value) { QMutexLocker locker(&mMutex); - mPreprocessor.projectIncludePaths().insert(includeTrailingPathDelimiter(value)); + mPreprocessor.addProjectIncludePath(includeTrailingPathDelimiter(value)); } void CppParser::clearIncludePaths() { QMutexLocker locker(&mMutex); - mPreprocessor.includePaths().clear(); + mPreprocessor.clearIncludePaths(); } void CppParser::clearProjectIncludePaths() { QMutexLocker locker(&mMutex); - mPreprocessor.projectIncludePaths().clear(); + mPreprocessor.clearProjectIncludePaths(); } void CppParser::clearProjectFiles() @@ -819,8 +819,8 @@ void CppParser::reset() mNamespaces.clear(); mInlineNamespaces.clear(); - mPreprocessor.projectIncludePaths().clear(); - mPreprocessor.includePaths().clear(); + mPreprocessor.clearProjectIncludePaths(); + mPreprocessor.clearIncludePaths(); mProjectFiles.clear(); } } diff --git a/RedPandaIDE/parser/cpppreprocessor.cpp b/RedPandaIDE/parser/cpppreprocessor.cpp index 2efae0a0..b0ad374f 100644 --- a/RedPandaIDE/parser/cpppreprocessor.cpp +++ b/RedPandaIDE/parser/cpppreprocessor.cpp @@ -212,6 +212,30 @@ void CppPreprocessor::dumpIncludesListTo(const QString &fileName) const } } +void CppPreprocessor::addIncludePath(const QString &fileName) +{ + mIncludePaths.insert(fileName); + mIncludePathList.append(fileName); +} + +void CppPreprocessor::addProjectIncludePath(const QString &fileName) +{ + mProjectIncludePaths.insert(fileName); + mProjectIncludeList.append(fileName); +} + +void CppPreprocessor::clearIncludePaths() +{ + mIncludePaths.clear(); + mIncludePathList.clear(); +} + +void CppPreprocessor::clearProjectIncludePaths() +{ + mProjectIncludePaths.clear(); + mProjectIncludeList.clear(); +} + QString CppPreprocessor::getNextPreprocessor() { skipToPreprocessor(); // skip until # at start of line @@ -323,15 +347,42 @@ void CppPreprocessor::handleDefine(const QString &line) } } -void CppPreprocessor::handleInclude(const QString &line) +void CppPreprocessor::handleInclude(const QString &line, bool fromNext) { if (!getCurrentBranch()) // we're skipping due to a branch failure return; PParsedFile file = mIncludes.back(); + QString fileName; // Get full header file name - QString fileName = getHeaderFilename(file->fileName, line,mIncludePaths, - mProjectIncludePaths); + QString currentDir = includeTrailingPathDelimiter(extractFileDir(file->fileName)); + QSet includes; + QSet projectIncludes; + if (fromNext && mIncludePaths.contains(currentDir)) { + bool found = false; + foreach(const QString& s, mIncludePathList) { + if (found) + includes.insert(s); + if (s == currentDir) + found = true; + } + } else + includes = mIncludePaths; + if (fromNext && mProjectIncludePaths.contains(currentDir)) { + bool found = false; + foreach(const QString& s, mProjectIncludeList) { + if (found) + projectIncludes.insert(s); + if (s == currentDir) + found = true; + } + } else + projectIncludes = mProjectIncludePaths; + fileName = getHeaderFilename( + file->fileName, + line, + includes, + projectIncludes); if (fileName.isEmpty()) return; @@ -354,6 +405,8 @@ void CppPreprocessor::handlePreprocessor(const QString &value) handleBranch(value); else if (value.startsWith("include")) handleInclude(value); + else if (value.startsWith("include_next")) + handleInclude(value,true); } void CppPreprocessor::handleUndefine(const QString &line) @@ -1662,12 +1715,12 @@ const DefineMap &CppPreprocessor::hardDefines() const return mHardDefines; } -QSet &CppPreprocessor::projectIncludePaths() +const QSet &CppPreprocessor::projectIncludePaths() { return mProjectIncludePaths; } -QSet &CppPreprocessor::includePaths() +const QSet &CppPreprocessor::includePaths() { return mIncludePaths; } diff --git a/RedPandaIDE/parser/cpppreprocessor.h b/RedPandaIDE/parser/cpppreprocessor.h index 660143e9..8a2cbf47 100644 --- a/RedPandaIDE/parser/cpppreprocessor.h +++ b/RedPandaIDE/parser/cpppreprocessor.h @@ -60,15 +60,19 @@ public: void dumpDefinesTo(const QString& fileName) const; void dumpIncludesListTo(const QString& fileName) const; + void addIncludePath(const QString& fileName); + void addProjectIncludePath(const QString& fileName); + void clearIncludePaths(); + void clearProjectIncludePaths(); QStringList result() const; QHash &includesList(); QSet &scannedFiles(); - QSet &includePaths(); + const QSet &includePaths(); - QSet &projectIncludePaths(); + const QSet &projectIncludePaths(); const DefineMap &hardDefines() const; @@ -82,7 +86,7 @@ private: void simplify(QString& output); void handleBranch(const QString& line); void handleDefine(const QString& line); - void handleInclude(const QString& line); + void handleInclude(const QString& line, bool fromNext=false); void handlePreprocessor(const QString& value); void handleUndefine(const QString& line); QString expandMacros(const QString& line, int depth); @@ -183,6 +187,9 @@ private: QSet mIncludePaths; //{ List of current project's include path } QSet mProjectIncludePaths; + //we also need include paths in order (for #include_next) + QList mIncludePathList; + QList mProjectIncludeList; bool mParseSystem; bool mParseLocal; diff --git a/RedPandaIDE/widgets/functiontooltipwidget.cpp b/RedPandaIDE/widgets/functiontooltipwidget.cpp index 80f605c8..a7757fe8 100644 --- a/RedPandaIDE/widgets/functiontooltipwidget.cpp +++ b/RedPandaIDE/widgets/functiontooltipwidget.cpp @@ -70,6 +70,10 @@ void FunctionTooltipWidget::setParamPos(int newParamPos) void FunctionTooltipWidget::nextTip() { + if (mInfoIndex>=mInfos.length()-1) { + hide(); + return; + } if (mInfos.length()>0) mInfoIndex = std::min(mInfoIndex+1,mInfos.length()-1); updateTip(); @@ -77,6 +81,10 @@ void FunctionTooltipWidget::nextTip() void FunctionTooltipWidget::previousTip() { + if (mInfoIndex==0) { + hide(); + return ; + } if (mInfos.length()>0) mInfoIndex = std::max(mInfoIndex-1,0); updateTip();