From a62910e1a3e874bb8b1189dc26b3a8efec5c14ad Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Tue, 18 Oct 2022 12:24:59 +0800 Subject: [PATCH] - fix: editor tooltip for #include_next is not correctly calculated - fix: ctrl+click on #include_next header name doesn't open the right file - enhancement: parser used for non-project C files won't find header files in C++ include folders. --- NEWS.md | 4 + RedPandaIDE/editor.cpp | 52 +++-- RedPandaIDE/editor.h | 4 +- RedPandaIDE/mainwindow.cpp | 53 +++-- RedPandaIDE/mainwindow.h | 2 + RedPandaIDE/parser/cppparser.cpp | 183 +++++++++++------- RedPandaIDE/parser/cppparser.h | 7 +- RedPandaIDE/parser/cpppreprocessor.cpp | 49 +++-- RedPandaIDE/parser/cpppreprocessor.h | 4 + RedPandaIDE/parser/cpptokenizer.cpp | 1 + RedPandaIDE/parser/cpptokenizer.h | 2 + RedPandaIDE/parser/statementmodel.cpp | 3 + RedPandaIDE/project.cpp | 4 +- .../settingsdialog/compilersetoptionwidget.ui | 2 +- RedPandaIDE/utils.cpp | 16 +- tools/consolepauser/main.windows.cpp | 2 +- 16 files changed, 241 insertions(+), 147 deletions(-) diff --git a/NEWS.md b/NEWS.md index 557597dd..b6bfee2a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -25,6 +25,10 @@ Red Panda C++ Version 1.5 - fix: project files openned by double click in bookmark/breakpoint panel may cause app crash when closed. - fix: When open a project that's already openned, shouldn't close it. - enhancement: When open a project, let user choose weither open it in new window or replace the already openned project + - fix: editor tooltip for #include_next is not correctly calculated + - fix: ctrl+click on #include_next header name doesn't open the right file + - enhancement: parser used for non-project C files won't find header files in C++ include folders. + - fix: when physical memory is less than 16G or "Auto clearn Red Panda C++ Version 1.4 diff --git a/RedPandaIDE/editor.cpp b/RedPandaIDE/editor.cpp index aed3db26..e4f1911e 100644 --- a/RedPandaIDE/editor.cpp +++ b/RedPandaIDE/editor.cpp @@ -223,7 +223,7 @@ void Editor::loadFile(QString filename) { mUseCppSyntax = pSettings->editor().defaultFileCpp(); } if (highlighter()) { - reparse(); + reparse(true); if (pSettings->editor().syntaxCheckWhenLineChanged()) { checkSyntaxInBack(); } @@ -278,7 +278,7 @@ bool Editor::save(bool force, bool doReparse) { } if (doReparse && mParser) { - reparse(); + reparse(false); } if (doReparse && pSettings->editor().syntaxCheckWhenSave()) checkSyntaxInBack(); @@ -387,7 +387,7 @@ bool Editor::saveAs(const QString &name, bool fromProject){ } applyColorScheme(pSettings->editor().colorScheme()); - reparse(); + reparse(false); if (pSettings->editor().syntaxCheckWhenSave()) pMainWindow->checkSyntaxInBack(this); @@ -1054,6 +1054,7 @@ bool Editor::event(QEvent *event) // Get subject bool isIncludeLine = false; + bool isIncludeNextLine = false; QSynedit::BufferCoord pBeginPos,pEndPos; QString s; QStringList expression; @@ -1061,8 +1062,10 @@ bool Editor::event(QEvent *event) case TipType::Preprocessor: // When hovering above a preprocessor line, determine if we want to show an include or a identifier hint s = document()->getString(p.line - 1); - isIncludeLine = mParser->isIncludeLine(s); - if (!isIncludeLine) + isIncludeNextLine = mParser->isIncludeNextLine(s); + if (!isIncludeNextLine) + isIncludeLine = mParser->isIncludeLine(s); + if (!isIncludeNextLine &&!isIncludeLine) s = wordAtRowCol(p); break; case TipType::Identifier: @@ -1116,9 +1119,9 @@ bool Editor::event(QEvent *event) QString hint = ""; switch (reason) { case TipType::Preprocessor: - if (isIncludeLine) { + if (isIncludeNextLine || isIncludeLine) { if (pSettings->editor().enableHeaderToolTips()) - hint = getFileHint(s); + hint = getFileHint(s, isIncludeNextLine); } else if (//devEditor.ParserHints and !mCompletionPopup->isVisible() && !mHeaderCompletionPopup->isVisible()) { @@ -1204,7 +1207,14 @@ void Editor::mouseReleaseEvent(QMouseEvent *event) QSynedit::BufferCoord p; if (pointToCharLine(event->pos(),p)) { QString s = document()->getString(p.line - 1); - if (mParser->isIncludeLine(s)) { + if (mParser->isIncludeNextLine(s)) { + QString filename = mParser->getHeaderFileName(mFilename,s, true); + Editor * e = pMainWindow->editorList()->getEditorByFilename(filename); + if (e) { + e->setCaretPositionAndActivate(1,1); + return; + } + } if (mParser->isIncludeLine(s)) { QString filename = mParser->getHeaderFileName(mFilename,s); Editor * e = pMainWindow->editorList()->getEditorByFilename(filename); if (e) { @@ -1288,8 +1298,7 @@ void Editor::showEvent(QShowEvent */*event*/) &CppParser::onEndParsing, this, &QSynedit::SynEdit::invalidate); - resetCppParser(mParser); - reparse(); + reparse(false); } pMainWindow->debugger()->setIsForProject(inProject()); pMainWindow->bookmarkModel()->setIsForProject(inProject()); @@ -1303,17 +1312,18 @@ void Editor::showEvent(QShowEvent */*event*/) void Editor::hideEvent(QHideEvent */*event*/) { + if (pSettings->codeCompletion().clearWhenEditorHidden() + && !inProject() && mParser + && !pMainWindow->isMinimized()) { + //recreate a parser, to totally clean memories the parse uses; + initParser(); + } if (mParser) { disconnect(mParser.get(), &CppParser::onEndParsing, this, &QSynedit::SynEdit::invalidate); } - if (pSettings->codeCompletion().clearWhenEditorHidden() - && !inProject() && mParser - && !pMainWindow->isMinimized()) { - mParser->reset(); - } setHideTime(QDateTime::currentDateTime()); } @@ -1548,7 +1558,7 @@ void Editor::onStatusChanged(QSynedit::StatusChanges changes) && changes.testFlag(QSynedit::StatusChange::scCaretY))) { mCurrentLineModified = false; if (!changes.testFlag(QSynedit::StatusChange::scOpenFile)) - reparse(); + reparse(false); // if (pSettings->codeCompletion().clearWhenEditorHidden() // && changes.testFlag(SynStatusChange::scOpenFile)) { // } else{ @@ -2681,7 +2691,7 @@ Editor::QuoteStatus Editor::getQuoteStatus() return Result; } -void Editor::reparse() +void Editor::reparse(bool resetParser) { if (!pSettings->codeCompletion().enabled()) return; @@ -2699,6 +2709,8 @@ void Editor::reparse() if (language!=mParser->language() && !inProject()) { mParser->setLanguage(language); resetCppParser(mParser); + } else if (resetParser && !inProject()) { + resetCppParser(mParser); } parseFile(mParser,mFilename, inProject()); } @@ -3438,9 +3450,9 @@ void Editor::cancelHint() updateMouseCursor(); } -QString Editor::getFileHint(const QString &s) +QString Editor::getFileHint(const QString &s, bool fromNext) { - QString fileName = mParser->getHeaderFileName(mFilename, s); + QString fileName = mParser->getHeaderFileName(mFilename, s, fromNext); if (fileExists(fileName)) { return fileName + " - " + tr("Ctrl+click for more info"); } @@ -4333,7 +4345,7 @@ void Editor::reformat() setTopLine(oldTopLine); setOptions(oldOptions); endUndoBlock(); - reparse(); + reparse(true); checkSyntaxInBack(); reparseTodo(); pMainWindow->updateEditorActions(); diff --git a/RedPandaIDE/editor.h b/RedPandaIDE/editor.h index 5699750e..824de1ec 100644 --- a/RedPandaIDE/editor.h +++ b/RedPandaIDE/editor.h @@ -199,7 +199,7 @@ public: void checkSyntaxInBack(); void gotoDeclaration(const QSynedit::BufferCoord& pos); void gotoDefinition(const QSynedit::BufferCoord& pos); - void reparse(); + void reparse(bool resetParser); void reparseTodo(); void insertString(const QString& value, bool moveCursor); void insertCodeSnippet(const QString& code); @@ -277,7 +277,7 @@ private: TipType getTipType(QPoint point, QSynedit::BufferCoord& pos); void cancelHint(); - QString getFileHint(const QString& s); + QString getFileHint(const QString& s, bool fromNext); QString getParserHint(const QStringList& expression,const QString& s, int line); void showDebugHint(const QString& s,int line); QString getErrorHint(const PSyntaxIssue& issue); diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index 48fb9123..457687fb 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -1394,7 +1394,7 @@ void MainWindow::changeOptions(const QString &widgetName, const QString &groupNa } else if (mProject && e && e->inProject()) { scanActiveProject(true); } else if (e) { - e->reparse(); + reparseNonProjectEditors(); } } @@ -2254,7 +2254,7 @@ void MainWindow::scanActiveProject(bool parse) //UpdateClassBrowsing; if (parse) { - resetCppParser(mProject->cppParser(),mProject->options().compilerSet); + resetCppParser(mProject->cppParser(), mProject->options().compilerSet); mProject->resetParserProjectFiles(); parseFileList(mProject->cppParser()); } else { @@ -4815,26 +4815,28 @@ void MainWindow::onCompilerSetChanged(int index) { if (index<0) return; - if (mProject) { - Editor *e = mEditorList->getEditor(); - if (!e || e->inProject()) { - if(QMessageBox::warning( - e, - tr("Change Project Compiler Set"), - tr("Change the project's compiler set will lose all custom compiler set options.") - +"
" - + tr("Do you really want to do that?"), - QMessageBox::Yes | QMessageBox::No, - QMessageBox::No) != QMessageBox::Yes) { - return; - } - mProject->setCompilerSet(index); - mProject->saveOptions(); + Editor *e = mEditorList->getEditor(); + if (mProject && (!e || e->inProject())) { + if(QMessageBox::warning( + e, + tr("Change Project Compiler Set"), + tr("Change the project's compiler set will lose all custom compiler set options.") + +"
" + + tr("Do you really want to do that?"), + QMessageBox::Yes | QMessageBox::No, + QMessageBox::No) != QMessageBox::Yes) { return; } + mProject->setCompilerSet(index); + mProject->saveOptions(); + scanActiveProject(true); + return; } + pSettings->compilerSets().setDefaultIndex(index); pSettings->compilerSets().saveDefaultIndex(); + + reparseNonProjectEditors(); } void MainWindow::logToolsOutput(const QString& msg) @@ -6501,6 +6503,19 @@ void MainWindow::setProjectViewCurrentUnit(std::shared_ptr unit) { } } +void MainWindow::reparseNonProjectEditors() +{ + for (int i=0;ipageCount();i++) { + Editor* e=(*mEditorList)[i]; + if (!e->inProject()) { + if (!pSettings->codeCompletion().clearWhenEditorHidden() || e->isVisible()) { + e->reparse(true); + e->checkSyntaxInBack(); + } + } + } +} + void MainWindow::onProjectViewNodeRenamed() { updateProjectView(); @@ -6807,8 +6822,8 @@ void MainWindow::on_actionRename_Symbol_triggered() CppRefacter refactor; refactor.renameSymbol(editor,oldCaretXY,newWord); - editor->reparse(); - + editor->reparse(true); + editor->checkSyntaxInBack(); } diff --git a/RedPandaIDE/mainwindow.h b/RedPandaIDE/mainwindow.h index 2fa18780..44878335 100644 --- a/RedPandaIDE/mainwindow.h +++ b/RedPandaIDE/mainwindow.h @@ -279,6 +279,8 @@ private: void setProjectViewCurrentNode(std::shared_ptr node); void setProjectViewCurrentUnit(std::shared_ptr unit); + void reparseNonProjectEditors(); + private slots: void onProjectViewNodeRenamed(); void setDockExplorerToArea(const Qt::DockWidgetArea &area); diff --git a/RedPandaIDE/parser/cppparser.cpp b/RedPandaIDE/parser/cppparser.cpp index 0bd76663..76c0211a 100644 --- a/RedPandaIDE/parser/cppparser.cpp +++ b/RedPandaIDE/parser/cppparser.cpp @@ -54,6 +54,8 @@ CppParser::CppParser(QObject *parent) : QObject(parent), mCppKeywords = CppKeywords; mCppTypeKeywords = CppTypeKeywords; mEnabled = true; + + mPreprocessor = std::make_shared(); //mNamespaces; //mBlockBeginSkips; //mBlockEndSkips; @@ -82,34 +84,34 @@ void CppParser::addHardDefineByLine(const QString &line) { QMutexLocker locker(&mMutex); if (line.startsWith('#')) { - mPreprocessor.addHardDefineByLine(line.mid(1).trimmed()); + mPreprocessor->addHardDefineByLine(line.mid(1).trimmed()); } else { - mPreprocessor.addHardDefineByLine(line); + mPreprocessor->addHardDefineByLine(line); } } void CppParser::addIncludePath(const QString &value) { QMutexLocker locker(&mMutex); - mPreprocessor.addIncludePath(includeTrailingPathDelimiter(value)); + mPreprocessor->addIncludePath(includeTrailingPathDelimiter(value)); } void CppParser::addProjectIncludePath(const QString &value) { QMutexLocker locker(&mMutex); - mPreprocessor.addProjectIncludePath(includeTrailingPathDelimiter(value)); + mPreprocessor->addProjectIncludePath(includeTrailingPathDelimiter(value)); } void CppParser::clearIncludePaths() { QMutexLocker locker(&mMutex); - mPreprocessor.clearIncludePaths(); + mPreprocessor->clearIncludePaths(); } void CppParser::clearProjectIncludePaths() { QMutexLocker locker(&mMutex); - mPreprocessor.clearProjectIncludePaths(); + mPreprocessor->clearProjectIncludePaths(); } void CppParser::clearProjectFiles() @@ -154,7 +156,7 @@ PStatement CppParser::findAndScanBlockAt(const QString &filename, int line) if (mParsing) { return PStatement(); } - PFileIncludes fileIncludes = mPreprocessor.includesList().value(filename); + PFileIncludes fileIncludes = mPreprocessor->includesList().value(filename); if (!fileIncludes) return PStatement(); @@ -165,9 +167,9 @@ PStatement CppParser::findAndScanBlockAt(const QString &filename, int line) PFileIncludes CppParser::findFileIncludes(const QString &filename, bool deleteIt) { QMutexLocker locker(&mMutex); - PFileIncludes fileIncludes = mPreprocessor.includesList().value(filename,PFileIncludes()); + PFileIncludes fileIncludes = mPreprocessor->includesList().value(filename,PFileIncludes()); if (deleteIt && fileIncludes) - mPreprocessor.includesList().remove(filename); + mPreprocessor->includesList().remove(filename); return fileIncludes; } QString CppParser::findFirstTemplateParamOf(const QString &fileName, const QString &phrase, const PStatement& currentScope) @@ -199,7 +201,7 @@ QString CppParser::findFirstTemplateParamOf(const QString &fileName, const QStri PStatement CppParser::findFunctionAt(const QString &fileName, int line) { QMutexLocker locker(&mMutex); - PFileIncludes fileIncludes = mPreprocessor.includesList().value(fileName); + PFileIncludes fileIncludes = mPreprocessor->includesList().value(fileName); if (!fileIncludes) return PStatement(); for (PStatement& statement : fileIncludes->statements) { @@ -648,7 +650,7 @@ QStringList CppParser::getFileDirectIncludes(const QString &filename) return QStringList(); if (filename.isEmpty()) return QStringList(); - PFileIncludes fileIncludes = mPreprocessor.includesList().value(filename,PFileIncludes()); + PFileIncludes fileIncludes = mPreprocessor->includesList().value(filename,PFileIncludes()); if (fileIncludes) { return fileIncludes->directIncludes; @@ -666,7 +668,7 @@ QSet CppParser::getFileIncludes(const QString &filename) if (filename.isEmpty()) return list; list.insert(filename); - PFileIncludes fileIncludes = mPreprocessor.includesList().value(filename,PFileIncludes()); + PFileIncludes fileIncludes = mPreprocessor->includesList().value(filename,PFileIncludes()); if (fileIncludes) { foreach (const QString& file, fileIncludes->includeFiles.keys()) { @@ -684,13 +686,13 @@ QSet CppParser::getFileUsings(const QString &filename) return result; if (mParsing) return result; - PFileIncludes fileIncludes= mPreprocessor.includesList().value(filename,PFileIncludes()); + PFileIncludes fileIncludes= mPreprocessor->includesList().value(filename,PFileIncludes()); if (fileIncludes) { foreach (const QString& usingName, fileIncludes->usings) { result.insert(usingName); } foreach (const QString& subFile,fileIncludes->includeFiles.keys()){ - PFileIncludes subIncludes = mPreprocessor.includesList().value(subFile,PFileIncludes()); + PFileIncludes subIncludes = mPreprocessor->includesList().value(subFile,PFileIncludes()); if (subIncludes) { foreach (const QString& usingName, subIncludes->usings) { result.insert(usingName); @@ -701,11 +703,37 @@ QSet CppParser::getFileUsings(const QString &filename) return result; } -QString CppParser::getHeaderFileName(const QString &relativeTo, const QString &line) +QString CppParser::getHeaderFileName(const QString &relativeTo, const QString &headerName, bool fromNext) { QMutexLocker locker(&mMutex); - return ::getHeaderFilename(relativeTo, line, mPreprocessor.includePathList(), - mPreprocessor.projectIncludePathList()); + QString currentDir = includeTrailingPathDelimiter(extractFileDir(relativeTo)); + QStringList includes; + QStringList projectIncludes; + bool found; + if (fromNext && mPreprocessor->includePaths().contains(currentDir)) { + foreach(const QString& s, mPreprocessor->includePathList()) { + if (found) { + includes.append(s); + continue; + } else if (s == currentDir) + found = true; + } + projectIncludes = mPreprocessor->projectIncludePathList(); + } else if (fromNext && mPreprocessor->projectIncludePaths().contains(currentDir)) { + includes = mPreprocessor->includePathList(); + foreach(const QString& s, mPreprocessor->projectIncludePathList()) { + if (found) { + includes.append(s); + continue; + } else if (s == currentDir) + found = true; + } + } else { + includes = mPreprocessor->includePathList(); + projectIncludes = mPreprocessor->projectIncludePathList(); + } + return ::getHeaderFilename(relativeTo, headerName, includes, + projectIncludes); } void CppParser::invalidateFile(const QString &fileName) @@ -735,16 +763,27 @@ bool CppParser::isIncludeLine(const QString &line) return false; } +bool CppParser::isIncludeNextLine(const QString &line) +{ + QString trimmedLine = line.trimmed(); + if ((trimmedLine.length() > 0) + && trimmedLine.startsWith('#')) { // it's a preprocessor line + if (trimmedLine.mid(1).trimmed().startsWith("include_next")) + return true; + } + return false; +} + bool CppParser::isProjectHeaderFile(const QString &fileName) { QMutexLocker locker(&mMutex); - return ::isSystemHeaderFile(fileName,mPreprocessor.projectIncludePaths()); + return ::isSystemHeaderFile(fileName,mPreprocessor->projectIncludePaths()); } bool CppParser::isSystemHeaderFile(const QString &fileName) { QMutexLocker locker(&mMutex); - return ::isSystemHeaderFile(fileName,mPreprocessor.includePaths()); + return ::isSystemHeaderFile(fileName,mPreprocessor->includePaths()); } void CppParser::parseFile(const QString &fileName, bool inProject, bool onlyIfNotParsed, bool updateView) @@ -771,7 +810,7 @@ void CppParser::parseFile(const QString &fileName, bool inProject, bool onlyIfNo emit onEndParsing(mFilesScannedCount,0); }); QString fName = fileName; - if (onlyIfNotParsed && mPreprocessor.scannedFiles().contains(fName)) + if (onlyIfNotParsed && mPreprocessor->scannedFiles().contains(fName)) return; QSet files = calculateFilesToBeReparsed(fileName); @@ -792,7 +831,7 @@ void CppParser::parseFile(const QString &fileName, bool inProject, bool onlyIfNo if (isHFile(file)) { mFilesScannedCount++; emit onProgress(file,mFilesToScanCount,mFilesScannedCount); - if (!mPreprocessor.scannedFiles().contains(file)) { + if (!mPreprocessor->scannedFiles().contains(file)) { internalParse(file); } } @@ -802,7 +841,7 @@ void CppParser::parseFile(const QString &fileName, bool inProject, bool onlyIfNo if (!isHFile(file)) { mFilesScannedCount++; emit onProgress(file,mFilesToScanCount,mFilesScannedCount); - if (!mPreprocessor.scannedFiles().contains(file)) { + if (!mPreprocessor->scannedFiles().contains(file)) { internalParse(file); } } @@ -840,7 +879,7 @@ void CppParser::parseFileList(bool updateView) if (isHFile(file)) { mFilesScannedCount++; emit onProgress(mCurrentFile,mFilesToScanCount,mFilesScannedCount); - if (!mPreprocessor.scannedFiles().contains(file)) { + if (!mPreprocessor->scannedFiles().contains(file)) { internalParse(file); } } @@ -850,7 +889,7 @@ void CppParser::parseFileList(bool updateView) if (isCFile(file)) { mFilesScannedCount++; emit onProgress(mCurrentFile,mFilesToScanCount,mFilesScannedCount); - if (!mPreprocessor.scannedFiles().contains(file)) { + if (!mPreprocessor->scannedFiles().contains(file)) { internalParse(file); } } @@ -872,7 +911,7 @@ void CppParser::parseHardDefines() mParsing = false; mIsSystemHeader=oldIsSystemHeader; }); - for (const PDefine& define:mPreprocessor.hardDefines()) { + for (const PDefine& define:mPreprocessor->hardDefines()) { addStatement( PStatement(), // defines don't belong to any scope "", @@ -895,7 +934,7 @@ bool CppParser::parsing() const return mParsing; } -void CppParser::reset() +void CppParser::resetParser() { while (true) { { @@ -914,38 +953,34 @@ void CppParser::reset() mParsing = false; }); emit onBusy(); - mPreprocessor.clear(); + mPreprocessor->clear(); mUniqId = 0; - mSkipList.clear(); - mBlockBeginSkips.clear(); - mBlockEndSkips.clear(); - mInlineNamespaceEndSkips.clear(); + mParseLocalHeaders = true; mParseGlobalHeaders = true; mIsSystemHeader = false; mIsHeader = false; mIsProjectFile = false; + mFilesScannedCount=0; + mFilesToScanCount = 0; mCurrentScope.clear(); mCurrentClassScope.clear(); - mProjectFiles.clear(); - mFilesToScan.clear(); - mTokenizer.reset(); - // Remove all statements + mSkipList.clear(); mStatementList.clear(); - // We haven't scanned anything anymore - mPreprocessor.scannedFiles().clear(); - - // We don't include anything anymore - mPreprocessor.includesList().clear(); - - mNamespaces.clear(); + mProjectFiles.clear(); + mBlockBeginSkips.clear(); //list of for/catch block begin token index; + mBlockEndSkips.clear(); //list of for/catch block end token index; + mInlineNamespaceEndSkips.clear(); // list for inline namespace end token index; + mFilesToScan.clear(); // list of base files to scan + mNamespaces.clear(); //TStringList> namespace and the statements in its scope mInlineNamespaces.clear(); - mPreprocessor.clearProjectIncludePaths(); - mPreprocessor.clearIncludePaths(); - mProjectFiles.clear(); + // We haven't scanned anything anymore + mPreprocessor = std::make_shared(); + mTokenizer.reset(); + } } @@ -957,12 +992,12 @@ void CppParser::unFreeze() QSet CppParser::scannedFiles() { - return mPreprocessor.scannedFiles(); + return mPreprocessor->scannedFiles(); } bool CppParser::isFileParsed(const QString &filename) { - return mPreprocessor.scannedFiles().contains(filename); + return mPreprocessor->scannedFiles().contains(filename); } QString CppParser::getScopePrefix(const PStatement& statement){ @@ -1099,7 +1134,7 @@ void CppParser::addFileToScan(const QString& value, bool inProject) mProjectFiles.insert(value); // Only parse given file - if (!mPreprocessor.scannedFiles().contains(value)) { + if (!mPreprocessor->scannedFiles().contains(value)) { mFilesToScan.insert(value); } @@ -1179,12 +1214,12 @@ PStatement CppParser::addStatement(const PStatement& parent, if (oldStatement && !oldStatement->hasDefinition) { oldStatement->hasDefinition = true; if (oldStatement->fileName!=fileName) { - PFileIncludes fileIncludes1=mPreprocessor.includesList().value(fileName); + PFileIncludes fileIncludes1=mPreprocessor->includesList().value(fileName); if (fileIncludes1) { fileIncludes1->statements.insert(oldStatement->fullName, oldStatement); fileIncludes1->dependingFiles.insert(oldStatement->fileName); - PFileIncludes fileIncludes2=mPreprocessor.includesList().value(oldStatement->fileName); + PFileIncludes fileIncludes2=mPreprocessor->includesList().value(oldStatement->fileName); if (fileIncludes2) { fileIncludes2->dependedFiles.insert(fileName); } @@ -1242,7 +1277,7 @@ PStatement CppParser::addStatement(const PStatement& parent, } if (result->kind!= StatementKind::skBlock) { - PFileIncludes fileIncludes = mPreprocessor.includesList().value(fileName); + PFileIncludes fileIncludes = mPreprocessor->includesList().value(fileName); if (fileIncludes) { fileIncludes->statements.insert(result->fullName,result); fileIncludes->declaredStatements.insert(result->fullName,result); @@ -1323,7 +1358,7 @@ void CppParser::addSoloScopeLevel(PStatement& statement, int line, bool shouldRe mCurrentScope.append(statement); - PFileIncludes fileIncludes = mPreprocessor.includesList().value(mCurrentFile); + PFileIncludes fileIncludes = mPreprocessor->includesList().value(mCurrentFile); if (fileIncludes) { fileIncludes->scopes.addScope(line,statement); @@ -1347,7 +1382,7 @@ void CppParser::removeScopeLevel(int line) if (mCurrentScope.isEmpty()) return; // TODO: should be an exception PStatement currentScope = mCurrentScope.back();; - PFileIncludes fileIncludes = mPreprocessor.includesList().value(mCurrentFile); + PFileIncludes fileIncludes = mPreprocessor->includesList().value(mCurrentFile); if (currentScope && (currentScope->kind == StatementKind::skBlock)) { if (currentScope->children.isEmpty()) { // remove no children block @@ -2562,7 +2597,7 @@ void CppParser::handlePreprocessor() s = s.trimmed(); // Ask the preprocessor to cut parts up QString name,args,value; - mPreprocessor.getDefineParts(s,name,args,value); + mPreprocessor->getDefineParts(s,name,args,value); addStatement( nullptr, // defines don't belong to any scope @@ -3044,7 +3079,7 @@ void CppParser::handleUsing() scopeStatement->usingList.insert(fullName); } } else { - PFileIncludes fileInfo = mPreprocessor.includesList().value(mCurrentFile); + PFileIncludes fileInfo = mPreprocessor->includesList().value(mCurrentFile); if (!fileInfo) return; if (mNamespaces.contains(usingName)) { @@ -3232,24 +3267,24 @@ void CppParser::internalParse(const QString &fileName) // Preprocess the file... { auto action = finally([this]{ - mPreprocessor.reset(); + mPreprocessor->reset(); mTokenizer.reset(); }); // Let the preprocessor augment the include records -// mPreprocessor.setIncludesList(mIncludesList); -// mPreprocessor.setScannedFileList(mScannedFiles); -// mPreprocessor.setIncludePaths(mIncludePaths); -// mPreprocessor.setProjectIncludePaths(mProjectIncludePaths); - mPreprocessor.setScanOptions(mParseGlobalHeaders, mParseLocalHeaders); - mPreprocessor.preprocess(fileName, buffer); +// mPreprocessor->setIncludesList(mIncludesList); +// mPreprocessor->setScannedFileList(mScannedFiles); +// mPreprocessor->setIncludePaths(mIncludePaths); +// mPreprocessor->setProjectIncludePaths(mProjectIncludePaths); + mPreprocessor->setScanOptions(mParseGlobalHeaders, mParseLocalHeaders); + mPreprocessor->preprocess(fileName, buffer); - QStringList preprocessResult = mPreprocessor.result(); + QStringList preprocessResult = mPreprocessor->result(); //reduce memory usage - mPreprocessor.clearResult(); + mPreprocessor->clearResult(); #ifdef QT_DEBUG -// stringsToFile(mPreprocessor.result(),"r:\\preprocess.txt"); -// mPreprocessor.dumpDefinesTo("r:\\defines.txt"); -// mPreprocessor.dumpIncludesListTo("r:\\includes.txt"); +// stringsToFile(mPreprocessor->result(),"r:\\preprocess.txt"); +// mPreprocessor->dumpDefinesTo("r:\\defines.txt"); +// mPreprocessor->dumpIncludesListTo("r:\\includes.txt"); #endif // Tokenize the preprocessed buffer file @@ -3280,8 +3315,8 @@ void CppParser::internalParse(const QString &fileName) void CppParser::inheritClassStatement(const PStatement& derived, bool isStruct, const PStatement& base, StatementClassScope access) { - PFileIncludes fileIncludes1=mPreprocessor.includesList().value(derived->fileName); - PFileIncludes fileIncludes2=mPreprocessor.includesList().value(base->fileName); + PFileIncludes fileIncludes1=mPreprocessor->includesList().value(derived->fileName); + PFileIncludes fileIncludes2=mPreprocessor->includesList().value(base->fileName); if (fileIncludes1 && fileIncludes2) { //derived class depeneds on base class fileIncludes1->dependingFiles.insert(base->fileName); @@ -4245,7 +4280,7 @@ void CppParser::internalInvalidateFile(const QString &fileName) } } // delete it from scannedfiles - mPreprocessor.scannedFiles().remove(fileName); + mPreprocessor->scannedFiles().remove(fileName); // remove its include files list PFileIncludes p = findFileIncludes(fileName, true); @@ -4291,7 +4326,7 @@ QSet CppParser::calculateFilesToBeReparsed(const QString &fileName) while (!queue.isEmpty()) { QString name = queue.dequeue(); processed.insert(name); - PFileIncludes p=mPreprocessor.includesList().value(name); + PFileIncludes p=mPreprocessor->includesList().value(name); if (!p) continue; foreach (const QString& s,p->dependedFiles) { @@ -4680,12 +4715,12 @@ void CppParser::setParseGlobalHeaders(bool newParseGlobalHeaders) const QSet &CppParser::includePaths() { - return mPreprocessor.includePaths(); + return mPreprocessor->includePaths(); } const QSet &CppParser::projectIncludePaths() { - return mPreprocessor.projectIncludePaths(); + return mPreprocessor->projectIncludePaths(); } bool CppParser::parseLocalHeaders() const @@ -4733,7 +4768,7 @@ void CppParser::setEnabled(bool newEnabled) if (mEnabled!=newEnabled) { mEnabled = newEnabled; if (!mEnabled) { - this->reset(); + resetParser(); } } } diff --git a/RedPandaIDE/parser/cppparser.h b/RedPandaIDE/parser/cppparser.h index 36e9f1ba..16e776d1 100644 --- a/RedPandaIDE/parser/cppparser.h +++ b/RedPandaIDE/parser/cppparser.h @@ -97,10 +97,11 @@ public: QSet getFileIncludes(const QString& filename); QSet getFileUsings(const QString& filename); - QString getHeaderFileName(const QString& relativeTo, const QString& line);// both + QString getHeaderFileName(const QString& relativeTo, const QString& headerName, bool fromNext=false);// both void invalidateFile(const QString& fileName); bool isIncludeLine(const QString &line); + bool isIncludeNextLine(const QString &line); bool isProjectHeaderFile(const QString& fileName); bool isSystemHeaderFile(const QString& fileName); void parseFile(const QString& fileName, bool inProject, @@ -108,7 +109,7 @@ public: void parseFileList(bool updateView = true); void parseHardDefines(); bool parsing() const; - void reset(); + void resetParser(); void unFreeze(); // UnFree/UnLock (reparse while searching) QSet scannedFiles(); @@ -534,7 +535,7 @@ private: //It's used in preprocessor, so we can't use fIncludeList instead CppTokenizer mTokenizer; - CppPreprocessor mPreprocessor; + PCppPreprocessor mPreprocessor; //{ List of current project's file } QSet mProjectFiles; QVector mBlockBeginSkips; //list of for/catch block begin token index; diff --git a/RedPandaIDE/parser/cpppreprocessor.cpp b/RedPandaIDE/parser/cpppreprocessor.cpp index 0d6f5a74..3dcb677d 100644 --- a/RedPandaIDE/parser/cpppreprocessor.cpp +++ b/RedPandaIDE/parser/cpppreprocessor.cpp @@ -334,6 +334,16 @@ void CppPreprocessor::clearProjectIncludePaths() mProjectIncludePathList.clear(); } +void CppPreprocessor::clearScannedFiles() +{ + mScannedFiles.clear(); +} + +void CppPreprocessor::clearIncludeList() +{ + mIncludesList.clear(); +} + QString CppPreprocessor::getNextPreprocessor() { skipToPreprocessor(); // skip until # at start of line @@ -457,26 +467,27 @@ void CppPreprocessor::handleInclude(const QString &line, bool fromNext) QStringList includes; QStringList projectIncludes; bool found; - if (fromNext && mIncludePaths.contains(currentDir)) - found = false; - else - found = true; - foreach(const QString& s, mIncludePathList) { - if (found) { - includes.append(s); + if (fromNext && mIncludePaths.contains(currentDir)) { + foreach(const QString& s, mIncludePathList) { + if (found) { + includes.append(s); + continue; + } else if (s == currentDir) + found = true; } - if (s == currentDir) - found = true; - } - if (fromNext && mProjectIncludePaths.contains(currentDir)) - found = false; - else - found = true; - foreach(const QString& s, mProjectIncludePathList) { - if (found) - projectIncludes.append(s); - if (s == currentDir) - found = true; + projectIncludes = mProjectIncludePathList; + } else if (fromNext && mProjectIncludePaths.contains(currentDir)) { + includes = mIncludePathList; + foreach(const QString& s, mProjectIncludePathList) { + if (found) { + includes.append(s); + continue; + } else if (s == currentDir) + found = true; + } + } else { + includes = mIncludePathList; + projectIncludes = mProjectIncludePathList; } fileName = getHeaderFilename( file->fileName, diff --git a/RedPandaIDE/parser/cpppreprocessor.h b/RedPandaIDE/parser/cpppreprocessor.h index 5ae5f9ce..fc879f3a 100644 --- a/RedPandaIDE/parser/cpppreprocessor.h +++ b/RedPandaIDE/parser/cpppreprocessor.h @@ -75,6 +75,8 @@ public: void addProjectIncludePath(const QString& fileName); void clearIncludePaths(); void clearProjectIncludePaths(); + void clearScannedFiles(); + void clearIncludeList(); QStringList result() const; QHash &includesList(); @@ -217,4 +219,6 @@ private: QSet mScannedFiles; }; +using PCppPreprocessor = std::shared_ptr; + #endif // CPPPREPROCESSOR_H diff --git a/RedPandaIDE/parser/cpptokenizer.cpp b/RedPandaIDE/parser/cpptokenizer.cpp index 46a3f93b..5830c663 100644 --- a/RedPandaIDE/parser/cpptokenizer.cpp +++ b/RedPandaIDE/parser/cpptokenizer.cpp @@ -29,6 +29,7 @@ void CppTokenizer::reset() mTokenList.clear(); mBuffer.clear(); mBufferStr.clear(); + mLastToken.clear(); } void CppTokenizer::tokenize(const QStringList &buffer) diff --git a/RedPandaIDE/parser/cpptokenizer.h b/RedPandaIDE/parser/cpptokenizer.h index 7ac73b64..ec8a0426 100644 --- a/RedPandaIDE/parser/cpptokenizer.h +++ b/RedPandaIDE/parser/cpptokenizer.h @@ -94,4 +94,6 @@ private: TokenList mTokenList; }; +using PCppTokenizer = std::shared_ptr; + #endif // CPPTOKENIZER_H diff --git a/RedPandaIDE/parser/statementmodel.cpp b/RedPandaIDE/parser/statementmodel.cpp index 030682e6..764ea0d2 100644 --- a/RedPandaIDE/parser/statementmodel.cpp +++ b/RedPandaIDE/parser/statementmodel.cpp @@ -79,6 +79,9 @@ const StatementMap &StatementModel::childrenStatements(std::weak_ptr void StatementModel::clear() { mCount=0; mGlobalStatements.clear(); +#ifdef QT_DEBUG + mAllStatements.clear(); +#endif } void StatementModel::dump(const QString &logFile) diff --git a/RedPandaIDE/project.cpp b/RedPandaIDE/project.cpp index b94dbe57..e8187162 100644 --- a/RedPandaIDE/project.cpp +++ b/RedPandaIDE/project.cpp @@ -71,7 +71,7 @@ std::shared_ptr Project::load(const QString &filename, EditorList *edit parent); project->open(); project->mModified = false; - resetCppParser(project->mParser,project->mOptions.compilerSet); + resetCppParser(project->mParser, project->mOptions.compilerSet); return project; } @@ -94,7 +94,7 @@ std::shared_ptr Project::create( project->mParser->setEnabled(false); if (!project->assignTemplate(pTemplate,useCpp)) return std::shared_ptr(); - resetCppParser(project->mParser,project->mOptions.compilerSet); + resetCppParser(project->mParser, project->mOptions.compilerSet); project->mModified = true; return project; diff --git a/RedPandaIDE/settingsdialog/compilersetoptionwidget.ui b/RedPandaIDE/settingsdialog/compilersetoptionwidget.ui index 690954eb..b7e8e99d 100644 --- a/RedPandaIDE/settingsdialog/compilersetoptionwidget.ui +++ b/RedPandaIDE/settingsdialog/compilersetoptionwidget.ui @@ -110,7 +110,7 @@ - 4 + 0 false diff --git a/RedPandaIDE/utils.cpp b/RedPandaIDE/utils.cpp index cb016401..cc9f446c 100644 --- a/RedPandaIDE/utils.cpp +++ b/RedPandaIDE/utils.cpp @@ -280,7 +280,7 @@ void resetCppParser(std::shared_ptr parser, int compilerSetIndex) if (!parser) return; // Configure parser - parser->reset(); + parser->resetParser(); //paser->enabled = pSettings-> devCodeCompletion.Enabled; // CppParser.ParseLocalHeaders := devCodeCompletion.ParseLocalHeaders; // CppParser.ParseGlobalHeaders := devCodeCompletion.ParseGlobalHeaders; @@ -288,21 +288,25 @@ void resetCppParser(std::shared_ptr parser, int compilerSetIndex) parser->setParseGlobalHeaders(true); parser->setParseLocalHeaders(true); // Set options depending on the current compiler set - // TODO: do this every time OnCompilerSetChanged if (compilerSetIndex<0) { compilerSetIndex=pSettings->compilerSets().defaultIndex(); } Settings::PCompilerSet compilerSet = pSettings->compilerSets().getSet(compilerSetIndex); parser->clearIncludePaths(); + bool isCpp = parser->language()==ParserLanguage::CPlusPlus; if (compilerSet) { - foreach (const QString& file,compilerSet->CppIncludeDirs()) { - parser->addIncludePath(file); + if (isCpp) { + foreach (const QString& file,compilerSet->CppIncludeDirs()) { + parser->addIncludePath(file); + } } foreach (const QString& file,compilerSet->CIncludeDirs()) { parser->addIncludePath(file); } - foreach (const QString& file,compilerSet->defaultCppIncludeDirs()) { - parser->addIncludePath(file); + if (isCpp) { + foreach (const QString& file,compilerSet->defaultCppIncludeDirs()) { + parser->addIncludePath(file); + } } foreach (const QString& file,compilerSet->defaultCIncludeDirs()) { parser->addIncludePath(file); diff --git a/tools/consolepauser/main.windows.cpp b/tools/consolepauser/main.windows.cpp index 4ec6d53d..d4ed90b3 100644 --- a/tools/consolepauser/main.windows.cpp +++ b/tools/consolepauser/main.windows.cpp @@ -133,7 +133,7 @@ DWORD ExecuteCommand(string& command,bool reInp) { } WINBOOL bSuccess = AssignProcessToJobObject( hJob, pi.hProcess ); if ( bSuccess == FALSE ) { - printf( "AssignProcessToJobObject failed: error %d\n", GetLastError() ); + printf( "AssignProcessToJobObject failed: error %u\n", GetLastError() ); return 0; }