From f4b239e15dca55c570fcc1657501bcc622a0ce01 Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Fri, 17 Feb 2023 23:56:13 +0800 Subject: [PATCH] - enhancement: Greatly reduce time to open/edit big files. --- NEWS.md | 1 + RedPandaIDE/editor.cpp | 4 +- libs/qsynedit/qsynedit/codefolding.cpp | 8 +- libs/qsynedit/qsynedit/codefolding.h | 5 +- libs/qsynedit/qsynedit/document.cpp | 5 +- libs/qsynedit/qsynedit/qsynedit.cpp | 69 ++++---- libs/qsynedit/qsynedit/qsynedit.h | 6 +- libs/qsynedit/qsynedit/syntaxer/cpp.cpp | 212 ++++-------------------- libs/qsynedit/qsynedit/syntaxer/cpp.h | 1 - 9 files changed, 95 insertions(+), 216 deletions(-) diff --git a/NEWS.md b/NEWS.md index 7e7acab0..2451000e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -36,6 +36,7 @@ Red Panda C++ Version 2.12 - change: Remove "Compile & Run" menu item. It's replaced by "Run". - enhancement: Show "..." instead of "...}" when folding #if/#endif - enhancement: Correctly handle high-precision mouse wheel / touchpad in editors. + - enhancement: Greatly reduce time to open/edit big files. Red Panda C++ Version 2.11 diff --git a/RedPandaIDE/editor.cpp b/RedPandaIDE/editor.cpp index 3dcbb842..3ad109e3 100644 --- a/RedPandaIDE/editor.cpp +++ b/RedPandaIDE/editor.cpp @@ -246,6 +246,7 @@ void Editor::loadFile(QString filename) { unit->setRealEncoding(mFileEncoding); } } + //this->setModified(false); updateCaption(); if (mParentPageControl) @@ -267,6 +268,7 @@ void Editor::loadFile(QString filename) { } reparseTodo(); } + mLastIdCharPressed = 0; saveAutoBackup(); } @@ -355,6 +357,7 @@ bool Editor::save(bool force, bool doReparse) { checkSyntaxInBack(); reparseTodo(); } + return true; } @@ -3273,7 +3276,6 @@ void Editor::showCompletion(const QString& preWord,bool autoComplete, CodeComple } pMainWindow->functionTip()->hide(); mCompletionPopup->show(); - // Scan the current function body QSet keywords; if (syntaxer()) { diff --git a/libs/qsynedit/qsynedit/codefolding.cpp b/libs/qsynedit/qsynedit/codefolding.cpp index 6244b195..be161489 100644 --- a/libs/qsynedit/qsynedit/codefolding.cpp +++ b/libs/qsynedit/qsynedit/codefolding.cpp @@ -58,14 +58,13 @@ CodeFoldingRange::CodeFoldingRange(PCodeFoldingRange parent, toLine(toLine), linesCollapsed(0), collapsed(false), - hintMarkLeft(0), parent(parent) { subFoldRanges = std::make_shared(); } -PCodeFoldingRange CodeFoldingRanges::range(int index) +PCodeFoldingRange CodeFoldingRanges::range(int index) const { return mRanges[index]; } @@ -118,4 +117,9 @@ PCodeFoldingRange CodeFoldingRanges::operator[](int index) const return mRanges[index]; } +const QVector &CodeFoldingRanges::ranges() const +{ + return mRanges; +} + } diff --git a/libs/qsynedit/qsynedit/codefolding.h b/libs/qsynedit/qsynedit/codefolding.h index e7624730..1e0f870c 100644 --- a/libs/qsynedit/qsynedit/codefolding.h +++ b/libs/qsynedit/qsynedit/codefolding.h @@ -44,7 +44,7 @@ public: explicit CodeFoldingRanges(); CodeFoldingRanges& operator=(const CodeFoldingRanges&)=delete; - PCodeFoldingRange range(int index); + PCodeFoldingRange range(int index) const; void clear(); int count() const; PCodeFoldingRange addByParts(PCodeFoldingRange parent, PCodeFoldingRanges allFold, @@ -54,6 +54,8 @@ public: void remove(int index); void add(PCodeFoldingRange foldRange); PCodeFoldingRange operator[](int index) const; + const QVector &ranges() const; + private: QVector mRanges; }; @@ -69,7 +71,6 @@ public: int linesCollapsed; // Number of collapsed lines PCodeFoldingRanges subFoldRanges; // Sub fold ranges bool collapsed; // Is collapsed? - int hintMarkLeft; std::weak_ptr parent; bool parentCollapsed(); void move(int count); diff --git a/libs/qsynedit/qsynedit/document.cpp b/libs/qsynedit/qsynedit/document.cpp index 8c369338..bfb65e7b 100644 --- a/libs/qsynedit/qsynedit/document.cpp +++ b/libs/qsynedit/qsynedit/document.cpp @@ -206,9 +206,9 @@ void Document::setSyntaxState(int Index, const SyntaxState& range) if (Index<0 || Index>=mLines.count()) { ListIndexOutOfBounds(Index); } - beginUpdate(); + //beginUpdate(); mLines[Index]->syntaxState = range; - endUpdate(); + //endUpdate(); } QString Document::getLine(int Index) @@ -581,6 +581,7 @@ void Document::setTabWidth(int newTabWidth) resetColumns(); } } + void Document::loadFromFile(const QString& filename, const QByteArray& encoding, QByteArray& realEncoding) { QMutexLocker locker(&mMutex); diff --git a/libs/qsynedit/qsynedit/qsynedit.cpp b/libs/qsynedit/qsynedit/qsynedit.cpp index 39bf3de0..f8b1203f 100644 --- a/libs/qsynedit/qsynedit/qsynedit.cpp +++ b/libs/qsynedit/qsynedit/qsynedit.cpp @@ -3377,12 +3377,16 @@ void QSynEdit::reparseLine(int line) void QSynEdit::reparseDocument() { if (mSyntaxer && !mDocument->empty()) { +// qint64 begin=QDateTime::currentMSecsSinceEpoch(); mSyntaxer->resetState(); for (int i =0;icount();i++) { mSyntaxer->setLine(mDocument->getLine(i), i); mSyntaxer->nextToEol(); mDocument->setSyntaxState(i, mSyntaxer->getState()); } +// qint64 diff= QDateTime::currentMSecsSinceEpoch() - begin; + +// qDebug()<count(); } if (mUseCodeFolding) rescanFolds(); @@ -3461,7 +3465,11 @@ void QSynEdit::rescanFolds() //qDebug()< 0) { - CodeFoldingRanges ranges{mAllFoldRanges}; + QMap rangeIndexes; + foreach(const PCodeFoldingRange& r, mAllFoldRanges.ranges()) { + if (r->collapsed) + rangeIndexes.insert(QString("%1-%2").arg(r->fromLine).arg(r->toLine),r); + } mAllFoldRanges.clear(); // Add folds to a separate list PCodeFoldingRanges temporaryAllFoldRanges = std::make_shared(); scanForFoldRanges(temporaryAllFoldRanges); + PCodeFoldingRange tempFoldRange; + PCodeFoldingRange r2; // Combine new with old folds, preserve parent order for (int i = 0; i< temporaryAllFoldRanges->count();i++) { - PCodeFoldingRange tempFoldRange=temporaryAllFoldRanges->range(i); - int j=0; - while (j range(i)->fromLine<fromLine; - if (tempFoldRange->fromLine == foldRange->fromLine - && tempFoldRange->toLine == foldRange->toLine) { - //qDebug()<<"-"<fromLine; - mAllFoldRanges.add(foldRange); - break; - } - j++; - } - if (j>=ranges.count()) { - //qDebug()<<"--"<fromLine; - mAllFoldRanges.add(tempFoldRange); + tempFoldRange=temporaryAllFoldRanges->range(i); + r2=rangeIndexes.value(QString("%1-%2").arg(tempFoldRange->fromLine).arg(tempFoldRange->toLine), + PCodeFoldingRange()); + if (r2) { + tempFoldRange->collapsed=true; + tempFoldRange->linesCollapsed=r2->linesCollapsed; } + mAllFoldRanges.add(tempFoldRange); } - } else { - // We ended up with no folds after deleting, just pass standard data... PCodeFoldingRanges temp(&mAllFoldRanges, null_deleter); scanForFoldRanges(temp); @@ -3516,7 +3519,11 @@ void QSynEdit::rescanForFoldRanges() void QSynEdit::scanForFoldRanges(PCodeFoldingRanges topFoldRanges) { PCodeFoldingRanges parentFoldRanges = topFoldRanges; +// qint64 begin=QDateTime::currentMSecsSinceEpoch(); + findSubFoldRange(topFoldRanges, parentFoldRanges,PCodeFoldingRange()); +// qint64 diff= QDateTime::currentMSecsSinceEpoch() - begin; +// qDebug()<<"?"<count()) { // index is valid for LinesToScan and fLines // If there is a collapsed fold over here, skip it - collapsedFold = collapsedFoldStartAtLine(line + 1); // only collapsed folds remain - if (collapsedFold) { - line = collapsedFold->toLine; - continue; - } +// collapsedFold = collapsedFoldStartAtLine(line + 1); // only collapsed folds remain +// if (collapsedFold) { +// line = collapsedFold->toLine; +// continue; +// } // Find an opening character on this line curLine = mDocument->getLine(line); - if (mDocument->blockEnded(line)>0) { - for (int i=0; iblockEnded(line);i++) { + int blockEnded=mDocument->blockEnded(line); + int blockStarted=mDocument->blockStarted(line); + if (blockEnded>0) { + for (int i=0; iblockStarted(line)>0) + if (blockStarted>0) parent->toLine = line; else parent->toLine = line + 1; @@ -3584,8 +3593,8 @@ void QSynEdit::findSubFoldRange(PCodeFoldingRanges topFoldRanges, PCodeFoldingRa } } } - if (mDocument->blockStarted(line)>0) { - for (int i=0; iblockStarted(line);i++) { + if (blockStarted>0) { + for (int i=0; iaddByParts( parent, @@ -3604,7 +3613,7 @@ void QSynEdit::findSubFoldRange(PCodeFoldingRanges topFoldRanges, PCodeFoldingRa PCodeFoldingRange QSynEdit::collapsedFoldStartAtLine(int Line) { for (int i = 0; i< mAllFoldRanges.count() - 1; i++ ) { - if (mAllFoldRanges[i]->fromLine == Line && mAllFoldRanges[i]->collapsed) { + if (mAllFoldRanges[i]->collapsed && mAllFoldRanges[i]->fromLine == Line) { return mAllFoldRanges[i]; } else if (mAllFoldRanges[i]->fromLine > Line) { break; // sorted by line. don't bother scanning further diff --git a/libs/qsynedit/qsynedit/qsynedit.h b/libs/qsynedit/qsynedit/qsynedit.h index 7c0df07c..20b079a7 100644 --- a/libs/qsynedit/qsynedit/qsynedit.h +++ b/libs/qsynedit/qsynedit/qsynedit.h @@ -469,6 +469,8 @@ protected: virtual void onBeginFirstPaintLock(); private: + void beginEditingWithoutUndo(); + void endEditingWithoutUndo(); void clearAreaList(EditingAreaList areaList); void computeCaret(); void computeScroll(bool isDragging); @@ -500,8 +502,8 @@ private: QString expandAtWideGlyphs(const QString& S); void updateModifiedStatus(); void scanFrom(int index); - void rescanRange(int line); - void rescanRanges(); + void reparseLine(int line); + void reparseDocument(); void uncollapse(PCodeFoldingRange FoldRange); void collapse(PCodeFoldingRange FoldRange); diff --git a/libs/qsynedit/qsynedit/syntaxer/cpp.cpp b/libs/qsynedit/qsynedit/syntaxer/cpp.cpp index 7b22b4fb..e1f86cfd 100644 --- a/libs/qsynedit/qsynedit/syntaxer/cpp.cpp +++ b/libs/qsynedit/qsynedit/syntaxer/cpp.cpp @@ -361,12 +361,6 @@ void CppSyntaxer::asciiCharProc() mRange.state = RangeState::rsUnknown; } -void CppSyntaxer::atSymbolProc() -{ - mTokenId = TokenId::Unknown; - mRun+=1; -} - void CppSyntaxer::braceCloseProc() { mRun += 1; @@ -673,43 +667,32 @@ void CppSyntaxer::nullProc() void CppSyntaxer::numberProc() { - int idx1; // token[1] - idx1 = mRun; - mRun+=1; mTokenId = TokenId::Number; - bool shouldExit = false; + if (mRun+1='0' && mLine[mRun+1]<='7') { + mTokenId=TokenId::Octal; + mRun+=2; + } + } else + mRun+=1; while (mRun float. an arithmetic operator - return; - if (mRun-1>=0 && mLine[mRun-1]!= 'e' && mLine[mRun-1]!='E') // number = float, but no exponent. an arithmetic operator - return; - if (mRun+1'9')) {// invalid - mRun+=1; - mTokenId = TokenId::Unknown; - return; - } - break; case '0': case '1': case '2': @@ -718,15 +701,8 @@ void CppSyntaxer::numberProc() case '5': case '6': case '7': - if ((mRun == idx1+1) && (mLine[idx1] == '0')) { // octal number - mTokenId = TokenId::Octal; - } - break; case '8': case '9': - if ( (mLine[idx1]=='0') && (mTokenId != TokenId::Hex) && (mTokenId != TokenId::Float) ) // invalid octal char - mTokenId = TokenId::Unknown; // we must continue parse, it may be an float number - break; case 'a': case 'b': case 'c': @@ -735,110 +711,31 @@ void CppSyntaxer::numberProc() case 'B': case 'C': case 'D': - if (mTokenId!=TokenId::Hex) { //invalid - mTokenId = TokenId::Unknown; - return; - } break; case 'e': case 'E': + if (mTokenId==TokenId::Number) { + mTokenId = TokenId::Float; + mRun++; + if (mRun < mLineSize && (mLine[mRun]== '+' || mLine[mRun]== '-')) // number = float, but no exponent. an arithmetic operator + mRun++; + break; + } + break; + case 'p': + case 'P': if (mTokenId!=TokenId::Hex) { - if (mRun-1>=0 && (mLine[mRun-1]>='0' || mLine[mRun-1]<='9') ) {//exponent - for (int i=idx1;i='0' && mLine[mRun+1]<='9')) { - return; - } else { - mTokenId = TokenId::Float; - } - } else { - mRun+=1; - mTokenId = TokenId::Unknown; - return; - } - } + mTokenId = TokenId::Float; + mRun++; + if (mRun < mLineSize && (mLine[mRun]== '+' || mLine[mRun]== '-')) // number = float, but no exponent. an arithmetic operator + mRun++; break; - case 'f': - case 'F': - if (mTokenId!=TokenId::Hex) { - for (int i=idx1;i=0 && (mLine[mRun-1]=='l' || mLine[mRun-1]=='L')) { - mRun+=1; - mTokenId = TokenId::Unknown; - return; - } - } else { - mTokenId = TokenId::Float; - } - } - break; - case 'l': - case 'L': - for (int i=idx1;i<=mRun-2;i++) { - if (mLine[i] == 'l' && mLine[i]=='L') { - mRun+=1; - mTokenId = TokenId::Unknown; - return; - } - } - if (mTokenId == TokenId::Float && (mLine[mRun-1]=='f' || mLine[mRun-1]=='F')) { - mRun+=1; - mTokenId = TokenId::Unknown; - return; - } - break; - case 'u': - case 'U': - if (mTokenId == TokenId::Float) { - mRun+=1; - mTokenId = TokenId::Unknown; - return; - } else { - for (int i=idx1;i='0' && mLine[mRun+1]<='9') - || (mLine[mRun+1]>='a' && mLine[mRun+1]<='f') - || (mLine[mRun+1]>='A' && mLine[mRun+1]<='F')) ) { - mTokenId = TokenId::Hex; - } else { - mRun+=1; - mTokenId = TokenId::Unknown; - return; } break; default: - shouldExit=true; + return; } - if (shouldExit) { - break; - } - mRun+=1; - } - if (mRun-1>=0 && mLine[mRun-1] == '\'') { - mTokenId = TokenId::Unknown; + mRun+=1; } } @@ -1123,11 +1020,7 @@ void CppSyntaxer::stringEscapeSeqProc() case '5': case '6': case '7': - for (int i=0;i<3;i++) { - if (mRun>=mLineSize || mLine[mRun]<'0' || mLine[mRun]>'7') - break; - mRun+=1; - } + mRun+=3; break; case '8': case '9': @@ -1136,49 +1029,19 @@ void CppSyntaxer::stringEscapeSeqProc() break; case 'x': mRun+=1; - if (mRun>=mLineSize || !( - (mLine[mRun]>='0' && mLine[mRun]<='9') - || (mLine[mRun]>='a' && mLine[mRun]<='f') - || (mLine[mRun]>='A' && mLine[mRun]<='F') - )) { - mTokenId = TokenId::Unknown; - } else { - while (mRun='0' && mLine[mRun]<='9') - || (mLine[mRun]>='a' && mLine[mRun]<='f') - || (mLine[mRun]>='A' && mLine[mRun]<='F') - )) { - mRun+=1; - } + while (mRun='0' && mLine[mRun]<='9') + || (mLine[mRun]>='a' && mLine[mRun]<='f') + || (mLine[mRun]>='A' && mLine[mRun]<='F') + )) { + mRun+=1; } break; case 'u': - mRun+=1; - for (int i=0;i<4;i++) { - if (mRun>=mLineSize || !( - (mLine[mRun]>='0' && mLine[mRun]<='9') - || (mLine[mRun]>='a' && mLine[mRun]<='f') - || (mLine[mRun]>='A' && mLine[mRun]<='F') - )) { - mTokenId = TokenId::Unknown; - return; - } - mRun+=1; - } + mRun+=5; break; case 'U': - mRun+=1; - for (int i=0;i<8;i++) { - if (mRun>=mLineSize || !( - (mLine[mRun]>='0' && mLine[mRun]<='9') - || (mLine[mRun]>='a' && mLine[mRun]<='f') - || (mLine[mRun]>='A' && mLine[mRun]<='F') - )) { - mTokenId = TokenId::Unknown; - return; - } - mRun+=1; - } + mRun+=9; break; } } @@ -1283,9 +1146,6 @@ void CppSyntaxer::processChar() case '\'': asciiCharProc(); break; - case '@': - atSymbolProc(); - break; case '}': braceCloseProc(); break; diff --git a/libs/qsynedit/qsynedit/syntaxer/cpp.h b/libs/qsynedit/qsynedit/syntaxer/cpp.h index 609636ee..8b5e4b69 100644 --- a/libs/qsynedit/qsynedit/syntaxer/cpp.h +++ b/libs/qsynedit/qsynedit/syntaxer/cpp.h @@ -94,7 +94,6 @@ private: void ansiCppProc(); void ansiCProc(); void asciiCharProc(); - void atSymbolProc(); void braceCloseProc(); void braceOpenProc(); void colonProc();