From 33e804294458fa10662929d4d847c06bc37f8f81 Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Sun, 19 Dec 2021 10:16:46 +0800 Subject: [PATCH] - enhancement: use the new expression parser to implement rename symbol - fix: rename symbol shouldn't remove empty lines --- NEWS.md | 2 + RedPandaIDE/cpprefacter.cpp | 77 ++++++++++++++++---------------- RedPandaIDE/editor.cpp | 25 ++++++----- RedPandaIDE/mainwindow.cpp | 5 +-- RedPandaIDE/parser/cppparser.cpp | 10 +++++ RedPandaIDE/parser/cppparser.h | 4 ++ 6 files changed, 70 insertions(+), 53 deletions(-) diff --git a/NEWS.md b/NEWS.md index e6cc19d6..7dab8936 100644 --- a/NEWS.md +++ b/NEWS.md @@ -2,6 +2,8 @@ Version 0.11.3 For Dev-C++ 7 Beta - fix: use pixel size for fonts, to fit different dpi in multiple displays - enhancement: use the new expression parser to parse info for tips - enhancement: better highlight processing for preprocess directives + - enhancement: use the new expression parser to implement rename symbol + - fix: rename symbol shouldn't remove empty lines Version 0.11.2 For Dev-C++ 7 Beta - fix: button "run all problem cases" not disabled when compiling or debugging diff --git a/RedPandaIDE/cpprefacter.cpp b/RedPandaIDE/cpprefacter.cpp index 6f4b6e7f..90236814 100644 --- a/RedPandaIDE/cpprefacter.cpp +++ b/RedPandaIDE/cpprefacter.cpp @@ -29,7 +29,7 @@ bool CppRefacter::findOccurence(Editor *editor, const BufferCoord &pos) PStatement statement = editor->parser()->findStatementOf( editor->filename(), expression, - editor->parser()->findAndScanBlockAt(editor->filename(),pos.Line)); + pos.Line); // definition of the symbol not found if (!statement) return false; @@ -98,12 +98,11 @@ void CppRefacter::renameSymbol(Editor *editor, const BufferCoord &pos, const QSt editor->parser()->unFreeze(); }); // get full phrase (such as s.name instead of name) - BufferCoord pBeginPos,pEndPos; - QString phrase = getWordAtPosition(editor,pos,pBeginPos,pEndPos,Editor::WordPurpose::wpInformation); + QStringList expression = editor->getExpressionAtPosition(pos); // Find it's definition PStatement oldStatement = editor->parser()->findStatementOf( editor->filename(), - phrase, + expression, pos.Line); QString oldScope = fullParentName(oldStatement); // definition of the symbol not found @@ -118,10 +117,11 @@ void CppRefacter::renameSymbol(Editor *editor, const BufferCoord &pos, const QSt return; } - QString newPhrase = phrase.mid(0,phrase.length()-word.length()) + newWord; + QStringList newExpression = expression; + newExpression[newExpression.count()-1]=newWord; PStatement newStatement = editor->parser()->findStatementOf( editor->filename(), - newPhrase, + newExpression, pos.Line); if (newStatement && fullParentName(newStatement) == oldScope) { QMessageBox::critical(editor, @@ -177,7 +177,7 @@ PSearchResultTreeItem CppRefacter::findOccurenceInFile( parentItem->filename = filename; parentItem->parent = nullptr; QStringList buffer; - SynEdit editor; + Editor editor(nullptr); if (pMainWindow->editorList()->getContentFromOpenedEditor( filename,buffer)){ editor.lines()->setContents(buffer); @@ -204,28 +204,31 @@ PSearchResultTreeItem CppRefacter::findOccurenceInFile( while (!editor.highlighter()->eol()) { int start = editor.highlighter()->getTokenPos() + 1; QString token = editor.highlighter()->getToken(); - if (token == statement->command) { - //same name symbol , test if the same statement; - BufferCoord p,pBeginPos,pEndPos; - p.Line = posY+1; - p.Char = start; - QString phrase = getWordAtPosition(&editor, p, pBeginPos,pEndPos, - Editor::WordPurpose::wpInformation); - PStatement tokenStatement = parser->findStatementOf( - filename, - phrase, p.Line); - if (tokenStatement - && (tokenStatement->line == statement->line) - && (tokenStatement->fileName == statement->fileName)) { - PSearchResultTreeItem item = std::make_shared(); - item->filename = filename; - item->line = p.Line; - item->start = start; - item->len = phrase.length(); - item->parent = parentItem.get(); - item->text = line; - item->text.replace('\t',' '); - parentItem->results.append(item); + PSynHighlighterAttribute attr = editor.highlighter()->getTokenAttribute(); + if (!attr || attr!=editor.highlighter()->commentAttribute()) { + if (token == statement->command) { + //same name symbol , test if the same statement; + BufferCoord p; + p.Line = posY+1; + p.Char = start+1; + + QStringList expression = editor.getExpressionAtPosition(p); + PStatement tokenStatement = parser->findStatementOf( + filename, + expression, p.Line); + if (tokenStatement + && (tokenStatement->line == statement->line) + && (tokenStatement->fileName == statement->fileName)) { + PSearchResultTreeItem item = std::make_shared(); + item->filename = filename; + item->line = p.Line; + item->start = start; + item->len = token.length(); + item->parent = parentItem.get(); + item->text = line; + item->text.replace('\t',' '); + parentItem->results.append(item); + } } } editor.highlighter()->next(); @@ -238,7 +241,7 @@ PSearchResultTreeItem CppRefacter::findOccurenceInFile( void CppRefacter::renameSymbolInFile(const QString &filename, const PStatement &statement, const QString &newWord, const PCppParser &parser) { QStringList buffer; - SynEdit editor; + Editor editor(nullptr); if (pMainWindow->editorList()->getContentFromOpenedEditor( filename,buffer)){ editor.lines()->setContents(buffer); @@ -251,10 +254,6 @@ void CppRefacter::renameSymbolInFile(const QString &filename, const PStatement & int posY = 0; while (posY < editor.lines()->count()) { QString line = editor.lines()->getString(posY); - if (line.isEmpty()) { - posY++; - continue; - } if (posY == 0) { editor.highlighter()->resetState(); @@ -269,14 +268,14 @@ void CppRefacter::renameSymbolInFile(const QString &filename, const PStatement & QString token = editor.highlighter()->getToken(); if (token == statement->command) { //same name symbol , test if the same statement; - BufferCoord p,pBeginPos,pEndPos; + BufferCoord p; p.Line = posY+1; - p.Char = start; - QString phrase = getWordAtPosition(&editor, p, pBeginPos,pEndPos, - Editor::WordPurpose::wpInformation); + p.Char = start+1; + + QStringList expression = editor.getExpressionAtPosition(p); PStatement tokenStatement = parser->findStatementOf( filename, - phrase, p.Line); + expression, p.Line); if (tokenStatement && (tokenStatement->line == statement->line) && (tokenStatement->fileName == statement->fileName)) { diff --git a/RedPandaIDE/editor.cpp b/RedPandaIDE/editor.cpp index 52130df6..bbecb4ee 100644 --- a/RedPandaIDE/editor.cpp +++ b/RedPandaIDE/editor.cpp @@ -1644,35 +1644,38 @@ QStringList Editor::getExpressionAtPosition( int ch = pos.Char-1; int symbolMatchingLevel = 0; LastSymbolType lastSymbolType=LastSymbolType::None; + PSynHighlighter highlighter = highlighterManager.getHighlighter(mFilename); + if (!highlighter) + return result; while (true) { if (line>=lines()->count() || line<0) break; QStringList tokens; if (line==0) { - highlighter()->resetState(); + highlighter->resetState(); } else { - highlighter()->setState(lines()->ranges(line-1)); + highlighter->setState(lines()->ranges(line-1)); } QString sLine = lines()->getString(line); - highlighter()->setLine(sLine,line-1); - while (!highlighter()->eol()) { - int start = highlighter()->getTokenPos() + 1; - QString token = highlighter()->getToken(); + highlighter->setLine(sLine,line-1); + while (!highlighter->eol()) { + int start = highlighter->getTokenPos(); + QString token = highlighter->getToken(); int endPos = start + token.length()-1; if (start>ch) { break; } - PSynHighlighterAttribute attr = highlighter()->getTokenAttribute(); + PSynHighlighterAttribute attr = highlighter->getTokenAttribute(); if ( (line == pos.Line-1) && (start<=ch) && (ch<=endPos)) { - if (attr==highlighter()->commentAttribute() || attr == highlighter()->stringAttribute()) { + if (attr==highlighter->commentAttribute() || attr == highlighter->stringAttribute()) { return result; } } - if (attr!=highlighter()->commentAttribute() && attr!=highlighter()->whitespaceAttribute()){ + if (attr!=highlighter->commentAttribute() && attr!=highlighter->whitespaceAttribute()){ tokens.append(token); } - highlighter()->next(); + highlighter->next(); } for (int i=tokens.count()-1;i>=0;i--) { QString token = tokens[i]; @@ -3057,7 +3060,7 @@ QString Editor::getParserHint(const QStringList& expression,const QString &s, in QString result; PStatement statement = mParser->findStatementOf( mFilename,expression, - mParser->findAndScanBlockAt(mFilename,line)); + line); if (!statement) return result; if (statement->kind == StatementKind::skFunction diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index 00816722..b0b6f6a0 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -5116,12 +5116,11 @@ void MainWindow::on_actionRename_Symbol_triggered() BufferCoord oldCaretXY = editor->caretXY(); if (editor->inProject() && mProject) { mProject->cppParser()->parseFileList(); - BufferCoord pBeginPos,pEndPos; - QString phrase = getWordAtPosition(editor,oldCaretXY,pBeginPos,pEndPos,Editor::WordPurpose::wpInformation); + QStringList expression = editor->getExpressionAtPosition(oldCaretXY); // Find it's definition PStatement oldStatement = editor->parser()->findStatementOf( editor->filename(), - phrase, + expression, oldCaretXY.Line); // definition of the symbol not found if (!oldStatement) diff --git a/RedPandaIDE/parser/cppparser.cpp b/RedPandaIDE/parser/cppparser.cpp index 8edad39e..381a6b72 100644 --- a/RedPandaIDE/parser/cppparser.cpp +++ b/RedPandaIDE/parser/cppparser.cpp @@ -246,6 +246,8 @@ PStatement CppParser::findStatement(const QString &fullname) PStatement CppParser::findStatementOf(const QString &fileName, const QString &phrase, int line) { QMutexLocker locker(&mMutex); + if (mParsing) + return PStatement(); return findStatementOf(fileName,phrase,findAndScanBlockAt(fileName,line)); } @@ -447,6 +449,14 @@ PStatement CppParser::findStatementOf(const QString &fileName, const QStringList } +PStatement CppParser::findStatementOf(const QString &fileName, const QStringList &expression, int line) +{ + QMutexLocker locker(&mMutex); + if (mParsing) + return PStatement(); + return findStatementOf(fileName,expression,findAndScanBlockAt(fileName,line)); +} + PStatement CppParser::findStatementStartingFrom(const QString &fileName, const QString &phrase, const PStatement& startScope) { PStatement scopeStatement = startScope; diff --git a/RedPandaIDE/parser/cppparser.h b/RedPandaIDE/parser/cppparser.h index bad138e8..7f1b5b2d 100644 --- a/RedPandaIDE/parser/cppparser.h +++ b/RedPandaIDE/parser/cppparser.h @@ -53,6 +53,10 @@ public: PStatement findStatementOf(const QString& fileName, const QStringList& expression, const PStatement& currentScope); + PStatement findStatementOf(const QString& fileName, + const QStringList& expression, + int line); + /** * @brief evaluate the expression * @param fileName