From b6df4fcf415fba775bb066c1231fbb04ca384425 Mon Sep 17 00:00:00 2001 From: "royqh1979@gmail.com" Date: Sun, 19 Sep 2021 14:28:30 +0800 Subject: [PATCH] - fix: debug very slow when local infos are long - fix: wrong code fold calculation --- RedPandaIDE/compiler/compilermanager.cpp | 1 + RedPandaIDE/debugger.cpp | 115 ++++++++++++-------- RedPandaIDE/debugger.h | 12 +- RedPandaIDE/mainwindow.cpp | 38 +++++++ RedPandaIDE/mainwindow.h | 3 + RedPandaIDE/mainwindow.ui | 27 ++++- RedPandaIDE/qsynedit/SynEdit.cpp | 133 ++++++++++++++--------- 7 files changed, 226 insertions(+), 103 deletions(-) diff --git a/RedPandaIDE/compiler/compilermanager.cpp b/RedPandaIDE/compiler/compilermanager.cpp index 0259c3c6..055bfa31 100644 --- a/RedPandaIDE/compiler/compilermanager.cpp +++ b/RedPandaIDE/compiler/compilermanager.cpp @@ -54,6 +54,7 @@ void CompilerManager::compile(const QString& filename, const QByteArray& encodin mCompiler->setRebuild(rebuild); connect(mCompiler, &Compiler::compileFinished, this ,&CompilerManager::onCompileFinished); connect(mCompiler, &Compiler::compileIssue, this, &CompilerManager::onCompileIssue); + connect(mCompiler, &Compiler::compileStarted, pMainWindow, &MainWindow::onCompileStarted); connect(mCompiler, &Compiler::compileFinished, pMainWindow, &MainWindow::onCompileFinished); connect(mCompiler, &Compiler::compileOutput, pMainWindow, &MainWindow::onCompileLog); connect(mCompiler, &Compiler::compileIssue, pMainWindow, &MainWindow::onCompileIssue); diff --git a/RedPandaIDE/debugger.cpp b/RedPandaIDE/debugger.cpp index b26bc456..bb2ab171 100644 --- a/RedPandaIDE/debugger.cpp +++ b/RedPandaIDE/debugger.cpp @@ -48,9 +48,11 @@ bool Debugger::start() connect(mReader, &QThread::finished,this,&Debugger::clearUpReader); connect(mReader, &DebugReader::parseFinished,this,&Debugger::syncFinishedParsing,Qt::BlockingQueuedConnection); connect(mReader, &DebugReader::changeDebugConsoleLastLine,this,&Debugger::onChangeDebugConsoleLastline); - connect(mReader, &DebugReader::addLocalWithLinebreak,this,&Debugger::onAddLocalWithLinebreak); - connect(mReader, &DebugReader::addLocalWithoutLinebreak,this,&Debugger::onAddLocalWithoutLinebreak); + connect(mReader, &DebugReader::addLocalLine,this,&Debugger::onAddLocalLine); connect(mReader, &DebugReader::clearLocals,this,&Debugger::onClearLocals); + connect(mReader, &DebugReader::cmdStarted,pMainWindow, &MainWindow::disableDebugActions); + connect(mReader, &DebugReader::cmdFinished,pMainWindow, &MainWindow::enableDebugActions); + mReader->start(); mReader->mStartSemaphore.acquire(1); @@ -100,12 +102,7 @@ void Debugger::clearUpReader() } } -void Debugger::onAddLocalWithoutLinebreak(const QString &text) -{ - pMainWindow->txtLocals()->insertPlainText(text); -} - -void Debugger::onAddLocalWithLinebreak(const QString &text) +void Debugger::onAddLocalLine(const QString &text) { pMainWindow->txtLocals()->appendPlainText(text); } @@ -968,6 +965,7 @@ void DebugReader::handleLocalOutput() QString s = getNextFilledLine(); bool nobreakLine = false; + QString line; while (true) { if (!s.startsWith("\032\032")) { s = TrimLeft(s); @@ -979,9 +977,11 @@ void DebugReader::handleLocalOutput() } //todo: update local view if (nobreakLine && pMainWindow->txtLocals()->document()->lineCount()>0) { - emit addLocalWithoutLinebreak(s); + line += s; +// emit addLocalWithoutLinebreak(s); } else { - emit addLocalWithLinebreak(s); + emit addLocalLine(line); + line = s; } nobreakLine=false; } else { @@ -991,6 +991,9 @@ void DebugReader::handleLocalOutput() if (!nobreakLine && s.isEmpty()) break; } + if (!line.isEmpty()) { + emit addLocalLine(line); + } } void DebugReader::handleLocals() @@ -1237,10 +1240,11 @@ void DebugReader::processWatchOutput(PWatchVar watchVar) watchVar->children.clear(); watchVar->value = ""; // Process output parsed by ProcessEvalStruct - QString s = watchVar->name + " = " + processEvalOutput(); + QString s = processEvalOutput(); QStringList tokens = tokenize(s); PWatchVar parentVar = watchVar; + PWatchVar currentVar = watchVar; QVector varStack; int i=0; @@ -1249,20 +1253,15 @@ void DebugReader::processWatchOutput(PWatchVar watchVar) QChar ch = token[0]; if (ch =='_' || (ch>='a' && ch<='z') || (ch>='A' && ch<='Z') || (ch>127)) { - if (parentVar != watchVar) { - //is identifier,create new child node - PWatchVar newVar = std::make_shared(); - newVar->parent = parentVar.get(); - newVar->name = token; - if (parentVar) - newVar->fullName = parentVar->fullName + '.'+token; - else - newVar->fullName = token; - newVar->value = ""; - newVar->gdbIndex = -1; - parentVar->children.append(newVar); - parentVar = newVar; - } + //is identifier,create new child node + PWatchVar newVar = std::make_shared(); + newVar->parent = parentVar.get(); + newVar->name = token; + newVar->fullName = parentVar->fullName + '.'+token; + newVar->value = ""; + newVar->gdbIndex = -1; + parentVar->children.append(newVar); + currentVar = newVar; } else if (ch == '{') { if (parentVar->value.isEmpty()) { parentVar->value = "{"; @@ -1272,7 +1271,7 @@ void DebugReader::processWatchOutput(PWatchVar watchVar) if (parentVar) { int count = parentVar->children.count(); newVar->name = QString("[%1]").arg(count); - newVar->fullName = parentVar->fullName + '.'+newVar->name; + newVar->fullName = parentVar->fullName + newVar->name; } else { newVar->name = QString("[0]"); newVar->fullName = newVar->name; @@ -1293,22 +1292,23 @@ void DebugReader::processWatchOutput(PWatchVar watchVar) parentVar = varStack.back(); varStack.pop_back(); } - } else if (ch == '=' || ch ==',' ) { - // just skip them + } else if (ch == '=') { + // just skip it + } else if (ch == ',') { + } else { - if (parentVar->value.isEmpty()) { - parentVar->value = token; + if (currentVar) { + currentVar->value = token; + currentVar = nullptr; } else { - WatchVar* parent = parentVar->parent; - if (parent) { - PWatchVar newVar = std::make_shared(); - newVar->parent = parent; - newVar->name = QString("[%1]") - .arg(parent->children.count()); - newVar->value = token; - newVar->gdbIndex = -1; - parent->children.append(newVar); - } + PWatchVar newVar = std::make_shared(); + newVar->parent = parentVar.get(); + newVar->name = QString("[%1]") + .arg(parentVar->children.count()); + newVar->fullName = parentVar->fullName + newVar->name; + newVar->value = token; + newVar->gdbIndex = -1; + parentVar->children.append(newVar); } } i++; @@ -1381,6 +1381,7 @@ void DebugReader::runNextCmd() if (mUpdateCount>0) { mUpdateCount=0; } + emit cmdFinished(); } return; } @@ -1389,9 +1390,10 @@ void DebugReader::runNextCmd() mCurrentCmd.reset(); } + emit cmdStarted(); PDebugCommand pCmd = mCmdQueue.dequeue(); mCmdRunning = true; - mCurrentCmd = pCmd; + mCurrentCmd = pCmd; QByteArray s; s=pCmd->command.toLocal8Bit(); @@ -1466,13 +1468,13 @@ QStringList DebugReader::tokenize(const QString &s) break; } else if (s[i] == '\\') { i+=2; - break; + continue; } i++; } tEnd = std::min(i,s.length()); result.append(s.mid(tStart,tEnd-tStart)); - } if (ch == '\"') { + } else if (ch == '\"') { tStart = i; i++; //skip \' while (i') { + i++; break; } i++; @@ -1490,7 +1504,7 @@ QStringList DebugReader::tokenize(const QString &s) } else if (ch == '_' || ch.isLetterOrNumber()) { tStart = i; while (i mWatchVars; int mUpdateCount; + + // QAbstractItemModel interface +public: + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; }; @@ -248,8 +252,7 @@ private slots: void syncFinishedParsing(); void onChangeDebugConsoleLastline(const QString& text); void clearUpReader(); - void onAddLocalWithoutLinebreak(const QString& text); - void onAddLocalWithLinebreak(const QString& text); + void onAddLocalLine(const QString& text); void onClearLocals(); private: bool mExecuting; @@ -288,9 +291,10 @@ signals: void updateWatch(); void processError(QProcess::ProcessError error); void changeDebugConsoleLastLine(const QString& text); - void addLocalWithoutLinebreak(const QString& text); - void addLocalWithLinebreak(const QString& text); + void addLocalLine(const QString& text); void clearLocals(); + void cmdStarted(); + void cmdFinished(); private: void clearCmdQueue(); bool findAnnotation(AnnotationType annotation); diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index 9edf41c0..b71211e9 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -760,6 +760,7 @@ void MainWindow::setupActions() { void MainWindow::updateCompilerSet() { + mCompilerSet->blockSignals(true); mCompilerSet->clear(); for (size_t i=0;icompilerSets().list().size();i++) { mCompilerSet->addItem(pSettings->compilerSets().list()[i]->name()); @@ -775,6 +776,8 @@ void MainWindow::updateCompilerSet() index = pSettings->compilerSets().defaultIndex(); } mCompilerSet->setCurrentIndex(index); + mCompilerSet->blockSignals(false); + mCompilerSet->update(); } void MainWindow::updateDebuggerSettings() @@ -1166,6 +1169,8 @@ void MainWindow::debug() mDebugger->sendCommand("set", "width 0"); // don't wrap output, very annoying mDebugger->sendCommand("set", "new-console on"); mDebugger->sendCommand("set", "confirm off"); + mDebugger->sendCommand("set", "print repeats 0"); // don't repeat elements + mDebugger->sendCommand("set", "print elements 0"); // don't limit elements mDebugger->sendCommand("cd", excludeTrailingPathDelimiter(debugFile.path())); // restore working directory if (!debugInferiorhasBreakpoint()) { QString params; @@ -1790,6 +1795,26 @@ void MainWindow::onEditorTabContextMenu(const QPoint &pos) menu.exec(tabBar->mapToGlobal(pos)); } +void MainWindow::disableDebugActions() +{ + ui->actionStep_Into->setEnabled(false); + ui->actionStep_Over->setEnabled(false); + ui->actionStep_Out->setEnabled(false); + ui->actionRun_To_Cursor->setEnabled(false); + ui->actionContinue->setEnabled(false); + ui->cbEvaluate->setEnabled(false); +} + +void MainWindow::enableDebugActions() +{ + ui->actionStep_Into->setEnabled(true); + ui->actionStep_Over->setEnabled(true); + ui->actionStep_Out->setEnabled(true); + ui->actionRun_To_Cursor->setEnabled(true); + ui->actionContinue->setEnabled(true); + ui->cbEvaluate->setEnabled(true); +} + void MainWindow::prepareProjectForCompile() { if (!mProject) @@ -2124,6 +2149,14 @@ void MainWindow::onCompilerSetChanged(int index) { if (index<0) return; + if (mProject) { + Editor *e = mEditorList->getEditor(); + if (!e || e->inProject()) { + mProject->options().compilerSet = index; + mProject->saveOptions(); + return; + } + } pSettings->compilerSets().setDefaultIndex(index); pSettings->compilerSets().saveDefaultIndex(); } @@ -2157,6 +2190,11 @@ void MainWindow::onCompileIssue(PCompileIssue issue) } } +void MainWindow::onCompileStarted() +{ + ui->txtCompilerOutput->clear(); +} + void MainWindow::onCompileFinished() { // Update tab caption diff --git a/RedPandaIDE/mainwindow.h b/RedPandaIDE/mainwindow.h index e74992b9..ce60e3ba 100644 --- a/RedPandaIDE/mainwindow.h +++ b/RedPandaIDE/mainwindow.h @@ -110,6 +110,7 @@ public: public slots: void onCompileLog(const QString& msg); void onCompileIssue(PCompileIssue issue); + void onCompileStarted(); void onCompileFinished(); void onCompileErrorOccured(const QString& reason); void onRunErrorOccured(const QString& reason); @@ -123,6 +124,8 @@ public slots: void onEvalValueReady(const QString& value); void onEditorContextMenu(const QPoint& pos); void onEditorTabContextMenu(const QPoint& pos); + void disableDebugActions(); + void enableDebugActions(); private: void prepareProjectForCompile(); diff --git a/RedPandaIDE/mainwindow.ui b/RedPandaIDE/mainwindow.ui index 4f01770f..de40a9eb 100644 --- a/RedPandaIDE/mainwindow.ui +++ b/RedPandaIDE/mainwindow.ui @@ -85,7 +85,7 @@ QTabWidget::West - 0 + 1 true @@ -147,6 +147,9 @@ QAbstractItemView::NoEditTriggers + + Qt::ElideNone + true @@ -285,7 +288,7 @@ QTabWidget::South - 1 + 2 @@ -475,6 +478,9 @@ + + false + true @@ -487,7 +493,7 @@ QTabWidget::North - 1 + 3 @@ -606,7 +612,14 @@ 0 - + + + false + + + true + + @@ -667,6 +680,9 @@ 0 + + QComboBox::AdjustToContents + @@ -737,6 +753,9 @@ QComboBox::InsertAtTop + + QComboBox::AdjustToContents + diff --git a/RedPandaIDE/qsynedit/SynEdit.cpp b/RedPandaIDE/qsynedit/SynEdit.cpp index 2394a9e9..0baf76b2 100644 --- a/RedPandaIDE/qsynedit/SynEdit.cpp +++ b/RedPandaIDE/qsynedit/SynEdit.cpp @@ -2959,6 +2959,9 @@ void SynEdit::findSubFoldRange(PSynEditFoldRanges TopFoldRanges, int FoldIndex,P PSynEditFoldRange CollapsedFold; int Line = 0; QString CurLine; + bool useBraces = ( mCodeFolding.foldRegions.get(FoldIndex)->openSymbol == "{" + && mCodeFolding.foldRegions.get(FoldIndex)->closeSymbol == "}"); + int lastBraceLevel = 0; if (!mHighlighter) return; @@ -2970,59 +2973,87 @@ void SynEdit::findSubFoldRange(PSynEditFoldRanges TopFoldRanges, int FoldIndex,P continue; } - // Find an opening character on this line - CurLine = mLines->getString(Line); - - mHighlighter->setState(mLines->ranges(Line), - mLines->braceLevels(Line), - mLines->bracketLevels(Line), - mLines->parenthesisLevels(Line)); - mHighlighter->setLine(CurLine,Line); - - QString token; - int pos; - while (!mHighlighter->eol()) { - token = mHighlighter->getToken(); - pos = mHighlighter->getTokenPos()+token.length(); - PSynHighlighterAttribute attr = mHighlighter->getTokenAttribute(); - // We've found a starting character and it have proper highlighting (ignore stuff inside comments...) - if (token == mCodeFolding.foldRegions.get(FoldIndex)->openSymbol && attr->name()==mCodeFolding.foldRegions.get(FoldIndex)->highlight) { - // And ignore lines with both opening and closing chars in them - if (lineHasChar(Line,pos,mCodeFolding.foldRegions.get(FoldIndex)->closeSymbol, - mCodeFolding.foldRegions.get(FoldIndex)->highlight)<0) { - // Add it to the top list of folds - Parent = parentFoldRanges->addByParts( - Parent, - TopFoldRanges, - Line + 1, - mCodeFolding.foldRegions.get(FoldIndex), - Line + 1); - parentFoldRanges = Parent->subFoldRanges; - - // Skip until a newline - break; - } - - } else if (token == mCodeFolding.foldRegions.get(FoldIndex)->closeSymbol && attr->name()==mCodeFolding.foldRegions.get(FoldIndex)->highlight) { - // And ignore lines with both opening and closing chars in them - if (lineHasChar(Line,pos,mCodeFolding.foldRegions.get(FoldIndex)->openSymbol, - mCodeFolding.foldRegions.get(FoldIndex)->highlight)<0) { - // Stop the recursion if we find a closing char, and return to our parent - if (Parent) { - Parent->toLine = Line + 1; - Parent = Parent->parent; - if (!Parent) { - parentFoldRanges = TopFoldRanges; - } else { - parentFoldRanges = Parent->subFoldRanges; - } - } - - // Skip until a newline - break; + //we just use braceLevel + if (useBraces) { + int curBraceLevel = mLines->braceLevels(Line); + if (curBraceLevel > lastBraceLevel) { + // Add it to the top list of folds + Parent = parentFoldRanges->addByParts( + Parent, + TopFoldRanges, + Line + 1, + mCodeFolding.foldRegions.get(FoldIndex), + Line + 1); + parentFoldRanges = Parent->subFoldRanges; + } else if (curBraceLevel < lastBraceLevel) { + // Stop the recursion if we find a closing char, and return to our parent + if (Parent) { + Parent->toLine = Line + 1; + Parent = Parent->parent; + if (!Parent) { + parentFoldRanges = TopFoldRanges; + } else { + parentFoldRanges = Parent->subFoldRanges; + } } } - mHighlighter->next(); + lastBraceLevel = curBraceLevel; + } else { + + // Find an opening character on this line + CurLine = mLines->getString(Line); + + mHighlighter->setState(mLines->ranges(Line), + mLines->braceLevels(Line), + mLines->bracketLevels(Line), + mLines->parenthesisLevels(Line)); + mHighlighter->setLine(CurLine,Line); + + QString token; + int pos; + while (!mHighlighter->eol()) { + token = mHighlighter->getToken(); + pos = mHighlighter->getTokenPos()+token.length(); + PSynHighlighterAttribute attr = mHighlighter->getTokenAttribute(); + // We've found a starting character and it have proper highlighting (ignore stuff inside comments...) + if (token == mCodeFolding.foldRegions.get(FoldIndex)->openSymbol && attr->name()==mCodeFolding.foldRegions.get(FoldIndex)->highlight) { + // And ignore lines with both opening and closing chars in them + if (lineHasChar(Line,pos,mCodeFolding.foldRegions.get(FoldIndex)->closeSymbol, + mCodeFolding.foldRegions.get(FoldIndex)->highlight)<0) { + // Add it to the top list of folds + Parent = parentFoldRanges->addByParts( + Parent, + TopFoldRanges, + Line + 1, + mCodeFolding.foldRegions.get(FoldIndex), + Line + 1); + parentFoldRanges = Parent->subFoldRanges; + + // Skip until a newline + break; + } + + } else if (token == mCodeFolding.foldRegions.get(FoldIndex)->closeSymbol && attr->name()==mCodeFolding.foldRegions.get(FoldIndex)->highlight) { + // And ignore lines with both opening and closing chars in them + if (lineHasChar(Line,pos,mCodeFolding.foldRegions.get(FoldIndex)->openSymbol, + mCodeFolding.foldRegions.get(FoldIndex)->highlight)<0) { + // Stop the recursion if we find a closing char, and return to our parent + if (Parent) { + Parent->toLine = Line + 1; + Parent = Parent->parent; + if (!Parent) { + parentFoldRanges = TopFoldRanges; + } else { + parentFoldRanges = Parent->subFoldRanges; + } + } + + // Skip until a newline + break; + } + } + mHighlighter->next(); + } } Line++; }