- fix: debug very slow when local infos are long

- fix: wrong code fold calculation
This commit is contained in:
royqh1979@gmail.com 2021-09-19 14:28:30 +08:00
parent ae4eaf0746
commit b6df4fcf41
7 changed files with 226 additions and 103 deletions

View File

@ -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);

View File

@ -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<PWatchVar> 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<WatchVar>();
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<WatchVar>();
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<WatchVar>();
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<WatchVar>();
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<s.length()) {
@ -1481,6 +1483,18 @@ QStringList DebugReader::tokenize(const QString &s)
break;
} else if (s[i] == '\\') {
i+=2;
continue;
}
i++;
}
tEnd = std::min(i,s.length());
result.append(s.mid(tStart,tEnd-tStart));
} else if (ch == '<') {
tStart = i;
i++;
while (i<s.length()) {
if (s[i]=='>') {
i++;
break;
}
i++;
@ -1490,7 +1504,7 @@ QStringList DebugReader::tokenize(const QString &s)
} else if (ch == '_' || ch.isLetterOrNumber()) {
tStart = i;
while (i<s.length()) {
if ((ch!='_') &&(!ch.isLetterOrNumber()))
if ((s[i]!='_') &&(!s[i].isLetterOrNumber()))
break;
i++;
}
@ -2044,6 +2058,19 @@ void WatchModel::notifyUpdated(PWatchVar var)
emit dataChanged(createIndex(row,0,var.get()),createIndex(row,0,var.get()));
}
QVariant WatchModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
switch(section) {
case 0:
return tr("Expression");
case 1:
return tr("Value");
}
}
return QVariant();
}
RegisterModel::RegisterModel(QObject *parent):QAbstractTableModel(parent)
{

View File

@ -163,6 +163,10 @@ public:
private:
QList<PWatchVar> 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);

View File

@ -760,6 +760,7 @@ void MainWindow::setupActions() {
void MainWindow::updateCompilerSet()
{
mCompilerSet->blockSignals(true);
mCompilerSet->clear();
for (size_t i=0;i<pSettings->compilerSets().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

View File

@ -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();

View File

@ -85,7 +85,7 @@
<enum>QTabWidget::West</enum>
</property>
<property name="currentIndex">
<number>0</number>
<number>1</number>
</property>
<property name="usesScrollButtons">
<bool>true</bool>
@ -147,6 +147,9 @@
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="textElideMode">
<enum>Qt::ElideNone</enum>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
@ -285,7 +288,7 @@
<enum>QTabWidget::South</enum>
</property>
<property name="currentIndex">
<number>1</number>
<number>2</number>
</property>
<widget class="QWidget" name="tabIssues">
<attribute name="icon">
@ -475,6 +478,9 @@
</item>
<item>
<widget class="QPlainTextEdit" name="txtEvalOutput">
<property name="undoRedoEnabled">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
@ -487,7 +493,7 @@
<enum>QTabWidget::North</enum>
</property>
<property name="currentIndex">
<number>1</number>
<number>3</number>
</property>
<widget class="QWidget" name="tabDebugConsole">
<attribute name="title">
@ -606,7 +612,14 @@
<number>0</number>
</property>
<item>
<widget class="QPlainTextEdit" name="txtLocals"/>
<widget class="QPlainTextEdit" name="txtLocals">
<property name="undoRedoEnabled">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
@ -667,6 +680,9 @@
<height>0</height>
</size>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum>
</property>
</widget>
</item>
<item>
@ -737,6 +753,9 @@
<property name="insertPolicy">
<enum>QComboBox::InsertAtTop</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum>
</property>
</widget>
</item>
<item>

View File

@ -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++;
}